DHCP代码

来源:互联网 发布:小黄鸭淘宝客软件 编辑:程序博客网 时间:2024/06/04 04:16
 


/*********************************************************************
 *
 *                  DHCP Module for Modtronix TCP/IP Stack
 *
 *********************************************************************
 * FileName:        DHCP.c
 * Dependencies:    stacktsk.h
 *                  UDP.h
 * Processor:       PIC18
 * Complier:        MCC18 v1.00.50 or higher
 *                  HITECH PICC-18 V8.35PL3 or higher
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * The software supplied herewith by Modtronix Engineering is based on
 * v2.20.04.01 of the Microchip TCP/IP stack. The original code base
 * is owned by Microchip Technology Incorporated (the Company), and is
 * protected under applicable copyright laws. The modifications are
 * owned by Modtronix Engineering, and is protected under applicable
 * copyright laws. The software supplied herewith is intended and
 * supplied to you, the Company customer, for use solely and
 * exclusively on Microchip PICmicro Microcontroller based products
 * manufactured by Modtronix Engineering. The code may be modified and
 * can be used free of charge for non commercial and commercial
 * applications. All rights are reserved. Any use in violation of the
 * foregoing restrictions may subject the user to criminal sanctions
 * under applicable laws, as well as to civil liability for the breach
 * of the terms and conditions of this license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN 'AS IS' CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * HiTech PICC18 Compiler Options excluding device selection:
 *                  -FAKELOCAL -G -Zg -E -C
 *
 * Author               Date    Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Nilesh Rajbharti     3/21/01  Original        (Rev 1.0)
 * Nilesh Rajbharti     7/10/02  Explicitly initialized tempIPAddress
 *                                               (Rev 2.11)
 * Nilesh Rajbharti     5/16/03 Increased DHCP_TIMEOUT to 2 seconds.
 * Nilesh Rajbharti     5/16/03 Fixed SM_DHCP_BROADCAST logic
 *                              where UDPPut was called before setting
 *                              active socket.
 * Robert Sloan         5/29/03 Improved DHCP State machine to handle
 *                              NAK and renew existing IP address.
 * Nilesh Rajbharti     8/15/03 Modified _DHCPRecieve() to check for
 *                              chaddr field before accpting the packet.
 *                              Fixed DHCPTask() where it would not
 *                              reply to first OFFER.
 * 2005-12-21, David Hosken (DH):
 *    - Increased DHCP timeout to 4 seconds
 *    - Modified ticks to use 16 bit variable
 * 2006-09-08, David Hosken (DH): Implemented changes from Microchip TCP/IP stack 3.75
 *
 * 2008-05-08, Andrew Eckhardt: Implemented changes from Microchip
 *              TCP/IP Stack Version v4.18 dated 28 November 2007
 ********************************************************************/
#define __DHCP_C
#define THIS_IS_DHCP

#include "projdefs.h"
#include "net\checkcfg.h"
#include "net\dhcp.h"
#include "net\udp.h"
#include "net\tick.h"
#include "debug.h"
#include <string.h>   // memset

#if defined(STACK_USE_DHCP)

#define DHCP_TIMEOUT                    (TICK)(2*TICK_SECOND)

/////////////////////////////////////////////////
//Debug defines
#define debugPutMsg(msgCode) debugPut2Bytes(0xE1, msgCode)
#define debugPutMsgRomStr(msgCode, strStr) debugMsgRomStr(0xE1, msgCode, msgStr)

/////////////////////////////////////////////////
//Do some checks
#if defined(STACK_USE_SLIP)
#error DHCP module is not available when SLIP is used.
#endif

SM_DHCP smDHCPState = SM_DHCP_GET_SOCKET;
DHCP_CLIENT_FLAGS DHCPFlags = {{0x00}};
BYTE DHCPBindCount = 0;

static UDP_SOCKET DHCPSocket = INVALID_UDP_SOCKET;

static DWORD_VAL DHCPServerID;
static DWORD_VAL DHCPLeaseTime;

static IP_ADDR tempIPAddress;
static IP_ADDR tempGateway;
static IP_ADDR tempMask;
#if defined(STACK_USE_DNS)
static IP_ADDR tempDNS;
static IP_ADDR tempDNS2;
#endif

//ToDo: Fix UDP code to be compatible to new UCHIP stack
//WORD UDPTxCount;

typedef signed long LONG; // g:/hvac/uchip_TCP/Microchip
     // Solutions/Microchip/Include/GenericTypeDefs.h

static union
{
 struct
 {
  char IPAddress:1;
  char Gateway:1;
  char Mask:1;
  char DNS:1;
  char DNS2:1;
  char HostName:1;
 } bits;
 BYTE Val;
} ValidValues;

static BYTE _DHCPReceive(void);
static void _DHCPSend(BYTE messageType, BOOL bRenewing);


/*********************************************************************
 * Function:        void DHCPReset(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:   Resets the DHCP client, giving up any lease, knowledge of
 *             DHCP servers, etc.
 *
 * Note:            None
 ********************************************************************/
void DHCPReset(void)
{
   // Do nothing if DHCP is disabled
   if ( smDHCPState == SM_DHCP_DISABLED )
      return;

   if(DHCPSocket != INVALID_UDP_SOCKET)
      smDHCPState = SM_DHCP_SEND_DISCOVERY;
   else
      smDHCPState = SM_DHCP_GET_SOCKET;

   DHCPBindCount = 0;
   DHCPFlags.bits.bIsBound = FALSE;
}

/*********************************************************************
 * Function:        void DHCPDisable(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Puts DHCPTask into unhandled state "SM_DHCP_DISABLED"
 *                  and hence DHCP is effectively disabled.
 *
 * Note: If the board was configured by DHCP before DHCPDisable() was
 * called, then the configuration will continue to be used, but the
 * DHCP module will no longer perform any lease renewals or otherwise.
 * In other words, if the lease expires the board will still be using
 * the old IP address and the DHCP server may decide to give the IP
 * address to someone else.  The application should change the current
 * IP address and other configuration with static information provided
 * by the user following a call to DHCPDisable().
 *
 ********************************************************************/
void DHCPDisable(void)
{
   if(DHCPSocket != INVALID_UDP_SOCKET)
      {
  UDPClose(DHCPSocket);
  DHCPSocket = INVALID_UDP_SOCKET;
      }
 
   smDHCPState = SM_DHCP_DISABLED;
   AppConfig.Flags.bIsDHCPEnabled = 0;
}


/*********************************************************************
 * Function:        void DHCPEnable(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Puts DHCPTask into the original initialization
 *  state, if currently disabled.  Does nothing if
 *  already enabled.
 *
 * Note:            None
 ********************************************************************/
void DHCPEnable(void)
{
   if(smDHCPState == SM_DHCP_DISABLED)
      {
  AppConfig.Flags.bIsDHCPEnabled = 1;
  smDHCPState = SM_DHCP_GET_SOCKET;
  DHCPBindCount = 0;
  DHCPFlags.bits.bIsBound = FALSE;
      }
}

/*********************************************************************
 * Function:        void DHCPTask(void)
 *
 * PreCondition:    DHCPInit() is already called
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Gets and generates DHCP messages to obtain a
 *     lease and keep it from expiring
 *
 * Note:            None
 ********************************************************************/
void DHCPTask(void)
{

   static TICK eventTime;

   switch(smDHCPState)
      {
      case SM_DHCP_GET_SOCKET:
  // Open a socket to send and receive broadcast messages on
  DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT);
  if(DHCPSocket == INVALID_UDP_SOCKET) {
#if (DEBUG_DHCP >= LOG_ERROR)
            debugPutMsg(7); //@mxd:7:Could not open UDP socket
#endif
     break;
  }
  smDHCPState = SM_DHCP_SEND_DISCOVERY;
  // No break

      case SM_DHCP_SEND_DISCOVERY:
  if(!UDPIsPutReady(DHCPSocket)) {
#if (DEBUG_DHCP >= LOG_INFO)
            debugPutMsg(8); //@mxd:8:Can not Broadcast, UDP Not ready!
#endif
     break;
  }

  // Ensure that we transmit to the broadcast IP and MAC addresses
  // The UDP Socket remembers who it was last talking to
  memset((void*)&UDPSocketInfo[DHCPSocket].remoteNode, 0xFF, \
  sizeof(UDPSocketInfo[DHCPSocket].remoteNode));

  // Assume default IP Lease time of 60 seconds.  This should
  // be minimum possible to make sure that if server did not
  // specify lease time, we try again after this minimum time.
  DHCPLeaseTime.Val = 60;
  ValidValues.Val = 0x00;
  DHCPBindCount = 0;
  DHCPFlags.bits.bIsBound = FALSE; 
  DHCPFlags.bits.bOfferReceived = FALSE;
   
  // Send the DHCP Discover broadcast
  _DHCPSend(DHCP_DISCOVER_MESSAGE, FALSE);
 
#if (DEBUG_DHCP >= LOG_INFO)
  debugPutMsg(1); //@mxd:1:Broadcast
#endif
  // Start a timer and begin looking for a response
  eventTime = TickGet() + DHCP_TIMEOUT;
  smDHCPState = SM_DHCP_GET_OFFER;
  break;

      case SM_DHCP_GET_OFFER:
  // Check to see if a packet has arrived
  if(!UDPIsGetReady(DHCPSocket))
     {
        // Go back and transmit a new discovery if we didn't
        // get an offer after 2 seconds
        if((LONG)(eventTime - TickGet()) <= (LONG)0) {
#if (DEBUG_DHCP >= LOG_INFO)
    debugPutMsg(9); //@mxd:9:Discover time out
#endif

    smDHCPState = SM_DHCP_SEND_DISCOVERY;
    break;
        }
     }

  // Let the DHCP server module know that there is a DHCP
  // server on this network
  DHCPFlags.bits.bDHCPServerDetected = TRUE;
 
  // Check to see if we received an offer
  if(_DHCPReceive() != DHCP_OFFER_MESSAGE)
     break;
 
#if (DEBUG_DHCP >= LOG_INFO)
  debugPutMsg(3); //@mxd:3:Offer Message
#endif

  smDHCPState = SM_DHCP_SEND_REQUEST;
  // No break
 
      case SM_DHCP_SEND_REQUEST:
  if(!UDPIsPutReady(DHCPSocket))
     break;

  // Send the DHCP request message
  _DHCPSend(DHCP_REQUEST_MESSAGE, FALSE);
   
#if (DEBUG_DHCP >= LOG_INFO)
  debugPutMsg(12); //@mxd:12:Sending Request
#endif
  // Start a timer and begin looking for a response
  eventTime = TickGet() + DHCP_TIMEOUT;
  smDHCPState = SM_DHCP_GET_REQUEST_ACK;
  break;

      case SM_DHCP_GET_REQUEST_ACK:
  // Check to see if a packet has arrived
  if(!UDPIsGetReady(DHCPSocket))
     {
        // Go back and transmit a new discovery if we didn't
        // get an ACK after 2 seconds
        if((LONG)(eventTime - TickGet()) <= (LONG)0)
    smDHCPState = SM_DHCP_SEND_DISCOVERY;
        break;
     }
 
  // Check to see if we received an offer
  switch(_DHCPReceive())
     {
     case DHCP_ACK_MESSAGE:
        eventTime = TickGet() + TICK_SECOND;
        smDHCPState = SM_DHCP_BOUND;

        DHCPFlags.bits.bIsBound = TRUE; 
        DHCPBindCount++;
        if(ValidValues.bits.IPAddress)
    AppConfig.MyIPAddr = tempIPAddress;
        if(ValidValues.bits.Mask)
    AppConfig.MyMask = tempMask;
        if(ValidValues.bits.Gateway)
    AppConfig.MyGateway = tempGateway;
#if defined(STACK_USE_DNS)
        if(ValidValues.bits.DNS)
    AppConfig.PrimaryDNSServer = tempDNS;
        if(ValidValues.bits.DNS2)
    AppConfig.SecondaryDNSServer = tempDNS2;
#endif
#if (DEBUG_DHCP >= LOG_INFO)
        debugPutMsg(5);     //@mxd:5:ACK Received
#endif
        break;
       
     case DHCP_NAK_MESSAGE:
        smDHCPState = SM_DHCP_SEND_DISCOVERY;
#if (DEBUG_DHCP >= LOG_WARN)
        debugPutMsg(4);     //@mxd:4:NAK recieved (RSS). DHCP server
#endif
        break;
     }
  break;

      case SM_DHCP_BOUND:
  if((LONG)(eventTime - TickGet()) >= (LONG)0)
     break;

  // Check to see if our lease has nearly expired and we must
  // renew
  eventTime += TICK_SECOND;
  DHCPLeaseTime.Val--;
  if(DHCPLeaseTime.Val) {
#if (DEBUG_DHCP >= LOG_INFO)
     debugPutMsg(11);     //@mxd:11:Lease time expired
#endif
     break;
  }

  smDHCPState = SM_DHCP_SEND_RENEW;
  // No break

      case SM_DHCP_SEND_RENEW:
      case SM_DHCP_SEND_RENEW2:
      case SM_DHCP_SEND_RENEW3:
  if(!UDPIsPutReady(DHCPSocket))
     break;

  // Send the DHCP request message
  _DHCPSend(DHCP_REQUEST_MESSAGE, TRUE);
  DHCPFlags.bits.bOfferReceived = FALSE;
 
  // Start a timer and begin looking for a response
  eventTime = TickGet() + DHCP_TIMEOUT;
  smDHCPState++;
  break;

      case SM_DHCP_GET_RENEW_ACK:
      case SM_DHCP_GET_RENEW_ACK2:
      case SM_DHCP_GET_RENEW_ACK3:
  // Check to see if a packet has arrived
  if(!UDPIsGetReady(DHCPSocket))
     {
        // Go back and transmit a new discovery if we didn't
        // get an ACK after 2 seconds
        if((LONG)(eventTime - TickGet()) <= (LONG)0)
    {
       if(++smDHCPState > SM_DHCP_GET_RENEW_ACK3)
   smDHCPState = SM_DHCP_SEND_DISCOVERY;
    }
        break;
     }

  // Check to see if we received an offer
  switch(_DHCPReceive())
     {
     case DHCP_ACK_MESSAGE:
        eventTime = TickGet() + TICK_SECOND;
        DHCPBindCount++;
        smDHCPState = SM_DHCP_BOUND;
#if (DEBUG_DHCP >= LOG_INFO)
        debugPutMsg(5);     //@mxd:5:ACK Received
#endif
        break;

     case DHCP_NAK_MESSAGE:
        smDHCPState = SM_DHCP_SEND_DISCOVERY;
#if (DEBUG_DHCP >= LOG_WARN)
        debugPutMsg(4);     //@mxd:4:NAK recieved (RSS). DHCP server
#endif
        break;
     }
  break;
      }
}


/**
 *  DHCP PACKET FORMAT AS PER RFC 1541
 *
 *  0                   1                   2                   3
 *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
 *   +---------------+---------------+---------------+---------------+
 *   |                            xid (4)                            |
 *   +-------------------------------+-------------------------------+
 *   |           secs (2)            |           flags (2)           |
 *   +-------------------------------+-------------------------------+
 *   |                          ciaddr  (4)                          |
 *   +---------------------------------------------------------------+
 *   |                          yiaddr  (4)                          |
 *   +---------------------------------------------------------------+
 *   |                          siaddr  (4)                          |
 *   +---------------------------------------------------------------+
 *   |                          giaddr  (4)                          |
 *   +---------------------------------------------------------------+
 *   |                                                               |
 *   |                          chaddr  (16)                         |
 *   |                                                               |
 *   |                                                               |
 *   +---------------------------------------------------------------+
 *   |                                                               |
 *   |                          sname   (64)                         |
 *   +---------------------------------------------------------------+
 *   |                                                               |
 *   |                          file    (128)                        |
 *   +---------------------------------------------------------------+
 *   |                                                               |
 *   |                          options (312)                        |
 *   +---------------------------------------------------------------+
 *
 */
static BYTE _DHCPReceive(void)
{
   BYTE v;
   BYTE i, j;
   BYTE type;
   BOOL lbDone;
   DWORD_VAL tempServerID;


   // Assume unknown message until proven otherwise.
   type = DHCP_UNKNOWN_MESSAGE;

   UDPGet(&v);                             // op

   // Make sure this is BOOT_REPLY.
   if ( v == BOOT_REPLY )
      {
  // Discard htype, hlen, hops, xid, secs, flags, ciaddr.
  for ( i = 0; i < 15u; i++ )
            UDPGet(&v);

  // Check to see if this is the first offer
  if(DHCPFlags.bits.bOfferReceived)
     {
        // Discard offered IP address, we already have an offer
        for ( i = 0; i < 4u; i++ )
    UDPGet(&v);
     }
  else
     {
        // Save offered IP address until we know for sure that
        // we have it.
        UDPGetArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
        ValidValues.bits.IPAddress = 1;
     }

  // Ignore siaddr, giaddr
  for ( i = 0; i < 8u; i++ )
            UDPGet(&v);

  // Check to see if chaddr (Client Hardware Address) belongs
  // to us.
  for ( i = 0; i < 6u; i++ )
     {
        UDPGet(&v);
        if ( v != AppConfig.MyMACAddr.v[i])
    goto UDPInvalid;
     }

  // Ignore part of chaddr, sname, file, magic cookie.
  for ( i = 0; i < 206u; i++ )
            UDPGet(&v);

  lbDone = FALSE;
  do
     {
        // Get the Option number
        // Break out eventually in case if this is a malformed
        // DHCP message, ie: missing DHCP_END_OPTION marker
        if(!UDPGet(&v))
    {
       lbDone = TRUE;
       break;
    }

        switch(v)      // handle the various option numbers
    {
    case DHCP_MESSAGE_TYPE:
       UDPGet(&v);                         // Skip len
       // Len must be 1.
       if ( v == 1u )
   {
      UDPGet(&type);                  // Get type

      // Throw away the packet if we know we
      // don't need it (ie: another offer when we
      // already have one)
      if(DHCPFlags.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE))
         {
     goto UDPInvalid;
         }
   }
       else
   goto UDPInvalid;
       break;

    case DHCP_SUBNET_MASK:
       UDPGet(&v);                     // Skip len
       // Len must be 4.
       if ( v == 4u )
   {
      // Check to see if this is the first offer
      if(DHCPFlags.bits.bOfferReceived)
         {
     // Discard offered IP mask, we
     // already have an offer
     for ( i = 0; i < 4u; i++ )
        UDPGet(&v);
         }
      else
         {
     UDPGetArray((BYTE*)&tempMask, sizeof(tempMask));
     ValidValues.bits.Mask = 1;
         }
   }
       else
   goto UDPInvalid;
       break;

    case DHCP_ROUTER:
       UDPGet(&j);
       // Len must be >= 4.
       if ( j >= 4u )
   {
      // Check to see if this is the first offer
      if(DHCPFlags.bits.bOfferReceived)
         {
     // Discard offered Gateway address,
     // we already have an offer
     for ( i = 0; i < 4u; i++ )
        UDPGet(&v);
         }
      else
         {
     UDPGetArray((BYTE*)&tempGateway, sizeof(tempGateway));
     ValidValues.bits.Gateway = 1;
         }
   }
       else
   goto UDPInvalid;

       // Discard any other router addresses.
       j -= 4;
       while(j--)
   UDPGet(&v);
       break;

#if defined(STACK_USE_DNS)
       UDPGet(&j);
       // Len must be >= 4.
       if(j < 4u)
   goto UDPInvalid;
      
       // Check to see if this is the first offer
       if(!DHCPFlags.bits.bOfferReceived)
   {
      UDPGetArray((BYTE*)&tempDNS, sizeof(tempDNS));
      ValidValues.bits.DNS = 1;
      j -= 4;
   }
      
       // Len must be >= 4 for a secondary DNS server address
       if(j >= 4u)
   {
      // Check to see if this is the first offer
      if(!DHCPFlags.bits.bOfferReceived)
         {
     UDPGetArray((BYTE*)&tempDNS2, sizeof(tempDNS2));
     ValidValues.bits.DNS2 = 1;
     j -= 4;
         }
   }

       // Discard any other DNS server addresses
       while(j--)
   UDPGet(&v);
       break;
#endif


    case DHCP_SERVER_IDENTIFIER:
       UDPGet(&v);                         // Get len
       // Len must be 4.
       if ( v == 4u )
   {
      UDPGet(&tempServerID.v[3]);   // Get the id
      UDPGet(&tempServerID.v[2]);
      UDPGet(&tempServerID.v[1]);
      UDPGet(&tempServerID.v[0]);
   }
       else
   goto UDPInvalid;
       break;

    case DHCP_END_OPTION:
       lbDone = TRUE;
       break;

    case DHCP_IP_LEASE_TIME:
       UDPGet(&v);                         // Get len
       // Len must be 4.
       if ( v == 4u )
   {
      // Check to see if this is the first offer
      if(DHCPFlags.bits.bOfferReceived)
         {
     // Discard offered lease time, we
     // already have an offer
     for ( i = 0; i < 4u; i++ )
        UDPGet(&v);
         }
      else
         {
     UDPGet(&DHCPLeaseTime.v[3]);
     UDPGet(&DHCPLeaseTime.v[2]);
     UDPGet(&DHCPLeaseTime.v[1]);
     UDPGet(&DHCPLeaseTime.v[0]);

     // In case our clock is not as
     // accurate as the remote DHCP
     // server's clock, let's treat the
     // lease time as only 96.875% of the
     // value given
     DHCPLeaseTime.Val -= DHCPLeaseTime.Val>>5;
       
         }
   }
       else
   goto UDPInvalid;
       break;

    default:
       // Ignore all unsupport tags.
       UDPGet(&j);                     // Get option len
       while( j-- )                    // Ignore option values
   UDPGet(&v);
    }
        FAST_USER_PROCESS();
     } while( !lbDone );
      }
  
   // If this is an OFFER message, remember current server id.
   if ( type == DHCP_OFFER_MESSAGE )
      {
  DHCPServerID.Val = tempServerID.Val;
  DHCPFlags.bits.bOfferReceived = TRUE;
      }
   else
      {
  // For other types of messages, make sure that received
  // server id matches with our previous one.
  if ( DHCPServerID.Val != tempServerID.Val )
            type = DHCP_UNKNOWN_MESSAGE;
      }
  
   UDPDiscard();    // We are done with this packet
   return type;

 UDPInvalid:
   UDPDiscard();
   return DHCP_UNKNOWN_MESSAGE;

}

 


static void _DHCPSend(BYTE messageType, BOOL bRenewing)
{
   BYTE i;
   IP_ADDR MyIP;


   UDPPut(BOOT_REQUEST);                       // op
   UDPPut(BOOT_HW_TYPE);                       // htype
   UDPPut(BOOT_LEN_OF_HW_TYPE);                // hlen
   UDPPut(0);                                  // hops
   UDPPut(0x12);                               // xid[0]
   UDPPut(0x23);                               // xid[1]
   UDPPut(0x34);                               // xid[2]
   UDPPut(0x56);                               // xid[3]
   UDPPut(0);                                  // secs[0]
   UDPPut(0);                                  // secs[1]
   UDPPut(0x80);                               // flags[0] with BF set
   UDPPut(0);                                  // flags[1]

   // If this is DHCP REQUEST message, use previously allocated IP
   // address.

   if((messageType == DHCP_REQUEST_MESSAGE) && bRenewing)
      {
  UDPPutArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
      }
   else
      {
  UDPPut(0x00);
  UDPPut(0x00);
  UDPPut(0x00);
  UDPPut(0x00);
      }

   // Set yiaddr, siaddr, giaddr as zeros,
   for ( i = 0; i < 12u; i++ )
      UDPPut(0x00);

   // Load chaddr - Client hardware address.
   UDPPutArray((BYTE*)&AppConfig.MyMACAddr, sizeof(AppConfig.MyMACAddr));

   // Set chaddr[6..15], sname and file as zeros.
   for ( i = 0; i < 202u; i++ )
      UDPPut(0);

   // Load magic cookie as per RFC 1533.
   UDPPut(99);
   UDPPut(130);
   UDPPut(83);
   UDPPut(99);

   // Load message type.
   UDPPut(DHCP_MESSAGE_TYPE);
   UDPPut(DHCP_MESSAGE_TYPE_LEN);
   UDPPut(messageType);

   if(messageType == DHCP_DISCOVER_MESSAGE)
      {
  // Reset offered flag so we know to act upon the next valid
  // offer
  DHCPFlags.bits.bOfferReceived = FALSE;
      }

   if((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing)
      {
         // DHCP REQUEST message must include server identifier the
         // first time to identify the server we are talking to.
         // _DHCPReceive() would populate "serverID" when it receives
         // DHCP OFFER message. We will simply use that when we are
         // replying to server.  If this is a renwal request, we must
         // not include server id.
         UDPPut(DHCP_SERVER_IDENTIFIER);
         UDPPut(DHCP_SERVER_IDENTIFIER_LEN);
         UDPPut(DHCPServerID.v[3]);
         UDPPut(DHCPServerID.v[2]);
         UDPPut(DHCPServerID.v[1]);
         UDPPut(DHCPServerID.v[0]);
     }

   // Load our interested parameters
   // This is hardcoded list.  If any new parameters are desired,
   // new lines must be added here.
   UDPPut(DHCP_PARAM_REQUEST_LIST);
   UDPPut(DHCP_PARAM_REQUEST_LIST_LEN);
   UDPPut(DHCP_SUBNET_MASK);
   UDPPut(DHCP_ROUTER);
   UDPPut(DHCP_DNS);
   UDPPut(DHCP_HOST_NAME);

   // Add requested IP address to DHCP Request Message
   if( ((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing) ||
       ((messageType == DHCP_DISCOVER_MESSAGE) && tempIPAddress.Val))
      {
  UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS);
  UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
  UDPPutArray((BYTE*)&tempIPAddress, DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
      }

   // Add any new parameter request here.

   // End of Options.
   UDPPut(DHCP_END_OPTION);

   // Add zero padding to ensure compatibility with old BOOTP
   // relays that discard small packets (<300 UDP octets)
   /* ToDo: 
      while (UDPSocketInfo[DHCPSocket].TxCount < 300)  // while(UDPTxCount < 300)
      UDPPut(0);
   */

   // Make sure we advertise a 0.0.0.0 IP address so all DHCP
   // servers will respond.  If we have a static IP outside the
   // DHCP server's scope, it may simply ignore discover
   // messages.
   MyIP.Val = AppConfig.MyIPAddr.Val;
   if(!bRenewing)
      AppConfig.MyIPAddr.Val = 0x00000000;
   UDPFlush();
   AppConfig.MyIPAddr.Val = MyIP.Val;
 
}

#endif    //#if defined(STACK_USE_DHCP)

原创粉丝点击