dhcp_client_misc.c
Go to the documentation of this file.
1 /**
2  * @file dhcp_client_misc.c
3  * @brief Helper functions for DHCP client
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL DHCP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "dhcp/dhcp_client.h"
37 #include "dhcp/dhcp_client_fsm.h"
38 #include "dhcp/dhcp_client_misc.h"
39 #include "dhcp/dhcp_common.h"
40 #include "dhcp/dhcp_debug.h"
41 #include "mdns/mdns_responder.h"
42 #include "date_time.h"
43 #include "debug.h"
44 
45 //Check TCP/IP stack configuration
46 #if (IPV4_SUPPORT == ENABLED && DHCP_CLIENT_SUPPORT == ENABLED)
47 
48 //Tick counter to handle periodic operations
50 
51 //Requested DHCP options
52 const uint8_t dhcpOptionList[] =
53 {
61 };
62 
63 
64 /**
65  * @brief DHCP client timer handler
66  *
67  * This routine must be periodically called by the TCP/IP stack to manage
68  * DHCP client operation
69  *
70  * @param[in] context Pointer to the DHCP client context
71  **/
72 
74 {
75  //Make sure the DHCP client has been properly instantiated
76  if(context != NULL)
77  {
78  //DHCP client finite state machine
79  switch(context->state)
80  {
81  //INIT state?
82  case DHCP_STATE_INIT:
83  //This is the initialization state, where a client begins the process
84  //of acquiring a lease. It also returns here when a lease ends, or
85  //when a lease negotiation fails
86  dhcpClientStateInit(context);
87  break;
88 
89  //SELECTING state?
91  //The client is waiting to receive DHCPOFFER messages from one or more
92  //DHCP servers, so it can choose one
93  dhcpClientStateSelecting(context);
94  break;
95 
96  //REQUESTING state?
98  //The client is waiting to hear back from the server to which it sent
99  //its request
100  dhcpClientStateRequesting(context);
101  break;
102 
103  //INIT REBOOT state?
105  //When a client that already has a valid lease starts up after a
106  //power-down or reboot, it starts here instead of the INIT state
107  dhcpClientStateInitReboot(context);
108  break;
109 
110  //REBOOTING state?
112  //A client that has rebooted with an assigned address is waiting for
113  //a confirming reply from a server
114  dhcpClientStateRebooting(context);
115  break;
116 
117  //PROBING state?
118  case DHCP_STATE_PROBING:
119  //The client probes the newly received address
120  dhcpClientStateProbing(context);
121  break;
122 
123  //ANNOUNCING state?
125  //The client announces its new IP address
126  dhcpClientStateAnnouncing(context);
127  break;
128 
129  //BOUND state?
130  case DHCP_STATE_BOUND:
131  //Client has a valid lease and is in its normal operating state
132  dhcpClientStateBound(context);
133  break;
134 
135  //RENEWING state?
136  case DHCP_STATE_RENEWING:
137  //Client is trying to renew its lease. It regularly sends DHCPREQUEST
138  //messages with the server that gave it its current lease specified,
139  //and waits for a reply
140  dhcpClientStateRenewing(context);
141  break;
142 
143  //REBINDING state?
145  //The client has failed to renew its lease with the server that
146  //originally granted it, and now seeks a lease extension with any
147  //server that can hear it. It periodically sends DHCPREQUEST messages
148  //with no server specified until it gets a reply or the lease ends
149  dhcpClientStateRebinding(context);
150  break;
151 
152  //Invalid state?
153  default:
154  //Switch to the default state
155  context->state = DHCP_STATE_INIT;
156  break;
157  }
158  }
159 }
160 
161 
162 /**
163  * @brief Callback function for link change event
164  * @param[in] context Pointer to the DHCP client context
165  **/
166 
168 {
169  NetInterface *interface;
170 
171  //Make sure the DHCP client has been properly instantiated
172  if(context == NULL)
173  return;
174 
175  //Point to the underlying network interface
176  interface = context->settings.interface;
177 
178  //Check whether the DHCP client is running
179  if(context->running)
180  {
181  //The host address is no longer valid
182  dhcpClientResetConfig(context);
183 
184 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
185  //Restart mDNS probing process
186  mdnsResponderStartProbing(interface->mdnsResponderContext);
187 #endif
188  }
189 
190  //Check whether the client already has a valid lease
191  if(context->state >= DHCP_STATE_INIT_REBOOT)
192  {
193  //Switch to the INIT-REBOOT state
194  context->state = DHCP_STATE_INIT_REBOOT;
195  }
196  else
197  {
198  //Switch to the INIT state
199  context->state = DHCP_STATE_INIT;
200  }
201 
202  //Any registered callback?
203  if(context->settings.linkChangeEvent != NULL)
204  {
205  //Release exclusive access
207  //Invoke user callback function
208  context->settings.linkChangeEvent(context, interface, interface->linkState);
209  //Get exclusive access
211  }
212 }
213 
214 
215 /**
216  * @brief Send DHCPDISCOVER message
217  * @param[in] context Pointer to the DHCP client context
218  * @return Error code
219  **/
220 
222 {
223  error_t error;
224  size_t offset;
225  size_t length;
226  NetBuffer *buffer;
227  NetInterface *interface;
228  NetInterface *logicalInterface;
232  NetTxAncillary ancillary;
233 
234  //DHCP message type
235  const uint8_t type = DHCP_MSG_TYPE_DISCOVER;
236 
237  //Point to the underlying network interface
238  interface = context->settings.interface;
239  //Point to the logical interface
240  logicalInterface = nicGetLogicalInterface(interface);
241 
242  //Allocate a memory buffer to hold the DHCP message
243  buffer = udpAllocBuffer(DHCP_MAX_MSG_SIZE, &offset);
244  //Failed to allocate buffer?
245  if(buffer == NULL)
246  return ERROR_OUT_OF_MEMORY;
247 
248  //Point to the beginning of the DHCP message
249  message = netBufferAt(buffer, offset);
250  //Clear memory buffer contents
252 
253  //Format DHCPDISCOVER message
256  message->hlen = sizeof(MacAddr);
257  message->xid = htonl(context->transactionId);
258  message->secs = dhcpClientComputeElapsedTime(context);
260  message->ciaddr = IPV4_UNSPECIFIED_ADDR;
261  message->chaddr = logicalInterface->macAddr;
262 
263  //Write magic cookie before setting any option
264  message->magicCookie = HTONL(DHCP_MAGIC_COOKIE);
265  //Properly terminate the options field
266  message->options[0] = DHCP_OPT_END;
267 
268  //Total length of the DHCP message
269  length = sizeof(DhcpMessage) + sizeof(uint8_t);
270 
271  //DHCP Message Type option
273  &type, sizeof(type));
274 
275  //Check whether rapid commit is enabled
276  if(context->settings.rapidCommit)
277  {
278  //Include the Rapid Commit option if the client is prepared
279  //to perform the DHCPDISCOVER-DHCPACK message exchange
281  }
282 
283  //Any registered callback?
284  if(context->settings.addOptionsCallback != NULL)
285  {
286  //Invoke user callback function
287  context->settings.addOptionsCallback(context, message, &length,
289  }
290 
291  //The minimum length of BOOTP frames is 300 octets (refer to RFC 951,
292  //section 3)
294 
295  //Adjust the length of the multi-part buffer
296  netBufferSetLength(buffer, offset + length);
297 
298  //DHCP messages broadcast by a client prior to that client obtaining its
299  //IP address must have the source address field in the IP header set to 0
300  //(refer to RFC 2131, section 4.1)
301  srcIpAddr.length = sizeof(Ipv4Addr);
302  srcIpAddr.ipv4Addr = IPV4_UNSPECIFIED_ADDR;
303 
304  //Set destination IP address
305  destIpAddr.length = sizeof(Ipv4Addr);
306  destIpAddr.ipv4Addr = IPV4_BROADCAST_ADDR;
307 
308  //Debug message
309  TRACE_DEBUG("\r\n%s: Sending DHCP message (%" PRIuSIZE " bytes)...\r\n",
311 
312  //Dump the contents of the message for debugging purpose
314 
315  //Additional options can be passed to the stack along with the packet
316  ancillary = NET_DEFAULT_TX_ANCILLARY;
317 
318  //Broadcast DHCPDISCOVER message
319  error = udpSendBuffer(interface, &srcIpAddr, DHCP_CLIENT_PORT, &destIpAddr,
320  DHCP_SERVER_PORT, buffer, offset, &ancillary);
321 
322  //Free previously allocated memory
323  netBufferFree(buffer);
324  //Return status code
325  return error;
326 }
327 
328 
329 /**
330  * @brief Send DHCPREQUEST message
331  * @param[in] context Pointer to the DHCP client context
332  * @return Error code
333  **/
334 
336 {
337  uint_t i;
338  error_t error;
339  size_t offset;
340  size_t length;
341  NetBuffer *buffer;
342  NetInterface *interface;
343  NetInterface *logicalInterface;
347  NetTxAncillary ancillary;
348 
349  //DHCP message type
350  const uint8_t type = DHCP_MSG_TYPE_REQUEST;
351 
352  //Point to the underlying network interface
353  interface = context->settings.interface;
354  //Point to the logical interface
355  logicalInterface = nicGetLogicalInterface(interface);
356 
357  //Index of the IP address in the list of addresses assigned to the interface
358  i = context->settings.ipAddrIndex;
359 
360  //Allocate a memory buffer to hold the DHCP message
361  buffer = udpAllocBuffer(DHCP_MAX_MSG_SIZE, &offset);
362  //Failed to allocate buffer?
363  if(buffer == NULL)
364  return ERROR_OUT_OF_MEMORY;
365 
366  //Point to the beginning of the DHCP message
367  message = netBufferAt(buffer, offset);
368  //Clear memory buffer contents
370 
371  //Format DHCPREQUEST message
374  message->hlen = sizeof(MacAddr);
375  message->xid = htonl(context->transactionId);
376  message->secs = dhcpClientComputeElapsedTime(context);
377 
378  //The client IP address must be included if the client is fully configured
379  //and can respond to ARP requests
380  if(context->state == DHCP_STATE_RENEWING ||
381  context->state == DHCP_STATE_REBINDING)
382  {
383  message->flags = 0;
384  message->ciaddr = interface->ipv4Context.addrList[i].addr;
385  }
386  else
387  {
389  message->ciaddr = IPV4_UNSPECIFIED_ADDR;
390  }
391 
392  //Client hardware address
393  message->chaddr = logicalInterface->macAddr;
394  //Write magic cookie before setting any option
395  message->magicCookie = HTONL(DHCP_MAGIC_COOKIE);
396  //Properly terminate the options field
397  message->options[0] = DHCP_OPT_END;
398 
399  //Total length of the DHCP message
400  length = sizeof(DhcpMessage) + sizeof(uint8_t);
401 
402  //DHCP Message Type option
404  &type, sizeof(type));
405 
406  //Server Identifier option
407  if(context->state == DHCP_STATE_REQUESTING)
408  {
410  &context->serverIpAddr, sizeof(Ipv4Addr));
411  }
412 
413  //Requested IP Address option
414  if(context->state == DHCP_STATE_REQUESTING ||
415  context->state == DHCP_STATE_REBOOTING)
416  {
418  &context->requestedIpAddr, sizeof(Ipv4Addr));
419  }
420 
421  //Any registered callback?
422  if(context->settings.addOptionsCallback != NULL)
423  {
424  //Invoke user callback function
425  context->settings.addOptionsCallback(context, message, &length,
427  }
428 
429  //Parameter Request List option
431  {
432  //Use the default list of requested options
434  dhcpOptionList, sizeof(dhcpOptionList));
435  }
436 
437  //The minimum length of BOOTP frames is 300 octets (refer to RFC 951,
438  //section 3)
440 
441  //Adjust the length of the multi-part buffer
442  netBufferSetLength(buffer, offset + length);
443 
444  //IP address is being renewed?
445  if(context->state == DHCP_STATE_RENEWING)
446  {
447  //Set source IP address
448  srcIpAddr.length = sizeof(Ipv4Addr);
449  srcIpAddr.ipv4Addr = interface->ipv4Context.addrList[i].addr;
450 
451  //The client transmits the message directly to the server that initially
452  //granted the lease
453  destIpAddr.length = sizeof(Ipv4Addr);
454  destIpAddr.ipv4Addr = context->serverIpAddr;
455  }
456  else
457  {
458  //DHCP messages broadcast by a client prior to that client obtaining its
459  //IP address must have the source address field in the IP header set to 0
460  //(refer to RFC 2131, section 4.1)
461  srcIpAddr.length = sizeof(Ipv4Addr);
462  srcIpAddr.ipv4Addr = IPV4_UNSPECIFIED_ADDR;
463 
464  //Broadcast the message
465  destIpAddr.length = sizeof(Ipv4Addr);
466  destIpAddr.ipv4Addr = IPV4_BROADCAST_ADDR;
467  }
468 
469  //Debug message
470  TRACE_DEBUG("\r\n%s: Sending DHCP message (%" PRIuSIZE " bytes)...\r\n",
472 
473  //Dump the contents of the message for debugging purpose
475 
476  //Additional options can be passed to the stack along with the packet
477  ancillary = NET_DEFAULT_TX_ANCILLARY;
478 
479  //Send DHCPREQUEST message
480  error = udpSendBuffer(interface, &srcIpAddr, DHCP_CLIENT_PORT, &destIpAddr,
481  DHCP_SERVER_PORT, buffer, offset, &ancillary);
482 
483  //Free previously allocated memory
484  netBufferFree(buffer);
485  //Return status code
486  return error;
487 }
488 
489 
490 /**
491  * @brief Send DHCPDECLINE message
492  * @param[in] context Pointer to the DHCP client context
493  * @return Error code
494  **/
495 
497 {
498  error_t error;
499  size_t offset;
500  size_t length;
501  NetBuffer *buffer;
502  NetInterface *interface;
503  NetInterface *logicalInterface;
507  NetTxAncillary ancillary;
508 
509  //DHCP message type
510  const uint8_t type = DHCP_MSG_TYPE_DECLINE;
511 
512  //Point to the underlying network interface
513  interface = context->settings.interface;
514  //Point to the logical interface
515  logicalInterface = nicGetLogicalInterface(interface);
516 
517  //Allocate a memory buffer to hold the DHCP message
518  buffer = udpAllocBuffer(DHCP_MAX_MSG_SIZE, &offset);
519  //Failed to allocate buffer?
520  if(buffer == NULL)
521  return ERROR_OUT_OF_MEMORY;
522 
523  //Point to the beginning of the DHCP message
524  message = netBufferAt(buffer, offset);
525  //Clear memory buffer contents
527 
528  //Format DHCPDECLINE message
531  message->hlen = sizeof(MacAddr);
532  message->xid = htonl(context->transactionId);
533  message->secs = 0;
534  message->flags = 0;
535  message->ciaddr = IPV4_UNSPECIFIED_ADDR;
536  message->chaddr = logicalInterface->macAddr;
537 
538  //Write magic cookie before setting any option
539  message->magicCookie = HTONL(DHCP_MAGIC_COOKIE);
540  //Properly terminate the options field
541  message->options[0] = DHCP_OPT_END;
542 
543  //Total length of the DHCP message
544  length = sizeof(DhcpMessage) + sizeof(uint8_t);
545 
546  //DHCP Message Type option
548  &type, sizeof(type));
549 
550  //Server Identifier option
552  &context->serverIpAddr, sizeof(Ipv4Addr));
553 
554  //Requested IP Address option
556  &context->requestedIpAddr, sizeof(Ipv4Addr));
557 
558  //Any registered callback?
559  if(context->settings.addOptionsCallback != NULL)
560  {
561  //Invoke user callback function
562  context->settings.addOptionsCallback(context, message, &length,
564  }
565 
566  //The minimum length of BOOTP frames is 300 octets (refer to RFC 951,
567  //section 3)
569 
570  //Adjust the length of the multi-part buffer
571  netBufferSetLength(buffer, offset + length);
572 
573  //Use the unspecified address as source address
574  srcIpAddr.length = sizeof(Ipv4Addr);
575  srcIpAddr.ipv4Addr = IPV4_UNSPECIFIED_ADDR;
576 
577  //Set destination IP address
578  destIpAddr.length = sizeof(Ipv4Addr);
579  destIpAddr.ipv4Addr = IPV4_BROADCAST_ADDR;
580 
581  //Debug message
582  TRACE_DEBUG("\r\n%s: Sending DHCP message (%" PRIuSIZE " bytes)...\r\n",
584 
585  //Dump the contents of the message for debugging purpose
587 
588  //Additional options can be passed to the stack along with the packet
589  ancillary = NET_DEFAULT_TX_ANCILLARY;
590 
591  //Broadcast DHCPDECLINE message
592  error = udpSendBuffer(interface, &srcIpAddr, DHCP_CLIENT_PORT, &destIpAddr,
593  DHCP_SERVER_PORT, buffer, offset, &ancillary);
594 
595  //Free previously allocated memory
596  netBufferFree(buffer);
597  //Return status code
598  return error;
599 }
600 
601 
602 /**
603  * @brief Send DHCPRELEASE message
604  * @param[in] context Pointer to the DHCP client context
605  * @return Error code
606  **/
607 
609 {
610  uint_t i;
611  error_t error;
612  size_t offset;
613  size_t length;
614  NetBuffer *buffer;
615  NetInterface *interface;
616  NetInterface *logicalInterface;
620  NetTxAncillary ancillary;
621 
622  //DHCP message type
623  const uint8_t type = DHCP_MSG_TYPE_RELEASE;
624 
625  //Point to the underlying network interface
626  interface = context->settings.interface;
627  //Point to the logical interface
628  logicalInterface = nicGetLogicalInterface(interface);
629 
630  //Index of the IP address in the list of addresses assigned to the interface
631  i = context->settings.ipAddrIndex;
632 
633  //Allocate a memory buffer to hold the DHCP message
634  buffer = udpAllocBuffer(DHCP_MAX_MSG_SIZE, &offset);
635  //Failed to allocate buffer?
636  if(buffer == NULL)
637  return ERROR_OUT_OF_MEMORY;
638 
639  //Point to the beginning of the DHCP message
640  message = netBufferAt(buffer, offset);
641  //Clear memory buffer contents
643 
644  //Format DHCP message
647  message->hlen = sizeof(MacAddr);
648  message->xid = htonl(context->transactionId);
649  message->secs = 0;
650  message->flags = 0;
651  message->ciaddr = interface->ipv4Context.addrList[i].addr;
652  message->chaddr = logicalInterface->macAddr;
653 
654  //Write magic cookie before setting any option
655  message->magicCookie = HTONL(DHCP_MAGIC_COOKIE);
656  //Properly terminate the options field
657  message->options[0] = DHCP_OPT_END;
658 
659  //Total length of the DHCP message
660  length = sizeof(DhcpMessage) + sizeof(uint8_t);
661 
662  //DHCP Message Type option
664  &type, sizeof(type));
665 
666  //Server Identifier option
668  &context->serverIpAddr, sizeof(Ipv4Addr));
669 
670  //Any registered callback?
671  if(context->settings.addOptionsCallback != NULL)
672  {
673  //Invoke user callback function
674  context->settings.addOptionsCallback(context, message, &length,
676  }
677 
678  //The minimum length of BOOTP frames is 300 octets (refer to RFC 951,
679  //section 3)
681 
682  //Adjust the length of the multi-part buffer
683  netBufferSetLength(buffer, offset + length);
684 
685  //Set source IP address
686  srcIpAddr.length = sizeof(Ipv4Addr);
687  srcIpAddr.ipv4Addr = interface->ipv4Context.addrList[i].addr;
688 
689  //The client unicasts DHCPRELEASE messages to the server (refer to RFC 2131,
690  //section 4.4.4)
691  destIpAddr.length = sizeof(Ipv4Addr);
692  destIpAddr.ipv4Addr = context->serverIpAddr;
693 
694  //Debug message
695  TRACE_DEBUG("\r\n%s: Sending DHCP message (%" PRIuSIZE " bytes)...\r\n",
697 
698  //Dump the contents of the message for debugging purpose
700 
701  //Additional options can be passed to the stack along with the packet
702  ancillary = NET_DEFAULT_TX_ANCILLARY;
703 
704  //Broadcast DHCP message
705  error = udpSendBuffer(interface, &srcIpAddr, DHCP_CLIENT_PORT, &destIpAddr,
706  DHCP_SERVER_PORT, buffer, offset, &ancillary);
707 
708  //Free previously allocated memory
709  netBufferFree(buffer);
710  //Return status code
711  return error;
712 }
713 
714 
715 /**
716  * @brief Process incoming DHCP message
717  * @param[in] interface Underlying network interface
718  * @param[in] pseudoHeader UDP pseudo header
719  * @param[in] udpHeader UDP header
720  * @param[in] buffer Multi-part buffer containing the incoming DHCP message
721  * @param[in] offset Offset to the first byte of the DHCP message
722  * @param[in] ancillary Additional options passed to the stack along with
723  * the packet
724  * @param[in] param Pointer to the DHCP client context
725  **/
726 
728  const IpPseudoHeader *pseudoHeader, const UdpHeader *udpHeader,
729  const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary,
730  void *param)
731 {
732  size_t length;
733  DhcpClientContext *context;
735  DhcpOption *option;
736 
737  //Point to the DHCP client context
738  context = (DhcpClientContext *) param;
739 
740  //Retrieve the length of the DHCP message
741  length = netBufferGetLength(buffer) - offset;
742 
743  //Make sure the DHCP message is valid
744  if(length < sizeof(DhcpMessage) || length > DHCP_MAX_MSG_SIZE)
745  return;
746 
747  //Point to the beginning of the DHCP message
748  message = netBufferAt(buffer, offset);
749  //Sanity check
750  if(message == NULL)
751  return;
752 
753  //Debug message
754  TRACE_DEBUG("\r\n%s: DHCP message received (%" PRIuSIZE " bytes)...\r\n",
756 
757  //Dump the contents of the message for debugging purpose
759 
760  //The DHCP server shall respond with a BOOTREPLY opcode
761  if(message->op != DHCP_OPCODE_BOOTREPLY)
762  return;
763 
764  //Enforce hardware type
765  if(message->htype != DHCP_HARDWARE_TYPE_ETH)
766  return;
767 
768  //Check the length of the hardware address
769  if(message->hlen != sizeof(MacAddr))
770  return;
771 
772  //Check magic cookie
773  if(message->magicCookie != HTONL(DHCP_MAGIC_COOKIE))
774  return;
775 
776  //The DHCP Message Type option must be included in every DHCP message
778 
779  //Failed to retrieve the Message Type option?
780  if(option == NULL || option->length != 1)
781  return;
782 
783  //Check message type
784  switch(option->value[0])
785  {
786  case DHCP_MSG_TYPE_OFFER:
787  //Parse DHCPOFFER message
789  break;
790 
791  case DHCP_MSG_TYPE_ACK:
792  //Parse DHCPACK message
793  dhcpClientParseAck(context, message, length);
794  break;
795 
796  case DHCP_MSG_TYPE_NAK:
797  //Parse DHCPNAK message
798  dhcpClientParseNak(context, message, length);
799  break;
800 
801  default:
802  //Silently drop incoming message
803  break;
804  }
805 }
806 
807 
808 /**
809  * @brief Parse DHCPOFFER message
810  * @param[in] context Pointer to the DHCP client context
811  * @param[in] message Pointer to the incoming DHCP message
812  * @param[in] length Length of the incoming message to parse
813  **/
814 
816  const DhcpMessage *message, size_t length)
817 {
818  error_t error;
819  DhcpOption *serverIdOption;
820  NetInterface *interface;
821  NetInterface *logicalInterface;
822 
823  //Point to the underlying network interface
824  interface = context->settings.interface;
825  //Point to the logical interface
826  logicalInterface = nicGetLogicalInterface(interface);
827 
828  //Discard any received packet that does not match the transaction ID
829  if(ntohl(message->xid) != context->transactionId)
830  return;
831 
832  //Make sure the IP address offered to the client is valid
833  if(message->yiaddr == IPV4_UNSPECIFIED_ADDR)
834  return;
835 
836  //Check MAC address
837  if(!macCompAddr(&message->chaddr, &logicalInterface->macAddr))
838  return;
839 
840  //Make sure that the DHCPOFFER message is received in response to
841  //a DHCPDISCOVER message
842  if(context->state != DHCP_STATE_SELECTING)
843  return;
844 
845  //A DHCP server always returns its own address in the Server Identifier option
846  serverIdOption = dhcpGetOption(message, length, DHCP_OPT_SERVER_ID);
847 
848  //Failed to retrieve the Server Identifier option?
849  if(serverIdOption == NULL || serverIdOption->length != 4)
850  return;
851 
852  //Any registered callback?
853  if(context->settings.parseOptionsCallback != NULL)
854  {
855  //Invoke user callback function
856  error = context->settings.parseOptionsCallback(context, message, length,
858  //Check status code
859  if(error)
860  return;
861  }
862 
863  //Record the IP address of the DHCP server
864  ipv4CopyAddr(&context->serverIpAddr, serverIdOption->value);
865  //Record the IP address offered to the client
866  context->requestedIpAddr = message->yiaddr;
867 
868  //Switch to the REQUESTING state
870 }
871 
872 
873 /**
874  * @brief Parse DHCPACK message
875  * @param[in] context Pointer to the DHCP client context
876  * @param[in] message Pointer to the incoming DHCP message
877  * @param[in] length Length of the incoming message to parse
878  **/
879 
881  const DhcpMessage *message, size_t length)
882 {
883  error_t error;
884  uint_t i;
885  uint_t j;
886  uint_t n;
887  DhcpOption *option;
888  DhcpOption *serverIdOption;
889  NetInterface *interface;
890  NetInterface *logicalInterface;
891  NetInterface *physicalInterface;
892 
893  //Point to the underlying network interface
894  interface = context->settings.interface;
895  //Point to the logical interface
896  logicalInterface = nicGetLogicalInterface(interface);
897  //Point to the physical interface
898  physicalInterface = nicGetPhysicalInterface(interface);
899 
900  //Index of the IP address in the list of addresses assigned to the interface
901  i = context->settings.ipAddrIndex;
902 
903  //Discard any received packet that does not match the transaction ID
904  if(ntohl(message->xid) != context->transactionId)
905  return;
906 
907  //Make sure the IP address assigned to the client is valid
908  if(message->yiaddr == IPV4_UNSPECIFIED_ADDR)
909  return;
910 
911  //Check MAC address
912  if(!macCompAddr(&message->chaddr, &logicalInterface->macAddr))
913  return;
914 
915  //A DHCP server always returns its own address in the Server Identifier option
916  serverIdOption = dhcpGetOption(message, length, DHCP_OPT_SERVER_ID);
917 
918  //Failed to retrieve the Server Identifier option?
919  if(serverIdOption == NULL || serverIdOption->length != 4)
920  return;
921 
922  //Check current state
923  if(context->state == DHCP_STATE_SELECTING)
924  {
925  //A DHCPACK message is not acceptable when rapid commit is disallowed
926  if(!context->settings.rapidCommit)
927  return;
928 
929  //Search for the Rapid Commit option
931 
932  //A server must include this option in a DHCPACK message sent
933  //in a response to a DHCPDISCOVER message when completing the
934  //DHCPDISCOVER-DHCPACK message exchange
935  if(option == NULL || option->length != 0)
936  return;
937  }
938  else if(context->state == DHCP_STATE_REQUESTING ||
939  context->state == DHCP_STATE_RENEWING)
940  {
941  //Check the server identifier
942  if(!ipv4CompAddr(serverIdOption->value, &context->serverIpAddr))
943  return;
944  }
945  else if(context->state == DHCP_STATE_REBOOTING ||
946  context->state == DHCP_STATE_REBINDING)
947  {
948  //Do not check the server identifier
949  }
950  else
951  {
952  //Silently discard the DHCPACK message
953  return;
954  }
955 
956  //Retrieve IP Address Lease Time option
958 
959  //Failed to retrieve specified option?
960  if(option == NULL || option->length != 4)
961  return;
962 
963  //Any registered callback?
964  if(context->settings.parseOptionsCallback != NULL)
965  {
966  //Invoke user callback function
967  error = context->settings.parseOptionsCallback(context, message, length,
969  //Check status code
970  if(error)
971  return;
972  }
973 
974  //Record the lease time
975  context->leaseTime = LOAD32BE(option->value);
976 
977  //Retrieve Renewal Time Value option
979 
980  //Specified option found?
981  if(option != NULL && option->length == 4)
982  {
983  //This option specifies the time interval from address assignment
984  //until the client transitions to the RENEWING state
985  context->t1 = LOAD32BE(option->value);
986  }
987  else if(context->leaseTime != DHCP_INFINITE_TIME)
988  {
989  //By default, T1 is set to 50% of the lease time
990  context->t1 = context->leaseTime / 2;
991  }
992  else
993  {
994  //Infinite lease
995  context->t1 = DHCP_INFINITE_TIME;
996  }
997 
998  //Retrieve Rebinding Time value option
1000 
1001  //Specified option found?
1002  if(option != NULL && option->length == 4)
1003  {
1004  //This option specifies the time interval from address assignment
1005  //until the client transitions to the REBINDING state
1006  context->t2 = LOAD32BE(option->value);
1007  }
1008  else if(context->leaseTime != DHCP_INFINITE_TIME)
1009  {
1010  //By default, T2 is set to 87.5% of the lease time
1011  context->t2 = context->leaseTime * 7 / 8;
1012  }
1013  else
1014  {
1015  //Infinite lease
1016  context->t2 = DHCP_INFINITE_TIME;
1017  }
1018 
1019  //Retrieve Subnet Mask option
1021 
1022  //Option found?
1023  if(option != NULL && option->length == sizeof(Ipv4Addr))
1024  {
1025  //Save subnet mask
1026  ipv4CopyAddr(&interface->ipv4Context.addrList[i].subnetMask,
1027  option->value);
1028  }
1029 
1030  //Retrieve Router option
1032 
1033  //Option found?
1034  if(option != NULL && !(option->length % sizeof(Ipv4Addr)))
1035  {
1036  //Save default gateway
1037  if(option->length >= sizeof(Ipv4Addr))
1038  {
1039  ipv4CopyAddr(&interface->ipv4Context.addrList[i].defaultGateway,
1040  option->value);
1041  }
1042  }
1043 
1044  //Automatic DNS server configuration?
1045  if(!context->settings.manualDnsConfig)
1046  {
1047  //Retrieve DNS Server option
1049 
1050  //Option found?
1051  if(option != NULL && !(option->length % sizeof(Ipv4Addr)))
1052  {
1053  //Get the number of addresses provided in the response
1054  n = option->length / sizeof(Ipv4Addr);
1055 
1056  //Loop through the list of addresses
1057  for(j = 0; j < n && j < IPV4_DNS_SERVER_LIST_SIZE; j++)
1058  {
1059  //Save DNS server address
1060  ipv4CopyAddr(&interface->ipv4Context.dnsServerList[j],
1061  option->value + j * sizeof(Ipv4Addr));
1062  }
1063  }
1064  }
1065 
1066  //Retrieve MTU option
1068 
1069  //Option found?
1070  if(option != NULL && option->length == 2)
1071  {
1072  //This option specifies the MTU to use on this interface
1073  n = LOAD16BE(option->value);
1074 
1075  //Make sure that the option's value is acceptable
1076  if(n >= IPV4_MINIMUM_MTU && n <= physicalInterface->nicDriver->mtu)
1077  {
1078  //Set the MTU to be used on the interface
1079  interface->ipv4Context.linkMtu = n;
1080  }
1081  }
1082 
1083  //Record the IP address of the DHCP server
1084  ipv4CopyAddr(&context->serverIpAddr, serverIdOption->value);
1085  //Record the IP address assigned to the client
1086  context->requestedIpAddr = message->yiaddr;
1087 
1088  //Save the time a which the lease was obtained
1089  context->leaseStartTime = osGetSystemTime();
1090 
1091  //Check current state
1092  if(context->state == DHCP_STATE_REQUESTING ||
1093  context->state == DHCP_STATE_REBOOTING)
1094  {
1095  //Use the IP address as a tentative address
1096  interface->ipv4Context.addrList[i].addr = message->yiaddr;
1097  interface->ipv4Context.addrList[i].state = IPV4_ADDR_STATE_TENTATIVE;
1098 
1099  //Clear conflict flag
1100  interface->ipv4Context.addrList[i].conflict = FALSE;
1101 
1102  //The client should probe the newly received address
1104  }
1105  else
1106  {
1107  //Assign the IP address to the client
1108  interface->ipv4Context.addrList[i].addr = message->yiaddr;
1109  interface->ipv4Context.addrList[i].state = IPV4_ADDR_STATE_VALID;
1110 
1111 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
1112  //Restart mDNS probing process
1113  mdnsResponderStartProbing(interface->mdnsResponderContext);
1114 #endif
1115  //The client transitions to the BOUND state
1117  }
1118 }
1119 
1120 
1121 /**
1122  * @brief Parse DHCPNAK message
1123  * @param[in] context Pointer to the DHCP client context
1124  * @param[in] message Pointer to the incoming DHCP message
1125  * @param[in] length Length of the incoming message to parse
1126  **/
1127 
1129  const DhcpMessage *message, size_t length)
1130 {
1131  error_t error;
1132  DhcpOption *serverIdOption;
1133  NetInterface *interface;
1134  NetInterface *logicalInterface;
1135 
1136  //Point to the underlying network interface
1137  interface = context->settings.interface;
1138  //Point to the logical interface
1139  logicalInterface = nicGetLogicalInterface(interface);
1140 
1141  //Discard any received packet that does not match the transaction ID
1142  if(ntohl(message->xid) != context->transactionId)
1143  return;
1144 
1145  //Check MAC address
1146  if(!macCompAddr(&message->chaddr, &logicalInterface->macAddr))
1147  return;
1148 
1149  //A DHCP server always returns its own address in the Server Identifier option
1150  serverIdOption = dhcpGetOption(message, length, DHCP_OPT_SERVER_ID);
1151 
1152  //Failed to retrieve the Server Identifier option?
1153  if(serverIdOption == NULL || serverIdOption->length != 4)
1154  return;
1155 
1156  //Check current state
1157  if(context->state == DHCP_STATE_REQUESTING ||
1158  context->state == DHCP_STATE_RENEWING)
1159  {
1160  //Check the server identifier
1161  if(!ipv4CompAddr(serverIdOption->value, &context->serverIpAddr))
1162  return;
1163  }
1164  else if(context->state == DHCP_STATE_REBOOTING ||
1165  context->state == DHCP_STATE_REBINDING)
1166  {
1167  //Do not check the server identifier
1168  }
1169  else
1170  {
1171  //Silently discard the DHCPNAK message
1172  return;
1173  }
1174 
1175  //Any registered callback?
1176  if(context->settings.parseOptionsCallback != NULL)
1177  {
1178  //Invoke user callback function
1179  error = context->settings.parseOptionsCallback(context, message, length,
1181  //Check status code
1182  if(error)
1183  return;
1184  }
1185 
1186  //The host address is no longer appropriate for the link
1187  dhcpClientResetConfig(context);
1188 
1189 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
1190  //Restart mDNS probing process
1191  mdnsResponderStartProbing(interface->mdnsResponderContext);
1192 #endif
1193 
1194  //Restart DHCP configuration
1196 }
1197 
1198 
1199 /**
1200  * @brief Manage DHCP configuration timeout
1201  * @param[in] context Pointer to the DHCP client context
1202  **/
1203 
1205 {
1206  systime_t time;
1207  NetInterface *interface;
1208 
1209  //Point to the underlying network interface
1210  interface = context->settings.interface;
1211 
1212  //Get current time
1213  time = osGetSystemTime();
1214 
1215  //Any registered callback?
1216  if(context->settings.timeoutEvent != NULL)
1217  {
1218  //DHCP configuration timeout?
1219  if(timeCompare(time, context->configStartTime + context->settings.timeout) >= 0)
1220  {
1221  //Ensure the callback function is only called once
1222  if(!context->timeoutEventDone)
1223  {
1224  //Release exclusive access
1226  //Invoke user callback function
1227  context->settings.timeoutEvent(context, interface);
1228  //Get exclusive access
1230 
1231  //Set flag
1232  context->timeoutEventDone = TRUE;
1233  }
1234  }
1235  }
1236 }
1237 
1238 
1239 /**
1240  * @brief Compute the appropriate secs field
1241  *
1242  * Compute the number of seconds elapsed since the client began address
1243  * acquisition or renewal process
1244  *
1245  * @param[in] context Pointer to the DHCP client context
1246  * @return The elapsed time expressed in seconds
1247  **/
1248 
1250 {
1251  systime_t time;
1252 
1253  //Compute the time elapsed since the DHCP configuration process started
1254  time = (osGetSystemTime() - context->configStartTime) / 1000;
1255 
1256  //The value 0xFFFF is used to represent any elapsed time values
1257  //greater than the largest time value that can be represented
1258  time = MIN(time, 0xFFFF);
1259 
1260  //Convert the 16-bit value to network byte order
1261  return htons(time);
1262 }
1263 
1264 
1265 /**
1266  * @brief Update DHCP FSM state
1267  * @param[in] context Pointer to the DHCP client context
1268  * @param[in] newState New DHCP state to switch to
1269  * @param[in] delay Initial delay
1270  **/
1271 
1273  DhcpState newState, systime_t delay)
1274 {
1275  systime_t time;
1276 
1277  //Get current time
1278  time = osGetSystemTime();
1279 
1280 #if (DHCP_TRACE_LEVEL >= TRACE_LEVEL_INFO)
1281  //Sanity check
1282  if(newState <= DHCP_STATE_REBINDING)
1283  {
1284  //DHCP FSM states
1285  static const char_t *const stateLabel[] =
1286  {
1287  "INIT",
1288  "SELECTING",
1289  "REQUESTING",
1290  "INIT-REBOOT",
1291  "REBOOTING",
1292  "PROBING",
1293  "ANNOUNCING",
1294  "BOUND",
1295  "RENEWING",
1296  "REBINDING"
1297  };
1298 
1299  //Debug message
1300  TRACE_INFO("%s: DHCP client %s state\r\n",
1301  formatSystemTime(time, NULL), stateLabel[newState]);
1302  }
1303 #endif
1304 
1305  //Set time stamp
1306  context->timestamp = time;
1307  //Set initial delay
1308  context->timeout = delay;
1309  //Reset retransmission counter
1310  context->retransmitCount = 0;
1311  //Switch to the new state
1312  context->state = newState;
1313 
1314  //Any registered callback?
1315  if(context->settings.stateChangeEvent != NULL)
1316  {
1317  NetInterface *interface;
1318 
1319  //Point to the underlying network interface
1320  interface = context->settings.interface;
1321 
1322  //Release exclusive access
1324  //Invoke user callback function
1325  context->settings.stateChangeEvent(context, interface, newState);
1326  //Get exclusive access
1328  }
1329 }
1330 
1331 
1332 /**
1333  * @brief Reset DHCP configuration
1334  * @param[in] context Pointer to the DHCP client context
1335  **/
1336 
1338 {
1339  uint_t i;
1340  uint_t j;
1341  NetInterface *interface;
1342 
1343  //Point to the underlying network interface
1344  interface = context->settings.interface;
1345  //Index of the IP address in the list of addresses assigned to the interface
1346  i = context->settings.ipAddrIndex;
1347 
1348  //The host address is not longer valid
1349  interface->ipv4Context.addrList[i].addr = IPV4_UNSPECIFIED_ADDR;
1350  interface->ipv4Context.addrList[i].state = IPV4_ADDR_STATE_INVALID;
1351 
1352  //Clear subnet mask
1353  interface->ipv4Context.addrList[i].subnetMask = IPV4_UNSPECIFIED_ADDR;
1354 
1355  //The default gateway is no longer valid
1356  interface->ipv4Context.addrList[i].defaultGateway = IPV4_UNSPECIFIED_ADDR;
1357 
1358  //Automatic DNS server configuration?
1359  if(!context->settings.manualDnsConfig)
1360  {
1361  //Loop through the list of DNS servers
1362  for(j = 0; j < IPV4_DNS_SERVER_LIST_SIZE; j++)
1363  {
1364  //The DNS server is no longer valid
1365  interface->ipv4Context.dnsServerList[j] = IPV4_UNSPECIFIED_ADDR;
1366  }
1367  }
1368 }
1369 
1370 
1371 /**
1372  * @brief Dump DHCP configuration for debugging purpose
1373  * @param[in] context Pointer to the DHCP client context
1374  **/
1375 
1377 {
1378 #if (DHCP_TRACE_LEVEL >= TRACE_LEVEL_INFO)
1379  uint_t i;
1380  uint_t j;
1381  NetInterface *interface;
1382  Ipv4Context *ipv4Context;
1383 
1384  //Point to the underlying network interface
1385  interface = context->settings.interface;
1386  //Point to the IPv4 context
1387  ipv4Context = &interface->ipv4Context;
1388 
1389  //Index of the IP address in the list of addresses assigned to the interface
1390  i = context->settings.ipAddrIndex;
1391 
1392  //Debug message
1393  TRACE_INFO("\r\n");
1394  TRACE_INFO("DHCP configuration:\r\n");
1395 
1396  //Lease start time
1397  TRACE_INFO(" Lease Start Time = %s\r\n",
1398  formatSystemTime(context->leaseStartTime, NULL));
1399 
1400  //Lease time
1401  TRACE_INFO(" Lease Time = %" PRIu32 "s\r\n", context->leaseTime);
1402  //Renewal time
1403  TRACE_INFO(" T1 = %" PRIu32 "s\r\n", context->t1);
1404  //Rebinding time
1405  TRACE_INFO(" T2 = %" PRIu32 "s\r\n", context->t2);
1406 
1407  //Host address
1408  TRACE_INFO(" IPv4 Address = %s\r\n",
1409  ipv4AddrToString(ipv4Context->addrList[i].addr, NULL));
1410 
1411  //Subnet mask
1412  TRACE_INFO(" Subnet Mask = %s\r\n",
1413  ipv4AddrToString(ipv4Context->addrList[i].subnetMask, NULL));
1414 
1415  //Default gateway
1416  TRACE_INFO(" Default Gateway = %s\r\n",
1417  ipv4AddrToString(ipv4Context->addrList[i].defaultGateway, NULL));
1418 
1419  //DNS servers
1420  for(j = 0; j < IPV4_DNS_SERVER_LIST_SIZE; j++)
1421  {
1422  TRACE_INFO(" DNS Server %u = %s\r\n", j + 1,
1423  ipv4AddrToString(ipv4Context->dnsServerList[j], NULL));
1424  }
1425 
1426  //Maximum transmit unit
1427  TRACE_INFO(" MTU = %" PRIuSIZE "\r\n", interface->ipv4Context.linkMtu);
1428  TRACE_INFO("\r\n");
1429 #endif
1430 }
1431 
1432 #endif
uint8_t message[]
Definition: chap.h:154
uint8_t type
Definition: coap_common.h:176
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
char char_t
Definition: compiler_port.h:48
#define HTONS(value)
Definition: cpu_endian.h:410
#define LOAD32BE(p)
Definition: cpu_endian.h:210
#define ntohl(value)
Definition: cpu_endian.h:422
#define htonl(value)
Definition: cpu_endian.h:414
#define htons(value)
Definition: cpu_endian.h:413
#define HTONL(value)
Definition: cpu_endian.h:411
#define LOAD16BE(p)
Definition: cpu_endian.h:186
const char_t * formatSystemTime(systime_t time, char_t *str)
Format system time.
Definition: date_time.c:77
Date and time management.
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
DHCP client (Dynamic Host Configuration Protocol)
#define DhcpClientContext
Definition: dhcp_client.h:145
DhcpState
DHCP FSM states.
Definition: dhcp_client.h:158
@ DHCP_STATE_INIT
Definition: dhcp_client.h:159
@ DHCP_STATE_BOUND
Definition: dhcp_client.h:166
@ DHCP_STATE_REBOOTING
Definition: dhcp_client.h:163
@ DHCP_STATE_SELECTING
Definition: dhcp_client.h:160
@ DHCP_STATE_ANNOUNCING
Definition: dhcp_client.h:165
@ DHCP_STATE_INIT_REBOOT
Definition: dhcp_client.h:162
@ DHCP_STATE_REQUESTING
Definition: dhcp_client.h:161
@ DHCP_STATE_PROBING
Definition: dhcp_client.h:164
@ DHCP_STATE_RENEWING
Definition: dhcp_client.h:167
@ DHCP_STATE_REBINDING
Definition: dhcp_client.h:168
void dhcpClientStateRenewing(DhcpClientContext *context)
RENEWING state.
void dhcpClientStateInit(DhcpClientContext *context)
INIT state.
void dhcpClientStateInitReboot(DhcpClientContext *context)
INIT-REBOOT state.
void dhcpClientStateSelecting(DhcpClientContext *context)
SELECTING state.
void dhcpClientStateRebooting(DhcpClientContext *context)
REBOOTING state.
void dhcpClientStateProbing(DhcpClientContext *context)
PROBING state.
void dhcpClientStateAnnouncing(DhcpClientContext *context)
ANNOUNCING state.
void dhcpClientStateRequesting(DhcpClientContext *context)
REQUESTING state.
void dhcpClientStateBound(DhcpClientContext *context)
BOUND state.
void dhcpClientStateRebinding(DhcpClientContext *context)
REBINDING state.
DHCP client finite state machine.
void dhcpClientTick(DhcpClientContext *context)
DHCP client timer handler.
const uint8_t dhcpOptionList[]
void dhcpClientParseNak(DhcpClientContext *context, const DhcpMessage *message, size_t length)
Parse DHCPNAK message.
error_t dhcpClientSendDecline(DhcpClientContext *context)
Send DHCPDECLINE message.
void dhcpClientParseAck(DhcpClientContext *context, const DhcpMessage *message, size_t length)
Parse DHCPACK message.
systime_t dhcpClientTickCounter
error_t dhcpClientSendRelease(DhcpClientContext *context)
Send DHCPRELEASE message.
error_t dhcpClientSendDiscover(DhcpClientContext *context)
Send DHCPDISCOVER message.
void dhcpClientResetConfig(DhcpClientContext *context)
Reset DHCP configuration.
void dhcpClientCheckTimeout(DhcpClientContext *context)
Manage DHCP configuration timeout.
void dhcpClientProcessMessage(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const UdpHeader *udpHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary, void *param)
Process incoming DHCP message.
void dhcpClientLinkChangeEvent(DhcpClientContext *context)
Callback function for link change event.
void dhcpClientDumpConfig(DhcpClientContext *context)
Dump DHCP configuration for debugging purpose.
void dhcpClientParseOffer(DhcpClientContext *context, const DhcpMessage *message, size_t length)
Parse DHCPOFFER message.
error_t dhcpClientSendRequest(DhcpClientContext *context)
Send DHCPREQUEST message.
void dhcpClientChangeState(DhcpClientContext *context, DhcpState newState, systime_t delay)
Update DHCP FSM state.
uint16_t dhcpClientComputeElapsedTime(DhcpClientContext *context)
Compute the appropriate secs field.
Helper functions for DHCP client.
error_t dhcpAddOption(DhcpMessage *message, size_t *messageLen, uint8_t optionCode, const void *optionValue, size_t optionLen)
Append an option to a DHCP message.
Definition: dhcp_common.c:56
DhcpOption * dhcpGetOption(const DhcpMessage *message, size_t length, uint8_t optionCode)
Search a DHCP message for a given option.
Definition: dhcp_common.c:118
Definitions common to DHCP client and server.
DhcpMessage
Definition: dhcp_common.h:226
@ DHCP_OPCODE_BOOTREPLY
Definition: dhcp_common.h:68
@ DHCP_OPCODE_BOOTREQUEST
Definition: dhcp_common.h:67
#define DHCP_CLIENT_PORT
Definition: dhcp_common.h:41
#define DHCP_MIN_MSG_SIZE
Definition: dhcp_common.h:44
@ DHCP_OPT_END
Definition: dhcp_common.h:191
@ DHCP_OPT_DHCP_MESSAGE_TYPE
Definition: dhcp_common.h:159
@ DHCP_OPT_RENEWAL_TIME_VALUE
Definition: dhcp_common.h:164
@ DHCP_OPT_IP_ADDRESS_LEASE_TIME
Definition: dhcp_common.h:157
@ DHCP_OPT_INTERFACE_MTU
Definition: dhcp_common.h:132
@ DHCP_OPT_PARAM_REQUEST_LIST
Definition: dhcp_common.h:161
@ DHCP_OPT_SERVER_ID
Definition: dhcp_common.h:160
@ DHCP_OPT_REBINDING_TIME_VALUE
Definition: dhcp_common.h:165
@ DHCP_OPT_RAPID_COMMIT
Definition: dhcp_common.h:181
@ DHCP_OPT_DNS_SERVER
Definition: dhcp_common.h:112
@ DHCP_OPT_SUBNET_MASK
Definition: dhcp_common.h:107
@ DHCP_OPT_ROUTER
Definition: dhcp_common.h:109
@ DHCP_OPT_REQUESTED_IP_ADDR
Definition: dhcp_common.h:156
#define DHCP_SERVER_PORT
Definition: dhcp_common.h:40
@ DHCP_FLAG_BROADCAST
Definition: dhcp_common.h:79
#define DHCP_HARDWARE_TYPE_ETH
Definition: dhcp_common.h:49
@ DHCP_MSG_TYPE_RELEASE
Definition: dhcp_common.h:95
@ DHCP_MSG_TYPE_OFFER
Definition: dhcp_common.h:90
@ DHCP_MSG_TYPE_REQUEST
Definition: dhcp_common.h:91
@ DHCP_MSG_TYPE_DISCOVER
Definition: dhcp_common.h:89
@ DHCP_MSG_TYPE_ACK
Definition: dhcp_common.h:93
@ DHCP_MSG_TYPE_NAK
Definition: dhcp_common.h:94
@ DHCP_MSG_TYPE_DECLINE
Definition: dhcp_common.h:92
DhcpOption
Definition: dhcp_common.h:238
#define DHCP_MAGIC_COOKIE
Definition: dhcp_common.h:51
#define DHCP_MAX_MSG_SIZE
Definition: dhcp_common.h:46
#define DHCP_INFINITE_TIME
Definition: dhcp_common.h:53
error_t dhcpDumpMessage(const DhcpMessage *message, size_t length)
Dump DHCP message for debugging purpose.
Definition: dhcp_debug.c:158
Data logging functions for debugging purpose (DHCP)
uint8_t n
uint32_t time
error_t
Error codes.
Definition: error.h:43
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
MacAddr
Definition: ethernet.h:195
Ipv4Addr destIpAddr
Definition: ipcp.h:80
Ipv4Addr srcIpAddr
Definition: ipcp.h:79
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1636
#define IPV4_BROADCAST_ADDR
Definition: ipv4.h:112
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:148
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:267
#define IPV4_MINIMUM_MTU
Definition: ipv4.h:91
@ IPV4_ADDR_STATE_INVALID
An address that is not assigned to any interface.
Definition: ipv4.h:195
@ IPV4_ADDR_STATE_VALID
An address assigned to an interface whose use is unrestricted.
Definition: ipv4.h:197
@ IPV4_ADDR_STATE_TENTATIVE
An address whose uniqueness on a link is being verified.
Definition: ipv4.h:196
#define ipv4CompAddr(ipAddr1, ipAddr2)
Definition: ipv4.h:152
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:110
#define IPV4_DNS_SERVER_LIST_SIZE
Definition: ipv4.h:76
error_t mdnsResponderStartProbing(MdnsResponderContext *context)
Restart probing process.
mDNS responder (Multicast DNS)
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netMutex
Definition: net_legacy.h:195
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:415
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:322
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:71
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
NetInterface * nicGetLogicalInterface(NetInterface *interface)
Retrieve logical interface.
Definition: nic.c:52
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:84
#define osMemset(p, value, length)
Definition: os_port.h:135
#define timeCompare(t1, t2)
Definition: os_port.h:40
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define MAX(a, b)
Definition: os_port.h:67
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t systime_t
System time.
IP network address.
Definition: ip.h:79
IP pseudo header.
Definition: ip.h:99
Ipv4Addr subnetMask
Subnet mask.
Definition: ipv4.h:347
Ipv4Addr defaultGateway
Default gateway.
Definition: ipv4.h:348
Ipv4Addr addr
IPv4 address.
Definition: ipv4.h:344
IPv4 context.
Definition: ipv4.h:371
Ipv4Addr dnsServerList[IPV4_DNS_SERVER_LIST_SIZE]
DNS servers.
Definition: ipv4.h:379
Ipv4AddrEntry addrList[IPV4_ADDR_LIST_SIZE]
IPv4 address list.
Definition: ipv4.h:378
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint8_t length
Definition: tcp.h:368
NetBuffer * udpAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a UDP packet.
Definition: udp.c:905
error_t udpSendBuffer(NetInterface *interface, const IpAddr *srcIpAddr, uint16_t srcPort, const IpAddr *destIpAddr, uint16_t destPort, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a UDP datagram.
Definition: udp.c:627
UdpHeader
Definition: udp.h:85