mirror of
https://github.com/albfan/miraclecast.git
synced 2025-02-15 00:01:53 +00:00
dhcp: sync with gdhcp
Copy over recent changes to gdhcp from ConnMan. We should really start exporting sd-dhcp from libsystemd so we can finally drop this alltogether. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
parent
eecf576fa9
commit
7c87510b34
4 changed files with 209 additions and 187 deletions
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* DHCP client library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2009-2012 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2009-2014 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -46,11 +46,11 @@
|
|||
#include "common.h"
|
||||
#include "ipv4ll.h"
|
||||
|
||||
#define DISCOVER_TIMEOUT 3
|
||||
#define DISCOVER_RETRIES 10
|
||||
#define DISCOVER_TIMEOUT 5
|
||||
#define DISCOVER_RETRIES 6
|
||||
|
||||
#define REQUEST_TIMEOUT 3
|
||||
#define REQUEST_RETRIES 5
|
||||
#define REQUEST_TIMEOUT 5
|
||||
#define REQUEST_RETRIES 3
|
||||
|
||||
typedef enum _listen_mode {
|
||||
L_NONE,
|
||||
|
@ -61,6 +61,7 @@ typedef enum _listen_mode {
|
|||
|
||||
typedef enum _dhcp_client_state {
|
||||
INIT_SELECTING,
|
||||
REBOOTING,
|
||||
REQUESTING,
|
||||
BOUND,
|
||||
RENEWING,
|
||||
|
@ -99,8 +100,10 @@ struct _GDHCPClient {
|
|||
uint8_t ack_retry_times;
|
||||
uint8_t conflicts;
|
||||
guint timeout;
|
||||
guint t1_timeout;
|
||||
guint t2_timeout;
|
||||
guint lease_timeout;
|
||||
guint listener_watch;
|
||||
GIOChannel *listener_channel;
|
||||
GList *require_list;
|
||||
GList *request_list;
|
||||
GHashTable *code_value_hash;
|
||||
|
@ -270,6 +273,25 @@ static int32_t get_time_diff(struct timeval *tv)
|
|||
return hsec;
|
||||
}
|
||||
|
||||
static void remove_timeouts(GDHCPClient *dhcp_client)
|
||||
{
|
||||
|
||||
if (dhcp_client->timeout > 0)
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
if (dhcp_client->t1_timeout > 0)
|
||||
g_source_remove(dhcp_client->t1_timeout);
|
||||
if (dhcp_client->t2_timeout > 0)
|
||||
g_source_remove(dhcp_client->t2_timeout);
|
||||
if (dhcp_client->lease_timeout > 0)
|
||||
g_source_remove(dhcp_client->lease_timeout);
|
||||
|
||||
dhcp_client->timeout = 0;
|
||||
dhcp_client->t1_timeout = 0;
|
||||
dhcp_client->t2_timeout = 0;
|
||||
dhcp_client->lease_timeout = 0;
|
||||
|
||||
}
|
||||
|
||||
static void add_dhcpv6_request_options(GDHCPClient *dhcp_client,
|
||||
struct dhcpv6_packet *packet,
|
||||
unsigned char *buf, int max_buf,
|
||||
|
@ -437,63 +459,37 @@ static int send_discover(GDHCPClient *dhcp_client, uint32_t requested)
|
|||
MAC_BCAST_ADDR, dhcp_client->ifindex);
|
||||
}
|
||||
|
||||
static int send_select(GDHCPClient *dhcp_client)
|
||||
static int send_request(GDHCPClient *dhcp_client)
|
||||
{
|
||||
struct dhcp_packet packet;
|
||||
|
||||
debug(dhcp_client, "sending DHCP select request");
|
||||
debug(dhcp_client, "sending DHCP request");
|
||||
|
||||
init_packet(dhcp_client, &packet, DHCPREQUEST);
|
||||
|
||||
packet.xid = dhcp_client->xid;
|
||||
packet.secs = dhcp_attempt_secs(dhcp_client);
|
||||
|
||||
dhcp_add_option_uint32(&packet, DHCP_REQUESTED_IP,
|
||||
dhcp_client->requested_ip);
|
||||
dhcp_add_option_uint32(&packet, DHCP_SERVER_ID,
|
||||
dhcp_client->server_ip);
|
||||
if (dhcp_client->state == REQUESTING || dhcp_client->state == REBOOTING)
|
||||
dhcp_add_option_uint32(&packet, DHCP_REQUESTED_IP,
|
||||
dhcp_client->requested_ip);
|
||||
|
||||
if (dhcp_client->state == REQUESTING)
|
||||
dhcp_add_option_uint32(&packet, DHCP_SERVER_ID,
|
||||
dhcp_client->server_ip);
|
||||
|
||||
dhcp_add_option_uint16(&packet, DHCP_MAX_SIZE, 576);
|
||||
|
||||
add_request_options(dhcp_client, &packet);
|
||||
|
||||
add_send_options(dhcp_client, &packet);
|
||||
|
||||
return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT,
|
||||
INADDR_BROADCAST, SERVER_PORT,
|
||||
MAC_BCAST_ADDR, dhcp_client->ifindex);
|
||||
}
|
||||
if (dhcp_client->state == RENEWING || dhcp_client->state == REBINDING)
|
||||
packet.ciaddr = htonl(dhcp_client->requested_ip);
|
||||
|
||||
static int send_renew(GDHCPClient *dhcp_client)
|
||||
{
|
||||
struct dhcp_packet packet;
|
||||
|
||||
debug(dhcp_client, "sending DHCP renew request");
|
||||
|
||||
init_packet(dhcp_client , &packet, DHCPREQUEST);
|
||||
packet.xid = dhcp_client->xid;
|
||||
packet.ciaddr = htonl(dhcp_client->requested_ip);
|
||||
|
||||
add_request_options(dhcp_client, &packet);
|
||||
|
||||
add_send_options(dhcp_client, &packet);
|
||||
|
||||
return dhcp_send_kernel_packet(&packet,
|
||||
dhcp_client->requested_ip, CLIENT_PORT,
|
||||
dhcp_client->server_ip, SERVER_PORT);
|
||||
}
|
||||
|
||||
static int send_rebound(GDHCPClient *dhcp_client)
|
||||
{
|
||||
struct dhcp_packet packet;
|
||||
|
||||
debug(dhcp_client, "sending DHCP rebound request");
|
||||
|
||||
init_packet(dhcp_client , &packet, DHCPREQUEST);
|
||||
packet.xid = dhcp_client->xid;
|
||||
packet.ciaddr = htonl(dhcp_client->requested_ip);
|
||||
|
||||
add_request_options(dhcp_client, &packet);
|
||||
|
||||
add_send_options(dhcp_client, &packet);
|
||||
if (dhcp_client->state == RENEWING)
|
||||
return dhcp_send_kernel_packet(&packet,
|
||||
dhcp_client->requested_ip, CLIENT_PORT,
|
||||
dhcp_client->server_ip, SERVER_PORT);
|
||||
|
||||
return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT,
|
||||
INADDR_BROADCAST, SERVER_PORT,
|
||||
|
@ -573,9 +569,7 @@ static gboolean send_announce_packet(gpointer dhcp_data)
|
|||
dhcp_client->requested_ip,
|
||||
dhcp_client->ifindex);
|
||||
|
||||
if (dhcp_client->timeout > 0)
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
dhcp_client->timeout = 0;
|
||||
remove_timeouts(dhcp_client);
|
||||
|
||||
if (dhcp_client->state == IPV4LL_DEFEND) {
|
||||
dhcp_client->timeout =
|
||||
|
@ -1167,7 +1161,6 @@ GDHCPClient *g_dhcp_client_new(GDHCPType type,
|
|||
get_interface_mac_address(ifindex, dhcp_client->mac_address);
|
||||
|
||||
dhcp_client->listener_sockfd = -1;
|
||||
dhcp_client->listener_channel = NULL;
|
||||
dhcp_client->listen_mode = L_NONE;
|
||||
dhcp_client->ref_count = 1;
|
||||
dhcp_client->type = type;
|
||||
|
@ -1257,7 +1250,7 @@ static int dhcp_l2_socket(int ifindex)
|
|||
|
||||
fd = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, htons(ETH_P_IP));
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
return -errno;
|
||||
|
||||
if (SERVER_PORT == 67 && CLIENT_PORT == 68)
|
||||
/* Use only if standard ports are in use */
|
||||
|
@ -1270,8 +1263,9 @@ static int dhcp_l2_socket(int ifindex)
|
|||
sock.sll_ifindex = ifindex;
|
||||
|
||||
if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) != 0) {
|
||||
int err = -errno;
|
||||
close(fd);
|
||||
return -errno;
|
||||
return err;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
@ -1350,10 +1344,7 @@ static void ipv4ll_start(GDHCPClient *dhcp_client)
|
|||
guint timeout;
|
||||
int seed;
|
||||
|
||||
if (dhcp_client->timeout > 0) {
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
dhcp_client->timeout = 0;
|
||||
}
|
||||
remove_timeouts(dhcp_client);
|
||||
|
||||
switch_listening_mode(dhcp_client, L_NONE);
|
||||
dhcp_client->retry_times = 0;
|
||||
|
@ -1379,8 +1370,7 @@ static void ipv4ll_stop(GDHCPClient *dhcp_client)
|
|||
|
||||
switch_listening_mode(dhcp_client, L_NONE);
|
||||
|
||||
if (dhcp_client->timeout > 0)
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
remove_timeouts(dhcp_client);
|
||||
|
||||
if (dhcp_client->listener_watch > 0) {
|
||||
g_source_remove(dhcp_client->listener_watch);
|
||||
|
@ -1533,7 +1523,6 @@ static int switch_listening_mode(GDHCPClient *dhcp_client,
|
|||
if (dhcp_client->listen_mode != L_NONE) {
|
||||
if (dhcp_client->listener_watch > 0)
|
||||
g_source_remove(dhcp_client->listener_watch);
|
||||
dhcp_client->listener_channel = NULL;
|
||||
dhcp_client->listen_mode = L_NONE;
|
||||
dhcp_client->listener_sockfd = -1;
|
||||
dhcp_client->listener_watch = 0;
|
||||
|
@ -1570,7 +1559,6 @@ static int switch_listening_mode(GDHCPClient *dhcp_client,
|
|||
|
||||
dhcp_client->listen_mode = listen_mode;
|
||||
dhcp_client->listener_sockfd = listener_sockfd;
|
||||
dhcp_client->listener_channel = listener_channel;
|
||||
|
||||
g_io_channel_set_close_on_unref(listener_channel, TRUE);
|
||||
dhcp_client->listener_watch =
|
||||
|
@ -1578,7 +1566,7 @@ static int switch_listening_mode(GDHCPClient *dhcp_client,
|
|||
G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
|
||||
listener_event, dhcp_client,
|
||||
NULL);
|
||||
g_io_channel_unref(dhcp_client->listener_channel);
|
||||
g_io_channel_unref(listener_channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1600,7 +1588,7 @@ static void start_request(GDHCPClient *dhcp_client)
|
|||
switch_listening_mode(dhcp_client, L2);
|
||||
}
|
||||
|
||||
send_select(dhcp_client);
|
||||
send_request(dhcp_client);
|
||||
|
||||
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||
REQUEST_TIMEOUT,
|
||||
|
@ -1631,10 +1619,7 @@ static void restart_dhcp(GDHCPClient *dhcp_client, int retry_times)
|
|||
{
|
||||
debug(dhcp_client, "restart DHCP (retries %d)", retry_times);
|
||||
|
||||
if (dhcp_client->timeout > 0) {
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
dhcp_client->timeout = 0;
|
||||
}
|
||||
remove_timeouts(dhcp_client);
|
||||
|
||||
dhcp_client->retry_times = retry_times;
|
||||
dhcp_client->requested_ip = 0;
|
||||
|
@ -1644,94 +1629,106 @@ static void restart_dhcp(GDHCPClient *dhcp_client, int retry_times)
|
|||
g_dhcp_client_start(dhcp_client, dhcp_client->last_address);
|
||||
}
|
||||
|
||||
static gboolean start_rebound_timeout(gpointer user_data)
|
||||
static gboolean start_expire(gpointer user_data)
|
||||
{
|
||||
GDHCPClient *dhcp_client = user_data;
|
||||
|
||||
debug(dhcp_client, "start rebound timeout");
|
||||
debug(dhcp_client, "lease expired");
|
||||
|
||||
/*remove all timeouts if they are set*/
|
||||
remove_timeouts(dhcp_client);
|
||||
|
||||
restart_dhcp(dhcp_client, 0);
|
||||
|
||||
/* ip need to be cleared */
|
||||
if (dhcp_client->lease_lost_cb)
|
||||
dhcp_client->lease_lost_cb(dhcp_client,
|
||||
dhcp_client->lease_lost_data);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static gboolean continue_rebound(gpointer user_data)
|
||||
{
|
||||
GDHCPClient *dhcp_client = user_data;
|
||||
|
||||
switch_listening_mode(dhcp_client, L2);
|
||||
send_request(dhcp_client);
|
||||
|
||||
dhcp_client->lease_seconds >>= 1;
|
||||
if (dhcp_client->t2_timeout> 0)
|
||||
g_source_remove(dhcp_client->t2_timeout);
|
||||
|
||||
/* We need to have enough time to receive ACK package*/
|
||||
if (dhcp_client->lease_seconds <= 6) {
|
||||
|
||||
/* ip need to be cleared */
|
||||
if (dhcp_client->lease_lost_cb)
|
||||
dhcp_client->lease_lost_cb(dhcp_client,
|
||||
dhcp_client->lease_lost_data);
|
||||
|
||||
restart_dhcp(dhcp_client, 0);
|
||||
} else {
|
||||
send_rebound(dhcp_client);
|
||||
|
||||
dhcp_client->timeout =
|
||||
g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||
dhcp_client->lease_seconds >> 1,
|
||||
start_rebound_timeout,
|
||||
dhcp_client,
|
||||
NULL);
|
||||
/*recalculate remaining rebind time*/
|
||||
dhcp_client->T2 >>= 1;
|
||||
if (dhcp_client->T2 > 60) {
|
||||
dhcp_client->t2_timeout =
|
||||
g_timeout_add_full(G_PRIORITY_HIGH,
|
||||
dhcp_client->T2 * 1000 + (rand() % 2000) - 1000,
|
||||
continue_rebound,
|
||||
dhcp_client,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void start_rebound(GDHCPClient *dhcp_client)
|
||||
static gboolean start_rebound(gpointer user_data)
|
||||
{
|
||||
debug(dhcp_client, "start rebound");
|
||||
GDHCPClient *dhcp_client = user_data;
|
||||
|
||||
/*remove renew timer*/
|
||||
if (dhcp_client->t1_timeout > 0)
|
||||
g_source_remove(dhcp_client->t1_timeout);
|
||||
|
||||
debug(dhcp_client, "start rebound");
|
||||
dhcp_client->state = REBINDING;
|
||||
|
||||
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||
dhcp_client->lease_seconds >> 1,
|
||||
start_rebound_timeout,
|
||||
dhcp_client,
|
||||
NULL);
|
||||
/*calculate total rebind time*/
|
||||
dhcp_client->T2 = dhcp_client->expire - dhcp_client->T2;
|
||||
|
||||
/*send the first rebound and reschedule*/
|
||||
continue_rebound(user_data);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean start_renew_request_timeout(gpointer user_data)
|
||||
static gboolean continue_renew (gpointer user_data)
|
||||
{
|
||||
GDHCPClient *dhcp_client = user_data;
|
||||
|
||||
debug(dhcp_client, "renew request timeout");
|
||||
|
||||
if (dhcp_client->no_lease_cb)
|
||||
dhcp_client->no_lease_cb(dhcp_client,
|
||||
dhcp_client->no_lease_data);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static gboolean start_renew_timeout(gpointer user_data)
|
||||
{
|
||||
GDHCPClient *dhcp_client = user_data;
|
||||
|
||||
debug(dhcp_client, "start renew timeout");
|
||||
|
||||
dhcp_client->state = RENEWING;
|
||||
|
||||
dhcp_client->lease_seconds >>= 1;
|
||||
|
||||
switch_listening_mode(dhcp_client, L3);
|
||||
if (dhcp_client->lease_seconds <= 60)
|
||||
start_rebound(dhcp_client);
|
||||
else {
|
||||
send_renew(dhcp_client);
|
||||
send_request(dhcp_client);
|
||||
|
||||
if (dhcp_client->timeout > 0)
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
if (dhcp_client->t1_timeout > 0)
|
||||
g_source_remove(dhcp_client->t1_timeout);
|
||||
|
||||
dhcp_client->timeout =
|
||||
g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||
REQUEST_TIMEOUT,
|
||||
start_renew_request_timeout,
|
||||
dhcp_client,
|
||||
NULL);
|
||||
dhcp_client->T1 >>= 1;
|
||||
|
||||
if (dhcp_client->T1 > 60) {
|
||||
dhcp_client->t1_timeout = g_timeout_add_full(G_PRIORITY_HIGH,
|
||||
dhcp_client->T1 * 1000 + (rand() % 2000) - 1000,
|
||||
continue_renew,
|
||||
dhcp_client,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
static gboolean start_renew(gpointer user_data)
|
||||
{
|
||||
GDHCPClient *dhcp_client = user_data;
|
||||
|
||||
debug(dhcp_client, "start renew");
|
||||
dhcp_client->state = RENEWING;
|
||||
|
||||
/*calculate total renew period*/
|
||||
dhcp_client->T1 = dhcp_client->T2 - dhcp_client->T1;
|
||||
|
||||
/*send first renew and reschedule for half the remaining time.*/
|
||||
continue_renew(user_data);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void start_bound(GDHCPClient *dhcp_client)
|
||||
{
|
||||
|
@ -1739,12 +1736,30 @@ static void start_bound(GDHCPClient *dhcp_client)
|
|||
|
||||
dhcp_client->state = BOUND;
|
||||
|
||||
if (dhcp_client->timeout > 0)
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
remove_timeouts(dhcp_client);
|
||||
|
||||
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||
dhcp_client->lease_seconds >> 1,
|
||||
start_renew_timeout, dhcp_client,
|
||||
/*
|
||||
*TODO: T1 and T2 should be set through options instead of
|
||||
* defaults as they are here.
|
||||
*/
|
||||
|
||||
dhcp_client->T1 = dhcp_client->lease_seconds >> 1;
|
||||
dhcp_client->T2 = dhcp_client->lease_seconds * 0.875;
|
||||
dhcp_client->expire = dhcp_client->lease_seconds;
|
||||
|
||||
dhcp_client->t1_timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||
dhcp_client->T1,
|
||||
start_renew, dhcp_client,
|
||||
NULL);
|
||||
|
||||
dhcp_client->t2_timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||
dhcp_client->T2,
|
||||
start_rebound, dhcp_client,
|
||||
NULL);
|
||||
|
||||
dhcp_client->lease_timeout= g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||
dhcp_client->expire,
|
||||
start_expire, dhcp_client,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
@ -1754,10 +1769,14 @@ static gboolean restart_dhcp_timeout(gpointer user_data)
|
|||
|
||||
debug(dhcp_client, "restart DHCP timeout");
|
||||
|
||||
dhcp_client->ack_retry_times++;
|
||||
|
||||
restart_dhcp(dhcp_client, dhcp_client->ack_retry_times);
|
||||
|
||||
if (dhcp_client->state == REBOOTING) {
|
||||
g_free(dhcp_client->last_address);
|
||||
dhcp_client->last_address = NULL;
|
||||
restart_dhcp(dhcp_client, 0);
|
||||
} else {
|
||||
dhcp_client->ack_retry_times++;
|
||||
restart_dhcp(dhcp_client, dhcp_client->ack_retry_times);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -2315,7 +2334,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
|
|||
if (*message_type != DHCPOFFER)
|
||||
return TRUE;
|
||||
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
remove_timeouts(dhcp_client);
|
||||
dhcp_client->timeout = 0;
|
||||
dhcp_client->retry_times = 0;
|
||||
|
||||
|
@ -2328,15 +2347,14 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
|
|||
start_request(dhcp_client);
|
||||
|
||||
return TRUE;
|
||||
case REBOOTING:
|
||||
case REQUESTING:
|
||||
case RENEWING:
|
||||
case REBINDING:
|
||||
if (*message_type == DHCPACK) {
|
||||
dhcp_client->retry_times = 0;
|
||||
|
||||
if (dhcp_client->timeout > 0)
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
dhcp_client->timeout = 0;
|
||||
remove_timeouts(dhcp_client);
|
||||
|
||||
dhcp_client->lease_seconds = get_lease(&packet);
|
||||
|
||||
|
@ -2347,6 +2365,12 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
|
|||
g_free(dhcp_client->assigned_ip);
|
||||
dhcp_client->assigned_ip = get_ip(packet.yiaddr);
|
||||
|
||||
if (dhcp_client->state == REBOOTING) {
|
||||
option = dhcp_get_option(&packet,
|
||||
DHCP_SERVER_ID);
|
||||
dhcp_client->server_ip = get_be32(option);
|
||||
}
|
||||
|
||||
/* Address should be set up here */
|
||||
if (dhcp_client->lease_available_cb)
|
||||
dhcp_client->lease_available_cb(dhcp_client,
|
||||
|
@ -2356,8 +2380,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
|
|||
} else if (*message_type == DHCPNAK) {
|
||||
dhcp_client->retry_times = 0;
|
||||
|
||||
if (dhcp_client->timeout > 0)
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
remove_timeouts(dhcp_client);
|
||||
|
||||
dhcp_client->timeout = g_timeout_add_seconds_full(
|
||||
G_PRIORITY_HIGH, 3,
|
||||
|
@ -2563,6 +2586,22 @@ static gboolean discover_timeout(gpointer user_data)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean reboot_timeout(gpointer user_data)
|
||||
{
|
||||
GDHCPClient *dhcp_client = user_data;
|
||||
dhcp_client->retry_times = 0;
|
||||
dhcp_client->requested_ip = 0;
|
||||
dhcp_client->state = INIT_SELECTING;
|
||||
/*
|
||||
* We do not send the REQUESTED IP option because the server didn't
|
||||
* respond when we send DHCPREQUEST with the REQUESTED IP option in
|
||||
* init-reboot state
|
||||
*/
|
||||
g_dhcp_client_start(dhcp_client, NULL);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean ipv4ll_defend_timeout(gpointer dhcp_data)
|
||||
{
|
||||
GDHCPClient *dhcp_client = dhcp_data;
|
||||
|
@ -2751,6 +2790,21 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
|
|||
dhcp_client->last_address = g_strdup(last_address);
|
||||
}
|
||||
}
|
||||
|
||||
if ((addr != 0) && (dhcp_client->type != G_DHCP_IPV4LL)) {
|
||||
debug(dhcp_client, "DHCP client start with state init_reboot");
|
||||
dhcp_client->requested_ip = addr;
|
||||
dhcp_client->state = REBOOTING;
|
||||
send_request(dhcp_client);
|
||||
|
||||
dhcp_client->timeout = g_timeout_add_seconds_full(
|
||||
G_PRIORITY_HIGH,
|
||||
REQUEST_TIMEOUT,
|
||||
reboot_timeout,
|
||||
dhcp_client,
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
send_discover(dhcp_client, addr);
|
||||
|
||||
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||
|
@ -2771,18 +2825,13 @@ void g_dhcp_client_stop(GDHCPClient *dhcp_client)
|
|||
send_release(dhcp_client, dhcp_client->server_ip,
|
||||
dhcp_client->requested_ip);
|
||||
|
||||
if (dhcp_client->timeout > 0) {
|
||||
g_source_remove(dhcp_client->timeout);
|
||||
dhcp_client->timeout = 0;
|
||||
}
|
||||
remove_timeouts(dhcp_client);
|
||||
|
||||
if (dhcp_client->listener_watch > 0) {
|
||||
g_source_remove(dhcp_client->listener_watch);
|
||||
dhcp_client->listener_watch = 0;
|
||||
}
|
||||
|
||||
dhcp_client->listener_channel = NULL;
|
||||
|
||||
dhcp_client->retry_times = 0;
|
||||
dhcp_client->ack_retry_times = 0;
|
||||
|
||||
|
@ -2917,6 +2966,7 @@ char *g_dhcp_client_get_netmask(GDHCPClient *dhcp_client)
|
|||
if (option)
|
||||
return g_strdup(option->data);
|
||||
case INIT_SELECTING:
|
||||
case REBOOTING:
|
||||
case REQUESTING:
|
||||
case RELEASED:
|
||||
case IPV4LL_PROBE:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* DHCP library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2007-2012 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -34,8 +34,8 @@
|
|||
#include <linux/if.h>
|
||||
#include <netpacket/packet.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "gdhcp.h"
|
||||
#include "common.h"
|
||||
|
@ -173,10 +173,7 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
|
|||
if (opt_code == code) {
|
||||
if (option_len)
|
||||
*option_len = opt_len;
|
||||
if (rem < 0)
|
||||
goto bad_packet;
|
||||
else
|
||||
found = optionptr + 2 + 2;
|
||||
found = optionptr + 2 + 2;
|
||||
count++;
|
||||
}
|
||||
|
||||
|
@ -372,34 +369,6 @@ void dhcpv6_init_header(struct dhcpv6_packet *packet, uint8_t type)
|
|||
packet->transaction_id[2] = id & 0xff;
|
||||
}
|
||||
|
||||
static bool check_vendor(uint8_t *option_vendor, const char *vendor)
|
||||
{
|
||||
uint8_t vendor_length = sizeof(vendor) - 1;
|
||||
|
||||
if (option_vendor[OPT_LEN - OPT_DATA] != vendor_length)
|
||||
return false;
|
||||
|
||||
if (memcmp(option_vendor, vendor, vendor_length) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void check_broken_vendor(struct dhcp_packet *packet)
|
||||
{
|
||||
uint8_t *vendor;
|
||||
|
||||
if (packet->op != BOOTREQUEST)
|
||||
return;
|
||||
|
||||
vendor = dhcp_get_option(packet, DHCP_VENDOR);
|
||||
if (!vendor)
|
||||
return;
|
||||
|
||||
if (check_vendor(vendor, "MSFT 98"))
|
||||
packet->flags |= htons(BROADCAST_FLAG);
|
||||
}
|
||||
|
||||
int dhcp_recv_l3_packet(struct dhcp_packet *packet, int fd)
|
||||
{
|
||||
int n;
|
||||
|
@ -413,8 +382,6 @@ int dhcp_recv_l3_packet(struct dhcp_packet *packet, int fd)
|
|||
if (packet->cookie != htonl(DHCP_MAGIC))
|
||||
return -EPROTO;
|
||||
|
||||
check_broken_vendor(packet);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -557,6 +524,8 @@ int dhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
|
|||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
dhcp_pkt->flags |= htons(BROADCAST_FLAG);
|
||||
|
||||
memset(&dest, 0, sizeof(dest));
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
packet.data = *dhcp_pkt;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* DHCP library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2009-2012 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2009-2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
|
@ -122,10 +122,13 @@ int ipv4ll_arp_socket(int ifindex)
|
|||
{
|
||||
int fd;
|
||||
struct sockaddr_ll sock;
|
||||
|
||||
fd = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, htons(ETH_P_ARP));
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
memset(&sock, 0, sizeof(sock));
|
||||
|
||||
sock.sll_family = AF_PACKET;
|
||||
sock.sll_protocol = htons(ETH_P_ARP);
|
||||
sock.sll_ifindex = ifindex;
|
||||
|
|
Loading…
Reference in a new issue