| Line No. | Rev | Author | Line | 
|---|---|---|---|
| 1 | 32 | kaklik | /********************************************************************* | 
| 2 | * | ||
| 3 | *	Dynamic Host Configuration Protocol (DHCP) Client | ||
| 4 | *	Module for Microchip TCP/IP Stack | ||
| 5 | *	 -Provides automatic IP address, subnet mask, gateway address,  | ||
| 6 | *	  DNS server address, and other configuration parameters on DHCP  | ||
| 7 | *	  enabled networks. | ||
| 8 | *	 -Reference: RFC 2131, 2132 | ||
| 9 | * | ||
| 10 | ********************************************************************* | ||
| 11 | * FileName:		DHCP.c | ||
| 12 | * Dependencies:	UDP | ||
| 13 | * Processor:	PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32 | ||
| 14 | * Compiler:		Microchip C32 v1.05 or higher | ||
| 15 | *				Microchip C30 v3.12 or higher | ||
| 16 | *				Microchip C18 v3.30 or higher | ||
| 17 | *				HI-TECH PICC-18 PRO 9.63PL2 or higher | ||
| 18 | * Company:		Microchip Technology, Inc. | ||
| 19 | * | ||
| 20 | * Software License Agreement | ||
| 21 | * | ||
| 22 | * Copyright (C) 2002-2009 Microchip Technology Inc.  All rights | ||
| 23 | * reserved. | ||
| 24 | * | ||
| 25 | * Microchip licenses to you the right to use, modify, copy, and | ||
| 26 | * distribute: | ||
| 27 | * (i)  the Software when embedded on a Microchip microcontroller or | ||
| 28 | *      digital signal controller product ("Device") which is | ||
| 29 | *      integrated into Licensee's product; or | ||
| 30 | * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h, | ||
| 31 | *		ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device | ||
| 32 | *		used in conjunction with a Microchip ethernet controller for | ||
| 33 | *		the sole purpose of interfacing with the ethernet controller. | ||
| 34 | * | ||
| 35 | * You should refer to the license agreement accompanying this | ||
| 36 | * Software for additional information regarding your rights and | ||
| 37 | * obligations. | ||
| 38 | * | ||
| 39 | * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT | ||
| 40 | * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT | ||
| 41 | * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A | ||
| 42 | * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 43 | * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR | ||
| 44 | * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF | ||
| 45 | * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS | ||
| 46 | * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE | ||
| 47 | * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER | ||
| 48 | * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT | ||
| 49 | * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE. | ||
| 50 | * | ||
| 51 | * | ||
| 52 | * Author               Date    Comment | ||
| 53 | *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 54 | * Nilesh Rajbharti     3/21/01  Original        (Rev 1.0) | ||
| 55 | * Nilesh Rajbharti     7/10/02  Explicitly initialized tempIPAddress | ||
| 56 | *                                               (Rev 2.11) | ||
| 57 | * Nilesh Rajbharti     5/16/03 Increased DHCP_TIMEOUT to 2 seconds. | ||
| 58 | * Nilesh Rajbharti     5/16/03 Fixed SM_DHCP_BROADCAST logic | ||
| 59 | *                              where UDPPut was called before setting | ||
| 60 | *                              active socket. | ||
| 61 | * Robert Sloan         5/29/03 Improved DHCP State machine to handle | ||
| 62 | *                              NAK and renew existing IP address. | ||
| 63 | * Nilesh Rajbharti     8/15/03 Modified _DHCPRecieve() to check for | ||
| 64 | *                              chaddr field before accpting the packet. | ||
| 65 | *                              Fixed DHCPTask() where it would not | ||
| 66 | *                              reply to first OFFER. | ||
| 67 | * Nilesh Rajbharti     3/1/04  Used tickDiff in DHCPTask() "bind" | ||
| 68 | *                              state to adjust for irregular TICK_SECOND | ||
| 69 | *                              Without this logic, actual lease time count | ||
| 70 | *                              down may be incorrect. | ||
| 71 | * Howard Schlunder		5/11/06	Fixed tickDiff usage, reducing  | ||
| 72 | *								accumulated timing error.  Fixed DHCP  | ||
| 73 | *								state machine requesting IP 0.0.0.0  | ||
| 74 | *								after lease expiration. | ||
| 75 | * Howard Schlunder		6/01/06	Added DHCPFlags.bits.bOfferReceived flag to  | ||
| 76 | *								allow operation on networks with multiple | ||
| 77 | *								DHCP servers offering multiple addresses | ||
| 78 | * Howard Schlunder		8/01/06 Added DNS server option to DHCP request,  | ||
| 79 | *								untested Host Name option to DHCP request | ||
| 80 | * Howard Schlunder		1/09/06	Fixed a DHCP renewal not renewing lease time bug | ||
| 81 | * Howard Schlunder		3/16/07 Rewrote DHCP state machine | ||
| 82 | ********************************************************************/ | ||
| 83 | #define __DHCP_C | ||
| 84 | |||
| 85 | #include "TCPIPConfig.h" | ||
| 86 | |||
| 87 | #if defined(STACK_USE_DHCP_CLIENT) | ||
| 88 | |||
| 89 | #include "TCPIP Stack/TCPIP.h" | ||
| 90 | |||
| 91 | // Defines how long to wait before a DHCP request times out | ||
| 92 | #define DHCP_TIMEOUT				(2ul*TICK_SECOND) | ||
| 93 | |||
| 94 | // Unique variables per interface | ||
| 95 | typedef struct | ||
| 96 | { | ||
| 97 | 	UDP_SOCKET			hDHCPSocket;	// Handle to DHCP client socket | ||
| 98 | 	SM_DHCP				smState;		// DHCP client state machine variable | ||
| 99 | 	union | ||
| 100 | 	{ | ||
| 101 | 	    struct | ||
| 102 | 	    { | ||
| 103 | 	        unsigned char bIsBound : 1;				// Whether or not DHCP is currently bound | ||
| 104 | 	        unsigned char bEvent : 1;				// Indicates to an external module that the DHCP client has been reset, has obtained new parameters via the DHCP client, or has refreshed a lease on existing ones | ||
| 105 | 	        unsigned char bOfferReceived : 1;		// Whether or not an offer has been received | ||
| 106 | 			unsigned char bDHCPServerDetected : 1;	// Indicates if a DCHP server has been detected | ||
| 107 | 			unsigned char bUseUnicastMode : 1;		// Indicates if the  | ||
| 108 | 	    } bits; | ||
| 109 | 	    BYTE val; | ||
| 110 | 	} flags; | ||
| 111 | 	DWORD 				dwTimer;		// Tick timer value used for triggering future events after a certain wait period. | ||
| 112 | 	DWORD				dwLeaseTime;	// DHCP lease time remaining, in seconds | ||
| 113 | 	DWORD				dwServerID;		// DHCP Server ID cache | ||
| 114 | 	IP_ADDR				tempIPAddress;	// Temporary IP address to use when no DHCP lease | ||
| 115 | 	IP_ADDR				tempGateway;	// Temporary gateway to use when no DHCP lease | ||
| 116 | 	IP_ADDR				tempMask;		// Temporary mask to use when no DHCP lease | ||
| 117 | 	#if defined(STACK_USE_DNS) | ||
| 118 | 	IP_ADDR				tempDNS;		// Temporary primary DNS server | ||
| 119 | 	IP_ADDR				tempDNS2;		// Temporary secondary DNS server | ||
| 120 | 	#endif	 | ||
| 121 | 	// Indicates which DHCP values are currently valid | ||
| 122 | 	union | ||
| 123 | 	{ | ||
| 124 | 		struct | ||
| 125 | 		{ | ||
| 126 | 			char IPAddress:1;	// Leased IP address is valid | ||
| 127 | 			char Gateway:1;		// Gateway address is valid | ||
| 128 | 			char Mask:1;		// Subnet mask is valid | ||
| 129 | 			char DNS:1;			// Primary DNS is valid | ||
| 130 | 			char DNS2:1;		// Secondary DNS is valid | ||
| 131 | 			char HostName:1;	// Host name is valid (not implemented) | ||
| 132 | 		} bits; | ||
| 133 | 		BYTE val; | ||
| 134 | 	} validValues; | ||
| 135 | } DHCP_CLIENT_VARS; | ||
| 136 | |||
| 137 | BOOL DHCPClientInitializedOnce = FALSE; | ||
| 138 | |||
| 139 | static BYTE _DHCPReceive(void); | ||
| 140 | static void _DHCPSend(BYTE messageType, BOOL bRenewing); | ||
| 141 | |||
| 142 | |||
| 143 | /***************************************************************************** | ||
| 144 |   Function: | ||
| 145 | 	static void LoadState(BYTE vInterface) | ||
| 146 | |||
| 147 |   Summary: | ||
| 148 | 	Saves the DHCPClient state information structure to the appropriate  | ||
| 149 | 	location and loads DHCPClient with the state information for the specified  | ||
| 150 | 	interface. | ||
| 151 | |||
| 152 |   Description: | ||
| 153 | 	Saves the DHCPClient state information structure to the appropriate  | ||
| 154 | 	location and loads DHCPClient with the state information for the specified  | ||
| 155 | 	interface. | ||
| 156 | |||
| 157 |   Precondition: | ||
| 158 | 	None | ||
| 159 | |||
| 160 |   Parameters: | ||
| 161 | 	None | ||
| 162 | |||
| 163 |   Returns: | ||
| 164 | 	None | ||
| 165 | |||
| 166 |   Remarks: | ||
| 167 |   	This function does nothing when you only have one physical interface. | ||
| 168 | ***************************************************************************/ | ||
| 169 | #if NETWORK_INTERFACES > 1 | ||
| 170 | |||
| 171 | static DHCP_CLIENT_VARS	DHCPClients[NETWORK_INTERFACES]; | ||
| 172 | static DHCP_CLIENT_VARS	*SelectedDHCPClient; | ||
| 173 | #define DHCPClient		(*SelectedDHCPClient) | ||
| 174 | #define LoadState(v)	do(SelectedDHCPClient = &DHCPClients[v])while(0) | ||
| 175 | |||
| 176 | #else | ||
| 177 | |||
| 178 | static DHCP_CLIENT_VARS DHCPClient; | ||
| 179 | #define LoadState(v) | ||
| 180 | |||
| 181 | #endif | ||
| 182 | |||
| 183 | |||
| 184 | /***************************************************************************** | ||
| 185 |   Function: | ||
| 186 | 	void DHCPInit(BYTE vInterface) | ||
| 187 | |||
| 188 |   Summary: | ||
| 189 | 	Resets the DHCP client module for the specified interface. | ||
| 190 | |||
| 191 |   Description: | ||
| 192 | 	Resets the DHCP client module, giving up any current lease, knowledge of  | ||
| 193 | 	DHCP servers, etc. for the specified interface. | ||
| 194 | |||
| 195 |   Precondition: | ||
| 196 | 	None | ||
| 197 | |||
| 198 |   Parameters: | ||
| 199 | 	vInterface - Interface number to initialize DHCP client state variables  | ||
| 200 | 		for.   If you only have one interface, specify 0x00. | ||
| 201 | |||
| 202 |   Returns: | ||
| 203 | 	None | ||
| 204 | |||
| 205 |   Remarks: | ||
| 206 | 	This function may be called multiple times throughout the life of the  | ||
| 207 | 	application, if desired.   | ||
| 208 | ***************************************************************************/ | ||
| 209 | void DHCPInit(BYTE vInterface) | ||
| 210 | { | ||
| 211 | 	BYTE i; | ||
| 212 | |||
| 213 | 	// Upon the first call after POR, we must reset all handles to invalid so  | ||
| 214 | 	// that we don't inadvertently close someone else's handle. | ||
| 215 | 	if(!DHCPClientInitializedOnce) | ||
| 216 | 	{ | ||
| 217 | 		DHCPClientInitializedOnce = TRUE; | ||
| 218 | 		for(i = 0; i < NETWORK_INTERFACES; i++) | ||
| 219 | 		{ | ||
| 220 | 			LoadState(i); | ||
| 221 | 			DHCPClient.hDHCPSocket = INVALID_UDP_SOCKET; | ||
| 222 | 		}		 | ||
| 223 | 	} | ||
| 224 | |||
| 225 | |||
| 226 | 	LoadState(vInterface); | ||
| 227 | |||
| 228 | 	if(DHCPClient.hDHCPSocket != INVALID_UDP_SOCKET) | ||
| 229 | 	{ | ||
| 230 | 		UDPClose(DHCPClient.hDHCPSocket); | ||
| 231 | 		DHCPClient.hDHCPSocket = INVALID_UDP_SOCKET; | ||
| 232 | 	} | ||
| 233 | |||
| 234 | 	// Reset state machine and flags to default values | ||
| 235 | 	DHCPClient.smState = SM_DHCP_GET_SOCKET; | ||
| 236 | 	DHCPClient.flags.val = 0; | ||
| 237 | 	DHCPClient.flags.bits.bUseUnicastMode = TRUE;	// This flag toggles before use, so this statement actually means to start out using broadcast mode. | ||
| 238 | 	DHCPClient.flags.bits.bEvent = TRUE; | ||
| 239 | } | ||
| 240 | |||
| 241 | |||
| 242 | /***************************************************************************** | ||
| 243 |   Function: | ||
| 244 | 	void DHCPDisable(BYTE vInterface) | ||
| 245 | |||
| 246 |   Summary: | ||
| 247 | 	Disables the DHCP Client for the specified interface. | ||
| 248 | |||
| 249 |   Description: | ||
| 250 | 	Disables the DHCP client for the specified interface by sending the state  | ||
| 251 | 	machine to "SM_DHCP_DISABLED".  If the interface was previously configured  | ||
| 252 | 	by DHCP, the configuration will continue to be used but the module will no  | ||
| 253 | 	longer preform any renewals. | ||
| 254 | |||
| 255 |   Precondition: | ||
| 256 | 	None | ||
| 257 | |||
| 258 |   Parameters: | ||
| 259 | 	vInterface - Interface number to disable the DHCP client on.   If you only  | ||
| 260 | 		have one interface, specify 0x00. | ||
| 261 | |||
| 262 |   Returns: | ||
| 263 | 	None | ||
| 264 | |||
| 265 |   Remarks: | ||
| 266 | 	Since the interface continues using its old configuration, it is possible  | ||
| 267 | 	that the lease may expire and the DHCP server provide the IP to another | ||
| 268 | 	client.  The application should replace the current IP address and other | ||
| 269 | 	configuration with static information following a call to this function. | ||
| 270 | ***************************************************************************/ | ||
| 271 | void DHCPDisable(BYTE vInterface) | ||
| 272 | { | ||
| 273 | 	LoadState(vInterface); | ||
| 274 | |||
| 275 | 	if(DHCPClient.hDHCPSocket != INVALID_UDP_SOCKET) | ||
| 276 | 	{ | ||
| 277 | 		UDPClose(DHCPClient.hDHCPSocket); | ||
| 278 | 		DHCPClient.hDHCPSocket = INVALID_UDP_SOCKET; | ||
| 279 | 	} | ||
| 280 | |||
| 281 | 	DHCPClient.smState = SM_DHCP_DISABLED; | ||
| 282 | } | ||
| 283 | |||
| 284 | |||
| 285 | /***************************************************************************** | ||
| 286 |   Function: | ||
| 287 | 	void DHCPEnable(BYTE vInterface) | ||
| 288 | |||
| 289 |   Summary: | ||
| 290 | 	Enables the DHCP client for the specified interface. | ||
| 291 | |||
| 292 |   Description: | ||
| 293 | 	Enables the DHCP client for the specified interface, if it is disabled.   | ||
| 294 | 	If it is already enabled, nothing is done. | ||
| 295 | |||
| 296 |   Precondition: | ||
| 297 | 	None | ||
| 298 | |||
| 299 |   Parameters: | ||
| 300 | 	vInterface - Interface number to enable the DHCP client on.   If you only  | ||
| 301 | 		have one interface, specify 0x00. | ||
| 302 | |||
| 303 |   Returns: | ||
| 304 | 	None | ||
| 305 | ***************************************************************************/ | ||
| 306 | void DHCPEnable(BYTE vInterface) | ||
| 307 | { | ||
| 308 | 	LoadState(vInterface); | ||
| 309 | |||
| 310 | 	if(DHCPClient.smState == SM_DHCP_DISABLED) | ||
| 311 | 	{ | ||
| 312 | 		DHCPClient.smState = SM_DHCP_GET_SOCKET; | ||
| 313 | 		DHCPClient.flags.bits.bIsBound = FALSE; | ||
| 314 | 	} | ||
| 315 | } | ||
| 316 | |||
| 317 | /***************************************************************************** | ||
| 318 |   Function: | ||
| 319 | 	BOOL DHCPIsEnabled(BYTE vInterface) | ||
| 320 | |||
| 321 |   Summary: | ||
| 322 | 	Determins if the DHCP client is enabled on the specified interface. | ||
| 323 | |||
| 324 |   Description: | ||
| 325 | 	Determins if the DHCP client is enabled on the specified interface. | ||
| 326 | |||
| 327 |   Precondition: | ||
| 328 | 	None | ||
| 329 | |||
| 330 |   Parameters: | ||
| 331 | 	vInterface - Interface number to query.   If you only have one interface,  | ||
| 332 | 		specify 0x00. | ||
| 333 | |||
| 334 |   Returns: | ||
| 335 | 	None | ||
| 336 | ***************************************************************************/ | ||
| 337 | BOOL DHCPIsEnabled(BYTE vInterface) | ||
| 338 | { | ||
| 339 | 	LoadState(vInterface); | ||
| 340 | 	return DHCPClient.smState != SM_DHCP_DISABLED; | ||
| 341 | } | ||
| 342 | |||
| 343 | |||
| 344 | /***************************************************************************** | ||
| 345 |   Function: | ||
| 346 | 	BOOL DHCPIsBound(BYTE vInterface) | ||
| 347 | |||
| 348 |   Summary: | ||
| 349 | 	Determins if the DHCP client has an IP address lease on the specified  | ||
| 350 | 	interface. | ||
| 351 | |||
| 352 |   Description: | ||
| 353 | 	Determins if the DHCP client has an IP address lease on the specified  | ||
| 354 | 	interface. | ||
| 355 | |||
| 356 |   Precondition: | ||
| 357 | 	None | ||
| 358 | |||
| 359 |   Parameters: | ||
| 360 | 	vInterface - Interface number to query.   If you only have one interface,  | ||
| 361 | 		specify 0x00. | ||
| 362 | |||
| 363 |   Returns: | ||
| 364 | 	TRUE - DHCP client has obtained an IP address lease (and likely other  | ||
| 365 | 		parameters) and these values are currently being used. | ||
| 366 | 	FALSE - No IP address is currently leased | ||
| 367 | ***************************************************************************/ | ||
| 368 | BOOL DHCPIsBound(BYTE vInterface) | ||
| 369 | { | ||
| 370 | 	LoadState(vInterface); | ||
| 371 | 	return DHCPClient.flags.bits.bIsBound; | ||
| 372 | } | ||
| 373 | |||
| 374 | /***************************************************************************** | ||
| 375 |   Function: | ||
| 376 | 	BOOL DHCPStateChanged(BYTE vInterface) | ||
| 377 | |||
| 378 |   Summary: | ||
| 379 | 	Determins if the DHCP client on the specified interface has changed states  | ||
| 380 | 	or refreshed its IP address lease. | ||
| 381 | |||
| 382 |   Description: | ||
| 383 | 	Determins if the DHCP client on the specified interface has changed states  | ||
| 384 | 	or refreshed its IP address lease.  This function can be used to determine | ||
| 385 | 	when to update an LCD or other display whenever the DHCP assigned IP  | ||
| 386 | 	address has potentially changed. | ||
| 387 | |||
| 388 |   Precondition: | ||
| 389 | 	None | ||
| 390 | |||
| 391 |   Parameters: | ||
| 392 | 	vInterface - Interface number to query.   If you only have one interface,  | ||
| 393 | 		specify 0x00. | ||
| 394 | |||
| 395 |   Returns: | ||
| 396 | 	TRUE - The IP address lease have been reliquished (due to reinitilization),  | ||
| 397 | 		obtained (first event), or renewed since the last call to  | ||
| 398 | 		DHCPStateChanged(). | ||
| 399 | 	FALSE - The DHCP client has not detected any changes since the last call to  | ||
| 400 | 		DHCPStateChanged(). | ||
| 401 | ***************************************************************************/ | ||
| 402 | BOOL DHCPStateChanged(BYTE vInterface) | ||
| 403 | { | ||
| 404 | 	LoadState(vInterface); | ||
| 405 | 	if(DHCPClient.flags.bits.bEvent) | ||
| 406 | 	{ | ||
| 407 | 		DHCPClient.flags.bits.bEvent = 0; | ||
| 408 | 		return TRUE; | ||
| 409 | 	} | ||
| 410 | 	return FALSE; | ||
| 411 | } | ||
| 412 | |||
| 413 | |||
| 414 | /***************************************************************************** | ||
| 415 |   Function: | ||
| 416 | 	BOOL DHCPIsServerDetected(BYTE vInterface) | ||
| 417 | |||
| 418 |   Summary: | ||
| 419 | 	Determins if the DHCP client on the specified interface has seen a DHCP  | ||
| 420 | 	server. | ||
| 421 | |||
| 422 |   Description: | ||
| 423 | 	Determins if the DHCP client on the specified interface has seen a DHCP  | ||
| 424 | 	server. | ||
| 425 | |||
| 426 |   Precondition: | ||
| 427 | 	None | ||
| 428 | |||
| 429 |   Parameters: | ||
| 430 | 	vInterface - Interface number to query.   If you only have one interface,  | ||
| 431 | 		specify 0x00. | ||
| 432 | |||
| 433 |   Returns: | ||
| 434 | 	TRUE - At least one DHCP server is attached to the specified network  | ||
| 435 | 		interface. | ||
| 436 | 	FALSE - No DHCP servers are currently detected on the specified network  | ||
| 437 | 		interface. | ||
| 438 | ***************************************************************************/ | ||
| 439 | BOOL DHCPIsServerDetected(BYTE vInterface) | ||
| 440 | { | ||
| 441 | 	LoadState(vInterface); | ||
| 442 | 	return DHCPClient.flags.bits.bDHCPServerDetected; | ||
| 443 | } | ||
| 444 | |||
| 445 | |||
| 446 | /***************************************************************************** | ||
| 447 |   Function: | ||
| 448 | 	void DHCPTask(void) | ||
| 449 | |||
| 450 |   Summary: | ||
| 451 | 	Performs periodic DHCP tasks for all interfaces. | ||
| 452 | |||
| 453 |   Description: | ||
| 454 | 	This function performs any periodic tasks requied by the DHCP module,  | ||
| 455 | 	such as sending and receiving messages involved with obtaining and | ||
| 456 | 	maintaining a lease. | ||
| 457 | |||
| 458 |   Precondition: | ||
| 459 | 	None | ||
| 460 | |||
| 461 |   Parameters: | ||
| 462 | 	None | ||
| 463 | |||
| 464 |   Returns: | ||
| 465 | 	None | ||
| 466 | ***************************************************************************/ | ||
| 467 | void DHCPTask(void) | ||
| 468 | { | ||
| 469 | 	BYTE i; | ||
| 470 | |||
| 471 | 	for(i = 0; i < NETWORK_INTERFACES; i++) | ||
| 472 | 	{ | ||
| 473 | 		LoadState(i); | ||
| 474 | 		switch(DHCPClient.smState) | ||
| 475 | 		{ | ||
| 476 | 			case SM_DHCP_DISABLED: | ||
| 477 | 				// When the module is disabled, do absolutely nothing | ||
| 478 | 				break; | ||
| 479 | |||
| 480 | 			case SM_DHCP_GET_SOCKET: | ||
| 481 | 				// Open a socket to send and receive broadcast messages on | ||
| 482 | 				DHCPClient.hDHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT); | ||
| 483 | 				if(DHCPClient.hDHCPSocket == INVALID_UDP_SOCKET) | ||
| 484 | 					break; | ||
| 485 | |||
| 486 | 				DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; | ||
| 487 | 				// No break | ||
| 488 | |||
| 489 | 			case SM_DHCP_SEND_DISCOVERY: | ||
| 490 | 				// Assume default IP Lease time of 60 seconds. | ||
| 491 | 				// This should be minimum possible to make sure that if the | ||
| 492 | 				// server did not specify lease time, we try again after this  | ||
| 493 | 				// minimum time. | ||
| 494 | 				DHCPClient.dwLeaseTime = 60; | ||
| 495 | 				DHCPClient.validValues.val = 0x00; | ||
| 496 | 				DHCPClient.flags.bits.bIsBound = FALSE;	 | ||
| 497 | 				DHCPClient.flags.bits.bOfferReceived = FALSE; | ||
| 498 | |||
| 499 | 				// No point in wasting time transmitting a discovery if we are  | ||
| 500 | 				// unlinked.  No one will see it.   | ||
| 501 | 				if(!MACIsLinked()) | ||
| 502 | 					break; | ||
| 503 | |||
| 504 | 				// Ensure transmitter is ready to accept data | ||
| 505 | 				if(UDPIsPutReady(DHCPClient.hDHCPSocket) < 300u) | ||
| 506 | 					break; | ||
| 507 | |||
| 508 | 				// Toggle the BOOTP Broadcast flag to ensure compatibility with  | ||
| 509 | 				// bad DHCP servers that don't know how to handle broadcast  | ||
| 510 | 				// responses.  This results in the next discovery attempt to be  | ||
| 511 | 				// made using the opposite mode. | ||
| 512 | 				DHCPClient.flags.bits.bUseUnicastMode ^= 1; | ||
| 513 | |||
| 514 | 				// Ensure that we transmit to the broadcast IP and MAC addresses | ||
| 515 | 				// The UDP Socket remembers who it was last talking to | ||
| 516 | 				memset((void*)&UDPSocketInfo[DHCPClient.hDHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[0].remoteNode)); | ||
| 517 | |||
| 518 | 				// Send the DHCP Discover broadcast | ||
| 519 | 				_DHCPSend(DHCP_DISCOVER_MESSAGE, FALSE); | ||
| 520 | |||
| 521 | 				// Start a timer and begin looking for a response | ||
| 522 | 				DHCPClient.dwTimer = TickGet(); | ||
| 523 | 				DHCPClient.smState = SM_DHCP_GET_OFFER; | ||
| 524 | 				break; | ||
| 525 | |||
| 526 | 			case SM_DHCP_GET_OFFER: | ||
| 527 | 				// Check to see if a packet has arrived | ||
| 528 | 				if(UDPIsGetReady(DHCPClient.hDHCPSocket) < 250u) | ||
| 529 | 				{ | ||
| 530 | 					// Go back and transmit a new discovery if we didn't get an offer after 2 seconds | ||
| 531 | 					if(TickGet() - DHCPClient.dwTimer >= DHCP_TIMEOUT) | ||
| 532 | 						DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; | ||
| 533 | 					break; | ||
| 534 | 				} | ||
| 535 | |||
| 536 | 				// Let the DHCP server module know that there is a DHCP server  | ||
| 537 | 				// on this network | ||
| 538 | 				DHCPClient.flags.bits.bDHCPServerDetected = TRUE; | ||
| 539 | |||
| 540 | 				// Check to see if we received an offer | ||
| 541 | 				if(_DHCPReceive() != DHCP_OFFER_MESSAGE) | ||
| 542 | 					break; | ||
| 543 | |||
| 544 | 				DHCPClient.smState = SM_DHCP_SEND_REQUEST; | ||
| 545 | 				// No break | ||
| 546 | |||
| 547 | 			case SM_DHCP_SEND_REQUEST: | ||
| 548 | 				if(UDPIsPutReady(DHCPClient.hDHCPSocket) < 258u) | ||
| 549 | 					break; | ||
| 550 | |||
| 551 | 				// Ensure that we transmit to the broadcast IP and MAC addresses | ||
| 552 | 				// The UDP Socket remembers who it was last talking to, so  | ||
| 553 | 				// we must set this back to the broadcast address since the  | ||
| 554 | 				// current socket values are the unicast addresses of the DHCP  | ||
| 555 | 				// server. | ||
| 556 | 				memset((void*)&UDPSocketInfo[DHCPClient.hDHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[0].remoteNode)); | ||
| 557 | |||
| 558 | 				// Send the DHCP request message | ||
| 559 | 				_DHCPSend(DHCP_REQUEST_MESSAGE, FALSE); | ||
| 560 | |||
| 561 | 				// Start a timer and begin looking for a response | ||
| 562 | 				DHCPClient.dwTimer = TickGet(); | ||
| 563 | 				DHCPClient.smState = SM_DHCP_GET_REQUEST_ACK; | ||
| 564 | 				break; | ||
| 565 | |||
| 566 | 			case SM_DHCP_GET_REQUEST_ACK: | ||
| 567 | 				// Check to see if a packet has arrived | ||
| 568 | 				if(UDPIsGetReady(DHCPClient.hDHCPSocket) < 250u) | ||
| 569 | 				{ | ||
| 570 | 					// Go back and transmit a new discovery if we didn't get an ACK after 2 seconds | ||
| 571 | 					if(TickGet() - DHCPClient.dwTimer >= DHCP_TIMEOUT) | ||
| 572 | 						DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; | ||
| 573 | 					break; | ||
| 574 | 				} | ||
| 575 | |||
| 576 | 				// Check to see if we received an offer | ||
| 577 | 				switch(_DHCPReceive()) | ||
| 578 | 				{ | ||
| 579 | 					case DHCP_ACK_MESSAGE: | ||
| 580 | 						UDPClose(DHCPClient.hDHCPSocket); | ||
| 581 | 						DHCPClient.hDHCPSocket = INVALID_UDP_SOCKET; | ||
| 582 | 						DHCPClient.dwTimer = TickGet(); | ||
| 583 | 						DHCPClient.smState = SM_DHCP_BOUND; | ||
| 584 | 						DHCPClient.flags.bits.bEvent = 1; | ||
| 585 | 						DHCPClient.flags.bits.bIsBound = TRUE;	 | ||
| 586 | |||
| 587 | 						if(DHCPClient.validValues.bits.IPAddress) | ||
| 588 | 							AppConfig.MyIPAddr = DHCPClient.tempIPAddress; | ||
| 589 | 						if(DHCPClient.validValues.bits.Mask) | ||
| 590 | 							AppConfig.MyMask = DHCPClient.tempMask; | ||
| 591 | 						if(DHCPClient.validValues.bits.Gateway) | ||
| 592 | 							AppConfig.MyGateway = DHCPClient.tempGateway; | ||
| 593 | 						#if defined(STACK_USE_DNS) | ||
| 594 | 							if(DHCPClient.validValues.bits.DNS) | ||
| 595 | 								AppConfig.PrimaryDNSServer.Val = DHCPClient.tempDNS.Val; | ||
| 596 | 							AppConfig.SecondaryDNSServer.Val = 0x00000000ul; | ||
| 597 | 							if(DHCPClient.validValues.bits.DNS2) | ||
| 598 | 								AppConfig.SecondaryDNSServer.Val = DHCPClient.tempDNS2.Val; | ||
| 599 | 						#endif | ||
| 600 | 						//if(DHCPClient.validValues.bits.HostName) | ||
| 601 | 						//	memcpy(AppConfig.NetBIOSName, (void*)DHCPClient.tempHostName, sizeof(AppConfig.NetBIOSName)); | ||
| 602 | |||
| 603 | 						break; | ||
| 604 | |||
| 605 | 					case DHCP_NAK_MESSAGE: | ||
| 606 | 						DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; | ||
| 607 | 						break; | ||
| 608 | 				} | ||
| 609 | 				break; | ||
| 610 | |||
| 611 | 			case SM_DHCP_BOUND: | ||
| 612 | 				if(TickGet() - DHCPClient.dwTimer < TICK_SECOND) | ||
| 613 | 					break; | ||
| 614 | |||
| 615 | 				// Check to see if our lease is still valid, if so, decrement lease  | ||
| 616 | 				// time | ||
| 617 | 				if(DHCPClient.dwLeaseTime >= 2ul) | ||
| 618 | 				{ | ||
| 619 | 					DHCPClient.dwTimer += TICK_SECOND; | ||
| 620 | 					DHCPClient.dwLeaseTime--; | ||
| 621 | 					break; | ||
| 622 | 				} | ||
| 623 | |||
| 624 | 				// Open a socket to send and receive DHCP messages on | ||
| 625 | 				DHCPClient.hDHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT); | ||
| 626 | 				if(DHCPClient.hDHCPSocket == INVALID_UDP_SOCKET) | ||
| 627 | 					break; | ||
| 628 | |||
| 629 | 				DHCPClient.smState = SM_DHCP_SEND_RENEW; | ||
| 630 | 				// No break | ||
| 631 | |||
| 632 | 			case SM_DHCP_SEND_RENEW: | ||
| 633 | 			case SM_DHCP_SEND_RENEW2: | ||
| 634 | 			case SM_DHCP_SEND_RENEW3: | ||
| 635 | 				if(UDPIsPutReady(DHCPClient.hDHCPSocket) < 258u) | ||
| 636 | 					break; | ||
| 637 | |||
| 638 | 				// Send the DHCP request message | ||
| 639 | 				_DHCPSend(DHCP_REQUEST_MESSAGE, TRUE); | ||
| 640 | 				DHCPClient.flags.bits.bOfferReceived = FALSE; | ||
| 641 | |||
| 642 | 				// Start a timer and begin looking for a response | ||
| 643 | 				DHCPClient.dwTimer = TickGet(); | ||
| 644 | 				DHCPClient.smState++; | ||
| 645 | 				break; | ||
| 646 | |||
| 647 | 			case SM_DHCP_GET_RENEW_ACK: | ||
| 648 | 			case SM_DHCP_GET_RENEW_ACK2: | ||
| 649 | 			case SM_DHCP_GET_RENEW_ACK3: | ||
| 650 | 				// Check to see if a packet has arrived | ||
| 651 | 				if(UDPIsGetReady(DHCPClient.hDHCPSocket) < 250u) | ||
| 652 | 				{ | ||
| 653 | 					// Go back and transmit a new discovery if we didn't get an ACK after 2 seconds | ||
| 654 | 					if(TickGet() - DHCPClient.dwTimer >=  DHCP_TIMEOUT) | ||
| 655 | 					{ | ||
| 656 | 						if(++DHCPClient.smState > SM_DHCP_GET_RENEW_ACK3) | ||
| 657 | 							DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; | ||
| 658 | 					} | ||
| 659 | 					break; | ||
| 660 | 				} | ||
| 661 | |||
| 662 | 				// Check to see if we received an offer | ||
| 663 | 				switch(_DHCPReceive()) | ||
| 664 | 				{ | ||
| 665 | 					case DHCP_ACK_MESSAGE: | ||
| 666 | 						UDPClose(DHCPClient.hDHCPSocket); | ||
| 667 | 						DHCPClient.hDHCPSocket = INVALID_UDP_SOCKET; | ||
| 668 | 						DHCPClient.dwTimer = TickGet(); | ||
| 669 | 						DHCPClient.smState = SM_DHCP_BOUND; | ||
| 670 | 						DHCPClient.flags.bits.bEvent = 1; | ||
| 671 | 						break; | ||
| 672 | |||
| 673 | 					case DHCP_NAK_MESSAGE: | ||
| 674 | 						DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; | ||
| 675 | 						break; | ||
| 676 | 				} | ||
| 677 | 				break; | ||
| 678 | 		} | ||
| 679 | 	} | ||
| 680 | } | ||
| 681 | |||
| 682 | |||
| 683 | |||
| 684 | /***************************************************************************** | ||
| 685 | Function: | ||
| 686 |   void _DHCPReceive(void) | ||
| 687 | |||
| 688 | Description: | ||
| 689 |   Receives and parses a DHCP message. | ||
| 690 | |||
| 691 | Precondition: | ||
| 692 |   A DHCP message is waiting in the UDP buffer. | ||
| 693 | |||
| 694 | Parameters: | ||
| 695 |   None | ||
| 696 | |||
| 697 | Returns: | ||
| 698 |   One of the DCHP_TYPE* contants. | ||
| 699 | ***************************************************************************/ | ||
| 700 | static BYTE _DHCPReceive(void) | ||
| 701 | { | ||
| 702 | 	/********************************************************************* | ||
| 703 | 	DHCP PACKET FORMAT AS PER RFC 1541 | ||
| 704 | |||
| 705 | |||
| 706 | |||
| 707 | 	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
| 708 | 	|     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    | | ||
| 709 | 	+---------------+---------------+---------------+---------------+ | ||
| 710 | 	|                            xid (4)                            | | ||
| 711 | 	+-------------------------------+-------------------------------+ | ||
| 712 | 	|           secs (2)            |           flags (2)           | | ||
| 713 | 	+-------------------------------+-------------------------------+ | ||
| 714 | 	|                          ciaddr  (4)                          | | ||
| 715 | 	+---------------------------------------------------------------+ | ||
| 716 | 	|                          yiaddr  (4)                          | | ||
| 717 | 	+---------------------------------------------------------------+ | ||
| 718 | 	|                          siaddr  (4)                          | | ||
| 719 | 	+---------------------------------------------------------------+ | ||
| 720 | 	|                          giaddr  (4)                          | | ||
| 721 | 	+---------------------------------------------------------------+ | ||
| 722 | 	|                                                               | | ||
| 723 | 	|                          chaddr  (16)                         | | ||
| 724 | 	|                                                               | | ||
| 725 | 	|                                                               | | ||
| 726 | 	+---------------------------------------------------------------+ | ||
| 727 | 	|                                                               | | ||
| 728 | 	|                          sname   (64)                         | | ||
| 729 | 	+---------------------------------------------------------------+ | ||
| 730 | 	|                                                               | | ||
| 731 | 	|                          file    (128)                        | | ||
| 732 | 	+---------------------------------------------------------------+ | ||
| 733 | 	|                                                               | | ||
| 734 | 	|                          options (312)                        | | ||
| 735 | 	+---------------------------------------------------------------+ | ||
| 736 | |||
| 737 | 	********************************************************************/ | ||
| 738 | 	BYTE v; | ||
| 739 | 	BYTE i, j; | ||
| 740 | 	BYTE type; | ||
| 741 | 	BOOL lbDone; | ||
| 742 | 	DWORD tempServerID; | ||
| 743 | |||
| 744 | |||
| 745 | 	// Assume unknown message until proven otherwise. | ||
| 746 | 	type = DHCP_UNKNOWN_MESSAGE; | ||
| 747 | |||
| 748 | 	UDPGet(&v);                             // op | ||
| 749 | |||
| 750 | 	// Make sure this is BOOT_REPLY. | ||
| 751 | 	if ( v == BOOT_REPLY ) | ||
| 752 | 	{ | ||
| 753 | 		// Jump to chaddr field (Client Hardware Address -- our MAC address for  | ||
| 754 | 		// Ethernet and WiFi networks) and verify that this message is directed  | ||
| 755 | 		// to us before doing any other processing. | ||
| 756 | 		UDPSetRxBuffer(28);		// chaddr field is at offset 28 in the UDP packet payload -- see DHCP packet format above | ||
| 757 | 		for ( i = 0; i < 6u; i++ ) | ||
| 758 | 		{ | ||
| 759 | 			UDPGet(&v); | ||
| 760 | 			if ( v != AppConfig.MyMACAddr.v[i]) | ||
| 761 | 				goto UDPInvalid; | ||
| 762 | 		} | ||
| 763 | |||
| 764 | 		// Check to see if this is the first offer.  If it is, record its  | ||
| 765 | 		// yiaddr value ("Your (client) IP address") so that we can REQUEST to  | ||
| 766 | 		// use it later. | ||
| 767 | 		if(!DHCPClient.flags.bits.bOfferReceived) | ||
| 768 | 		{ | ||
| 769 | 			UDPSetRxBuffer(16); | ||
| 770 | 			UDPGetArray((BYTE*)&DHCPClient.tempIPAddress, sizeof(DHCPClient.tempIPAddress)); | ||
| 771 | 			DHCPClient.validValues.bits.IPAddress = 1; | ||
| 772 | 		} | ||
| 773 | |||
| 774 | 		// Jump to DHCP options (ignore htype, hlen, hops, xid, secs, flags,  | ||
| 775 | 		// ciaddr, siaddr, giaddr, padding part of chaddr, sname, file, magic  | ||
| 776 | 		// cookie fields) | ||
| 777 | 		UDPSetRxBuffer(240); | ||
| 778 | |||
| 779 | 		lbDone = FALSE; | ||
| 780 | 		do | ||
| 781 | 		{ | ||
| 782 | 			// Get the Option number | ||
| 783 | 			// Break out eventually in case if this is a malformed  | ||
| 784 | 			// DHCP message, ie: missing DHCP_END_OPTION marker | ||
| 785 | 			if(!UDPGet(&v)) | ||
| 786 | 			{ | ||
| 787 | 				lbDone = TRUE; | ||
| 788 | 				break; | ||
| 789 | 			} | ||
| 790 | |||
| 791 | 			switch(v) | ||
| 792 | 			{ | ||
| 793 | 				case DHCP_MESSAGE_TYPE: | ||
| 794 | 					UDPGet(&v);                         // Skip len | ||
| 795 | 					// Len must be 1. | ||
| 796 | 					if ( v == 1u ) | ||
| 797 | 					{ | ||
| 798 | 						UDPGet(&type);                  // Get type | ||
| 799 | |||
| 800 | 						// Throw away the packet if we know we don't need it (ie: another offer when we already have one) | ||
| 801 | 						if(DHCPClient.flags.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE)) | ||
| 802 | 						{ | ||
| 803 | 							goto UDPInvalid; | ||
| 804 | 						} | ||
| 805 | 					} | ||
| 806 | 					else | ||
| 807 | 						goto UDPInvalid; | ||
| 808 | 					break; | ||
| 809 | |||
| 810 | 				case DHCP_SUBNET_MASK: | ||
| 811 | 					UDPGet(&v);                     // Skip len | ||
| 812 | 					// Len must be 4. | ||
| 813 | 					if ( v == 4u ) | ||
| 814 | 					{ | ||
| 815 | 						// Check to see if this is the first offer | ||
| 816 | 						if(DHCPClient.flags.bits.bOfferReceived) | ||
| 817 | 						{ | ||
| 818 | 							// Discard offered IP mask, we already have an offer | ||
| 819 | 							for ( i = 0; i < 4u; i++ ) | ||
| 820 | 								UDPGet(&v); | ||
| 821 | 						} | ||
| 822 | 						else | ||
| 823 | 						{ | ||
| 824 | 							UDPGetArray((BYTE*)&DHCPClient.tempMask, sizeof(DHCPClient.tempMask)); | ||
| 825 | 							DHCPClient.validValues.bits.Mask = 1; | ||
| 826 | 						} | ||
| 827 | 					} | ||
| 828 | 					else | ||
| 829 | 						goto UDPInvalid; | ||
| 830 | 					break; | ||
| 831 | |||
| 832 | 				case DHCP_ROUTER: | ||
| 833 | 					UDPGet(&j); | ||
| 834 | 					// Len must be >= 4. | ||
| 835 | 					if ( j >= 4u ) | ||
| 836 | 					{ | ||
| 837 | 						// Check to see if this is the first offer | ||
| 838 | 						if(DHCPClient.flags.bits.bOfferReceived) | ||
| 839 | 						{ | ||
| 840 | 							// Discard offered Gateway address, we already have an offer | ||
| 841 | 							for ( i = 0; i < 4u; i++ ) | ||
| 842 | 								UDPGet(&v); | ||
| 843 | 						} | ||
| 844 | 						else | ||
| 845 | 						{ | ||
| 846 | 							UDPGetArray((BYTE*)&DHCPClient.tempGateway, sizeof(DHCPClient.tempGateway)); | ||
| 847 | 							DHCPClient.validValues.bits.Gateway = 1; | ||
| 848 | 						} | ||
| 849 | 					} | ||
| 850 | 					else | ||
| 851 | 						goto UDPInvalid; | ||
| 852 | |||
| 853 | 					// Discard any other router addresses. | ||
| 854 | 					j -= 4; | ||
| 855 | 					while(j--) | ||
| 856 | 						UDPGet(&v); | ||
| 857 | 					break; | ||
| 858 | |||
| 859 | 				#if defined(STACK_USE_DNS) | ||
| 860 | 				case DHCP_DNS: | ||
| 861 | 					UDPGet(&j); | ||
| 862 | 					// Len must be >= 4. | ||
| 863 | 					if(j < 4u) | ||
| 864 | 						goto UDPInvalid; | ||
| 865 | |||
| 866 | 					// Check to see if this is the first offer | ||
| 867 | 					if(!DHCPClient.flags.bits.bOfferReceived) | ||
| 868 | 					{ | ||
| 869 | 						UDPGetArray((BYTE*)&DHCPClient.tempDNS, sizeof(DHCPClient.tempDNS)); | ||
| 870 | 						DHCPClient.validValues.bits.DNS = 1; | ||
| 871 | 						j -= 4; | ||
| 872 | 					} | ||
| 873 | |||
| 874 | 					// Len must be >= 4 for a secondary DNS server address | ||
| 875 | 					if(j >= 4u) | ||
| 876 | 					{ | ||
| 877 | 						// Check to see if this is the first offer | ||
| 878 | 						if(!DHCPClient.flags.bits.bOfferReceived) | ||
| 879 | 						{ | ||
| 880 | 							UDPGetArray((BYTE*)&DHCPClient.tempDNS2, sizeof(DHCPClient.tempDNS2)); | ||
| 881 | 							DHCPClient.validValues.bits.DNS2 = 1; | ||
| 882 | 							j -= 4; | ||
| 883 | 						} | ||
| 884 | 					} | ||
| 885 | |||
| 886 | 					// Discard any other DNS server addresses | ||
| 887 | 					while(j--) | ||
| 888 | 						UDPGet(&v); | ||
| 889 | 					break; | ||
| 890 | 				#endif | ||
| 891 | |||
| 892 | 					//            case DHCP_HOST_NAME: | ||
| 893 | 					//                UDPGet(&j); | ||
| 894 | 					//                // Len must be >= 4. | ||
| 895 | 					//                if(j < 1u) | ||
| 896 | 					//					goto UDPInvalid; | ||
| 897 | 					// | ||
| 898 | 					//				// Check to see if this is the first offer | ||
| 899 | 					//				if(DHCPFlags.bits.bOfferReceived) | ||
| 900 | 					//				{ | ||
| 901 | 					//			        // Discard offered host name, we already have an offer | ||
| 902 | 					//	                while(j--) | ||
| 903 | 					//	                    UDPGet(&v); | ||
| 904 | 					//				} | ||
| 905 | 					//				else | ||
| 906 | 					//				{ | ||
| 907 | 					//					for(i = 0; j, i < sizeof(tempHostName); i++, j--) | ||
| 908 | 					//					{ | ||
| 909 | 					//						UDPGet(&tempHostName[i]); | ||
| 910 | 					//					} | ||
| 911 | 					//					while(j--) | ||
| 912 | 					//					{ | ||
| 913 | 					//						UDPGet(&v); | ||
| 914 | 					//					} | ||
| 915 | 					//					ValidValues.bits.HostName = 1; | ||
| 916 | 					//				} | ||
| 917 | 					// | ||
| 918 | 					//                break; | ||
| 919 | |||
| 920 | 				case DHCP_SERVER_IDENTIFIER: | ||
| 921 | 					UDPGet(&v);                         // Get len | ||
| 922 | 					// Len must be 4. | ||
| 923 | 					if ( v == 4u ) | ||
| 924 | 					{ | ||
| 925 | 						UDPGet(&(((BYTE*)&tempServerID)[3]));   // Get the id | ||
| 926 | 						UDPGet(&(((BYTE*)&tempServerID)[2])); | ||
| 927 | 						UDPGet(&(((BYTE*)&tempServerID)[1])); | ||
| 928 | 						UDPGet(&(((BYTE*)&tempServerID)[0])); | ||
| 929 | 					} | ||
| 930 | 					else | ||
| 931 | 						goto UDPInvalid; | ||
| 932 | 					break; | ||
| 933 | |||
| 934 | 				case DHCP_END_OPTION: | ||
| 935 | 					lbDone = TRUE; | ||
| 936 | 					break; | ||
| 937 | |||
| 938 | 				case DHCP_IP_LEASE_TIME: | ||
| 939 | 					UDPGet(&v);                         // Get len | ||
| 940 | 					// Len must be 4. | ||
| 941 | 					if ( v == 4u ) | ||
| 942 | 					{ | ||
| 943 | 						// Check to see if this is the first offer | ||
| 944 | 						if(DHCPClient.flags.bits.bOfferReceived) | ||
| 945 | 						{ | ||
| 946 | 							// Discard offered lease time, we already have an offer | ||
| 947 | 							for ( i = 0; i < 4u; i++ ) | ||
| 948 | 								UDPGet(&v); | ||
| 949 | 						} | ||
| 950 | 						else | ||
| 951 | 						{ | ||
| 952 | 							UDPGet(&(((BYTE*)(&DHCPClient.dwLeaseTime))[3])); | ||
| 953 | 							UDPGet(&(((BYTE*)(&DHCPClient.dwLeaseTime))[2])); | ||
| 954 | 							UDPGet(&(((BYTE*)(&DHCPClient.dwLeaseTime))[1])); | ||
| 955 | 							UDPGet(&(((BYTE*)(&DHCPClient.dwLeaseTime))[0])); | ||
| 956 | |||
| 957 | 							// In case if our clock is not as accurate as the remote  | ||
| 958 | 							// DHCP server's clock, let's treat the lease time as only  | ||
| 959 | 							// 96.875% of the value given | ||
| 960 | 							DHCPClient.dwLeaseTime -= DHCPClient.dwLeaseTime>>5; | ||
| 961 | 						} | ||
| 962 | 					} | ||
| 963 | 					else | ||
| 964 | 						goto UDPInvalid; | ||
| 965 | 					break; | ||
| 966 | |||
| 967 | 				default: | ||
| 968 | 					// Ignore all unsupport tags. | ||
| 969 | 					UDPGet(&j);                     // Get option len | ||
| 970 | 					while( j-- )                    // Ignore option values | ||
| 971 | 						UDPGet(&v); | ||
| 972 | 			} | ||
| 973 | 		} while( !lbDone ); | ||
| 974 | 	} | ||
| 975 | |||
| 976 | 	// If this is an OFFER message, remember current server id. | ||
| 977 | 	if ( type == DHCP_OFFER_MESSAGE ) | ||
| 978 | 	{ | ||
| 979 | 		DHCPClient.dwServerID = tempServerID; | ||
| 980 | 		DHCPClient.flags.bits.bOfferReceived = TRUE; | ||
| 981 | 	} | ||
| 982 | 	else | ||
| 983 | 	{ | ||
| 984 | 		// For other types of messages, make sure that received | ||
| 985 | 		// server id matches with our previous one. | ||
| 986 | 		if ( DHCPClient.dwServerID != tempServerID ) | ||
| 987 | 			type = DHCP_UNKNOWN_MESSAGE; | ||
| 988 | 	} | ||
| 989 | |||
| 990 | 	UDPDiscard();                             // We are done with this packet | ||
| 991 | 	return type; | ||
| 992 | |||
| 993 | UDPInvalid: | ||
| 994 | 	UDPDiscard(); | ||
| 995 | 	return DHCP_UNKNOWN_MESSAGE; | ||
| 996 | } | ||
| 997 | |||
| 998 | |||
| 999 | |||
| 1000 | |||
| 1001 | /***************************************************************************** | ||
| 1002 |   Function: | ||
| 1003 | 	static void _DHCPSend(BYTE messageType, BOOL bRenewing) | ||
| 1004 | |||
| 1005 |   Description: | ||
| 1006 | 	Sends a DHCP message. | ||
| 1007 | |||
| 1008 |   Precondition: | ||
| 1009 | 	UDP is ready to write a DHCP packet. | ||
| 1010 | |||
| 1011 |   Parameters: | ||
| 1012 | 	messageType - One of the DHCP_TYPE constants | ||
| 1013 | 	bRenewing - Whether or not this is a renewal request | ||
| 1014 | |||
| 1015 |   Returns: | ||
| 1016 | 	None | ||
| 1017 | ***************************************************************************/ | ||
| 1018 | static void _DHCPSend(BYTE messageType, BOOL bRenewing) | ||
| 1019 | { | ||
| 1020 | 	BYTE i; | ||
| 1021 | 	IP_ADDR	MyIP; | ||
| 1022 | |||
| 1023 | |||
| 1024 | 	UDPPut(BOOT_REQUEST);                       // op | ||
| 1025 | 	UDPPut(BOOT_HW_TYPE);                       // htype | ||
| 1026 | 	UDPPut(BOOT_LEN_OF_HW_TYPE);                // hlen | ||
| 1027 | 	UDPPut(0);                                  // hops | ||
| 1028 | 	UDPPut(0x12);                               // xid[0] | ||
| 1029 | 	UDPPut(0x23);                               // xid[1] | ||
| 1030 | 	UDPPut(0x34);                               // xid[2] | ||
| 1031 | 	UDPPut(0x56);                               // xid[3] | ||
| 1032 | 	UDPPut(0);                                  // secs[0] | ||
| 1033 | 	UDPPut(0);                                  // secs[1] | ||
| 1034 | 	UDPPut(DHCPClient.flags.bits.bUseUnicastMode ? 0x00: 0x80);// flags[0] with Broadcast flag clear/set to correspond to bUseUnicastMode | ||
| 1035 | 	UDPPut(0);                                  // flags[1] | ||
| 1036 | |||
| 1037 | 	// If this is DHCP REQUEST message, use previously allocated IP address. | ||
| 1038 | 	if((messageType == DHCP_REQUEST_MESSAGE) && bRenewing) | ||
| 1039 | 	{ | ||
| 1040 | 		UDPPutArray((BYTE*)&DHCPClient.tempIPAddress, sizeof(DHCPClient.tempIPAddress)); | ||
| 1041 | 	} | ||
| 1042 | 	else | ||
| 1043 | 	{ | ||
| 1044 | 		UDPPut(0x00); | ||
| 1045 | 		UDPPut(0x00); | ||
| 1046 | 		UDPPut(0x00); | ||
| 1047 | 		UDPPut(0x00); | ||
| 1048 | 	} | ||
| 1049 | |||
| 1050 | 	// Set yiaddr, siaddr, giaddr as zeros, | ||
| 1051 | 	for ( i = 0; i < 12u; i++ ) | ||
| 1052 | 		UDPPut(0x00); | ||
| 1053 | |||
| 1054 | 	// Load chaddr - Client hardware address. | ||
| 1055 | 	UDPPutArray((BYTE*)&AppConfig.MyMACAddr, sizeof(AppConfig.MyMACAddr)); | ||
| 1056 | |||
| 1057 | 	// Set chaddr[6..15], sname and file as zeros. | ||
| 1058 | 	for ( i = 0; i < 202u; i++ ) | ||
| 1059 | 		UDPPut(0); | ||
| 1060 | |||
| 1061 | 	// Load magic cookie as per RFC 1533. | ||
| 1062 | 	UDPPut(99); | ||
| 1063 | 	UDPPut(130); | ||
| 1064 | 	UDPPut(83); | ||
| 1065 | 	UDPPut(99); | ||
| 1066 | |||
| 1067 | 	// Load message type. | ||
| 1068 | 	UDPPut(DHCP_MESSAGE_TYPE); | ||
| 1069 | 	UDPPut(DHCP_MESSAGE_TYPE_LEN); | ||
| 1070 | 	UDPPut(messageType); | ||
| 1071 | |||
| 1072 | 	if(messageType == DHCP_DISCOVER_MESSAGE) | ||
| 1073 | 	{ | ||
| 1074 | 		// Reset offered flag so we know to act upon the next valid offer | ||
| 1075 | 		DHCPClient.flags.bits.bOfferReceived = FALSE; | ||
| 1076 | 	} | ||
| 1077 | |||
| 1078 | |||
| 1079 | 	if((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing) | ||
| 1080 | 	{ | ||
| 1081 | 		// DHCP REQUEST message must include server identifier the first time | ||
| 1082 | 		// to identify the server we are talking to. | ||
| 1083 | 		// _DHCPReceive() would populate "serverID" when it | ||
| 1084 | 		// receives DHCP OFFER message. We will simply use that | ||
| 1085 | 		// when we are replying to server. | ||
| 1086 | 		// If this is a renwal request, we must not include server id. | ||
| 1087 | 		UDPPut(DHCP_SERVER_IDENTIFIER); | ||
| 1088 | 		UDPPut(DHCP_SERVER_IDENTIFIER_LEN); | ||
| 1089 | 		UDPPut(((BYTE*)(&DHCPClient.dwServerID))[3]); | ||
| 1090 | 		UDPPut(((BYTE*)(&DHCPClient.dwServerID))[2]); | ||
| 1091 | 		UDPPut(((BYTE*)(&DHCPClient.dwServerID))[1]); | ||
| 1092 | 		UDPPut(((BYTE*)(&DHCPClient.dwServerID))[0]); | ||
| 1093 | 	} | ||
| 1094 | |||
| 1095 | 	// Load our interested parameters | ||
| 1096 | 	// This is hardcoded list.  If any new parameters are desired, | ||
| 1097 | 	// new lines must be added here. | ||
| 1098 | 	UDPPut(DHCP_PARAM_REQUEST_LIST); | ||
| 1099 | 	UDPPut(DHCP_PARAM_REQUEST_LIST_LEN); | ||
| 1100 | 	UDPPut(DHCP_SUBNET_MASK); | ||
| 1101 | 	UDPPut(DHCP_ROUTER); | ||
| 1102 | 	UDPPut(DHCP_DNS); | ||
| 1103 | 	UDPPut(DHCP_HOST_NAME); | ||
| 1104 | |||
| 1105 | 	// Add requested IP address to DHCP Request Message | ||
| 1106 | 	if( ((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing) ||  | ||
| 1107 | 		((messageType == DHCP_DISCOVER_MESSAGE) && DHCPClient.tempIPAddress.Val)) | ||
| 1108 | 	{ | ||
| 1109 | 		UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS); | ||
| 1110 | 		UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS_LEN); | ||
| 1111 | 		UDPPutArray((BYTE*)&DHCPClient.tempIPAddress, DHCP_PARAM_REQUEST_IP_ADDRESS_LEN); | ||
| 1112 | 	} | ||
| 1113 | |||
| 1114 | 	// Add any new paramter request here. | ||
| 1115 | |||
| 1116 | 	// End of Options. | ||
| 1117 | 	UDPPut(DHCP_END_OPTION); | ||
| 1118 | |||
| 1119 | 	// Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets) | ||
| 1120 | 	while(UDPTxCount < 300u) | ||
| 1121 | 		UDPPut(0);  | ||
| 1122 | |||
| 1123 | 	// 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. | ||
| 1124 | 	MyIP.Val = AppConfig.MyIPAddr.Val; | ||
| 1125 | 	if(!bRenewing) | ||
| 1126 | 		AppConfig.MyIPAddr.Val = 0x00000000; | ||
| 1127 | 	UDPFlush(); | ||
| 1128 | 	AppConfig.MyIPAddr.Val = MyIP.Val; | ||
| 1129 | |||
| 1130 | } | ||
| 1131 | |||
| 1132 | |||
| 1133 | #endif	//#if defined(STACK_USE_DHCP_CLIENT) | 
Powered by WebSVN v2.8.3