summaryrefslogtreecommitdiff
path: root/gdhcp
diff options
context:
space:
mode:
authorGrant Erickson <marathon96@gmail.com>2012-02-28 16:30:00 (GMT)
committerDaniel Wagner <daniel.wagner@bmw-carit.de>2012-03-01 12:45:23 (GMT)
commit95e15c09350acf58d4707056ae2614570883ef66 (patch)
tree856edf9c177474388e8600af47388642ed96f0cf /gdhcp
parente8dbd3160116346eae8613c242dd8f4db3ed1781 (diff)
downloadconnman-95e15c09350acf58d4707056ae2614570883ef66.zip
connman-95e15c09350acf58d4707056ae2614570883ef66.tar.gz
connman-95e15c09350acf58d4707056ae2614570883ef66.tar.bz2
gdhcp: set secs in a RFC 951- and 2131-compliant manner
This patch sets the BOOTP secs field in a RFC 951- and 2131-compliant manner for DHCPv4 DISCOVER and REQUEST/SELECT packets. Certain DHCP servers, such as that implemented in Mac OS X (< 10.7) for its "Internet Sharing" feature, refuse to issue a DHCP lease to clients that have not set a non-zero value in their DISCOVER or REQUEST packets. In fact, based on http://hints.macworld.com/article.php? story=20071223001432304, it's not non-zero but a value greater than four (4) seconds to allow another "authoritative" DHCP server on the subnet to reply first. Side-by-side packet analysis of Mac OS X, iOS, Android, ISC and Windows clients show that these clients set the BOOTP 'secs' field and are successfully issued a DHCP lease by Mac OS X. By contrast, a connman-based client will issue 10 back-to-back DISCOVER packets and will not be returned a DHCP OFFER from the server.
Diffstat (limited to 'gdhcp')
-rw-r--r--gdhcp/client.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/gdhcp/client.c b/gdhcp/client.c
index a3b4b8a..cf4cc3c 100644
--- a/gdhcp/client.c
+++ b/gdhcp/client.c
@@ -88,6 +88,7 @@ struct _GDHCPClient {
uint32_t server_ip;
uint32_t requested_ip;
char *assigned_ip;
+ time_t start;
uint32_t lease_seconds;
ListenMode listen_mode;
int listener_sockfd;
@@ -339,6 +340,17 @@ static void add_send_options(GDHCPClient *dhcp_client,
add_binary_option, packet);
}
+/*
+ * Return an RFC 951- and 2131-complaint BOOTP 'secs' value that
+ * represents the number of seconds elapsed from the start of
+ * attempting DHCP to satisfy some DHCP servers that allow for an
+ * "authoritative" reply before responding.
+ */
+static uint16_t dhcp_attempt_secs(GDHCPClient *dhcp_client)
+{
+ return htons(MIN(time(NULL) - dhcp_client->start, UINT16_MAX));
+}
+
static int send_discover(GDHCPClient *dhcp_client, uint32_t requested)
{
struct dhcp_packet packet;
@@ -348,6 +360,7 @@ static int send_discover(GDHCPClient *dhcp_client, uint32_t requested)
init_packet(dhcp_client, &packet, DHCPDISCOVER);
packet.xid = dhcp_client->xid;
+ packet.secs = dhcp_attempt_secs(dhcp_client);
if (requested)
dhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
@@ -374,6 +387,7 @@ static int send_select(GDHCPClient *dhcp_client)
init_packet(dhcp_client, &packet, DHCPREQUEST);
packet.xid = dhcp_client->xid;
+ packet.secs = dhcp_attempt_secs(dhcp_client);
dhcp_add_simple_option(&packet, DHCP_REQUESTED_IP,
dhcp_client->requested_ip);
@@ -2240,6 +2254,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
return re;
dhcp_client->xid = rand();
+ dhcp_client->start = time(NULL);
}
if (last_address == NULL) {