Subversion Repositories HomeAutomation

Rev

Rev 363 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*********************************************************************
  2.  *
  3.  *                  DHCP Module for Microchip TCP/IP Stack
  4.  *
  5.  *********************************************************************
  6.  * FileName:        DHCP.c
  7.  * Dependencies:    StackTsk.h
  8.  *                  UDP.h
  9.  * Processor:       PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
  10.  * Complier:        Microchip C18 v3.02 or higher
  11.  *                  Microchip C30 v2.01 or higher
  12.  * Company:         Microchip Technology, Inc.
  13.  *
  14.  * Software License Agreement
  15.  *
  16.  * This software is owned by Microchip Technology Inc. ("Microchip")
  17.  * and is supplied to you for use exclusively as described in the
  18.  * associated software agreement.  This software is protected by
  19.  * software and other intellectual property laws.  Any use in
  20.  * violation of the software license may subject the user to criminal
  21.  * sanctions as well as civil liability.  Copyright 2006 Microchip
  22.  * Technology Inc.  All rights reserved.
  23.  *
  24.  * This software is provided "AS IS."  MICROCHIP DISCLAIMS ALL
  25.  * WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED
  26.  * TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
  27.  * INFRINGEMENT.  Microchip shall in no event be liable for special,
  28.  * incidental, or consequential damages.
  29.  *
  30.  *
  31.  * Author               Date    Comment
  32.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  33.  * Nilesh Rajbharti     3/21/01  Original        (Rev 1.0)
  34.  * Nilesh Rajbharti     7/10/02  Explicitly initialized tempIPAddress
  35.  *                                               (Rev 2.11)
  36.  * Nilesh Rajbharti     5/16/03 Increased DHCP_TIMEOUT to 2 seconds.
  37.  * Nilesh Rajbharti     5/16/03 Fixed SM_DHCP_BROADCAST logic
  38.  *                              where UDPPut was called before setting
  39.  *                              active socket.
  40.  * Robert Sloan         5/29/03 Improved DHCP State machine to handle
  41.  *                              NAK and renew existing IP address.
  42.  * Nilesh Rajbharti     8/15/03 Modified _DHCPRecieve() to check for
  43.  *                              chaddr field before accpting the packet.
  44.  *                              Fixed DHCPTask() where it would not
  45.  *                              reply to first OFFER.
  46.  * Nilesh Rajbharti     3/1/04  Used tickDiff in DHCPTask() "bind"
  47.  *                              state to adjust for irregular TICK_SECOND
  48.  *                              Without this logic, actual lease time count
  49.  *                              down may be incorrect.
  50.  * Howard Schlunder     5/11/06 Fixed tickDiff usage, reducing
  51.  *                              accumulated timing error.  Fixed DHCP
  52.  *                              state machine requesting IP 0.0.0.0
  53.  *                              after lease expiration.
  54.  * Howard Schlunder     6/01/06 Added DHCPState.bits.bOfferReceived flag to
  55.  *                              allow operation on networks with multiple
  56.  *                              DHCP servers offering multiple addresses
  57.  * Howard Schlunder     8/01/06 Added DNS server option to DHCP request,
  58.  *                              untested Host Name option to DHCP request
  59.  ********************************************************************/
  60. #define THIS_IS_DHCP
  61.  
  62. #include "..\Include\StackTsk.h"
  63.  
  64. #if defined(STACK_USE_DHCP)
  65.  
  66. #include "..\Include\DHCP.h"
  67. #include "..\Include\UDP.h"
  68. #include "..\Include\Tick.h"
  69.  
  70.  
  71. #if defined(STACK_USE_SLIP)
  72.     #error DHCP module is not available when SLIP is used.
  73. #endif
  74.  
  75.  
  76. #define DHCP_TIMEOUT                    (TICK)(2L * TICK_SECOND)
  77.  
  78.  
  79. #define DHCP_CLIENT_PORT                (68u)
  80. #define DHCP_SERVER_PORT                (67u)
  81.  
  82. #define BOOT_REQUEST                    (1u)
  83. #define BOOT_REPLY                      (2u)
  84. #define HW_TYPE                         (1u)
  85. #define LEN_OF_HW_TYPE                  (6u)
  86.  
  87. #define DHCP_MESSAGE_TYPE               (53u)
  88. #define DHCP_MESSAGE_TYPE_LEN           (1u)
  89.  
  90. #define DHCP_UNKNOWN_MESSAGE            (0u)
  91.  
  92. #define DHCP_DISCOVER_MESSAGE           (1u)
  93. #define DHCP_OFFER_MESSAGE              (2u)
  94. #define DHCP_REQUEST_MESSAGE            (3u)
  95. #define DHCP_DECLINE_MESSAGE            (4u)
  96. #define DHCP_ACK_MESSAGE                (5u)
  97. #define DHCP_NAK_MESSAGE                (6u)
  98. #define DHCP_RELEASE_MESSAGE            (7u)
  99.  
  100. #define DHCP_SERVER_IDENTIFIER          (54u)
  101. #define DHCP_SERVER_IDENTIFIER_LEN      (4u)
  102.  
  103. #define DHCP_PARAM_REQUEST_LIST         (55u)
  104. #define DHCP_PARAM_REQUEST_LIST_LEN     (4u)
  105. #define DHCP_PARAM_REQUEST_IP_ADDRESS       (50u)
  106. #define DHCP_PARAM_REQUEST_IP_ADDRESS_LEN   (4u)
  107. #define DHCP_SUBNET_MASK                (1u)
  108. #define DHCP_ROUTER                     (3u)
  109. #define DHCP_DNS                        (6u)
  110. #define DHCP_HOST_NAME                  (12u)
  111. #define DHCP_IP_LEASE_TIME              (51u)
  112. #define DHCP_END_OPTION                 (255u)
  113.  
  114. #define HALF_HOUR                       (WORD)((WORD)60 * (WORD)30)
  115.  
  116. SM_DHCP  smDHCPState = SM_DHCP_INIT_FIRST_TIME;
  117. static UDP_SOCKET DHCPSocket = INVALID_UDP_SOCKET;
  118.  
  119.  
  120. DHCP_STATE DHCPState = { 0x00 };
  121.  
  122. static DWORD_VAL DHCPServerID;
  123. static DWORD_VAL DHCPLeaseTime;
  124.  
  125. static IP_ADDR tempIPAddress;
  126. static IP_ADDR tempGateway;
  127. static IP_ADDR tempMask;
  128. #if defined(STACK_USE_DNS)
  129. static IP_ADDR tempDNS;
  130. #endif
  131. //static BYTE tempHostName[16];
  132.  
  133. static union
  134. {
  135.     struct
  136.     {
  137.         char IPAddress:1;
  138.         char Gateway:1;
  139.         char Mask:1;
  140.         char DNS:1;
  141.         char HostName:1;
  142.     } bits;
  143.     BYTE Val;
  144. } ValidValues;
  145.  
  146. static BYTE _DHCPReceive(void);
  147. static void _DHCPSend(BYTE messageType);
  148.  
  149. BYTE DHCPBindCount = 0;
  150.  
  151. // Uncomment following line if DHCP transactions are to be displayed on
  152. // RS-232 - for debug purpose only.
  153. //#define DHCP_DEBUG_MODE
  154.  
  155. #if defined(DHCP_DEBUG_MODE)
  156. static USARTPut(BYTE c)
  157. {
  158.     while( !TXSTA_TRMT);
  159.     TXREG = c;
  160. }
  161. #else
  162.  
  163. #define USARTPut(a)
  164.  
  165. #endif
  166.  
  167.  
  168. void DHCPReset(void)
  169. {
  170.     // Do not reset DHCP if it was previously disabled.
  171.     if ( smDHCPState == SM_DHCP_DISABLED )
  172.         return;
  173.  
  174.     if ( DHCPSocket != INVALID_UDP_SOCKET )
  175.         UDPClose(DHCPSocket);
  176.     DHCPSocket = INVALID_UDP_SOCKET;
  177.  
  178.     smDHCPState = SM_DHCP_INIT_FIRST_TIME;
  179.     DHCPBindCount = 0;
  180.  
  181.     DHCPState.bits.bIsBound = FALSE;
  182. }
  183.  
  184. /*********************************************************************
  185.  * Function:        void DHCPTask(void)
  186.  *
  187.  * PreCondition:    DHCPInit() is already called AND
  188.  *                  IPGetHeader() is called with
  189.  *                  IPFrameType == IP_PROT_UDP
  190.  *
  191.  * Input:           None
  192.  *
  193.  * Output:          None
  194.  *
  195.  * Side Effects:    None
  196.  *
  197.  * Overview:        Fetches pending UDP packet from MAC receive buffer
  198.  *                  and dispatches it appropriate UDP socket.
  199.  *                  If not UDP socket is matched, UDP packet is
  200.  *                  silently discarded.
  201.  *
  202.  * Note:            Caller must make sure that MAC receive buffer
  203.  *                  access pointer is set to begining of UDP packet.
  204.  *                  Required steps before calling this function is:
  205.  *
  206.  *                  If ( MACIsRxReady() )
  207.  *                  {
  208.  *                      MACGetHeader()
  209.  *                      If MACFrameType == IP
  210.  *                          IPGetHeader()
  211.  *                          if ( IPFrameType == IP_PROT_UDP )
  212.  *                              Call DHCPTask()
  213.  *                  ...
  214.  ********************************************************************/
  215. void DHCPTask(void)
  216. {
  217.     NODE_INFO DHCPServerNode;
  218.     static TICK lastTryTick;
  219.     BYTE DHCPRecvReturnValue;
  220.     TICK tickDiff;
  221.  
  222.     switch(smDHCPState)
  223.     {
  224.     case SM_DHCP_INIT_FIRST_TIME:
  225.         tempIPAddress.Val = 0x0;
  226. //        smDHCPState = SM_DHCP_INIT;           // State automatically changes
  227.         /* No break */
  228.  
  229.     case SM_DHCP_INIT:
  230.         DHCPServerNode.MACAddr.v[0] = 0xff;
  231.         DHCPServerNode.MACAddr.v[1] = 0xff;
  232.         DHCPServerNode.MACAddr.v[2] = 0xff;
  233.         DHCPServerNode.MACAddr.v[3] = 0xff;
  234.         DHCPServerNode.MACAddr.v[4] = 0xff;
  235.         DHCPServerNode.MACAddr.v[5] = 0xff;
  236.         DHCPServerNode.IPAddr.Val = 0xffffffff;
  237.         DHCPSocket = UDPOpen(DHCP_CLIENT_PORT,
  238.                              &DHCPServerNode,
  239.                              DHCP_SERVER_PORT);
  240.         lastTryTick = TickGet();
  241.         smDHCPState = SM_DHCP_RESET_WAIT;
  242.         /* No break */
  243.  
  244.     case SM_DHCP_RESET_WAIT:
  245.         if ( TickGetDiff(TickGet(), lastTryTick) >= (TICK_SECOND/(TICK)5) )
  246.             smDHCPState = SM_DHCP_BROADCAST;
  247.         break;
  248.  
  249.     case SM_DHCP_BROADCAST:
  250.         // Assume default IP Lease time of 60 seconds.
  251.         // This should be minimum possible to make sure that if
  252.         // server did not specify lease time, we try again after this minimum time.
  253.         DHCPLeaseTime.Val = 60;
  254.  
  255.         // If we have already obtained some IP address, renew it.
  256.         if(DHCPState.bits.bIsBound)
  257.         {
  258.             smDHCPState = SM_DHCP_REQUEST;
  259.         }
  260.         else if ( UDPIsPutReady(DHCPSocket) )
  261.         {
  262.             // To minimize code requirement, user must make sure that
  263.             // above call will be successful by making at least one
  264.             // UDP socket available.
  265.             // Usually this will be the case, given that DHCP will be
  266.             // the first one to use UDP socket.
  267.             // Also, we will not check for transmitter readiness,
  268.             // we assume it to be ready.
  269.             _DHCPSend(DHCP_DISCOVER_MESSAGE);
  270.             ValidValues.Val = 0x00;
  271.  
  272.             // DEBUG
  273.             USARTPut('\n');
  274.             USARTPut('\r');
  275.             USARTPut('D');
  276.  
  277.             lastTryTick = TickGet();
  278.             smDHCPState = SM_DHCP_DISCOVER;
  279.         }
  280.  
  281.         break;
  282.  
  283.  
  284.     case SM_DHCP_DISCOVER:
  285.         if ( TickGetDiff(TickGet(), lastTryTick) >= DHCP_TIMEOUT )
  286.         {
  287.             smDHCPState = SM_DHCP_BROADCAST;
  288.             //return;
  289.         }
  290.  
  291.         if ( UDPIsGetReady(DHCPSocket) )
  292.         {
  293.             // DEBUG
  294.             USARTPut('R');
  295.  
  296.             if ( _DHCPReceive() == DHCP_OFFER_MESSAGE )
  297.             {
  298.                 // DEBUG
  299.                 USARTPut('O');
  300.  
  301.                 smDHCPState = SM_DHCP_REQUEST;
  302.             }
  303.             else
  304.                 break;
  305.         }
  306.         else
  307.             break;
  308.  
  309.  
  310.  
  311.     case SM_DHCP_REQUEST:
  312.         if ( UDPIsPutReady(DHCPSocket) )
  313.         {
  314.             _DHCPSend(DHCP_REQUEST_MESSAGE);
  315.  
  316.             lastTryTick = TickGet();
  317.             smDHCPState = SM_DHCP_BIND;
  318.         }
  319.         break;
  320.  
  321.     case SM_DHCP_BIND:
  322.         if ( UDPIsGetReady(DHCPSocket) )
  323.         {
  324.             DHCPRecvReturnValue = _DHCPReceive();
  325.             if ( DHCPRecvReturnValue == DHCP_NAK_MESSAGE )
  326.             {
  327.                 // (RSS) NAK recieved.  DHCP server didn't like our DHCP Request (format wrong/IP address allocated to someone else/outside IP pool)
  328.                 USARTPut('n');
  329.                 DHCPReset();                        // Start all over again
  330.                 return;
  331.             }
  332.             else if ( DHCPRecvReturnValue == DHCP_ACK_MESSAGE )
  333.             {
  334.                 // DEBUG
  335.                 USARTPut('B');
  336.  
  337.                 // Once DCHP is successful, release the UDP socket
  338.                 // This will ensure that UDP layer discards any further DHCP related packets.
  339.                 UDPClose(DHCPSocket);
  340.                 DHCPSocket = INVALID_UDP_SOCKET;
  341.  
  342.                 lastTryTick = TickGet();
  343.                 smDHCPState = SM_DHCP_BOUND;
  344.  
  345.                 if(ValidValues.bits.IPAddress)
  346.                     AppConfig.MyIPAddr = tempIPAddress;
  347.                 if(ValidValues.bits.Mask)
  348.                     AppConfig.MyMask = tempMask;
  349.                 if(ValidValues.bits.Gateway)
  350.                     AppConfig.MyGateway = tempGateway;
  351. #if defined(STACK_USE_DNS)
  352.                 if(ValidValues.bits.DNS)
  353.                     AppConfig.PrimaryDNSServer = tempDNS;
  354. #endif
  355. //              if(ValidValues.bits.HostName)
  356. //                  memcpy(AppConfig.NetBIOSName, (void*)tempHostName, sizeof(AppConfig.NetBIOSName));
  357.  
  358.                 DHCPState.bits.bIsBound = TRUE;
  359.  
  360.                 DHCPBindCount++;
  361.  
  362.                 return;
  363.             }
  364.         }
  365.         else if ( TickGetDiff(TickGet(), lastTryTick) >= DHCP_TIMEOUT )
  366.         {
  367.             USARTPut('t');
  368.             smDHCPState = SM_DHCP_BROADCAST;
  369.         }
  370.         break;
  371.  
  372.     case SM_DHCP_BOUND:
  373.         // Keep track of how long we use this IP configuration.
  374.         // When lease period expires, renew the configuration.
  375.         tickDiff = TickGetDiff(TickGet(), lastTryTick);
  376.  
  377.         if(tickDiff >= TICK_SECOND)
  378.         {
  379.             do
  380.             {
  381.                 DHCPLeaseTime.Val--;
  382.                 tickDiff -= TICK_SECOND;
  383.                 if(DHCPLeaseTime.Val == 0u)
  384.                     smDHCPState = SM_DHCP_INIT;
  385.             } while(tickDiff >= TICK_SECOND);
  386.             lastTryTick = TickGet() - tickDiff;
  387.         }
  388.     }
  389. }
  390.  
  391.  
  392.  
  393. /*********************************************************************
  394.         DHCP PACKET FORMAT AS PER RFC 1541
  395.  
  396.    0                   1                   2                   3
  397.    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
  398.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  399.    |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
  400.    +---------------+---------------+---------------+---------------+
  401.    |                            xid (4)                            |
  402.    +-------------------------------+-------------------------------+
  403.    |           secs (2)            |           flags (2)           |
  404.    +-------------------------------+-------------------------------+
  405.    |                          ciaddr  (4)                          |
  406.    +---------------------------------------------------------------+
  407.    |                          yiaddr  (4)                          |
  408.    +---------------------------------------------------------------+
  409.    |                          siaddr  (4)                          |
  410.    +---------------------------------------------------------------+
  411.    |                          giaddr  (4)                          |
  412.    +---------------------------------------------------------------+
  413.    |                                                               |
  414.    |                          chaddr  (16)                         |
  415.    |                                                               |
  416.    |                                                               |
  417.    +---------------------------------------------------------------+
  418.    |                                                               |
  419.    |                          sname   (64)                         |
  420.    +---------------------------------------------------------------+
  421.    |                                                               |
  422.    |                          file    (128)                        |
  423.    +---------------------------------------------------------------+
  424.    |                                                               |
  425.    |                          options (312)                        |
  426.    +---------------------------------------------------------------+
  427.  
  428.  ********************************************************************/
  429. static BYTE _DHCPReceive(void)
  430. {
  431.     BYTE v;
  432.     BYTE i, j;
  433.     BYTE type;
  434.     BOOL lbDone;
  435.     DWORD_VAL tempServerID;
  436.  
  437.  
  438.     // Assume unknown message until proven otherwise.
  439.     type = DHCP_UNKNOWN_MESSAGE;
  440.  
  441.     UDPGet(&v);                             // op
  442.    
  443.     // Make sure this is BOOT_REPLY.
  444.     if ( v == BOOT_REPLY )
  445.     {
  446.         // Discard htype, hlen, hops, xid, secs, flags, ciaddr.
  447.         for ( i = 0; i < 15u; i++ )
  448.             UDPGet(&v);
  449.  
  450.         // Check to see if this is the first offer
  451.         if(DHCPState.bits.bOfferReceived)
  452.         {
  453.             // Discard offered IP address, we already have an offer
  454.             for ( i = 0; i < 4u; i++ )
  455.                 UDPGet(&v);
  456.         }
  457.         else
  458.         {
  459.             // Save offered IP address until we know for sure that we have it.
  460.             UDPGet(&tempIPAddress.v[0]);
  461.             UDPGet(&tempIPAddress.v[1]);
  462.             UDPGet(&tempIPAddress.v[2]);
  463.             UDPGet(&tempIPAddress.v[3]);
  464.             ValidValues.bits.IPAddress = 1;
  465.         }
  466.  
  467.         // Ignore siaddr, giaddr
  468.         for ( i = 0; i < 8u; i++ )
  469.             UDPGet(&v);
  470.  
  471.         // Check to see if chaddr (Client Hardware Address) belongs to us.
  472.         for ( i = 0; i < 6u; i++ )
  473.         {
  474.             UDPGet(&v);
  475.             if ( v != AppConfig.MyMACAddr.v[i])
  476.                 goto UDPInvalid;
  477.         }
  478.  
  479.  
  480.         // Ignore part of chaddr, sname, file, magic cookie.
  481.         for ( i = 0; i < 206u; i++ )
  482.             UDPGet(&v);
  483.  
  484.         lbDone = FALSE;
  485.         do
  486.         {
  487.             // Get the Option number
  488.             // Break out eventually in case if this is a malformed
  489.             // DHCP message, ie: missing DHCP_END_OPTION marker
  490.             if(!UDPGet(&v))
  491.             {
  492.                 lbDone = TRUE;
  493.                 break;
  494.             }
  495.  
  496.             switch(v)
  497.             {
  498.             case DHCP_MESSAGE_TYPE:
  499.                 UDPGet(&v);                         // Skip len
  500.                 // Len must be 1.
  501.                 if ( v == 1u )
  502.                 {
  503.                     UDPGet(&type);                  // Get type
  504.  
  505.                     // Throw away the packet if we know we don't need it (ie: another offer when we already have one)
  506.                     if(DHCPState.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE))
  507.                     {
  508.                         goto UDPInvalid;
  509.                     }
  510.                 }
  511.                 else
  512.                     goto UDPInvalid;
  513.                 break;
  514.  
  515.             case DHCP_SUBNET_MASK:
  516.                 UDPGet(&v);                     // Skip len
  517.                 // Len must be 4.
  518.                 if ( v == 4u )
  519.                 {
  520.                     // Check to see if this is the first offer
  521.                     if(DHCPState.bits.bOfferReceived)
  522.                     {
  523.                         // Discard offered IP mask, we already have an offer
  524.                         for ( i = 0; i < 4u; i++ )
  525.                             UDPGet(&v);
  526.                     }
  527.                     else
  528.                     {
  529.                         UDPGet(&tempMask.v[0]);
  530.                         UDPGet(&tempMask.v[1]);
  531.                         UDPGet(&tempMask.v[2]);
  532.                         UDPGet(&tempMask.v[3]);
  533.                         ValidValues.bits.Mask = 1;
  534.                     }
  535.                 }
  536.                 else
  537.                     goto UDPInvalid;
  538.                 break;
  539.  
  540.             case DHCP_ROUTER:
  541.                 UDPGet(&j);
  542.                 // Len must be >= 4.
  543.                 if ( j >= 4u )
  544.                 {
  545.                     // Check to see if this is the first offer
  546.                     if(DHCPState.bits.bOfferReceived)
  547.                     {
  548.                         // Discard offered Gateway address, we already have an offer
  549.                         for ( i = 0; i < 4u; i++ )
  550.                             UDPGet(&v);
  551.                     }
  552.                     else
  553.                     {
  554.                         UDPGet(&tempGateway.v[0]);
  555.                         UDPGet(&tempGateway.v[1]);
  556.                         UDPGet(&tempGateway.v[2]);
  557.                         UDPGet(&tempGateway.v[3]);
  558.                         ValidValues.bits.Gateway = 1;
  559.                     }
  560.                 }
  561.                 else
  562.                     goto UDPInvalid;
  563.  
  564.                 // Discard any other router addresses.
  565.                 j -= 4;
  566.                 while(j--)
  567.                     UDPGet(&v);
  568.                 break;
  569.  
  570. #if defined(STACK_USE_DNS)
  571.             case DHCP_DNS:
  572.                 UDPGet(&j);
  573.                 // Len must be >= 4.
  574.                 if ( j >= 4u )
  575.                 {
  576.                     // Check to see if this is the first offer
  577.                     if(DHCPState.bits.bOfferReceived)
  578.                     {
  579.                         // Discard offered DNS server address, we already have an offer
  580.                         for ( i = 0; i < 4u; i++ )
  581.                             UDPGet(&v);
  582.                     }
  583.                     else
  584.                     {
  585.                         UDPGet(&tempDNS.v[0]);
  586.                         UDPGet(&tempDNS.v[1]);
  587.                         UDPGet(&tempDNS.v[2]);
  588.                         UDPGet(&tempDNS.v[3]);
  589.                         ValidValues.bits.DNS = 1;
  590.                     }
  591.                 }
  592.                 else
  593.                     goto UDPInvalid;
  594.  
  595.                 // Discard any other DNS server addresses
  596.                 j -= 4;
  597.                 while(j--)
  598.                     UDPGet(&v);
  599.                 break;
  600. #endif
  601.  
  602. //            case DHCP_HOST_NAME:
  603. //                UDPGet(&j);
  604. //                // Len must be >= 4.
  605. //                if(j < 1u)
  606. //                  goto UDPInvalid;
  607. //
  608. //              // Check to see if this is the first offer
  609. //              if(DHCPState.bits.bOfferReceived)
  610. //              {
  611. //                  // Discard offered host name, we already have an offer
  612. //                  while(j--)
  613. //                      UDPGet(&v);
  614. //              }
  615. //              else
  616. //              {
  617. //                  for(i = 0; j, i < sizeof(tempHostName); i++, j--)
  618. //                  {
  619. //                      UDPGet(&tempHostName[i]);
  620. //                  }
  621. //                  while(j--)
  622. //                  {
  623. //                      UDPGet(&v);
  624. //                  }
  625. //                  ValidValues.bits.HostName = 1;
  626. //              }
  627. //
  628. //                break;
  629.  
  630.             case DHCP_SERVER_IDENTIFIER:
  631.                 UDPGet(&v);                         // Get len
  632.                 // Len must be 4.
  633.                 if ( v == 4u )
  634.                 {
  635.                     UDPGet(&tempServerID.v[3]);   // Get the id
  636.                     UDPGet(&tempServerID.v[2]);
  637.                     UDPGet(&tempServerID.v[1]);
  638.                     UDPGet(&tempServerID.v[0]);
  639.                 }
  640.                 else
  641.                     goto UDPInvalid;
  642.                 break;
  643.  
  644.             case DHCP_END_OPTION:
  645.                 lbDone = TRUE;
  646.                 break;
  647.  
  648.             case DHCP_IP_LEASE_TIME:
  649.                 UDPGet(&v);                         // Get len
  650.                 // Len must be 4.
  651.                 if ( v == 4u )
  652.                 {
  653.                     // Check to see if this is the first offer
  654.                     if(DHCPState.bits.bOfferReceived)
  655.                     {
  656.                         // Discard offered lease time, we already have an offer
  657.                         for ( i = 0; i < 4u; i++ )
  658.                             UDPGet(&v);
  659.                     }
  660.                     else
  661.                     {
  662.                         UDPGet(&DHCPLeaseTime.v[3]);
  663.                         UDPGet(&DHCPLeaseTime.v[2]);
  664.                         UDPGet(&DHCPLeaseTime.v[1]);
  665.                         UDPGet(&DHCPLeaseTime.v[0]);
  666.  
  667.                         // Due to possible timing delays, consider actual lease
  668.                         // time less by half hour.
  669.                         if ( DHCPLeaseTime.Val > HALF_HOUR )
  670.                             DHCPLeaseTime.Val = DHCPLeaseTime.Val - HALF_HOUR;
  671.                     }
  672.                 }
  673.                 else
  674.                     goto UDPInvalid;
  675.                 break;
  676.  
  677.             default:
  678.                 // Ignore all unsupport tags.
  679.                 UDPGet(&j);                     // Get option len
  680.                 while( j-- )                    // Ignore option values
  681.                     UDPGet(&v);
  682.             }
  683.         } while( !lbDone );
  684.     }
  685.  
  686.     // If this is an OFFER message, remember current server id.
  687.     if ( type == DHCP_OFFER_MESSAGE )
  688.     {
  689.         DHCPServerID.Val = tempServerID.Val;
  690.         DHCPState.bits.bOfferReceived = TRUE;
  691.     }
  692.     else
  693.     {
  694.         // For other types of messages, make sure that received
  695.         // server id matches with our previous one.
  696.         if ( DHCPServerID.Val != tempServerID.Val )
  697.             type = DHCP_UNKNOWN_MESSAGE;
  698.     }
  699.  
  700.     UDPDiscard();                             // We are done with this packet
  701.     return type;
  702.  
  703. UDPInvalid:
  704.     UDPDiscard();
  705.     return DHCP_UNKNOWN_MESSAGE;
  706.  
  707. }
  708.  
  709.  
  710.  
  711.  
  712.  
  713. static void _DHCPSend(BYTE messageType)
  714. {
  715.     BYTE i;
  716.  
  717.  
  718.     UDPPut(BOOT_REQUEST);                       // op
  719.     UDPPut(HW_TYPE);                            // htype
  720.     UDPPut(LEN_OF_HW_TYPE);                     // hlen
  721.     UDPPut(0);                                  // hops
  722.     UDPPut(0x12);                               // xid[0]
  723.     UDPPut(0x23);                               // xid[1]
  724.     UDPPut(0x34);                               // xid[2]
  725.     UDPPut(0x56);                               // xid[3]
  726.     UDPPut(0);                                  // secs[0]
  727.     UDPPut(0);                                  // secs[1]
  728.     UDPPut(0x80);                               // flags[0] with BF set
  729.     UDPPut(0);                                  // flags[1]
  730.  
  731.     // If this is DHCP REQUEST message, use previously allocated IP address.
  732. #if 0
  733.     if ( messageType == DHCP_REQUEST_MESSAGE )
  734.     {
  735.         UDPPut(tempIPAddress.v[0]);
  736.         UDPPut(tempIPAddress.v[1]);
  737.         UDPPut(tempIPAddress.v[2]);
  738.         UDPPut(tempIPAddress.v[3]);
  739.     }
  740.     else
  741. #endif
  742.     {
  743.         UDPPut(0x00);
  744.         UDPPut(0x00);
  745.         UDPPut(0x00);
  746.         UDPPut(0x00);
  747.     }
  748.  
  749.     // Set yiaddr, siaddr, giaddr as zeros,
  750.     for ( i = 0; i < 12u; i++ )
  751.         UDPPut(0x00);
  752.  
  753.     // Load chaddr - Client hardware address.
  754.     UDPPut(AppConfig.MyMACAddr.v[0]);
  755.     UDPPut(AppConfig.MyMACAddr.v[1]);
  756.     UDPPut(AppConfig.MyMACAddr.v[2]);
  757.     UDPPut(AppConfig.MyMACAddr.v[3]);
  758.     UDPPut(AppConfig.MyMACAddr.v[4]);
  759.     UDPPut(AppConfig.MyMACAddr.v[5]);
  760.  
  761.     // Set chaddr[6..15], sname and file as zeros.
  762.     for ( i = 0; i < 202u; i++ )
  763.         UDPPut(0);
  764.  
  765.     // Load magic cookie as per RFC 1533.
  766.     UDPPut(99);
  767.     UDPPut(130);
  768.     UDPPut(83);
  769.     UDPPut(99);
  770.  
  771.     // Load message type.
  772.     UDPPut(DHCP_MESSAGE_TYPE);
  773.     UDPPut(DHCP_MESSAGE_TYPE_LEN);
  774.     UDPPut(messageType);
  775.  
  776.     if(messageType == DHCP_DISCOVER_MESSAGE)
  777.     {
  778.         // Reset offered flag so we know to act upon the next valid offer
  779.         DHCPState.bits.bOfferReceived = FALSE;
  780.     }
  781.  
  782.  
  783.     if ( messageType != DHCP_DISCOVER_MESSAGE && tempIPAddress.Val != 0x0000u )
  784.     {
  785.          // DHCP REQUEST message may include server identifier,
  786.          // to identify the server we are talking to.
  787.          // DHCP ACK may include it too.  To simplify logic,
  788.          // we will include server identifier in DHCP ACK message too.
  789.          // _DHCPReceive() would populate "serverID" when it
  790.          // receives DHCP OFFER message. We will simply use that
  791.          // when we are replying to server.
  792.          // If this is a renwal request, do not include server id.
  793.          UDPPut(DHCP_SERVER_IDENTIFIER);
  794.          UDPPut(DHCP_SERVER_IDENTIFIER_LEN);
  795.          UDPPut(DHCPServerID.v[3]);
  796.          UDPPut(DHCPServerID.v[2]);
  797.          UDPPut(DHCPServerID.v[1]);
  798.          UDPPut(DHCPServerID.v[0]);
  799.      }
  800.  
  801.     // Load our interested parameters
  802.     // This is hardcoded list.  If any new parameters are desired,
  803.     // new lines must be added here.
  804.     UDPPut(DHCP_PARAM_REQUEST_LIST);
  805.     UDPPut(DHCP_PARAM_REQUEST_LIST_LEN);
  806.     UDPPut(DHCP_SUBNET_MASK);
  807.     UDPPut(DHCP_ROUTER);
  808.     UDPPut(DHCP_DNS);
  809.     UDPPut(DHCP_HOST_NAME);
  810.  
  811.      // Add requested IP address to DHCP Request Message
  812.     if ( messageType == DHCP_REQUEST_MESSAGE )
  813.     {
  814.         UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS);
  815.         UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
  816.  
  817.         UDPPut(tempIPAddress.v[0]);
  818.         UDPPut(tempIPAddress.v[1]);
  819.         UDPPut(tempIPAddress.v[2]);
  820.         UDPPut(tempIPAddress.v[3]);
  821.     }
  822.  
  823.     // Add any new paramter request here.
  824.  
  825.     // End of Options.
  826.     UDPPut(DHCP_END_OPTION);
  827.  
  828.     UDPFlush();
  829. }
  830.  
  831.  
  832. #endif  //#if defined(STACK_USE_DHCP)
  833.