mirror of
https://github.com/albfan/miraclecast.git
synced 2025-02-15 04:42:06 +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
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -46,11 +46,11 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "ipv4ll.h"
|
#include "ipv4ll.h"
|
||||||
|
|
||||||
#define DISCOVER_TIMEOUT 3
|
#define DISCOVER_TIMEOUT 5
|
||||||
#define DISCOVER_RETRIES 10
|
#define DISCOVER_RETRIES 6
|
||||||
|
|
||||||
#define REQUEST_TIMEOUT 3
|
#define REQUEST_TIMEOUT 5
|
||||||
#define REQUEST_RETRIES 5
|
#define REQUEST_RETRIES 3
|
||||||
|
|
||||||
typedef enum _listen_mode {
|
typedef enum _listen_mode {
|
||||||
L_NONE,
|
L_NONE,
|
||||||
|
@ -61,6 +61,7 @@ typedef enum _listen_mode {
|
||||||
|
|
||||||
typedef enum _dhcp_client_state {
|
typedef enum _dhcp_client_state {
|
||||||
INIT_SELECTING,
|
INIT_SELECTING,
|
||||||
|
REBOOTING,
|
||||||
REQUESTING,
|
REQUESTING,
|
||||||
BOUND,
|
BOUND,
|
||||||
RENEWING,
|
RENEWING,
|
||||||
|
@ -99,8 +100,10 @@ struct _GDHCPClient {
|
||||||
uint8_t ack_retry_times;
|
uint8_t ack_retry_times;
|
||||||
uint8_t conflicts;
|
uint8_t conflicts;
|
||||||
guint timeout;
|
guint timeout;
|
||||||
|
guint t1_timeout;
|
||||||
|
guint t2_timeout;
|
||||||
|
guint lease_timeout;
|
||||||
guint listener_watch;
|
guint listener_watch;
|
||||||
GIOChannel *listener_channel;
|
|
||||||
GList *require_list;
|
GList *require_list;
|
||||||
GList *request_list;
|
GList *request_list;
|
||||||
GHashTable *code_value_hash;
|
GHashTable *code_value_hash;
|
||||||
|
@ -270,6 +273,25 @@ static int32_t get_time_diff(struct timeval *tv)
|
||||||
return hsec;
|
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,
|
static void add_dhcpv6_request_options(GDHCPClient *dhcp_client,
|
||||||
struct dhcpv6_packet *packet,
|
struct dhcpv6_packet *packet,
|
||||||
unsigned char *buf, int max_buf,
|
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);
|
MAC_BCAST_ADDR, dhcp_client->ifindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_select(GDHCPClient *dhcp_client)
|
static int send_request(GDHCPClient *dhcp_client)
|
||||||
{
|
{
|
||||||
struct dhcp_packet packet;
|
struct dhcp_packet packet;
|
||||||
|
debug(dhcp_client, "sending DHCP request");
|
||||||
debug(dhcp_client, "sending DHCP select request");
|
|
||||||
|
|
||||||
init_packet(dhcp_client, &packet, DHCPREQUEST);
|
init_packet(dhcp_client, &packet, DHCPREQUEST);
|
||||||
|
|
||||||
packet.xid = dhcp_client->xid;
|
packet.xid = dhcp_client->xid;
|
||||||
packet.secs = dhcp_attempt_secs(dhcp_client);
|
packet.secs = dhcp_attempt_secs(dhcp_client);
|
||||||
|
|
||||||
|
if (dhcp_client->state == REQUESTING || dhcp_client->state == REBOOTING)
|
||||||
dhcp_add_option_uint32(&packet, DHCP_REQUESTED_IP,
|
dhcp_add_option_uint32(&packet, DHCP_REQUESTED_IP,
|
||||||
dhcp_client->requested_ip);
|
dhcp_client->requested_ip);
|
||||||
|
|
||||||
|
if (dhcp_client->state == REQUESTING)
|
||||||
dhcp_add_option_uint32(&packet, DHCP_SERVER_ID,
|
dhcp_add_option_uint32(&packet, DHCP_SERVER_ID,
|
||||||
dhcp_client->server_ip);
|
dhcp_client->server_ip);
|
||||||
|
|
||||||
|
dhcp_add_option_uint16(&packet, DHCP_MAX_SIZE, 576);
|
||||||
|
|
||||||
add_request_options(dhcp_client, &packet);
|
add_request_options(dhcp_client, &packet);
|
||||||
|
|
||||||
add_send_options(dhcp_client, &packet);
|
add_send_options(dhcp_client, &packet);
|
||||||
|
|
||||||
return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT,
|
if (dhcp_client->state == RENEWING || dhcp_client->state == REBINDING)
|
||||||
INADDR_BROADCAST, SERVER_PORT,
|
|
||||||
MAC_BCAST_ADDR, dhcp_client->ifindex);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
packet.ciaddr = htonl(dhcp_client->requested_ip);
|
||||||
|
|
||||||
add_request_options(dhcp_client, &packet);
|
if (dhcp_client->state == RENEWING)
|
||||||
|
|
||||||
add_send_options(dhcp_client, &packet);
|
|
||||||
|
|
||||||
return dhcp_send_kernel_packet(&packet,
|
return dhcp_send_kernel_packet(&packet,
|
||||||
dhcp_client->requested_ip, CLIENT_PORT,
|
dhcp_client->requested_ip, CLIENT_PORT,
|
||||||
dhcp_client->server_ip, SERVER_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);
|
|
||||||
|
|
||||||
return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT,
|
return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT,
|
||||||
INADDR_BROADCAST, SERVER_PORT,
|
INADDR_BROADCAST, SERVER_PORT,
|
||||||
|
@ -573,9 +569,7 @@ static gboolean send_announce_packet(gpointer dhcp_data)
|
||||||
dhcp_client->requested_ip,
|
dhcp_client->requested_ip,
|
||||||
dhcp_client->ifindex);
|
dhcp_client->ifindex);
|
||||||
|
|
||||||
if (dhcp_client->timeout > 0)
|
remove_timeouts(dhcp_client);
|
||||||
g_source_remove(dhcp_client->timeout);
|
|
||||||
dhcp_client->timeout = 0;
|
|
||||||
|
|
||||||
if (dhcp_client->state == IPV4LL_DEFEND) {
|
if (dhcp_client->state == IPV4LL_DEFEND) {
|
||||||
dhcp_client->timeout =
|
dhcp_client->timeout =
|
||||||
|
@ -1167,7 +1161,6 @@ GDHCPClient *g_dhcp_client_new(GDHCPType type,
|
||||||
get_interface_mac_address(ifindex, dhcp_client->mac_address);
|
get_interface_mac_address(ifindex, dhcp_client->mac_address);
|
||||||
|
|
||||||
dhcp_client->listener_sockfd = -1;
|
dhcp_client->listener_sockfd = -1;
|
||||||
dhcp_client->listener_channel = NULL;
|
|
||||||
dhcp_client->listen_mode = L_NONE;
|
dhcp_client->listen_mode = L_NONE;
|
||||||
dhcp_client->ref_count = 1;
|
dhcp_client->ref_count = 1;
|
||||||
dhcp_client->type = type;
|
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));
|
fd = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, htons(ETH_P_IP));
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return fd;
|
return -errno;
|
||||||
|
|
||||||
if (SERVER_PORT == 67 && CLIENT_PORT == 68)
|
if (SERVER_PORT == 67 && CLIENT_PORT == 68)
|
||||||
/* Use only if standard ports are in use */
|
/* Use only if standard ports are in use */
|
||||||
|
@ -1270,8 +1263,9 @@ static int dhcp_l2_socket(int ifindex)
|
||||||
sock.sll_ifindex = ifindex;
|
sock.sll_ifindex = ifindex;
|
||||||
|
|
||||||
if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) != 0) {
|
if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) != 0) {
|
||||||
|
int err = -errno;
|
||||||
close(fd);
|
close(fd);
|
||||||
return -errno;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
|
@ -1350,10 +1344,7 @@ static void ipv4ll_start(GDHCPClient *dhcp_client)
|
||||||
guint timeout;
|
guint timeout;
|
||||||
int seed;
|
int seed;
|
||||||
|
|
||||||
if (dhcp_client->timeout > 0) {
|
remove_timeouts(dhcp_client);
|
||||||
g_source_remove(dhcp_client->timeout);
|
|
||||||
dhcp_client->timeout = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch_listening_mode(dhcp_client, L_NONE);
|
switch_listening_mode(dhcp_client, L_NONE);
|
||||||
dhcp_client->retry_times = 0;
|
dhcp_client->retry_times = 0;
|
||||||
|
@ -1379,8 +1370,7 @@ static void ipv4ll_stop(GDHCPClient *dhcp_client)
|
||||||
|
|
||||||
switch_listening_mode(dhcp_client, L_NONE);
|
switch_listening_mode(dhcp_client, L_NONE);
|
||||||
|
|
||||||
if (dhcp_client->timeout > 0)
|
remove_timeouts(dhcp_client);
|
||||||
g_source_remove(dhcp_client->timeout);
|
|
||||||
|
|
||||||
if (dhcp_client->listener_watch > 0) {
|
if (dhcp_client->listener_watch > 0) {
|
||||||
g_source_remove(dhcp_client->listener_watch);
|
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->listen_mode != L_NONE) {
|
||||||
if (dhcp_client->listener_watch > 0)
|
if (dhcp_client->listener_watch > 0)
|
||||||
g_source_remove(dhcp_client->listener_watch);
|
g_source_remove(dhcp_client->listener_watch);
|
||||||
dhcp_client->listener_channel = NULL;
|
|
||||||
dhcp_client->listen_mode = L_NONE;
|
dhcp_client->listen_mode = L_NONE;
|
||||||
dhcp_client->listener_sockfd = -1;
|
dhcp_client->listener_sockfd = -1;
|
||||||
dhcp_client->listener_watch = 0;
|
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->listen_mode = listen_mode;
|
||||||
dhcp_client->listener_sockfd = listener_sockfd;
|
dhcp_client->listener_sockfd = listener_sockfd;
|
||||||
dhcp_client->listener_channel = listener_channel;
|
|
||||||
|
|
||||||
g_io_channel_set_close_on_unref(listener_channel, TRUE);
|
g_io_channel_set_close_on_unref(listener_channel, TRUE);
|
||||||
dhcp_client->listener_watch =
|
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,
|
G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
|
||||||
listener_event, dhcp_client,
|
listener_event, dhcp_client,
|
||||||
NULL);
|
NULL);
|
||||||
g_io_channel_unref(dhcp_client->listener_channel);
|
g_io_channel_unref(listener_channel);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1600,7 +1588,7 @@ static void start_request(GDHCPClient *dhcp_client)
|
||||||
switch_listening_mode(dhcp_client, L2);
|
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,
|
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
||||||
REQUEST_TIMEOUT,
|
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);
|
debug(dhcp_client, "restart DHCP (retries %d)", retry_times);
|
||||||
|
|
||||||
if (dhcp_client->timeout > 0) {
|
remove_timeouts(dhcp_client);
|
||||||
g_source_remove(dhcp_client->timeout);
|
|
||||||
dhcp_client->timeout = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dhcp_client->retry_times = retry_times;
|
dhcp_client->retry_times = retry_times;
|
||||||
dhcp_client->requested_ip = 0;
|
dhcp_client->requested_ip = 0;
|
||||||
|
@ -1644,32 +1629,42 @@ static void restart_dhcp(GDHCPClient *dhcp_client, int retry_times)
|
||||||
g_dhcp_client_start(dhcp_client, dhcp_client->last_address);
|
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;
|
GDHCPClient *dhcp_client = user_data;
|
||||||
|
|
||||||
debug(dhcp_client, "start rebound timeout");
|
debug(dhcp_client, "lease expired");
|
||||||
|
|
||||||
switch_listening_mode(dhcp_client, L2);
|
/*remove all timeouts if they are set*/
|
||||||
|
remove_timeouts(dhcp_client);
|
||||||
|
|
||||||
dhcp_client->lease_seconds >>= 1;
|
restart_dhcp(dhcp_client, 0);
|
||||||
|
|
||||||
/* We need to have enough time to receive ACK package*/
|
|
||||||
if (dhcp_client->lease_seconds <= 6) {
|
|
||||||
|
|
||||||
/* ip need to be cleared */
|
/* ip need to be cleared */
|
||||||
if (dhcp_client->lease_lost_cb)
|
if (dhcp_client->lease_lost_cb)
|
||||||
dhcp_client->lease_lost_cb(dhcp_client,
|
dhcp_client->lease_lost_cb(dhcp_client,
|
||||||
dhcp_client->lease_lost_data);
|
dhcp_client->lease_lost_data);
|
||||||
|
|
||||||
restart_dhcp(dhcp_client, 0);
|
return false;
|
||||||
} else {
|
}
|
||||||
send_rebound(dhcp_client);
|
|
||||||
|
|
||||||
dhcp_client->timeout =
|
static gboolean continue_rebound(gpointer user_data)
|
||||||
g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
{
|
||||||
dhcp_client->lease_seconds >> 1,
|
GDHCPClient *dhcp_client = user_data;
|
||||||
start_rebound_timeout,
|
|
||||||
|
switch_listening_mode(dhcp_client, L2);
|
||||||
|
send_request(dhcp_client);
|
||||||
|
|
||||||
|
if (dhcp_client->t2_timeout> 0)
|
||||||
|
g_source_remove(dhcp_client->t2_timeout);
|
||||||
|
|
||||||
|
/*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,
|
dhcp_client,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
@ -1677,61 +1672,63 @@ static gboolean start_rebound_timeout(gpointer user_data)
|
||||||
return FALSE;
|
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->state = REBINDING;
|
||||||
|
|
||||||
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
/*calculate total rebind time*/
|
||||||
dhcp_client->lease_seconds >> 1,
|
dhcp_client->T2 = dhcp_client->expire - dhcp_client->T2;
|
||||||
start_rebound_timeout,
|
|
||||||
dhcp_client,
|
/*send the first rebound and reschedule*/
|
||||||
NULL);
|
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;
|
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);
|
switch_listening_mode(dhcp_client, L3);
|
||||||
if (dhcp_client->lease_seconds <= 60)
|
send_request(dhcp_client);
|
||||||
start_rebound(dhcp_client);
|
|
||||||
else {
|
|
||||||
send_renew(dhcp_client);
|
|
||||||
|
|
||||||
if (dhcp_client->timeout > 0)
|
if (dhcp_client->t1_timeout > 0)
|
||||||
g_source_remove(dhcp_client->timeout);
|
g_source_remove(dhcp_client->t1_timeout);
|
||||||
|
|
||||||
dhcp_client->timeout =
|
dhcp_client->T1 >>= 1;
|
||||||
g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
|
||||||
REQUEST_TIMEOUT,
|
if (dhcp_client->T1 > 60) {
|
||||||
start_renew_request_timeout,
|
dhcp_client->t1_timeout = g_timeout_add_full(G_PRIORITY_HIGH,
|
||||||
|
dhcp_client->T1 * 1000 + (rand() % 2000) - 1000,
|
||||||
|
continue_renew,
|
||||||
dhcp_client,
|
dhcp_client,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
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)
|
static void start_bound(GDHCPClient *dhcp_client)
|
||||||
{
|
{
|
||||||
|
@ -1739,12 +1736,30 @@ static void start_bound(GDHCPClient *dhcp_client)
|
||||||
|
|
||||||
dhcp_client->state = BOUND;
|
dhcp_client->state = BOUND;
|
||||||
|
|
||||||
if (dhcp_client->timeout > 0)
|
remove_timeouts(dhcp_client);
|
||||||
g_source_remove(dhcp_client->timeout);
|
|
||||||
|
|
||||||
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
/*
|
||||||
dhcp_client->lease_seconds >> 1,
|
*TODO: T1 and T2 should be set through options instead of
|
||||||
start_renew_timeout, dhcp_client,
|
* 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);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1754,10 +1769,14 @@ static gboolean restart_dhcp_timeout(gpointer user_data)
|
||||||
|
|
||||||
debug(dhcp_client, "restart DHCP timeout");
|
debug(dhcp_client, "restart DHCP timeout");
|
||||||
|
|
||||||
|
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++;
|
dhcp_client->ack_retry_times++;
|
||||||
|
|
||||||
restart_dhcp(dhcp_client, dhcp_client->ack_retry_times);
|
restart_dhcp(dhcp_client, dhcp_client->ack_retry_times);
|
||||||
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2315,7 +2334,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
|
||||||
if (*message_type != DHCPOFFER)
|
if (*message_type != DHCPOFFER)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
g_source_remove(dhcp_client->timeout);
|
remove_timeouts(dhcp_client);
|
||||||
dhcp_client->timeout = 0;
|
dhcp_client->timeout = 0;
|
||||||
dhcp_client->retry_times = 0;
|
dhcp_client->retry_times = 0;
|
||||||
|
|
||||||
|
@ -2328,15 +2347,14 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
|
||||||
start_request(dhcp_client);
|
start_request(dhcp_client);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
case REBOOTING:
|
||||||
case REQUESTING:
|
case REQUESTING:
|
||||||
case RENEWING:
|
case RENEWING:
|
||||||
case REBINDING:
|
case REBINDING:
|
||||||
if (*message_type == DHCPACK) {
|
if (*message_type == DHCPACK) {
|
||||||
dhcp_client->retry_times = 0;
|
dhcp_client->retry_times = 0;
|
||||||
|
|
||||||
if (dhcp_client->timeout > 0)
|
remove_timeouts(dhcp_client);
|
||||||
g_source_remove(dhcp_client->timeout);
|
|
||||||
dhcp_client->timeout = 0;
|
|
||||||
|
|
||||||
dhcp_client->lease_seconds = get_lease(&packet);
|
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);
|
g_free(dhcp_client->assigned_ip);
|
||||||
dhcp_client->assigned_ip = get_ip(packet.yiaddr);
|
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 */
|
/* Address should be set up here */
|
||||||
if (dhcp_client->lease_available_cb)
|
if (dhcp_client->lease_available_cb)
|
||||||
dhcp_client->lease_available_cb(dhcp_client,
|
dhcp_client->lease_available_cb(dhcp_client,
|
||||||
|
@ -2356,8 +2380,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
|
||||||
} else if (*message_type == DHCPNAK) {
|
} else if (*message_type == DHCPNAK) {
|
||||||
dhcp_client->retry_times = 0;
|
dhcp_client->retry_times = 0;
|
||||||
|
|
||||||
if (dhcp_client->timeout > 0)
|
remove_timeouts(dhcp_client);
|
||||||
g_source_remove(dhcp_client->timeout);
|
|
||||||
|
|
||||||
dhcp_client->timeout = g_timeout_add_seconds_full(
|
dhcp_client->timeout = g_timeout_add_seconds_full(
|
||||||
G_PRIORITY_HIGH, 3,
|
G_PRIORITY_HIGH, 3,
|
||||||
|
@ -2563,6 +2586,22 @@ static gboolean discover_timeout(gpointer user_data)
|
||||||
return FALSE;
|
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)
|
static gboolean ipv4ll_defend_timeout(gpointer dhcp_data)
|
||||||
{
|
{
|
||||||
GDHCPClient *dhcp_client = 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);
|
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);
|
send_discover(dhcp_client, addr);
|
||||||
|
|
||||||
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
|
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,
|
send_release(dhcp_client, dhcp_client->server_ip,
|
||||||
dhcp_client->requested_ip);
|
dhcp_client->requested_ip);
|
||||||
|
|
||||||
if (dhcp_client->timeout > 0) {
|
remove_timeouts(dhcp_client);
|
||||||
g_source_remove(dhcp_client->timeout);
|
|
||||||
dhcp_client->timeout = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dhcp_client->listener_watch > 0) {
|
if (dhcp_client->listener_watch > 0) {
|
||||||
g_source_remove(dhcp_client->listener_watch);
|
g_source_remove(dhcp_client->listener_watch);
|
||||||
dhcp_client->listener_watch = 0;
|
dhcp_client->listener_watch = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dhcp_client->listener_channel = NULL;
|
|
||||||
|
|
||||||
dhcp_client->retry_times = 0;
|
dhcp_client->retry_times = 0;
|
||||||
dhcp_client->ack_retry_times = 0;
|
dhcp_client->ack_retry_times = 0;
|
||||||
|
|
||||||
|
@ -2917,6 +2966,7 @@ char *g_dhcp_client_get_netmask(GDHCPClient *dhcp_client)
|
||||||
if (option)
|
if (option)
|
||||||
return g_strdup(option->data);
|
return g_strdup(option->data);
|
||||||
case INIT_SELECTING:
|
case INIT_SELECTING:
|
||||||
|
case REBOOTING:
|
||||||
case REQUESTING:
|
case REQUESTING:
|
||||||
case RELEASED:
|
case RELEASED:
|
||||||
case IPV4LL_PROBE:
|
case IPV4LL_PROBE:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* DHCP library with GLib integration
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -34,8 +34,8 @@
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <netpacket/packet.h>
|
#include <netpacket/packet.h>
|
||||||
#include <net/ethernet.h>
|
#include <net/ethernet.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include "gdhcp.h"
|
#include "gdhcp.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -173,9 +173,6 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
|
||||||
if (opt_code == code) {
|
if (opt_code == code) {
|
||||||
if (option_len)
|
if (option_len)
|
||||||
*option_len = opt_len;
|
*option_len = opt_len;
|
||||||
if (rem < 0)
|
|
||||||
goto bad_packet;
|
|
||||||
else
|
|
||||||
found = optionptr + 2 + 2;
|
found = optionptr + 2 + 2;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -372,34 +369,6 @@ void dhcpv6_init_header(struct dhcpv6_packet *packet, uint8_t type)
|
||||||
packet->transaction_id[2] = id & 0xff;
|
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 dhcp_recv_l3_packet(struct dhcp_packet *packet, int fd)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
@ -413,8 +382,6 @@ int dhcp_recv_l3_packet(struct dhcp_packet *packet, int fd)
|
||||||
if (packet->cookie != htonl(DHCP_MAGIC))
|
if (packet->cookie != htonl(DHCP_MAGIC))
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
|
|
||||||
check_broken_vendor(packet);
|
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,6 +524,8 @@ int dhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
dhcp_pkt->flags |= htons(BROADCAST_FLAG);
|
||||||
|
|
||||||
memset(&dest, 0, sizeof(dest));
|
memset(&dest, 0, sizeof(dest));
|
||||||
memset(&packet, 0, sizeof(packet));
|
memset(&packet, 0, sizeof(packet));
|
||||||
packet.data = *dhcp_pkt;
|
packet.data = *dhcp_pkt;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* DHCP library with GLib integration
|
* 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
|
* 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
|
* 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;
|
int fd;
|
||||||
struct sockaddr_ll sock;
|
struct sockaddr_ll sock;
|
||||||
|
|
||||||
fd = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, htons(ETH_P_ARP));
|
fd = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, htons(ETH_P_ARP));
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
|
memset(&sock, 0, sizeof(sock));
|
||||||
|
|
||||||
sock.sll_family = AF_PACKET;
|
sock.sll_family = AF_PACKET;
|
||||||
sock.sll_protocol = htons(ETH_P_ARP);
|
sock.sll_protocol = htons(ETH_P_ARP);
|
||||||
sock.sll_ifindex = ifindex;
|
sock.sll_ifindex = ifindex;
|
||||||
|
|
Loading…
Reference in a new issue