[Solved] Problems with UIPEthernet DHCP and DNS on 32-bit processor (Teensy LC)

I’m having problems with UIPEthernet. I got the FTP server example working but I have to use hard-coded IPAddress.
In setup, I can’t use Ethernet.begin(mac) because it locks up in DHCP so I have to use Ethernet.begin(mac, myip) where I have to specify myip.
I can’t get DNS to work either. Here’s the test code I’m using:

/*
Derived from the arduino playground sketch:
http://playground.arduino.cc/Code/FTP
   FTP passive client for IDE v1.0.1 and w5100/w5200
   Posted October 2012 by SurferTim
   Modified 6 June 2015 by SurferTim
*/

#include <SD.h>
#include <SPI.h>
#include <UIPEthernet.h>
#include <Dns.h>
// this must be unique
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x59, 0x67 };  

/*
Start ethernet
localIP: 192.168.0.6
gatewayIP: 192.168.0.1
subnetMask: 255.255.255.0
Try DNS lookup on dnsServerIP 192.168.0.1
dns lookup failed
*/

// change to your network settings
IPAddress myip( 192, 168, 0, 6 );    

IPAddress google;

DNSClient ldns;
void setup()
{
  Serial.begin(9600);
  while(!Serial);

  Serial.println("Start ethernet");
//  Ethernet.begin(mac); // doesn't work. Hangs in DHCP
  Ethernet.begin(mac, myip); //, gateway, gateway, subnet);

  Serial.print("localIP: ");
  Serial.println(Ethernet.localIP());
  Serial.print("gatewayIP: ");
  Serial.println(Ethernet.gatewayIP());
  Serial.print("subnetMask: ");
  Serial.println(Ethernet.subnetMask());
  
  Serial.print("Try DNS lookup on dnsServerIP ");
  Serial.println(Ethernet.dnsServerIP());
  ldns.begin(Ethernet.dnsServerIP());
  if(ldns.getHostByName("www.google.com",google) == 1) {
    Serial.print("ip = ");
    Serial.println(google);
  }
  else Serial.print(F("dns lookup failed"));
}

void loop()
{
}

DNS always fails.

I’ve added debugging commands in the DHCP code to try to locate the problem. It fails in parseDHCPResponse. Today it is just timing out. Yesterday it was getting responses that the switch statement doesn’t handle, 53 (dhcpMessageType) and 54 (dhcpServerIdentifier).

Any ideas how to fix this?

Pete

I've found, and have a fix for, the DHCP problem. I had omitted one salient bit of info from my first post but in my defense it wasn't obvious that it was relevant at the time. I was trying to get this working on a Teensy LC which is a 32-bit beast. The problem arises when an IPAddress is accessed like this:

*((uint32_t*)_dhcpDhcpServerIp)

The address of dhcpDhcpServerIp is cast as a 32-bit pointer and then used as an address. On a 16-bit machine this won't cause any problems. On a 32-bit machine this will fail with a bus address error (or some other sort of fault) if the address isn't aligned on a 4-byte boundary. In the case of the DHCP code this is clearly what happened. In the private section of dhcp.h I forced the alignment of the IPAddresses and now the DHCP works.

  uint8_t  _dhcpMacAddr[6] __attribute__ ((aligned (4)));
  uint8_t  _dhcpLocalIp[4] __attribute__ ((aligned (4)));
  uint8_t  _dhcpSubnetMask[4] __attribute__ ((aligned (4)));
  uint8_t  _dhcpGatewayIp[4] __attribute__ ((aligned (4)));
  uint8_t  _dhcpDhcpServerIp[4] __attribute__ ((aligned (4)));
  uint8_t  _dhcpDnsServerIp[4] __attribute__ ((aligned (4)));

I made one other change to the code which speeds it up a bit. It seems to wait for a timeout in the DHCP process before proceeding. In parseDHCPResponse of dhcp.cpp there is a switch statement:

           switch (_dhcpUdpSocket.read())

which I changed to:

unsigned char sread = _dhcpUdpSocket.read();
            switch (sread)

and then immediately after the switch's closing brace add:

           if(sread == endOption)break;

It breaks out of the switch when endOption is received but it wasn't then breaking out of the enclosing while statement.

I'm now looking at the problem with DNS but it doesn't appear to be the same kind of thing.

Pete

I’ve found the DNS problem. It is again a 32/16 bit problem but this time it is caused by the htons macro in arduinouip\utility\util.h
Change it to this:

#define htons(x) ( (((x)<<8) & 0xff00) | (((x)>>8)&0xFF) )

Pete