DHCP.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00036 /*********************************************************************
00037  * Software License Agreement
00038  *
00039  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights 
00040  * reserved.
00041  *
00042  * Microchip licenses to you the right to use, modify, copy, and 
00043  * distribute: 
00044  * (i)  the Software when embedded on a Microchip microcontroller or 
00045  *      digital signal controller product ("Device") which is 
00046  *      integrated into Licensee's product; or
00047  * (ii) ONLY the Software driver source files ENC28J60.c and 
00048  *      ENC28J60.h ported to a non-Microchip device used in 
00049  *      conjunction with a Microchip ethernet controller for the 
00050  *      sole purpose of interfacing with the ethernet controller. 
00051  *
00052  * You should refer to the license agreement accompanying this 
00053  * Software for additional information regarding your rights and 
00054  * obligations.
00055  *
00056  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT 
00057  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT 
00058  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A 
00059  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL 
00060  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR 
00061  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF 
00062  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS 
00063  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE 
00064  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER 
00065  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT 
00066  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00067  *
00068  *
00069  * Author               Date    Comment
00070  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00071  * Nilesh Rajbharti     3/21/01  Original        (Rev 1.0)
00072  * Nilesh Rajbharti     7/10/02  Explicitly initialized tempIPAddress
00073  *                                               (Rev 2.11)
00074  * Nilesh Rajbharti     5/16/03 Increased DHCP_TIMEOUT to 2 seconds.
00075  * Nilesh Rajbharti     5/16/03 Fixed SM_DHCP_BROADCAST logic
00076  *                              where UDPPut was called before setting
00077  *                              active socket.
00078  * Robert Sloan         5/29/03 Improved DHCP State machine to handle
00079  *                              NAK and renew existing IP address.
00080  * Nilesh Rajbharti     8/15/03 Modified _DHCPRecieve() to check for
00081  *                              chaddr field before accpting the packet.
00082  *                              Fixed DHCPTask() where it would not
00083  *                              reply to first OFFER.
00084  * Nilesh Rajbharti     3/1/04  Used tickDiff in DHCPTask() "bind"
00085  *                              state to adjust for irregular TICK_SECOND
00086  *                              Without this logic, actual lease time count
00087  *                              down may be incorrect.
00088  * Howard Schlunder     5/11/06 Fixed tickDiff usage, reducing 
00089  *                              accumulated timing error.  Fixed DHCP 
00090  *                              state machine requesting IP 0.0.0.0 
00091  *                              after lease expiration.
00092  * Howard Schlunder     6/01/06 Added DHCPFlags.bits.bOfferReceived flag to 
00093  *                              allow operation on networks with multiple
00094  *                              DHCP servers offering multiple addresses
00095  * Howard Schlunder     8/01/06 Added DNS server option to DHCP request, 
00096  *                              untested Host Name option to DHCP request
00097  * Howard Schlunder     1/09/06 Fixed a DHCP renewal not renewing lease time bug
00098  * Howard Schlunder     3/16/07 Rewrote DHCP state machine
00099  ********************************************************************/
00100 #define __DHCP_C
00101 #include "TCPIP.h"
00102 
00103 // Defines how long to wait before a DHCP request times out
00104 #define DHCP_TIMEOUT                    (TICK)(2*TICK_SECOND)
00105 // MODIFIX: Added a second timeout for supporting Auto IP.
00106 #define DHCP_TIMEOUT2                   (TICK)(180*TICK_SECOND)
00107 
00108 // DHCP state machien variable
00109 SM_DHCP smDHCPState = SM_DHCP_GET_SOCKET;
00110 
00111 // DHCP Client Flags to use 
00112 DHCP_CLIENT_FLAGS DHCPFlags = {{0x00}};
00113 
00114 // Socket for DHCP client to use
00115 static UDP_SOCKET DHCPSocket = INVALID_UDP_SOCKET;
00116 
00117 // MODIFIX: New member for retry counter of DHCP discoveries.
00118 BYTE DHCPDiscRetry = 0;     
00119 
00120 BYTE DHCPBindCount = 0;         // Counts how many times DHCP has been bound
00121 static DWORD_VAL DHCPServerID;  // DHCP Server ID cache
00122 static DWORD_VAL DHCPLeaseTime; // DHCP Lease Time
00123 static IP_ADDR tempIPAddress;   // Temporary IP address to use when no DHCP lease
00124 static IP_ADDR tempGateway;     // Temporary gateway to use when no DHCP lease
00125 static IP_ADDR tempMask;        // Temporary mask to use when no DHCP lease
00126 
00127 // MODIFIX: Removed DNS variables due eWicht does not use unicast DNS. 
00128 
00129 // Indicates which DHCP values are currently valid
00130 static union
00131 {
00132     struct
00133     {
00134         char IPAddress:1;   // Leased IP address is valid
00135         char Gateway:1;     // Gateway address is valid
00136         char Mask:1;        // Subnet mask is valid
00137         char DNS:1;         // Primary DNS is valid
00138         char DNS2:1;        // Secondary DNS is valid
00139         char HostName:1;    // Host name is valid (not implemented)
00140     } bits;
00141     BYTE Val;
00142 } ValidValues;
00143 
00144 
00145 static BYTE _DHCPReceive(void);
00146 static void _DHCPSend(BYTE messageType, BOOL bRenewing);
00147 
00148 
00149 /*****************************************************************************
00150   Function:
00151     void DHCPReset(void)
00152 
00153   Summary:
00154     Resets the DHCP Client.
00155 
00156   Description:
00157     Resets the DHCP Client, giving up any current lease, knowledge of 
00158     DHCP servers, etc.
00159 
00160   Precondition:
00161     None
00162 
00163   Parameters:
00164     None
00165 
00166   Returns:
00167     None
00168 
00169   MODIFIX:          
00170     Added AutoIP support.
00171   ***************************************************************************/
00172 void DHCPReset( BOOL bNoAutoIP )
00173 {
00174     // Do nothing if DHCP is disabled
00175     if(smDHCPState == SM_DHCP_DISABLED)
00176         return;
00177 
00178     if(DHCPSocket != INVALID_UDP_SOCKET)
00179         // MODIFIX: Starting withe Auto IP state instead of 
00180         // SM_DHCP_SEND_DISCOVERY
00181         smDHCPState = SM_DHCP_AUTOIP;
00182     else
00183         smDHCPState = SM_DHCP_GET_SOCKET;
00184 
00185     // MODIFIX:
00186     // Reset the eWicht structure sIPConfig to a well known state, in case
00187     // Auto IP is enabled or the last used IP was not unique in the network.
00188     if ( ( bNoAutoIP == FALSE ) || ( sIPConfig.Flags.bIPunique == FALSE ) )
00189     {
00190         sIPConfig.MyIPAddr.Val = 0;
00191         sIPConfig.MyMask.Val = 0;
00192         sIPConfig.MyGateway.Val = 0;
00193         sIPConfig.Flags.bIPunique = FALSE;
00194     }
00195 
00196     DHCPBindCount = 0;
00197     DHCPDiscRetry = 0;  // MODIFIX: New member must be initialized with 0.
00198     DHCPFlags.bits.bIsBound = FALSE;
00199 
00200     // MODIFIX: This flag was never reseted!
00201     DHCPFlags.bits.bDHCPServerDetected = FALSE;  
00202 }
00203 
00204 
00205 /*****************************************************************************
00206   Function:
00207     void DHCPDisable(void)
00208 
00209   Summary:
00210     Disables the DHCP Client.
00211 
00212   Description:
00213     Disables the DHCP client by sending the state machine to 
00214     "SM_DHCP_DISABLED".  If the board was previously configured by DHCP, the
00215     configuration will continue to be used but the module will no longer
00216     preform any renewals.
00217 
00218   Precondition:
00219     None
00220 
00221   Parameters:
00222     None
00223 
00224   Returns:
00225     None
00226     
00227   Remarks:
00228     Since the board continues using its old configuration, it is possible 
00229     that the lease may expire and the DHCP server provide the IP to another
00230     client.  The application should replace the current IP address and other
00231     configuration with static information following a call to this function.
00232   ***************************************************************************/
00233 void DHCPDisable(void)
00234 {
00235     if(DHCPSocket != INVALID_UDP_SOCKET)
00236     {
00237         UDPClose(DHCPSocket);
00238         DHCPSocket = INVALID_UDP_SOCKET;
00239     }
00240     
00241     smDHCPState = SM_DHCP_DISABLED;
00242 
00243     // MODIFIX: The flags are stored in the persistant IP configuration 
00244     // structure of eWicht.
00245     sPCommonConfig.Flags.bIsDHCPEnabled = 0;
00246 }
00247 
00248 
00249 /*****************************************************************************
00250   Function:
00251     void DHCPEnable(void)
00252 
00253   Summary:
00254     Enables the DHCP Client.
00255 
00256   Description:
00257     Enables the DHCP client if it is disabled.  If it is already enabled,
00258     nothing is done.
00259 
00260   Precondition:
00261     None
00262 
00263   Parameters:
00264     None
00265 
00266   Returns:
00267     None
00268   ***************************************************************************/
00269 void DHCPEnable(void)
00270 {
00271     if(smDHCPState == SM_DHCP_DISABLED)
00272     {
00273         // MODIFIX: This flag is stored in the eWicht sPCommonConfig structure
00274         // and not needed here.
00275 //      AppConfig.Flags.bIsDHCPEnabled = 1;
00276         smDHCPState = SM_DHCP_GET_SOCKET;
00277         DHCPBindCount = 0;
00278         DHCPFlags.bits.bIsBound = FALSE;
00279     }
00280 }
00281 
00282 
00283 /*****************************************************************************
00284   Function:
00285     void DHCPTask(void)
00286 
00287   Summary:
00288     Performs periodic DHCP tasks.
00289 
00290   Description:
00291     This function performs any periodic tasks requied by the DHCP module, 
00292     such as sending and receiving messages involved with obtaining and
00293     maintaining a lease.
00294 
00295   Precondition:
00296     None
00297 
00298   Parameters:
00299     None
00300 
00301   Returns:
00302     None
00303 
00304   MODIFIX:      
00305     Added AutoIP support.
00306   ***************************************************************************/
00307 void DHCPTask(void)
00308 {
00309     static TICK eventTime;
00310 
00311     switch(smDHCPState)
00312     {
00313         case SM_DHCP_GET_SOCKET:
00314             // Open a socket to send and receive broadcast messages on
00315             DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT);
00316             if(DHCPSocket == INVALID_UDP_SOCKET)
00317                 break;
00318 
00319             smDHCPState = SM_DHCP_AUTOIP;
00320             // No break
00321 
00322         // MODIFIX: Added the following case label for supporting Auto IP. 
00323         case SM_DHCP_AUTOIP:
00324             if (sIPConfig.MyIPAddr.Val == 0)
00325             {
00326                 if ((DHCPDiscRetry > 0) && (DHCPDiscRetry < 4))
00327                 {
00328                     // No DHCP-Server found yet, select an so called AutoIP during the further search time
00329                     // Take an auto IP address, that worked the last time.
00330                     
00331                     MAC_ADDR dummy;
00332                     if (ARPIsResolved(&sPCommonConfig.LastAutoIP, &dummy) == FALSE)
00333                         ARPResolve(&sPCommonConfig.LastAutoIP);
00334                     else
00335                     {
00336                         sPCommonConfig.LastAutoIP = GenerateAutoIP(&sPCommonConfig.LastAutoIP);
00337                         // Restart probing!
00338                         DHCPDiscRetry = 1;
00339                         ARPResolve(&sPCommonConfig.LastAutoIP);
00340                     }
00341                 }
00342                 else if (DHCPDiscRetry == 4)
00343                 {
00344                     // IP is probed and no answers have received!
00345                     sIPConfig.MyIPAddr = sPCommonConfig.LastAutoIP;
00346                     sIPConfig.MyMask.Val = 0xFFFF;  // subnet mask is 255.255.0.0
00347     
00348                     // ToDo: Save the probed auto IP-Address in EEPROM
00349                 }
00350             }
00351             smDHCPState = SM_DHCP_SEND_DISCOVERY;
00352             // No break
00353 
00354         case SM_DHCP_SEND_DISCOVERY:
00355             if(UDPIsPutReady(DHCPSocket) < 300u)
00356                 break;
00357 
00358             // Ensure that we transmit to the broadcast IP and MAC addresses
00359             // The UDP Socket remembers who it was last talking to
00360             memset((void*)&UDPSocketInfo[DHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[DHCPSocket].remoteNode));
00361 
00362             // Assume default IP Lease time of 60 seconds.
00363             // This should be minimum possible to make sure that if
00364             // server did not specify lease time, we try again after this minimum time.
00365             DHCPLeaseTime.Val = 60;
00366             ValidValues.Val = 0x00;
00367             DHCPBindCount = 0;
00368             DHCPFlags.bits.bIsBound = FALSE;    
00369             DHCPFlags.bits.bOfferReceived = FALSE;
00370             
00371             // Send the DHCP Discover broadcast
00372             _DHCPSend(DHCP_DISCOVER_MESSAGE, FALSE);
00373             
00374             // Start a timer and begin looking for a response
00375             eventTime = TickGet();
00376 
00377             smDHCPState = SM_DHCP_GET_OFFER;
00378             break;
00379 
00380         case SM_DHCP_GET_OFFER:
00381             // Check to see if a packet has arrived
00382             if(UDPIsGetReady(DHCPSocket) < 250u)
00383             {
00384                 // MODIFIX: Added the if else block for supporting Auto IP. 
00385                 DWORD tmp =  DHCP_TIMEOUT2;
00386                 if (DHCPDiscRetry != 5)
00387                     tmp = DHCP_TIMEOUT;
00388 
00389                 // Go back and transmit a new discovery if we didn't get an offer after 2 seconds
00390                 if (TickGet() - eventTime >= tmp)
00391                 {
00392                     // MODIFIX: Changed from SM_DHCP_SEND_DISCOVERY to AUTOIP
00393                     smDHCPState = SM_DHCP_AUTOIP;
00394                     
00395                     // MODIFIX: Added the if else block for supporting Auto IP. 
00396                     if (DHCPDiscRetry != 5)
00397                         DHCPDiscRetry++;
00398                 }
00399                 break;
00400             }
00401 
00402             // Let the DHCP server module know that there is a DHCP server 
00403             // on this network
00404             DHCPFlags.bits.bDHCPServerDetected = TRUE;
00405 
00406             // Check to see if we received an offer
00407             if(_DHCPReceive() != DHCP_OFFER_MESSAGE)
00408                 break;
00409 
00410             smDHCPState = SM_DHCP_SEND_REQUEST;
00411             // No break
00412 
00413         case SM_DHCP_SEND_REQUEST:
00414             if(UDPIsPutReady(DHCPSocket) < 258u)
00415                 break;
00416 
00417             // Send the DHCP request message
00418             _DHCPSend(DHCP_REQUEST_MESSAGE, FALSE);
00419             
00420             // Start a timer and begin looking for a response
00421             eventTime = TickGet();
00422             smDHCPState = SM_DHCP_GET_REQUEST_ACK;
00423             break;
00424 
00425         case SM_DHCP_GET_REQUEST_ACK:
00426             // Check to see if a packet has arrived
00427             if(UDPIsGetReady(DHCPSocket) < 250u)
00428             {
00429                 // Go back and transmit a new discovery if we didn't get an ACK after 2 seconds
00430                 if(TickGet() - eventTime >= DHCP_TIMEOUT)
00431                     smDHCPState = SM_DHCP_AUTOIP;
00432                 break;
00433             }
00434 
00435             // Check to see if we received an offer
00436             switch(_DHCPReceive())
00437             {
00438                 case DHCP_ACK_MESSAGE:
00439                     UDPClose(DHCPSocket);
00440                     DHCPSocket = INVALID_UDP_SOCKET;
00441                     eventTime = TickGet();
00442                     smDHCPState = SM_DHCP_BOUND;
00443 
00444                     DHCPFlags.bits.bIsBound = TRUE; 
00445                     DHCPBindCount++;
00446                     if(ValidValues.bits.IPAddress)
00447                         // MODIFIX: Use eWicht struct sIPConfig
00448                         sIPConfig.MyIPAddr = tempIPAddress; 
00449                     if(ValidValues.bits.Mask)
00450                         // MODIFIX: Use eWicht struct sIPConfig
00451                         sIPConfig.MyMask = tempMask;
00452                     if(ValidValues.bits.Gateway)
00453                         // MODIFIX: Use eWicht struct sIPConfig
00454                         sIPConfig.MyGateway = tempGateway;
00455                     #if defined(STACK_USE_DNS)
00456                         if(ValidValues.bits.DNS)
00457                             // MODIFIX: Use eWicht struct sIPConfig
00458                             sIPConfig.PrimaryDNSServer = tempDNS;
00459                         if(ValidValues.bits.DNS2)
00460                             // MODIFIX: Use eWicht struct sIPConfig
00461                             sIPConfig.SecondaryDNSServer = tempDNS2;
00462                     #endif
00463 //                  if(ValidValues.bits.HostName)
00464 //                      memcpy(AppConfig.NetBIOSName, (void*)tempHostName, sizeof(AppConfig.NetBIOSName));
00465 
00466                     break;
00467 
00468                 case DHCP_NAK_MESSAGE:
00469                     // MODIFIX Changed state from SEND_DISCOVERY to AUTOIP: 
00470                     smDHCPState = SM_DHCP_AUTOIP;
00471                     break;
00472             }
00473             break;
00474 
00475         case SM_DHCP_BOUND:
00476             if(TickGet() - eventTime < TICK_SECOND)
00477                 break;
00478 
00479             // Check to see if our lease is still valid, if so, decrement lease 
00480             // time
00481             if(DHCPLeaseTime.Val >= 2ul)
00482             {
00483                 eventTime += TICK_SECOND;
00484                 DHCPLeaseTime.Val--;
00485                 break;
00486             }
00487             
00488             // Open a socket to send and receive DHCP messages on
00489             DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT);
00490             if(DHCPSocket == INVALID_UDP_SOCKET)
00491                 break;
00492             
00493             smDHCPState = SM_DHCP_SEND_RENEW;
00494             // No break
00495 
00496         case SM_DHCP_SEND_RENEW:
00497         case SM_DHCP_SEND_RENEW2:
00498         case SM_DHCP_SEND_RENEW3:
00499             if(UDPIsPutReady(DHCPSocket) < 258u)
00500                 break;
00501 
00502             // Send the DHCP request message
00503             _DHCPSend(DHCP_REQUEST_MESSAGE, TRUE);
00504             DHCPFlags.bits.bOfferReceived = FALSE;
00505             
00506             // Start a timer and begin looking for a response
00507             eventTime = TickGet();
00508             smDHCPState++;
00509             break;
00510 
00511         case SM_DHCP_GET_RENEW_ACK:
00512         case SM_DHCP_GET_RENEW_ACK2:
00513         case SM_DHCP_GET_RENEW_ACK3:
00514             // Check to see if a packet has arrived
00515             if(UDPIsGetReady(DHCPSocket) < 250u)
00516             {
00517                 // Go back and transmit a new discovery if we didn't get an ACK after 2 seconds
00518                 if(TickGet() - eventTime >=  DHCP_TIMEOUT)
00519                 {
00520                     // MODIFIX: Changed the new state from SEND_DISCOVERY to
00521                     // AUTOIP:
00522                     if(++smDHCPState > SM_DHCP_GET_RENEW_ACK3)
00523                         smDHCPState = SM_DHCP_AUTOIP;
00524                 }
00525                 break;
00526             }
00527 
00528             // Check to see if we received an offer
00529             switch(_DHCPReceive())
00530             {
00531                 case DHCP_ACK_MESSAGE:
00532                     UDPClose(DHCPSocket);
00533                     DHCPSocket = INVALID_UDP_SOCKET;
00534                     eventTime = TickGet();
00535                     DHCPBindCount++;
00536                     smDHCPState = SM_DHCP_BOUND;
00537                     break;
00538 
00539                 case DHCP_NAK_MESSAGE:
00540                     // MODIFIX: Changed from SM_DHCP_SEND_DISCOVERY to AUTOIP.
00541                     smDHCPState = SM_DHCP_AUTOIP;
00542                     break;
00543             }
00544             break;
00545 
00546         // Handle SM_DHCP_DISABLED state by doing nothing.  Default case needed 
00547         // to supress compiler diagnostic.
00548         default:    
00549             break;
00550     }
00551 }
00552 
00553 
00554 /*****************************************************************************
00555   Function:
00556     void _DHCPReceive(void)
00557 
00558   Description:
00559     Receives and parses a DHCP message.
00560 
00561   Precondition:
00562     A DHCP message is waiting in the UDP buffer.
00563 
00564   Parameters:
00565     None
00566 
00567   Returns:
00568     One of the DCHP_TYPE* contants.
00569   ***************************************************************************/
00570 static BYTE _DHCPReceive(void)
00571 {
00572     /*********************************************************************
00573             DHCP PACKET FORMAT AS PER RFC 1541
00574     
00575        0                   1                   2                   3
00576        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
00577        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00578        |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
00579        +---------------+---------------+---------------+---------------+
00580        |                            xid (4)                            |
00581        +-------------------------------+-------------------------------+
00582        |           secs (2)            |           flags (2)           |
00583        +-------------------------------+-------------------------------+
00584        |                          ciaddr  (4)                          |
00585        +---------------------------------------------------------------+
00586        |                          yiaddr  (4)                          |
00587        +---------------------------------------------------------------+
00588        |                          siaddr  (4)                          |
00589        +---------------------------------------------------------------+
00590        |                          giaddr  (4)                          |
00591        +---------------------------------------------------------------+
00592        |                                                               |
00593        |                          chaddr  (16)                         |
00594        |                                                               |
00595        |                                                               |
00596        +---------------------------------------------------------------+
00597        |                                                               |
00598        |                          sname   (64)                         |
00599        +---------------------------------------------------------------+
00600        |                                                               |
00601        |                          file    (128)                        |
00602        +---------------------------------------------------------------+
00603        |                                                               |
00604        |                          options (312)                        |
00605        +---------------------------------------------------------------+
00606     
00607      ********************************************************************/
00608     BYTE v;
00609     BYTE i, j;
00610     BYTE type;
00611     BOOL lbDone;
00612     DWORD_VAL tempServerID;
00613 
00614 
00615     // Assume unknown message until proven otherwise.
00616     type = DHCP_UNKNOWN_MESSAGE;
00617 
00618     UDPGet(&v);                             // op
00619     
00620     // Make sure this is BOOT_REPLY.
00621     if ( v == BOOT_REPLY )
00622     {
00623         // Discard htype, hlen, hops, xid, secs, flags, ciaddr.
00624         for ( i = 0; i < 15u; i++ )
00625             UDPGet(&v);
00626 
00627         // Check to see if this is the first offer
00628         if(DHCPFlags.bits.bOfferReceived)
00629         {
00630             // Discard offered IP address, we already have an offer
00631             for ( i = 0; i < 4u; i++ )
00632                 UDPGet(&v);
00633         }
00634         else
00635         {
00636             // Save offered IP address until we know for sure that we have it.
00637             UDPGetArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
00638             ValidValues.bits.IPAddress = 1;
00639         }
00640 
00641         // Ignore siaddr, giaddr
00642         for ( i = 0; i < 8u; i++ )
00643             UDPGet(&v);
00644 
00645         // Check to see if chaddr (Client Hardware Address) belongs to us.
00646         for ( i = 0; i < 6u; i++ )
00647         {
00648             UDPGet(&v);
00649             // MODIFIX: eWicht MAC address is stored in flash.
00650             if ( v != pu8MAC[i])
00651                 goto UDPInvalid;
00652         }
00653 
00654 
00655         // Ignore part of chaddr, sname, file, magic cookie.
00656         for ( i = 0; i < 206u; i++ )
00657             UDPGet(&v);
00658 
00659         lbDone = FALSE;
00660         do
00661         {
00662             // Get the Option number
00663             // Break out eventually in case if this is a malformed 
00664             // DHCP message, ie: missing DHCP_END_OPTION marker
00665             if(!UDPGet(&v))
00666             {
00667                 lbDone = TRUE;
00668                 break;
00669             }
00670 
00671             switch(v)
00672             {
00673             case DHCP_MESSAGE_TYPE:
00674                 UDPGet(&v);                         // Skip len
00675                 // Len must be 1.
00676                 if ( v == 1u )
00677                 {
00678                     UDPGet(&type);                  // Get type
00679 
00680                     // Throw away the packet if we know we don't need it (ie: another offer when we already have one)
00681                     if(DHCPFlags.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE))
00682                     {
00683                         goto UDPInvalid;
00684                     }
00685                 }
00686                 else
00687                     goto UDPInvalid;
00688                 break;
00689 
00690             case DHCP_SUBNET_MASK:
00691                 UDPGet(&v);                     // Skip len
00692                 // Len must be 4.
00693                 if ( v == 4u )
00694                 {
00695                     // Check to see if this is the first offer
00696                     if(DHCPFlags.bits.bOfferReceived)
00697                     {
00698                         // Discard offered IP mask, we already have an offer
00699                         for ( i = 0; i < 4u; i++ )
00700                             UDPGet(&v);
00701                     }
00702                     else
00703                     {
00704                         UDPGetArray((BYTE*)&tempMask, sizeof(tempMask));
00705                         ValidValues.bits.Mask = 1;
00706                     }
00707                 }
00708                 else
00709                     goto UDPInvalid;
00710                 break;
00711 
00712             case DHCP_ROUTER:
00713                 UDPGet(&j);
00714                 // Len must be >= 4.
00715                 if ( j >= 4u )
00716                 {
00717                     // Check to see if this is the first offer
00718                     if(DHCPFlags.bits.bOfferReceived)
00719                     {
00720                         // Discard offered Gateway address, we already have an offer
00721                         for ( i = 0; i < 4u; i++ )
00722                             UDPGet(&v);
00723                     }
00724                     else
00725                     {
00726                         UDPGetArray((BYTE*)&tempGateway, sizeof(tempGateway));
00727                         ValidValues.bits.Gateway = 1;
00728                     }
00729                 }
00730                 else
00731                     goto UDPInvalid;
00732 
00733                 // Discard any other router addresses.
00734                 j -= 4;
00735                 while(j--)
00736                     UDPGet(&v);
00737                 break;
00738 
00739 #if defined(STACK_USE_DNS)
00740             case DHCP_DNS:
00741                 UDPGet(&j);
00742                 // Len must be >= 4.
00743                 if(j < 4u)
00744                     goto UDPInvalid;
00745 
00746                 // Check to see if this is the first offer
00747                 if(!DHCPFlags.bits.bOfferReceived)
00748                 {
00749                     UDPGetArray((BYTE*)&tempDNS, sizeof(tempDNS));
00750                     ValidValues.bits.DNS = 1;
00751                     j -= 4;
00752                 }
00753 
00754                 // Len must be >= 4 for a secondary DNS server address
00755                 if(j >= 4u)
00756                 {
00757                     // Check to see if this is the first offer
00758                     if(!DHCPFlags.bits.bOfferReceived)
00759                     {
00760                         UDPGetArray((BYTE*)&tempDNS2, sizeof(tempDNS2));
00761                         ValidValues.bits.DNS2 = 1;
00762                         j -= 4;
00763                     }
00764                 }
00765 
00766                 // Discard any other DNS server addresses
00767                 while(j--)
00768                     UDPGet(&v);
00769                 break;
00770 #endif
00771 
00772 //            case DHCP_HOST_NAME:
00773 //                UDPGet(&j);
00774 //                // Len must be >= 4.
00775 //                if(j < 1u)
00776 //                  goto UDPInvalid;
00777 //
00778 //              // Check to see if this is the first offer
00779 //              if(DHCPFlags.bits.bOfferReceived)
00780 //              {
00781 //                  // Discard offered host name, we already have an offer
00782 //                  while(j--)
00783 //                      UDPGet(&v);
00784 //              }
00785 //              else
00786 //              {
00787 //                  for(i = 0; j, i < sizeof(tempHostName); i++, j--)
00788 //                  {
00789 //                      UDPGet(&tempHostName[i]);
00790 //                  }
00791 //                  while(j--)
00792 //                  {
00793 //                      UDPGet(&v);
00794 //                  }
00795 //                  ValidValues.bits.HostName = 1;
00796 //              }
00797 //
00798 //                break;
00799 
00800             case DHCP_SERVER_IDENTIFIER:
00801                 UDPGet(&v);                         // Get len
00802                 // Len must be 4.
00803                 if ( v == 4u )
00804                 {
00805                     UDPGet(&tempServerID.v[3]);   // Get the id
00806                     UDPGet(&tempServerID.v[2]);
00807                     UDPGet(&tempServerID.v[1]);
00808                     UDPGet(&tempServerID.v[0]);
00809                 }
00810                 else
00811                     goto UDPInvalid;
00812                 break;
00813 
00814             case DHCP_END_OPTION:
00815                 lbDone = TRUE;
00816                 break;
00817 
00818             case DHCP_IP_LEASE_TIME:
00819                 UDPGet(&v);                         // Get len
00820                 // Len must be 4.
00821                 if ( v == 4u )
00822                 {
00823                     // Check to see if this is the first offer
00824                     if(DHCPFlags.bits.bOfferReceived)
00825                     {
00826                         // Discard offered lease time, we already have an offer
00827                         for ( i = 0; i < 4u; i++ )
00828                             UDPGet(&v);
00829                     }
00830                     else
00831                     {
00832                         UDPGet(&DHCPLeaseTime.v[3]);
00833                         UDPGet(&DHCPLeaseTime.v[2]);
00834                         UDPGet(&DHCPLeaseTime.v[1]);
00835                         UDPGet(&DHCPLeaseTime.v[0]);
00836 
00837                         // In case if our clock is not as accurate as the remote 
00838                         // DHCP server's clock, let's treat the lease time as only 
00839                         // 96.875% of the value given
00840                         DHCPLeaseTime.Val -= DHCPLeaseTime.Val>>5;
00841                     }
00842                 }
00843                 else
00844                     goto UDPInvalid;
00845                 break;
00846 
00847             default:
00848                 // Ignore all unsupport tags.
00849                 UDPGet(&j);                     // Get option len
00850                 while( j-- )                    // Ignore option values
00851                     UDPGet(&v);
00852             }
00853         } while( !lbDone );
00854     }
00855 
00856     // If this is an OFFER message, remember current server id.
00857     if ( type == DHCP_OFFER_MESSAGE )
00858     {
00859         DHCPServerID.Val = tempServerID.Val;
00860         DHCPFlags.bits.bOfferReceived = TRUE;
00861     }
00862     else
00863     {
00864         // For other types of messages, make sure that received
00865         // server id matches with our previous one.
00866         if ( DHCPServerID.Val != tempServerID.Val )
00867             type = DHCP_UNKNOWN_MESSAGE;
00868     }
00869 
00870     UDPDiscard();                             // We are done with this packet
00871     return type;
00872 
00873 UDPInvalid:
00874     UDPDiscard();
00875     return DHCP_UNKNOWN_MESSAGE;
00876 
00877 }
00878 
00879 
00880 
00881 /*****************************************************************************
00882   Function:
00883     static void _DHCPSend(BYTE messageType, BOOL bRenewing)
00884 
00885   Description:
00886     Sends a DHCP message.
00887 
00888   Precondition:
00889     UDP is ready to write a DHCP packet.
00890 
00891   Parameters:
00892     messageType - One of the DHCP_TYPE constants
00893     bRenewing - Whether or not this is a renewal request
00894 
00895   Returns:
00896     None
00897   ***************************************************************************/
00898 static void _DHCPSend(BYTE messageType, BOOL bRenewing)
00899 {
00900     BYTE i;
00901     IP_ADDR MyIP;
00902 
00903 
00904     UDPPut(BOOT_REQUEST);                       // op
00905     UDPPut(BOOT_HW_TYPE);                       // htype
00906     UDPPut(BOOT_LEN_OF_HW_TYPE);                // hlen
00907     UDPPut(0);                                  // hops
00908     UDPPut(0x12);                               // xid[0]
00909     UDPPut(0x23);                               // xid[1]
00910     UDPPut(0x34);                               // xid[2]
00911     UDPPut(0x56);                               // xid[3]
00912     UDPPut(0);                                  // secs[0]
00913     UDPPut(0);                                  // secs[1]
00914     UDPPut(0x80);                               // flags[0] with BF set
00915     UDPPut(0);                                  // flags[1]
00916 
00917     // If this is DHCP REQUEST message, use previously allocated IP address.
00918     if((messageType == DHCP_REQUEST_MESSAGE) && bRenewing)
00919     {
00920         UDPPutArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
00921     }
00922     else
00923     {
00924         UDPPut(0x00);
00925         UDPPut(0x00);
00926         UDPPut(0x00);
00927         UDPPut(0x00);
00928     }
00929 
00930     // Set yiaddr, siaddr, giaddr as zeros,
00931     for ( i = 0; i < 12u; i++ )
00932         UDPPut(0x00);
00933 
00934     // Load chaddr - Client hardware address.
00935     // MODIFIX: eWicht MAC address is located in flash. 
00936     UDPPutROMArray( ( ROM BYTE *) pu8MAC, sizeof( MAC_ADDR ) );
00937 
00938     // Set chaddr[6..15], sname and file as zeros.
00939     for ( i = 0; i < 202u; i++ )
00940         UDPPut(0);
00941 
00942     // Load magic cookie as per RFC 1533.
00943     UDPPut(99);
00944     UDPPut(130);
00945     UDPPut(83);
00946     UDPPut(99);
00947 
00948     // Load message type.
00949     UDPPut(DHCP_MESSAGE_TYPE);
00950     UDPPut(DHCP_MESSAGE_TYPE_LEN);
00951     UDPPut(messageType);
00952 
00953     if(messageType == DHCP_DISCOVER_MESSAGE)
00954     {
00955         // Reset offered flag so we know to act upon the next valid offer
00956         DHCPFlags.bits.bOfferReceived = FALSE;
00957     }
00958 
00959 
00960     if((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing)
00961     {
00962          // DHCP REQUEST message must include server identifier the first time
00963          // to identify the server we are talking to.
00964          // _DHCPReceive() would populate "serverID" when it
00965          // receives DHCP OFFER message. We will simply use that
00966          // when we are replying to server.
00967          // If this is a renwal request, we must not include server id.
00968          UDPPut(DHCP_SERVER_IDENTIFIER);
00969          UDPPut(DHCP_SERVER_IDENTIFIER_LEN);
00970          UDPPut(DHCPServerID.v[3]);
00971          UDPPut(DHCPServerID.v[2]);
00972          UDPPut(DHCPServerID.v[1]);
00973          UDPPut(DHCPServerID.v[0]);
00974      }
00975 
00976     // Load our interested parameters
00977     // This is hardcoded list.  If any new parameters are desired,
00978     // new lines must be added here.
00979     UDPPut(DHCP_PARAM_REQUEST_LIST);
00980     UDPPut(DHCP_PARAM_REQUEST_LIST_LEN);
00981     UDPPut(DHCP_SUBNET_MASK);
00982     UDPPut(DHCP_ROUTER);
00983     UDPPut(DHCP_DNS);
00984     UDPPut(DHCP_HOST_NAME);
00985 
00986      // Add requested IP address to DHCP Request Message
00987     if( ((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing) || 
00988         ((messageType == DHCP_DISCOVER_MESSAGE) && tempIPAddress.Val))
00989     {
00990         UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS);
00991         UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
00992         UDPPutArray((BYTE*)&tempIPAddress, DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
00993     }
00994 
00995     // Add any new paramter request here.
00996 
00997     // End of Options.
00998     UDPPut(DHCP_END_OPTION);
00999 
01000     // Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
01001     while(UDPTxCount < 300u)
01002         UDPPut(0);
01003 
01004     // 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.
01005     // MODIFIX: Use eWicht struct sIPConfig (3 times)
01006     MyIP.Val = sIPConfig.MyIPAddr.Val;
01007     if(!bRenewing)
01008         sIPConfig.MyIPAddr.Val = 0x00000000;
01009     UDPFlush();
01010     sIPConfig.MyIPAddr.Val = MyIP.Val;
01011 }
01012 
01013 
01014 /*********************************************************************
01015  * Function:        IP_ADDR GenerateAutoIP( IP_ADDR * lastIP )
01016  ********************************************************************/
01017 IP_ADDR GenerateAutoIP( IP_ADDR * lastIP )
01018 {
01019     IP_ADDR newIP;
01020     newIP.v[0] = 169;
01021     newIP.v[1] = 254;
01022 
01023     if ( lastIP == 0 )
01024     {
01025         newIP.v[2] = pu8MAC[4];
01026         newIP.v[3] = pu8MAC[5];
01027     }
01028     else
01029         newIP.w[1] = lastIP->w[1] + TickGet();
01030 
01031     while ( newIP.w[1] < 256 || newIP.w[1] > 65279 )
01032         newIP.w[1] += TickGet();
01033 
01034     return newIP;
01035 }
01036 

Generated on Sun Nov 27 20:02:38 2011 for eWicht by  doxygen 1.5.5