| Line No. | Rev | Author | Line |
|---|---|---|---|
| 1 | 32 | kaklik | /********************************************************************* |
| 2 | * |
||
| 3 | * Dynamic Host Configuration Protocol (DHCP) Server |
||
| 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: DHCPs.c |
||
| 12 | * Dependencies: UDP, ARP, Tick |
||
| 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 | * Howard Schlunder 02/28/07 Original |
||
| 55 | ********************************************************************/ |
||
| 56 | #define __DHCPS_C |
||
| 57 | |||
| 58 | #include "TCPIPConfig.h" |
||
| 59 | |||
| 60 | #if defined(STACK_USE_DHCP_SERVER) |
||
| 61 | |||
| 62 | #include "TCPIP Stack/TCPIP.h" |
||
| 63 | |||
| 64 | // Duration of our DHCP Lease in seconds. This is extrememly short so |
||
| 65 | // the client won't use our IP for long if we inadvertantly |
||
| 66 | // provide a lease on a network that has a more authoratative DHCP server. |
||
| 67 | #define DHCP_LEASE_DURATION 60ul |
||
| 68 | /// Ignore: #define DHCP_MAX_LEASES 2 // Not implemented |
||
| 69 | |||
| 70 | // DHCP Control Block. Lease IP address is derived from index into DCB array. |
||
| 71 | typedef struct |
||
| 72 | { |
||
| 73 | DWORD LeaseExpires; // Expiration time for this lease |
||
| 74 | MAC_ADDR ClientMAC; // Client's MAC address. Multicase bit is used to determine if a lease is given out or not |
||
| 75 | enum |
||
| 76 | { |
||
| 77 | LEASE_UNUSED = 0, |
||
| 78 | LEASE_REQUESTED, |
||
| 79 | LEASE_GRANTED |
||
| 80 | } smLease; // Status of this lease |
||
| 81 | } DHCP_CONTROL_BLOCK; |
||
| 82 | |||
| 83 | static UDP_SOCKET MySocket; // Socket used by DHCP Server |
||
| 84 | static IP_ADDR DHCPNextLease; // IP Address to provide for next lease |
||
| 85 | /// Ignore: static DHCP_CONTROL_BLOCK DCB[DHCP_MAX_LEASES]; // Not Implmented |
||
| 86 | BOOL bDHCPServerEnabled = TRUE; // Whether or not the DHCP server is enabled |
||
| 87 | |||
| 88 | static void DHCPReplyToDiscovery(BOOTP_HEADER *Header); |
||
| 89 | static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept); |
||
| 90 | |||
| 91 | |||
| 92 | /***************************************************************************** |
||
| 93 | Function: |
||
| 94 | void DHCPServerTask(void) |
||
| 95 | |||
| 96 | Summary: |
||
| 97 | Performs periodic DHCP server tasks. |
||
| 98 | |||
| 99 | Description: |
||
| 100 | This function performs any periodic tasks requied by the DHCP server |
||
| 101 | module, such as processing DHCP requests and distributing IP addresses. |
||
| 102 | |||
| 103 | Precondition: |
||
| 104 | None |
||
| 105 | |||
| 106 | Parameters: |
||
| 107 | None |
||
| 108 | |||
| 109 | Returns: |
||
| 110 | None |
||
| 111 | ***************************************************************************/ |
||
| 112 | void DHCPServerTask(void) |
||
| 113 | { |
||
| 114 | BYTE i; |
||
| 115 | BYTE Option, Len; |
||
| 116 | BOOTP_HEADER BOOTPHeader; |
||
| 117 | DWORD dw; |
||
| 118 | BOOL bAccept; |
||
| 119 | static enum |
||
| 120 | { |
||
| 121 | DHCP_OPEN_SOCKET, |
||
| 122 | DHCP_LISTEN |
||
| 123 | } smDHCPServer = DHCP_OPEN_SOCKET; |
||
| 124 | |||
| 125 | #if defined(STACK_USE_ZEROCONF_LINK_LOCAL) |
||
| 126 | static BOOL bLeaseAvailable = TRUE; |
||
| 127 | #endif |
||
| 128 | |||
| 129 | #if defined(STACK_USE_DHCP_CLIENT) |
||
| 130 | // Make sure we don't clobber anyone else's DHCP server |
||
| 131 | if(DHCPIsServerDetected(0)) |
||
| 132 | return; |
||
| 133 | #endif |
||
| 134 | |||
| 135 | if(!bDHCPServerEnabled) |
||
| 136 | return; |
||
| 137 | |||
| 138 | switch(smDHCPServer) |
||
| 139 | { |
||
| 140 | case DHCP_OPEN_SOCKET: |
||
| 141 | // Obtain a UDP socket to listen/transmit on |
||
| 142 | MySocket = UDPOpen(DHCP_SERVER_PORT, NULL, DHCP_CLIENT_PORT); |
||
| 143 | if(MySocket == INVALID_UDP_SOCKET) |
||
| 144 | break; |
||
| 145 | |||
| 146 | |||
| 147 | // Decide which address to lease out |
||
| 148 | // Note that this needs to be changed if we are to |
||
| 149 | // support more than one lease |
||
| 150 | DHCPNextLease.Val = (AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val) + 0x02000000; |
||
| 151 | if(DHCPNextLease.v[3] == 255u) |
||
| 152 | DHCPNextLease.v[3] += 0x03; |
||
| 153 | if(DHCPNextLease.v[3] == 0u) |
||
| 154 | DHCPNextLease.v[3] += 0x02; |
||
| 155 | |||
| 156 | smDHCPServer++; |
||
| 157 | |||
| 158 | case DHCP_LISTEN: |
||
| 159 | // Check to see if a valid DHCP packet has arrived |
||
| 160 | if(UDPIsGetReady(MySocket) < 241u) |
||
| 161 | break; |
||
| 162 | |||
| 163 | // Retrieve the BOOTP header |
||
| 164 | UDPGetArray((BYTE*)&BOOTPHeader, sizeof(BOOTPHeader)); |
||
| 165 | |||
| 166 | bAccept = (BOOTPHeader.ClientIP.Val == DHCPNextLease.Val) || (BOOTPHeader.ClientIP.Val == 0x00000000u); |
||
| 167 | |||
| 168 | // Validate first three fields |
||
| 169 | if(BOOTPHeader.MessageType != 1u) |
||
| 170 | break; |
||
| 171 | if(BOOTPHeader.HardwareType != 1u) |
||
| 172 | break; |
||
| 173 | if(BOOTPHeader.HardwareLen != 6u) |
||
| 174 | break; |
||
| 175 | |||
| 176 | // Throw away 10 unused bytes of hardware address, |
||
| 177 | // server host name, and boot file name -- unsupported/not needed. |
||
| 178 | for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++) |
||
| 179 | UDPGet(&Option); |
||
| 180 | |||
| 181 | // Obtain Magic Cookie and verify |
||
| 182 | UDPGetArray((BYTE*)&dw, sizeof(DWORD)); |
||
| 183 | if(dw != 0x63538263ul) |
||
| 184 | break; |
||
| 185 | |||
| 186 | // Obtain options |
||
| 187 | while(1) |
||
| 188 | { |
||
| 189 | // Get option type |
||
| 190 | if(!UDPGet(&Option)) |
||
| 191 | break; |
||
| 192 | if(Option == DHCP_END_OPTION) |
||
| 193 | break; |
||
| 194 | |||
| 195 | // Get option length |
||
| 196 | UDPGet(&Len); |
||
| 197 | |||
| 198 | // Process option |
||
| 199 | switch(Option) |
||
| 200 | { |
||
| 201 | case DHCP_MESSAGE_TYPE: |
||
| 202 | UDPGet(&i); |
||
| 203 | switch(i) |
||
| 204 | { |
||
| 205 | case DHCP_DISCOVER_MESSAGE: |
||
| 206 | DHCPReplyToDiscovery(&BOOTPHeader); |
||
| 207 | break; |
||
| 208 | |||
| 209 | case DHCP_REQUEST_MESSAGE: |
||
| 210 | #if defined(STACK_USE_ZEROCONF_LINK_LOCAL) |
||
| 211 | if ( (BOOTPHeader.ClientIP.Val == 0x00000000u) && |
||
| 212 | (bLeaseAvailable == FALSE) ) |
||
| 213 | { |
||
| 214 | // Lease available only to the current lease holder |
||
| 215 | break; |
||
| 216 | } |
||
| 217 | #endif |
||
| 218 | |||
| 219 | DHCPReplyToRequest(&BOOTPHeader, bAccept); |
||
| 220 | |||
| 221 | #if defined(STACK_USE_ZEROCONF_LINK_LOCAL) |
||
| 222 | bLeaseAvailable = FALSE; |
||
| 223 | #endif |
||
| 224 | |||
| 225 | break; |
||
| 226 | |||
| 227 | // Need to handle these if supporting more than one DHCP lease |
||
| 228 | case DHCP_RELEASE_MESSAGE: |
||
| 229 | case DHCP_DECLINE_MESSAGE: |
||
| 230 | break; |
||
| 231 | } |
||
| 232 | break; |
||
| 233 | |||
| 234 | case DHCP_PARAM_REQUEST_IP_ADDRESS: |
||
| 235 | if(Len == 4u) |
||
| 236 | { |
||
| 237 | // Get the requested IP address and see if it is the one we have on offer. |
||
| 238 | UDPGetArray((BYTE*)&dw, 4); |
||
| 239 | Len -= 4; |
||
| 240 | bAccept = (dw == DHCPNextLease.Val); |
||
| 241 | } |
||
| 242 | break; |
||
| 243 | |||
| 244 | case DHCP_END_OPTION: |
||
| 245 | UDPDiscard(); |
||
| 246 | return; |
||
| 247 | } |
||
| 248 | |||
| 249 | // Remove any unprocessed bytes that we don't care about |
||
| 250 | while(Len--) |
||
| 251 | { |
||
| 252 | UDPGet(&i); |
||
| 253 | } |
||
| 254 | } |
||
| 255 | |||
| 256 | UDPDiscard(); |
||
| 257 | break; |
||
| 258 | } |
||
| 259 | } |
||
| 260 | |||
| 261 | |||
| 262 | /***************************************************************************** |
||
| 263 | Function: |
||
| 264 | static void DHCPReplyToDiscovery(BOOTP_HEADER *Header) |
||
| 265 | |||
| 266 | Summary: |
||
| 267 | Replies to a DHCP Discover message. |
||
| 268 | |||
| 269 | Description: |
||
| 270 | This function replies to a DHCP Discover message by sending out a |
||
| 271 | DHCP Offer message. |
||
| 272 | |||
| 273 | Precondition: |
||
| 274 | None |
||
| 275 | |||
| 276 | Parameters: |
||
| 277 | Header - the BootP header this is in response to. |
||
| 278 | |||
| 279 | Returns: |
||
| 280 | None |
||
| 281 | ***************************************************************************/ |
||
| 282 | static void DHCPReplyToDiscovery(BOOTP_HEADER *Header) |
||
| 283 | { |
||
| 284 | BYTE i; |
||
| 285 | |||
| 286 | // Set the correct socket to active and ensure that |
||
| 287 | // enough space is available to generate the DHCP response |
||
| 288 | if(UDPIsPutReady(MySocket) < 300u) |
||
| 289 | return; |
||
| 290 | |||
| 291 | // Begin putting the BOOTP Header and DHCP options |
||
| 292 | UDPPut(BOOT_REPLY); // Message Type: 2 (BOOTP Reply) |
||
| 293 | // Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields |
||
| 294 | UDPPutArray((BYTE*)&(Header->HardwareType), 7); |
||
| 295 | UDPPut(0x00); // Seconds Elapsed: 0 (Not used) |
||
| 296 | UDPPut(0x00); // Seconds Elapsed: 0 (Not used) |
||
| 297 | UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags)); |
||
| 298 | UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned) |
||
| 299 | UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned) |
||
| 300 | UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned) |
||
| 301 | UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned) |
||
| 302 | UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR)); // Lease IP address to give out |
||
| 303 | UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used) |
||
| 304 | UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used) |
||
| 305 | UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used) |
||
| 306 | UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used) |
||
| 307 | UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used) |
||
| 308 | UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used) |
||
| 309 | UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used) |
||
| 310 | UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used) |
||
| 311 | UDPPutArray((BYTE*)&(Header->ClientMAC), sizeof(MAC_ADDR)); // Client MAC address: Same as given by client |
||
| 312 | for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++) // Remaining 10 bytes of client hardware address, server host name: Null string (not used) |
||
| 313 | UDPPut(0x00); // Boot filename: Null string (not used) |
||
| 314 | UDPPut(0x63); // Magic Cookie: 0x63538263 |
||
| 315 | UDPPut(0x82); // Magic Cookie: 0x63538263 |
||
| 316 | UDPPut(0x53); // Magic Cookie: 0x63538263 |
||
| 317 | UDPPut(0x63); // Magic Cookie: 0x63538263 |
||
| 318 | |||
| 319 | // Options: DHCP Offer |
||
| 320 | UDPPut(DHCP_MESSAGE_TYPE); |
||
| 321 | UDPPut(1); |
||
| 322 | UDPPut(DHCP_OFFER_MESSAGE); |
||
| 323 | |||
| 324 | // Option: Subnet Mask |
||
| 325 | UDPPut(DHCP_SUBNET_MASK); |
||
| 326 | UDPPut(sizeof(IP_ADDR)); |
||
| 327 | UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR)); |
||
| 328 | |||
| 329 | // Option: Lease duration |
||
| 330 | UDPPut(DHCP_IP_LEASE_TIME); |
||
| 331 | UDPPut(4); |
||
| 332 | UDPPut((DHCP_LEASE_DURATION>>24) & 0xFF); |
||
| 333 | UDPPut((DHCP_LEASE_DURATION>>16) & 0xFF); |
||
| 334 | UDPPut((DHCP_LEASE_DURATION>>8) & 0xFF); |
||
| 335 | UDPPut((DHCP_LEASE_DURATION) & 0xFF); |
||
| 336 | |||
| 337 | // Option: Server identifier |
||
| 338 | UDPPut(DHCP_SERVER_IDENTIFIER); |
||
| 339 | UDPPut(sizeof(IP_ADDR)); |
||
| 340 | UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR)); |
||
| 341 | |||
| 342 | // Option: Router/Gateway address |
||
| 343 | UDPPut(DHCP_ROUTER); |
||
| 344 | UDPPut(sizeof(IP_ADDR)); |
||
| 345 | UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR)); |
||
| 346 | |||
| 347 | // Option: DNS server address |
||
| 348 | UDPPut(DHCP_DNS); |
||
| 349 | UDPPut(sizeof(IP_ADDR)); |
||
| 350 | UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR)); |
||
| 351 | |||
| 352 | // No more options, mark ending |
||
| 353 | UDPPut(DHCP_END_OPTION); |
||
| 354 | |||
| 355 | // Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets) |
||
| 356 | while(UDPTxCount < 300u) |
||
| 357 | UDPPut(0); |
||
| 358 | |||
| 359 | // Force remote destination address to be the broadcast address, regardless |
||
| 360 | // of what the node's source IP address was (to ensure we don't try to |
||
| 361 | // unicast to 0.0.0.0). |
||
| 362 | memset((void*)&UDPSocketInfo[MySocket].remoteNode, 0xFF, sizeof(NODE_INFO)); |
||
| 363 | |||
| 364 | // Transmit the packet |
||
| 365 | UDPFlush(); |
||
| 366 | } |
||
| 367 | |||
| 368 | |||
| 369 | /***************************************************************************** |
||
| 370 | Function: |
||
| 371 | static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept) |
||
| 372 | |||
| 373 | Summary: |
||
| 374 | Replies to a DHCP Request message. |
||
| 375 | |||
| 376 | Description: |
||
| 377 | This function replies to a DHCP Request message by sending out a |
||
| 378 | DHCP Acknowledge message. |
||
| 379 | |||
| 380 | Precondition: |
||
| 381 | None |
||
| 382 | |||
| 383 | Parameters: |
||
| 384 | Header - the BootP header this is in response to. |
||
| 385 | bAccept - whether or not we've accepted this request |
||
| 386 | |||
| 387 | Returns: |
||
| 388 | None |
||
| 389 | |||
| 390 | Internal: |
||
| 391 | Needs to support more than one simultaneous lease in the future. |
||
| 392 | ***************************************************************************/ |
||
| 393 | static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept) |
||
| 394 | { |
||
| 395 | BYTE i; |
||
| 396 | |||
| 397 | // Set the correct socket to active and ensure that |
||
| 398 | // enough space is available to generate the DHCP response |
||
| 399 | if(UDPIsPutReady(MySocket) < 300u) |
||
| 400 | return; |
||
| 401 | |||
| 402 | // Search through all remaining options and look for the Requested IP address field |
||
| 403 | // Obtain options |
||
| 404 | while(UDPIsGetReady(MySocket)) |
||
| 405 | { |
||
| 406 | BYTE Option, Len; |
||
| 407 | DWORD dw; |
||
| 408 | |||
| 409 | // Get option type |
||
| 410 | if(!UDPGet(&Option)) |
||
| 411 | break; |
||
| 412 | if(Option == DHCP_END_OPTION) |
||
| 413 | break; |
||
| 414 | |||
| 415 | // Get option length |
||
| 416 | UDPGet(&Len); |
||
| 417 | |||
| 418 | // Process option |
||
| 419 | if((Option == DHCP_PARAM_REQUEST_IP_ADDRESS) && (Len == 4u)) |
||
| 420 | { |
||
| 421 | // Get the requested IP address and see if it is the one we have on offer. If not, we should send back a NAK, but since there could be some other DHCP server offering this address, we'll just silently ignore this request. |
||
| 422 | UDPGetArray((BYTE*)&dw, 4); |
||
| 423 | Len -= 4; |
||
| 424 | if(dw != DHCPNextLease.Val) |
||
| 425 | { |
||
| 426 | bAccept = FALSE; |
||
| 427 | } |
||
| 428 | break; |
||
| 429 | } |
||
| 430 | |||
| 431 | // Remove the unprocessed bytes that we don't care about |
||
| 432 | while(Len--) |
||
| 433 | { |
||
| 434 | UDPGet(&i); |
||
| 435 | } |
||
| 436 | } |
||
| 437 | |||
| 438 | // Begin putting the BOOTP Header and DHCP options |
||
| 439 | UDPPut(BOOT_REPLY); // Message Type: 2 (BOOTP Reply) |
||
| 440 | // Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields |
||
| 441 | UDPPutArray((BYTE*)&(Header->HardwareType), 7); |
||
| 442 | UDPPut(0x00); // Seconds Elapsed: 0 (Not used) |
||
| 443 | UDPPut(0x00); // Seconds Elapsed: 0 (Not used) |
||
| 444 | UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags)); |
||
| 445 | UDPPutArray((BYTE*)&(Header->ClientIP), sizeof(IP_ADDR));// Your (client) IP Address: |
||
| 446 | UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR)); // Lease IP address to give out |
||
| 447 | UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used) |
||
| 448 | UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used) |
||
| 449 | UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used) |
||
| 450 | UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used) |
||
| 451 | UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used) |
||
| 452 | UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used) |
||
| 453 | UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used) |
||
| 454 | UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used) |
||
| 455 | UDPPutArray((BYTE*)&(Header->ClientMAC), sizeof(MAC_ADDR)); // Client MAC address: Same as given by client |
||
| 456 | for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++) // Remaining 10 bytes of client hardware address, server host name: Null string (not used) |
||
| 457 | UDPPut(0x00); // Boot filename: Null string (not used) |
||
| 458 | UDPPut(0x63); // Magic Cookie: 0x63538263 |
||
| 459 | UDPPut(0x82); // Magic Cookie: 0x63538263 |
||
| 460 | UDPPut(0x53); // Magic Cookie: 0x63538263 |
||
| 461 | UDPPut(0x63); // Magic Cookie: 0x63538263 |
||
| 462 | |||
| 463 | // Options: DHCP lease ACKnowledge |
||
| 464 | if(bAccept) |
||
| 465 | { |
||
| 466 | UDPPut(DHCP_OPTION_ACK_MESSAGE); |
||
| 467 | UDPPut(1); |
||
| 468 | UDPPut(DHCP_ACK_MESSAGE); |
||
| 469 | } |
||
| 470 | else // Send a NACK |
||
| 471 | { |
||
| 472 | UDPPut(DHCP_OPTION_ACK_MESSAGE); |
||
| 473 | UDPPut(1); |
||
| 474 | UDPPut(DHCP_NAK_MESSAGE); |
||
| 475 | } |
||
| 476 | |||
| 477 | // Option: Lease duration |
||
| 478 | UDPPut(DHCP_IP_LEASE_TIME); |
||
| 479 | UDPPut(4); |
||
| 480 | UDPPut((DHCP_LEASE_DURATION>>24) & 0xFF); |
||
| 481 | UDPPut((DHCP_LEASE_DURATION>>16) & 0xFF); |
||
| 482 | UDPPut((DHCP_LEASE_DURATION>>8) & 0xFF); |
||
| 483 | UDPPut((DHCP_LEASE_DURATION) & 0xFF); |
||
| 484 | |||
| 485 | // Option: Server identifier |
||
| 486 | UDPPut(DHCP_SERVER_IDENTIFIER); |
||
| 487 | UDPPut(sizeof(IP_ADDR)); |
||
| 488 | UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR)); |
||
| 489 | |||
| 490 | // Option: Subnet Mask |
||
| 491 | UDPPut(DHCP_SUBNET_MASK); |
||
| 492 | UDPPut(sizeof(IP_ADDR)); |
||
| 493 | UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR)); |
||
| 494 | |||
| 495 | // Option: Router/Gateway address |
||
| 496 | UDPPut(DHCP_ROUTER); |
||
| 497 | UDPPut(sizeof(IP_ADDR)); |
||
| 498 | UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR)); |
||
| 499 | |||
| 500 | // Option: DNS server address |
||
| 501 | UDPPut(DHCP_DNS); |
||
| 502 | UDPPut(sizeof(IP_ADDR)); |
||
| 503 | UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR)); |
||
| 504 | |||
| 505 | // No more options, mark ending |
||
| 506 | UDPPut(DHCP_END_OPTION); |
||
| 507 | |||
| 508 | // Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets) |
||
| 509 | while(UDPTxCount < 300u) |
||
| 510 | UDPPut(0); |
||
| 511 | |||
| 512 | // Force remote destination address to be the broadcast address, regardless |
||
| 513 | // of what the node's source IP address was (to ensure we don't try to |
||
| 514 | // unicast to 0.0.0.0). |
||
| 515 | memset((void*)&UDPSocketInfo[MySocket].remoteNode, 0xFF, sizeof(NODE_INFO)); |
||
| 516 | |||
| 517 | // Transmit the packet |
||
| 518 | UDPFlush(); |
||
| 519 | } |
||
| 520 | |||
| 521 | #endif //#if defined(STACK_USE_DHCP_SERVER) |
Powered by WebSVN v2.8.3