Arduino Ethernet library DHCP patch

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