For some reason the Ethernet library keeps incrementing the DHCP transaction ID
throughout the DHCP cycle, even though the ID is supposed to remain stable for
a (single) DHCP lease's lifetime. The patch below, against the Dhcp.cpp in
Arduino 1.0.4, implements the standard behaviour.
(Note that the patch deals only with the Transaction ID; there are a lot of
other warnings in the library which have not been touched.)
The diff command was: diff -urbN Dhcp.cpp.1.0.4 Dhcp.cpp
===8<======8<======8<======8<======8<======8<======8<======8<===
--- Dhcp.cpp.1.0.4 2013-03-11 13:08:55.000000000 +0000
+++ Dhcp.cpp.upd 2013-03-29 12:49:43.088298295 +0000
@@ -9,6 +9,16 @@
#include "Arduino.h"
#include "util.h"
+uint32_t gen_rand() {
- uint32_t seed = 0;
- int count = 32;
- // Analog port jitter is approximately random
- while (--count)
- seed = (seed << 1) | ((uint32_t) analogRead(0) & 1);
- return seed;
+}
int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
{
_dhcpLeaseTime=0;
@@ -37,11 +47,8 @@
uint8_t messageType = 0;
- // Pick an initial transaction ID
- _dhcpTransactionId = random(1UL, 2000UL);
- _dhcpInitialTransactionId = _dhcpTransactionId;
- // The lease ID is supposed to stay the same
- // throughout the duration of the lease.
_dhcpUdpSocket.stop();
if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0)
@@ -60,34 +67,30 @@
{
if(_dhcp_state == STATE_DHCP_START)
{
- _dhcpTransactionId++;
- _dhcpInitialTransactionId = gen_rand();
- _dhcpTransactionId = _dhcpInitialTransactionId;
send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000));
_dhcp_state = STATE_DHCP_DISCOVER;
}
else if(_dhcp_state == STATE_DHCP_REREQUEST){
- _dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000));
_dhcp_state = STATE_DHCP_REQUEST;
}
else if(_dhcp_state == STATE_DHCP_DISCOVER)
{ - uint32_t respId;
- uint32_t respId = 0;
messageType = parseDHCPResponse(_responseTimeout, respId);
- if(messageType == DHCP_OFFER)
- if(messageType == DHCP_OFFER && _dhcpTransactionId == respId)
{
- // We'll use the transaction ID that the offer came with,
- // rather than the one we were up to
- _dhcpTransactionId = respId;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000));
_dhcp_state = STATE_DHCP_REQUEST;
}
}
else if(_dhcp_state == STATE_DHCP_REQUEST)
{ - uint32_t respId;
- uint32_t respId = 0;
messageType = parseDHCPResponse(_responseTimeout, respId);
- if(messageType == DHCP_ACK)
- if(messageType == DHCP_ACK && _dhcpTransactionId == respId)
{
_dhcp_state = STATE_DHCP_LEASED;
result = 1;
@@ -108,13 +111,17 @@
_rebindInSec = _dhcpT2;
}
else if(messageType == DHCP_NAK) - {
_dhcp_state = STATE_DHCP_START; - _dhcpInitialTransactionId = _dhcpTransactionId = 0;
- }
}
if(messageType == 255)
{
messageType = 0;
_dhcp_state = STATE_DHCP_START;
- _dhcpInitialTransactionId = _dhcpTransactionId = 0;
}
if(result != 1 && ((millis() - startTime) > _timeout))
@@ -123,7 +130,6 @@
// We're done with the socket now
_dhcpUdpSocket.stop();
- _dhcpTransactionId++;
return result;
}
@@ -272,7 +278,7 @@
if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT)
{
transactionId = ntohl(fixedMsg.xid);
- if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId))
- if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId != _dhcpTransactionId))
{
// Need to read the rest of the packet here regardless
_dhcpUdpSocket.flush();
===8<======8<======8<======8<======8<======8<======8<======8<===