1
0
Fork 0
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:
David Herrmann 2014-08-13 08:45:15 +02:00
parent eecf576fa9
commit 7c87510b34
4 changed files with 209 additions and 187 deletions

View file

@ -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:

View file

@ -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;

View file

@ -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

View file

@ -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;