Trying to build DHCP for arduino0019 and more

Hi everyone,
i'm an italian software developer (objective-c, java, php), just started playing with arduino a week ago.
I want to build a DHCP library for the new arduino release, at this moment i was able to send the DHCPDISCOVER packet well composed, and the dhcp server reply with a packet, but i can't receive that packet with the UDP library in arduino.
Probably i miss something, are here someone able with udp and dhcp and want to collaborate in this library?
thanks
:wink:

Have you searched for UDP and DHCP libraries allready (just to see how others did it?) e.g.
http://bitbucket.org/bjoern/arduino_osc/src/tip/libraries/Ethernet/
http://blog.jordanterrell.com/post/Arduino-DHCP-Library-Version-04.aspx
(google Arduino DHCP libraries)

yes i see other libraries, but they're based on old version of ethernet library.

I do some progress, but don't understand why, when serial monitor is opened, program does not receive the udp, as i close the serial monitor popup the led light up.
see the sketch attached, any help is approached (it's a study sketch, so don't take care by comments :-[ )

#include <SPI.h>
#include <Ethernet.h>
#include <Udp.h>

#define DEBUG

/* DHCP state machine. */
#define STATE_DHCP_START        0
#define      STATE_DHCP_DISCOVER      1
#define      STATE_DHCP_REQUEST      2
#define      STATE_DHCP_LEASED      3
#define      STATE_DHCP_REREQUEST      4
#define      STATE_DHCP_RELEASE      5

#define DHCP_FLAGSBROADCAST      0x8000

/* UDP port numbers for DHCP */
#define      DHCP_SERVER_PORT      67
#define DHCP_CLIENT_PORT      68

/* DHCP message OP code */
#define DHCP_BOOTREQUEST      1
#define DHCP_BOOTREPLY            2

/* DHCP message type */
#define      DHCP_DISCOVER            1
#define DHCP_OFFER            2
#define      DHCP_REQUEST            3
#define      DHCP_DECLINE            4
#define      DHCP_ACK            5
#define DHCP_NAK            6
#define      DHCP_RELEASE            7
#define DHCP_INFORM            8

#define DHCP_HTYPE10MB            1
#define DHCP_HTYPE100MB            2

#define DHCP_HLENETHERNET      6
#define DHCP_HOPS            0
#define DHCP_SECS            0

#define dhcpSIZE                240

#define zap(x) if(x){free(x); x=0;}

/**
 * @brief            for the DHCP message
 */
typedef struct RIP_MSG{
      byte              op;
      byte              htype;
      byte              hlen;
      byte              hops;
      unsigned long      xid;
      unsigned int      secs;
      unsigned int      flags;
      byte              ciaddr[4];
      byte              yiaddr[4];
      byte          siaddr[4];
      byte              giaddr[4];
      byte          chaddr[16];
      byte          sname[64];
      byte          file[128];
        byte            magic[4];
      byte          OPT[];
};

/**
 * @brief      DHCP option and value (cf. RFC1533)
 */
enum{
   DhcpOptionPadding            = 0,
   DhcpOptionSubnetMask         = 1,
   DhcpOptionRoutersOnSubnet    = 3,
   DhcpOptionDNS                = 6,
   DhcpOptionHostName           = 12,
   DhcpOptionDomainName         = 15,
   DhcpOptionRequestedIPaddr      = 50,
   DhcpOptionIPAddrLeaseTime      = 51,
   DhcpOptionOptionOverload      = 52,
   DhcpOptionMessageType      = 53,
   DhcpOptionServerIdentifier      = 54,
   DhcpOptionParamRequest      = 55,
   DhcpOptionMsg            = 56,
   DhcpOptionMaxMsgSize       = 57,
   DhcpOptionT1value                  = 58,
   DhcpOptionT2value            = 59,
   DhcpOptionClassIdentifier      = 60,
   DhcpOptionClientIdentifier      = 61,
   DhcpOptionEnd                 = 255
};

byte mac[] = { 0xDE, 0xAF, 0xAE, 0xDF, 0xFE, 0xED };
byte ip[] = { 0,0,0,0 };

unsigned int dhcp_state;
unsigned long startTime;
unsigned long lastTime;
unsigned long _dhcpTransactionId = 123456; /* todo */

byte broadcastIp[] = { 255,255,255,255 };
byte dhcpServerIp[4];

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,


void setup() {
  Serial.begin(9600);
  // start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  Udp.begin(DHCP_CLIENT_PORT);
  startTime = millis();
  lastTime = startTime;

  dhcp_state = STATE_DHCP_START;
  
  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);
}

void loop() {
  if(dhcp_state == STATE_DHCP_START) {
    #ifdef DEBUG
    Serial.println("STATE_DHCP_START");
    #endif
    
    RIP_MSG *packet = (RIP_MSG *)malloc(dhcpSIZE +4 * sizeof(byte *));
    packet->op = DHCP_BOOTREQUEST;
    packet->htype = DHCP_HTYPE10MB;
    packet->hlen = DHCP_HLENETHERNET;
    packet->hops = DHCP_HOPS;
    packet->xid = dhcp_swapl(_dhcpTransactionId);
    packet->secs = 0;
    packet->flags = dhcp_swaps(DHCP_FLAGSBROADCAST);
    memset(packet->ciaddr, 0, 4);
    memset(packet->yiaddr, 0, 4);
    memset(packet->siaddr, 0, 4);
    memset(packet->giaddr, 0, 4);
    memset(packet->sname, 0, 64);
    memset(packet->file, 0, 128);
    memcpy(packet->chaddr, mac, sizeof(mac));
    packet->magic[0] = 99;
    packet->magic[1] = 130;
    packet->magic[2] = 83;
    packet->magic[3] = 99;
    
    unsigned int ptr = 0;
    // OPTION: message type
    packet->OPT[ptr] = DhcpOptionMessageType;
    ptr += 1;
    packet->OPT[ptr] = 1;
    ptr += 1;
    packet->OPT[ptr] = 1; //DhcpMessageDiscover
    ptr += 1;
    packet->OPT[ptr] = DhcpOptionEnd;
    ptr += 1;
    
    Udp.sendPacket((byte *)packet,dhcpSIZE +4,broadcastIp,DHCP_SERVER_PORT);
    #ifdef DEBUG
    Serial.println("STATE_DHCP_DISCOVER");
    Serial.print("send pack size: ");
    Serial.println(sizeof(*packet));
    #endif
    dhcp_state = STATE_DHCP_DISCOVER;
    zap(packet);
  }
  
  if(Udp.available()) {
    
    // Get packet size and allocate memory
    int packetSize = Udp.available()-8;
    RIP_MSG *packet = (RIP_MSG *)malloc(packetSize * sizeof(byte *));
    Udp.readPacket((byte *)packet,packetSize);
  
  // Find real size and make copy of incoming options
  // Attempt to handle missing 'DhcpOptionEnd' - corrupted line?
    int optLoc = 0;
    while(packet->OPT[optLoc] != DhcpOptionEnd && optLoc < packetSize-dhcpSIZE){
      optLoc = 2+optLoc+packet->OPT[optLoc+1];
    }
    int optSize = optLoc;
    byte *options = (byte *)malloc(optSize * sizeof(byte *));
    memcpy( options , packet->OPT , optSize);
    digitalWrite(9, HIGH);
  
    #ifdef DEBUG
    Serial.print("Packet size ");
    Serial.println(packetSize, DEC);
    Serial.print("Options size ");
    Serial.println(optSize, DEC);
    Serial.println("Fetched");
    for(int i = 0;i < (optSize);i++){
      Serial.print(options[i], DEC);
      Serial.print(" ");
    }
    Serial.println();
    #endif

  }
  
  
  #ifdef DEBUG
  /*
  if( millis()-lastTime > 1000 ){
    Serial.print(".");
    lastTime = millis();
  }
  */
  #endif
}


uint16_t dhcp_swaps(uint16_t i) {
      uint16_t ret=0;
      ret = (i & 0xFF) << 8;
      ret |= ((i >> 8)& 0xFF);
      return ret;      
}

uint32_t dhcp_swapl(uint32_t l) {
      uint32_t ret=0;
      ret = (l & 0xFF) << 24;
      ret |= ((l >> 8) & 0xFF) << 16;
      ret |= ((l >> 16) & 0xFF) << 8;
      ret |= ((l >> 24) & 0xFF);
      return ret;
}

This might give you some ideas:

http://www.musically.me.uk/DHCP_Web_Server_12.pde

it's the most recent version of my attempt to get a DHCP server.

More details here:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1273689407

Check the last few entries :slight_smile: