ipv4.c
Go to the documentation of this file.
1 /**
2  * @file ipv4.c
3  * @brief IPv4 (Internet Protocol Version 4)
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  * @section Description
28  *
29  * The Internet Protocol (IP) provides the functions necessary to deliver a
30  * datagram from a source to a destination over an interconnected system of
31  * networks. Refer to RFC 791 for complete details
32  *
33  * @author Oryx Embedded SARL (www.oryx-embedded.com)
34  * @version 2.4.0
35  **/
36 
37 //Switch to the appropriate trace level
38 #define TRACE_LEVEL IPV4_TRACE_LEVEL
39 
40 //Dependencies
41 #include "core/net.h"
42 #include "core/ethernet.h"
43 #include "core/ip.h"
44 #include "core/udp.h"
45 #include "core/tcp_fsm.h"
46 #include "core/raw_socket.h"
47 #include "ipv4/arp_cache.h"
48 #include "ipv4/ipv4.h"
49 #include "ipv4/ipv4_misc.h"
50 #include "ipv4/ipv4_routing.h"
51 #include "ipv4/icmp.h"
52 #include "ipv4/auto_ip_misc.h"
53 #include "igmp/igmp_host.h"
54 #include "dhcp/dhcp_client_misc.h"
55 #include "mdns/mdns_responder.h"
56 #include "mibs/mib2_module.h"
57 #include "mibs/ip_mib_module.h"
58 #include "debug.h"
59 
60 //IPsec supported?
61 #if (IPV4_IPSEC_SUPPORT == ENABLED)
62  #include "ipsec/ipsec.h"
63  #include "ipsec/ipsec_inbound.h"
64  #include "ipsec/ipsec_outbound.h"
65  #include "ah/ah.h"
66  #include "esp/esp.h"
67 #endif
68 
69 //Check TCP/IP stack configuration
70 #if (IPV4_SUPPORT == ENABLED)
71 
72 
73 /**
74  * @brief IPv4 related initialization
75  * @param[in] interface Underlying network interface
76  * @return Error code
77  **/
78 
80 {
81  Ipv4Context *context;
82  NetInterface *physicalInterface;
83 
84  //Point to the physical interface
85  physicalInterface = nicGetPhysicalInterface(interface);
86 
87  //Point to the IPv4 context
88  context = &interface->ipv4Context;
89 
90  //Clear the IPv4 context
91  osMemset(context, 0, sizeof(Ipv4Context));
92 
93  //Initialize interface specific variables
94  context->linkMtu = physicalInterface->nicDriver->mtu;
95  context->isRouter = FALSE;
96  context->defaultTtl = IPV4_DEFAULT_TTL;
97 
98  //ICMP Echo Request messages are allowed by default
99  context->enableEchoReq = TRUE;
100  context->enableBroadcastEchoReq = TRUE;
101 
102  //Identification field is primarily used to identify
103  //fragments of an original IP datagram
104  context->identification = 0;
105 
106  //Initialize the list of DNS servers
107  osMemset(context->dnsServerList, 0, sizeof(context->dnsServerList));
108  //Initialize the multicast filter table
109  osMemset(context->multicastFilter, 0, sizeof(context->multicastFilter));
110 
111 #if (IPV4_FRAG_SUPPORT == ENABLED)
112  //Initialize the reassembly queue
113  osMemset(context->fragQueue, 0, sizeof(context->fragQueue));
114 #endif
115 
116  //Successful initialization
117  return NO_ERROR;
118 }
119 
120 
121 /**
122  * @brief Set default TTL value for outgoing IPv4 packets
123  * @param[in] interface Underlying network interface
124  * @param[in] ttl Default time-to-live value
125  * @return Error code
126  **/
127 
129 {
130  //Check parameters
131  if(interface == NULL || ttl == 0)
133 
134  //Get exclusive access
136  //Set default time-to-live value
137  interface->ipv4Context.defaultTtl = ttl;
138  //Release exclusive access
140 
141  //Successful processing
142  return NO_ERROR;
143 }
144 
145 
146 /**
147  * @brief Assign host address
148  * @param[in] interface Pointer to the desired network interface
149  * @param[in] addr IPv4 host address
150  * @return Error code
151  **/
152 
154 {
155  //Set IPv4 host address
156  return ipv4SetHostAddrEx(interface, 0, addr);
157 }
158 
159 
160 /**
161  * @brief Assign host address
162  * @param[in] interface Pointer to the desired network interface
163  * @param[in] index Zero-based index
164  * @param[in] addr IPv4 host address
165  * @return Error code
166  **/
167 
169 {
170  Ipv4AddrEntry *entry;
171 
172  //Check parameters
173  if(interface == NULL)
175 
176  //Make sure that the index is valid
177  if(index >= IPV4_ADDR_LIST_SIZE)
178  return ERROR_OUT_OF_RANGE;
179 
180  //The IPv4 address must be a valid unicast address
182  return ERROR_INVALID_ADDRESS;
183 
184  //Get exclusive access
186 
187  //Point to the corresponding entry
188  entry = &interface->ipv4Context.addrList[index];
189 
190  //Set up host address
191  entry->addr = addr;
192  //Clear conflict flag
193  entry->conflict = FALSE;
194 
195  //Check whether the new host address is valid
197  {
198  //The use of the IPv4 address is now unrestricted
199  entry->state = IPV4_ADDR_STATE_VALID;
200  }
201  else
202  {
203  //The IPv4 address is no longer valid
205  }
206 
207 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
208  //Restart mDNS probing process
209  mdnsResponderStartProbing(interface->mdnsResponderContext);
210 #endif
211 
212  //Release exclusive access
214 
215  //Successful processing
216  return NO_ERROR;
217 }
218 
219 
220 /**
221  * @brief Retrieve host address
222  * @param[in] interface Pointer to the desired network interface
223  * @param[out] addr IPv4 host address
224  * @return Error code
225  **/
226 
228 {
229  //Get IPv4 host address
230  return ipv4GetHostAddrEx(interface, 0, addr);
231 }
232 
233 
234 /**
235  * @brief Retrieve host address
236  * @param[in] interface Pointer to the desired network interface
237  * @param[in] index Zero-based index
238  * @param[out] addr IPv4 host address
239  * @return Error code
240  **/
241 
243 {
244  Ipv4AddrEntry *entry;
245 
246  //Check parameters
247  if(interface == NULL || addr == NULL)
249 
250  //Make sure that the index is valid
251  if(index >= IPV4_ADDR_LIST_SIZE)
252  {
253  //Return the unspecified address when the index is out of range
255  //Report an error
256  return ERROR_OUT_OF_RANGE;
257  }
258 
259  //Get exclusive access
261 
262  //Point to the corresponding entry
263  entry = &interface->ipv4Context.addrList[index];
264 
265  //Check whether the host address is valid
266  if(entry->state == IPV4_ADDR_STATE_VALID)
267  {
268  //Get IPv4 address
269  *addr = entry->addr;
270  }
271  else
272  {
273  //Return the unspecified address when no address has been assigned
275  }
276 
277  //Release exclusive access
279 
280  //Successful processing
281  return NO_ERROR;
282 }
283 
284 
285 /**
286  * @brief Configure subnet mask
287  * @param[in] interface Pointer to the desired network interface
288  * @param[in] mask Subnet mask
289  * @return Error code
290  **/
291 
293 {
294  //Set subnet mask
295  return ipv4SetSubnetMaskEx(interface, 0, mask);
296 }
297 
298 
299 /**
300  * @brief Configure subnet mask
301  * @param[in] interface Pointer to the desired network interface
302  * @param[in] index Zero-based index
303  * @param[in] mask Subnet mask
304  * @return Error code
305  **/
306 
308 {
309  //Check parameters
310  if(interface == NULL)
312 
313  //Make sure that the index is valid
314  if(index >= IPV4_ADDR_LIST_SIZE)
315  return ERROR_OUT_OF_RANGE;
316 
317  //Get exclusive access
319  //Set up subnet mask
320  interface->ipv4Context.addrList[index].subnetMask = mask;
321  //Release exclusive access
323 
324  //Successful processing
325  return NO_ERROR;
326 }
327 
328 
329 /**
330  * @brief Retrieve subnet mask
331  * @param[in] interface Pointer to the desired network interface
332  * @param[out] mask Subnet mask
333  * @return Error code
334  **/
335 
337 {
338  //Get subnet mask
339  return ipv4GetSubnetMaskEx(interface, 0, mask);
340 }
341 
342 
343 /**
344  * @brief Retrieve subnet mask
345  * @param[in] interface Pointer to the desired network interface
346  * @param[in] index Zero-based index
347  * @param[out] mask Subnet mask
348  * @return Error code
349  **/
350 
352 {
353  //Check parameters
354  if(interface == NULL || mask == NULL)
356 
357  //Make sure that the index is valid
358  if(index >= IPV4_ADDR_LIST_SIZE)
359  {
360  //Return the default mask when the index is out of range
362  //Report an error
363  return ERROR_OUT_OF_RANGE;
364  }
365 
366  //Get exclusive access
368  //Get subnet mask
369  *mask = interface->ipv4Context.addrList[index].subnetMask;
370  //Release exclusive access
372 
373  //Successful processing
374  return NO_ERROR;
375 }
376 
377 
378 /**
379  * @brief Configure default gateway
380  * @param[in] interface Pointer to the desired network interface
381  * @param[in] addr Default gateway address
382  * @return Error code
383  **/
384 
386 {
387  //Set default gateway
388  return ipv4SetDefaultGatewayEx(interface, 0, addr);
389 }
390 
391 
392 /**
393  * @brief Configure default gateway
394  * @param[in] interface Pointer to the desired network interface
395  * @param[in] index Zero-based index
396  * @param[in] addr Default gateway address
397  * @return Error code
398  **/
399 
401  Ipv4Addr addr)
402 {
403  //Check parameters
404  if(interface == NULL)
406 
407  //Make sure that the index is valid
408  if(index >= IPV4_ADDR_LIST_SIZE)
409  return ERROR_OUT_OF_RANGE;
410 
411  //The IPv4 address must be a valid unicast address
413  return ERROR_INVALID_ADDRESS;
414 
415  //Get exclusive access
417  //Set up default gateway address
418  interface->ipv4Context.addrList[index].defaultGateway = addr;
419  //Release exclusive access
421 
422  //Successful processing
423  return NO_ERROR;
424 }
425 
426 
427 /**
428  * @brief Retrieve default gateway
429  * @param[in] interface Pointer to the desired network interface
430  * @param[out] addr Default gateway address
431  * @return Error code
432  **/
433 
435 {
436  //Get default gateway
437  return ipv4GetDefaultGatewayEx(interface, 0, addr);
438 }
439 
440 
441 /**
442  * @brief Retrieve default gateway
443  * @param[in] interface Pointer to the desired network interface
444  * @param[in] index Zero-based index
445  * @param[out] addr Default gateway address
446  * @return Error code
447  **/
448 
450  Ipv4Addr *addr)
451 {
452  //Check parameters
453  if(interface == NULL || addr == NULL)
455 
456  //Make sure that the index is valid
457  if(index >= IPV4_ADDR_LIST_SIZE)
458  {
459  //Return the unspecified address when the index is out of range
461  //Report an error
462  return ERROR_OUT_OF_RANGE;
463  }
464 
465  //Get exclusive access
467  //Get default gateway address
468  *addr = interface->ipv4Context.addrList[index].defaultGateway;
469  //Release exclusive access
471 
472  //Successful processing
473  return NO_ERROR;
474 }
475 
476 
477 /**
478  * @brief Configure DNS server
479  * @param[in] interface Pointer to the desired network interface
480  * @param[in] index This parameter selects between the primary and secondary DNS server
481  * @param[in] addr DNS server address
482  * @return Error code
483  **/
484 
486 {
487  //Check parameters
488  if(interface == NULL)
490 
491  //Make sure that the index is valid
492  if(index >= IPV4_DNS_SERVER_LIST_SIZE)
493  return ERROR_OUT_OF_RANGE;
494 
495  //The IPv4 address must be a valid unicast address
497  return ERROR_INVALID_ADDRESS;
498 
499  //Get exclusive access
501  //Set up DNS server address
502  interface->ipv4Context.dnsServerList[index] = addr;
503  //Release exclusive access
505 
506  //Successful processing
507  return NO_ERROR;
508 }
509 
510 
511 /**
512  * @brief Retrieve DNS server
513  * @param[in] interface Pointer to the desired network interface
514  * @param[in] index This parameter selects between the primary and secondary DNS server
515  * @param[out] addr DNS server address
516  * @return Error code
517  **/
518 
520 {
521  //Check parameters
522  if(interface == NULL || addr == NULL)
524 
525  //Make sure that the index is valid
526  if(index >= IPV4_DNS_SERVER_LIST_SIZE)
527  {
528  //Return the unspecified address when the index is out of range
530  //Report an error
531  return ERROR_OUT_OF_RANGE;
532  }
533 
534  //Get exclusive access
536  //Get DNS server address
537  *addr = interface->ipv4Context.dnsServerList[index];
538  //Release exclusive access
540 
541  //Successful processing
542  return NO_ERROR;
543 }
544 
545 
546 /**
547  * @brief Callback function for link change event
548  * @param[in] interface Underlying network interface
549  **/
550 
552 {
553  Ipv4Context *context;
554  NetInterface *physicalInterface;
555 
556  //Point to the physical interface
557  physicalInterface = nicGetPhysicalInterface(interface);
558 
559  //Point to the IPv4 context
560  context = &interface->ipv4Context;
561 
562  //Restore default MTU
563  context->linkMtu = physicalInterface->nicDriver->mtu;
564 
565 #if (ETH_SUPPORT == ENABLED)
566  //Flush ARP cache contents
567  arpFlushCache(interface);
568 #endif
569 
570 #if (IPV4_FRAG_SUPPORT == ENABLED)
571  //Flush the reassembly queue
572  ipv4FlushFragQueue(interface);
573 #endif
574 
575 #if (IGMP_HOST_SUPPORT == ENABLED || IGMP_ROUTER_SUPPORT == ENABLED || \
576  IGMP_SNOOPING_SUPPORT == ENABLED)
577  //Notify IGMP of link state changes
578  igmpLinkChangeEvent(interface);
579 #endif
580 
581 #if (AUTO_IP_SUPPORT == ENABLED)
582  //Notify Auto-IP of link state changes
583  autoIpLinkChangeEvent(interface->autoIpContext);
584 #endif
585 
586 #if (DHCP_CLIENT_SUPPORT == ENABLED)
587  //Notify the DHCP client of link state changes
588  dhcpClientLinkChangeEvent(interface->dhcpClientContext);
589 #endif
590 }
591 
592 
593 /**
594  * @brief Incoming IPv4 packet processing
595  * @param[in] interface Underlying network interface
596  * @param[in] packet Incoming IPv4 packet
597  * @param[in] length Packet length including header and payload
598  * @param[in] ancillary Additional options passed to the stack along with
599  * the packet
600  **/
601 
602 void ipv4ProcessPacket(NetInterface *interface, Ipv4Header *packet,
603  size_t length, NetRxAncillary *ancillary)
604 {
605  error_t error;
606 
607  //Initialize status code
608  error = NO_ERROR;
609 
610  //Total number of input datagrams received, including those received in error
611  MIB2_IP_INC_COUNTER32(ipInReceives, 1);
612  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInReceives, 1);
613  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInReceives, 1);
614  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInReceives, 1);
615  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInReceives, 1);
616 
617  //Total number of octets received in input IP datagrams
618  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInOctets, length);
619  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInOctets, length);
620  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInOctets, length);
621  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInOctets, length);
622 
623  //Start of exception handling block
624  do
625  {
626  //Ensure the packet length is greater than 20 bytes
627  if(length < sizeof(Ipv4Header))
628  {
629  //Discard the received packet
630  error = ERROR_INVALID_LENGTH;
631  break;
632  }
633 
634  //Debug message
635  TRACE_INFO("IPv4 packet received (%" PRIuSIZE " bytes)...\r\n", length);
636  //Dump IP header contents for debugging purpose
637  ipv4DumpHeader(packet);
638 
639  //A packet whose version number is not 4 must be silently discarded
640  if(packet->version != IPV4_VERSION)
641  {
642  //Discard the received packet
643  error = ERROR_INVALID_HEADER;
644  break;
645  }
646 
647  //Valid IPv4 header shall contains more than five 32-bit words
648  if(packet->headerLength < 5)
649  {
650  //Discard the received packet
651  error = ERROR_INVALID_HEADER;
652  break;
653  }
654 
655  //Ensure the total length is correct before processing the packet
656  if(ntohs(packet->totalLength) < (packet->headerLength * 4))
657  {
658  //Discard the received packet
659  error = ERROR_INVALID_HEADER;
660  break;
661  }
662 
663  //Truncated packet?
664  if(length < ntohs(packet->totalLength))
665  {
666  //Discard the received packet
667  error = ERROR_INVALID_LENGTH;
668  break;
669  }
670 
671  //Source address filtering
672  if(ipv4CheckSourceAddr(interface, packet->srcAddr))
673  {
674  //Discard the received packet
675  error = ERROR_INVALID_HEADER;
676  break;
677  }
678 
679 #if (IGMP_ROUTER_SUPPORT == ENABLED)
680  //Trap IGMP packets when IGMP router is enabled
681  if(interface->igmpRouterContext != NULL && ipv4TrapIgmpPacket(packet))
682  {
683  //Forward the packet to the IGMP router
684  error = NO_ERROR;
685  }
686  else
687 #endif
688 #if (IGMP_SNOOPING_SUPPORT == ENABLED)
689  //Trap IGMP packets when IGMP snooping is enabled
690  if(interface->igmpSnoopingContext != NULL && ipv4TrapIgmpPacket(packet))
691  {
692  //Forward the packet to the IGMP snooping switch
693  error = NO_ERROR;
694  }
695  else
696 #endif
697 #if (IGMP_ROUTER_SUPPORT == ENABLED && IPV4_ROUTING_SUPPORT == ENABLED)
698  //Trap multicast packets
699  if(ipv4IsMulticastAddr(packet->destAddr))
700  {
701  NetBuffer1 buffer;
702 
703  //Unfragmented datagrams fit in a single chunk
704  buffer.chunkCount = 1;
705  buffer.maxChunkCount = 1;
706  buffer.chunk[0].address = packet;
707  buffer.chunk[0].length = length;
708 
709  //Forward the multicast packet
710  ipv4ForwardPacket(interface, (NetBuffer *) &buffer, 0);
711 
712  //Destination address filtering
713  error = ipv4CheckDestAddr(interface, packet->destAddr);
714  }
715  else
716 #endif
717  {
718  //Destination address filtering
719  error = ipv4CheckDestAddr(interface, packet->destAddr);
720 
721 #if defined(IPV4_PACKET_FORWARD_HOOK)
722  IPV4_PACKET_FORWARD_HOOK(interface, packet, length);
723 #elif (IPV4_ROUTING_SUPPORT == ENABLED)
724  //Invalid destination address?
725  if(error)
726  {
727  NetBuffer1 buffer;
728 
729  //Unfragmented datagrams fit in a single chunk
730  buffer.chunkCount = 1;
731  buffer.maxChunkCount = 1;
732  buffer.chunk[0].address = packet;
733  buffer.chunk[0].length = length;
734 
735  //Forward the packet according to the routing table
736  ipv4ForwardPacket(interface, (NetBuffer *) &buffer, 0);
737  }
738 #endif
739  }
740 
741  //Invalid destination address?
742  if(error)
743  {
744  //Discard the received packet
745  error = ERROR_INVALID_ADDRESS;
746  break;
747  }
748 
749  //Packets addressed to a tentative address should be silently discarded
750  if(ipv4IsTentativeAddr(interface, packet->destAddr))
751  {
752  //Discard the received packet
753  error = ERROR_INVALID_ADDRESS;
754  break;
755  }
756 
757  //The host must verify the IP header checksum on every received datagram
758  //and silently discard every datagram that has a bad checksum (refer to
759  //RFC 1122, section 3.2.1.2)
760  if(ipCalcChecksum(packet, packet->headerLength * 4) != 0x0000)
761  {
762  //Debug message
763  TRACE_WARNING("Wrong IP header checksum!\r\n");
764 
765  //Discard incoming packet
766  error = ERROR_INVALID_HEADER;
767  break;
768  }
769 
770  //Update IP statistics
771  ipv4UpdateInStats(interface, packet->destAddr, length);
772 
773  //Convert the total length from network byte order
774  length = ntohs(packet->totalLength);
775 
776  //A fragmented packet was received?
777  if((ntohs(packet->fragmentOffset) & (IPV4_FLAG_MF | IPV4_OFFSET_MASK)) != 0)
778  {
779 #if (IPV4_FRAG_SUPPORT == ENABLED)
780  //Reassemble the original datagram
781  ipv4ReassembleDatagram(interface, packet, length, ancillary);
782 #endif
783  }
784  else
785  {
786  NetBuffer1 buffer;
787 
788  //Unfragmented datagrams fit in a single chunk
789  buffer.chunkCount = 1;
790  buffer.maxChunkCount = 1;
791  buffer.chunk[0].address = packet;
792  buffer.chunk[0].length = (uint16_t) length;
793 
794  //Pass the IPv4 datagram to the higher protocol layer
795  ipv4ProcessDatagram(interface, (NetBuffer *) &buffer, 0, ancillary);
796  }
797 
798  //End of exception handling block
799  } while(0);
800 
801  //Invalid IPv4 packet received?
802  if(error)
803  {
804  //Update IP statistics
805  ipv4UpdateErrorStats(interface, error);
806  }
807 }
808 
809 
810 /**
811  * @brief Incoming IPv4 datagram processing
812  * @param[in] interface Underlying network interface
813  * @param[in] buffer Multi-part buffer that holds the incoming IPv4 datagram
814  * @param[in] offset Offset from the beginning of the buffer
815  * @param[in] ancillary Additional options passed to the stack along with
816  * the packet
817  **/
818 
819 void ipv4ProcessDatagram(NetInterface *interface, const NetBuffer *buffer,
820  size_t offset, NetRxAncillary *ancillary)
821 {
822  error_t error;
823  size_t length;
824  Ipv4Header *header;
825  IpPseudoHeader pseudoHeader;
826 
827  //Retrieve the length of the IPv4 datagram
828  length = netBufferGetLength(buffer) - offset;
829 
830  //Point to the IPv4 header
831  header = netBufferAt(buffer, offset);
832  //Sanity check
833  if(header == NULL)
834  return;
835 
836  //Debug message
837  TRACE_INFO("IPv4 datagram received (%" PRIuSIZE " bytes)...\r\n", length);
838  //Dump IP header contents for debugging purpose
839  ipv4DumpHeader(header);
840 
841  //Get the offset to the payload
842  offset += header->headerLength * 4;
843  //Compute the length of the payload
844  length -= header->headerLength * 4;
845 
846  //Form the IPv4 pseudo header
847  pseudoHeader.length = sizeof(Ipv4PseudoHeader);
848  pseudoHeader.ipv4Data.srcAddr = header->srcAddr;
849  pseudoHeader.ipv4Data.destAddr = header->destAddr;
850  pseudoHeader.ipv4Data.reserved = 0;
851  pseudoHeader.ipv4Data.protocol = header->protocol;
852  pseudoHeader.ipv4Data.length = htons(length);
853 
854  //Save TTL value
855  ancillary->ttl = header->timeToLive;
856  //Save ToS value
857  ancillary->tos = header->typeOfService;
858 
859 #if defined(IPV4_DATAGRAM_FORWARD_HOOK)
860  IPV4_DATAGRAM_FORWARD_HOOK(interface, &pseudoHeader, buffer, offset);
861 #endif
862 
863  //Initialize status code
864  error = NO_ERROR;
865 
866 #if (IPV4_IPSEC_SUPPORT == ENABLED)
867  //Process inbound IP traffic (unprotected-to-protected)
868  error = ipsecProcessInboundIpv4Packet(interface, header, buffer, offset);
869  //Any error to report?
870  if(error)
871  return;
872 #endif
873 
874  //Check the protocol field
875  switch(header->protocol)
876  {
877  //ICMP protocol?
878  case IPV4_PROTOCOL_ICMP:
879  //Process incoming ICMP message
880  icmpProcessMessage(interface, &pseudoHeader.ipv4Data, buffer, offset);
881 
882 #if (RAW_SOCKET_SUPPORT == ENABLED)
883  //Allow raw sockets to process ICMP messages
884  rawSocketProcessIpPacket(interface, &pseudoHeader, buffer, offset,
885  ancillary);
886 #endif
887 
888  //Continue processing
889  break;
890 
891 #if (IGMP_HOST_SUPPORT == ENABLED || IGMP_ROUTER_SUPPORT == ENABLED || \
892  IGMP_SNOOPING_SUPPORT == ENABLED)
893  //IGMP protocol?
894  case IPV4_PROTOCOL_IGMP:
895  //Process incoming IGMP message
896  igmpProcessMessage(interface, &pseudoHeader.ipv4Data, buffer, offset,
897  ancillary);
898 
899 #if (RAW_SOCKET_SUPPORT == ENABLED)
900  //Allow raw sockets to process IGMP messages
901  rawSocketProcessIpPacket(interface, &pseudoHeader, buffer, offset,
902  ancillary);
903 #endif
904 
905  //Continue processing
906  break;
907 #endif
908 
909 #if (TCP_SUPPORT == ENABLED)
910  //TCP protocol?
911  case IPV4_PROTOCOL_TCP:
912  //Process incoming TCP segment
913  tcpProcessSegment(interface, &pseudoHeader, buffer, offset, ancillary);
914  //Continue processing
915  break;
916 #endif
917 
918 #if (UDP_SUPPORT == ENABLED)
919  //UDP protocol?
920  case IPV4_PROTOCOL_UDP:
921  //Process incoming UDP datagram
922  error = udpProcessDatagram(interface, &pseudoHeader, buffer, offset,
923  ancillary);
924  //Continue processing
925  break;
926 #endif
927 
928 #if (IPV4_IPSEC_SUPPORT == ENABLED && AH_SUPPORT == ENABLED)
929  //AH header?
930  case IPV4_PROTOCOL_AH:
931  //Process AH header
932  error = ipv4ProcessAhHeader(interface, header, buffer, offset,
933  ancillary);
934  //Continue processing
935  break;
936 #endif
937 
938 #if (IPV4_IPSEC_SUPPORT == ENABLED && ESP_SUPPORT == ENABLED)
939  //ESP header?
940  case IPV4_PROTOCOL_ESP:
941  //Process ESP header
942  error = ipv4ProcessEspHeader(interface, header, buffer, offset,
943  ancillary);
944  //Continue processing
945  break;
946 #endif
947 
948  //Unknown protocol?
949  default:
950 #if (RAW_SOCKET_SUPPORT == ENABLED)
951  //Allow raw sockets to process IPv4 packets
952  error = rawSocketProcessIpPacket(interface, &pseudoHeader, buffer, offset,
953  ancillary);
954 #else
955  //Report an error
957 #endif
958  //Continue processing
959  break;
960  }
961 
962  //Unreachable protocol?
963  if(error == ERROR_PROTOCOL_UNREACHABLE)
964  {
965  //Update IP statistics
966  ipv4UpdateErrorStats(interface, error);
967 
968  //Send a Destination Unreachable message
970  ICMP_CODE_PROTOCOL_UNREACHABLE, 0, buffer, 0);
971  }
972  else
973  {
974  //Total number of input datagrams successfully delivered to IP
975  //user-protocols
976  MIB2_IP_INC_COUNTER32(ipInDelivers, 1);
977  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInDelivers, 1);
978  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInDelivers, 1);
979  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInDelivers, 1);
980  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInDelivers, 1);
981  }
982 
983  //Unreachable port?
984  if(error == ERROR_PORT_UNREACHABLE)
985  {
986  //Send a Destination Unreachable message
988  ICMP_CODE_PORT_UNREACHABLE, 0, buffer, 0);
989  }
990 }
991 
992 
993 /**
994  * @brief Send an IPv4 datagram
995  * @param[in] interface Underlying network interface
996  * @param[in] pseudoHeader IPv4 pseudo header
997  * @param[in] buffer Multi-part buffer containing the payload
998  * @param[in] offset Offset to the first byte of the payload
999  * @param[in] ancillary Additional options passed to the stack along with
1000  * the packet
1001  * @return Error code
1002  **/
1003 
1005  const Ipv4PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset,
1006  NetTxAncillary *ancillary)
1007 {
1008  error_t error;
1009  uint16_t id;
1010 #if (IPV4_IPSEC_SUPPORT == DISABLED)
1011  size_t length;
1012 #endif
1013 
1014  //Total number of IP datagrams which local IP user-protocols supplied to IP
1015  //in requests for transmission
1016  MIB2_IP_INC_COUNTER32(ipOutRequests, 1);
1017  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutRequests, 1);
1018  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutRequests, 1);
1019  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutRequests, 1);
1020  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutRequests, 1);
1021 
1022  //Identification field is primarily used to identify fragments of an
1023  //original IP datagram
1024  id = interface->ipv4Context.identification++;
1025 
1026 #if (IPV4_IPSEC_SUPPORT == ENABLED)
1027  //Process outbound IP traffic (protected-to-unprotected)
1028  error = ipsecProcessOutboundIpv4Packet(interface, pseudoHeader, id, buffer,
1029  offset, ancillary);
1030 
1031  //Check status code
1032  if(error == ERROR_IN_PROGRESS)
1033  {
1034  //The establishment of the SA pair is in progress
1035  error = NO_ERROR;
1036  }
1037 #else
1038  //Retrieve the length of payload
1039  length = netBufferGetLength(buffer) - offset;
1040 
1041  //Check the length of the payload
1042  if((length + sizeof(Ipv4Header)) <= interface->ipv4Context.linkMtu)
1043  {
1044  //If the payload length is smaller than the network interface MTU
1045  //then no fragmentation is needed
1046  error = ipv4SendPacket(interface, pseudoHeader, id, 0, buffer,
1047  offset, ancillary);
1048  }
1049  else
1050  {
1051 #if (IPV4_FRAG_SUPPORT == ENABLED)
1052  //An IP datagram can be marked "don't fragment". Any IP datagram so
1053  //marked is not to be fragmented under any circumstances (refer to
1054  //RFC791, section 2.3)
1055  if(!ancillary->dontFrag)
1056  {
1057  //If the payload length exceeds the network interface MTU then the
1058  //device must fragment the data
1059  error = ipv4FragmentDatagram(interface, pseudoHeader, id, buffer,
1060  offset, ancillary);
1061  }
1062  else
1063 #endif
1064  {
1065  //If IP datagram cannot be delivered to its destination without
1066  //fragmenting it, it is to be discarded instead
1067  error = ERROR_MESSAGE_TOO_LONG;
1068  }
1069  }
1070 #endif
1071 
1072  //Return status code
1073  return error;
1074 }
1075 
1076 
1077 /**
1078  * @brief Send an IPv4 packet
1079  * @param[in] interface Underlying network interface
1080  * @param[in] pseudoHeader IPv4 pseudo header
1081  * @param[in] fragId Fragment identification field
1082  * @param[in] fragOffset Fragment offset field
1083  * @param[in] buffer Multi-part buffer containing the payload
1084  * @param[in] offset Offset to the first byte of the payload
1085  * @param[in] ancillary Additional options passed to the stack along with
1086  * the packet
1087  * @return Error code
1088  **/
1089 
1091  const Ipv4PseudoHeader *pseudoHeader, uint16_t fragId, size_t fragOffset,
1092  NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
1093 {
1094  error_t error;
1095  size_t length;
1096  Ipv4Header *packet;
1097 #if (ETH_SUPPORT == ENABLED)
1098  NetInterface *physicalInterface;
1099 #endif
1100 
1101  //Check whether an IP Router Alert option should be added
1102  if(ancillary->routerAlert)
1103  {
1104  //Add an IP Router Alert option
1105  error = ipv4AddRouterAlertOption(buffer, &offset);
1106  //Any error to report?
1107  if(error)
1108  return error;
1109  }
1110 
1111  //Sanity check
1112  if(offset < sizeof(Ipv4Header))
1113  return ERROR_INVALID_PARAMETER;
1114 
1115  //Make room for the header
1116  offset -= sizeof(Ipv4Header);
1117  //Calculate the size of the entire packet, including header and data
1118  length = netBufferGetLength(buffer) - offset;
1119 
1120  //Point to the IPv4 header
1121  packet = netBufferAt(buffer, offset);
1122 
1123  //Format IPv4 header
1124  packet->version = IPV4_VERSION;
1125  packet->headerLength = 5;
1126  packet->typeOfService = ancillary->tos;
1127  packet->totalLength = htons(length);
1128  packet->identification = htons(fragId);
1129  packet->fragmentOffset = htons(fragOffset);
1130  packet->timeToLive = ancillary->ttl;
1131  packet->protocol = pseudoHeader->protocol;
1132  packet->headerChecksum = 0;
1133  packet->srcAddr = pseudoHeader->srcAddr;
1134  packet->destAddr = pseudoHeader->destAddr;
1135 
1136  //The IHL field is the length of the IP packet header in 32-bit words, and
1137  //thus points to the beginning of the data. Note that the minimum value for
1138  //a correct header is 5 (refer to RFC 791, section 3.1)
1139  if(ancillary->routerAlert)
1140  {
1141  packet->headerLength = 6;
1142  }
1143 
1144  //An IP datagram can be marked "don't fragment"
1145  if(ancillary->dontFrag)
1146  {
1147  //Any IP datagram so marked is not to be fragmented under any
1148  //circumstances (refer to RFC791, section 2.3)
1149  packet->fragmentOffset |= HTONS(IPV4_FLAG_DF);
1150  }
1151 
1152  //Check whether the TTL value is zero
1153  if(packet->timeToLive == 0)
1154  {
1155  //Use default time-to-live value
1156  packet->timeToLive = interface->ipv4Context.defaultTtl;
1157  }
1158 
1159  //Calculate IP header checksum
1160  packet->headerChecksum = ipCalcChecksumEx(buffer, offset,
1161  packet->headerLength * 4);
1162 
1163  //Ensure the source address is valid
1164  error = ipv4CheckSourceAddr(interface, pseudoHeader->srcAddr);
1165  //Invalid source address?
1166  if(error)
1167  return error;
1168 
1169  //Check destination address
1170  if(pseudoHeader->destAddr == IPV4_UNSPECIFIED_ADDR)
1171  {
1172  //The unspecified address must not appear on the public Internet
1173  error = ERROR_INVALID_ADDRESS;
1174  }
1175  else if(ipv4IsLocalHostAddr(pseudoHeader->destAddr))
1176  {
1177 #if (NET_LOOPBACK_IF_SUPPORT == ENABLED)
1178  uint_t i;
1179 
1180  //Initialize status code
1181  error = ERROR_NO_ROUTE;
1182 
1183  //Loop through network interfaces
1184  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1185  {
1186  //Point to the current interface
1187  interface = &netInterface[i];
1188 
1189  //Loopback interface?
1190  if(interface->nicDriver != NULL &&
1191  interface->nicDriver->type == NIC_TYPE_LOOPBACK)
1192  {
1193  //Forward the packet to the loopback interface
1194  error = nicSendPacket(interface, buffer, offset, ancillary);
1195  break;
1196  }
1197  }
1198 #else
1199  //Addresses within the entire 127.0.0.0/8 block do not legitimately
1200  //appear on any network anywhere
1201  error = ERROR_NO_ROUTE;
1202 #endif
1203  }
1204  else
1205  {
1206 #if (ETH_SUPPORT == ENABLED)
1207  //Point to the physical interface
1208  physicalInterface = nicGetPhysicalInterface(interface);
1209 
1210  //Ethernet interface?
1211  if(physicalInterface->nicDriver != NULL &&
1212  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
1213  {
1215 
1216  //Get the destination IPv4 address
1217  destIpAddr = pseudoHeader->destAddr;
1218 
1219  //Perform address resolution
1220  if(!macCompAddr(&ancillary->destMacAddr, &MAC_UNSPECIFIED_ADDR))
1221  {
1222  //The destination address is already resolved
1223  error = NO_ERROR;
1224  }
1225  else if(ipv4IsBroadcastAddr(interface, destIpAddr))
1226  {
1227  //Use of the broadcast MAC address to send the packet
1228  ancillary->destMacAddr = MAC_BROADCAST_ADDR;
1229  //Successful address resolution
1230  error = NO_ERROR;
1231  }
1233  {
1234  //Map IPv4 multicast address to MAC-layer multicast address
1235  error = ipv4MapMulticastAddrToMac(destIpAddr, &ancillary->destMacAddr);
1236  }
1237  else if(ipv4IsLinkLocalAddr(pseudoHeader->srcAddr) ||
1239  {
1240  //Packets with a link-local source or destination address are not
1241  //routable off the link
1242  error = arpResolve(interface, destIpAddr, &ancillary->destMacAddr);
1243  }
1244  else if(ipv4IsOnLink(interface, destIpAddr))
1245  {
1246  //Resolve destination address before sending the packet
1247  error = arpResolve(interface, destIpAddr, &ancillary->destMacAddr);
1248  }
1249  else if(ancillary->dontRoute)
1250  {
1251  //Do not send the packet via a gateway
1252  error = arpResolve(interface, destIpAddr, &ancillary->destMacAddr);
1253  }
1254  else
1255  {
1256  //Default gateway selection
1257  error = ipv4SelectDefaultGateway(interface, pseudoHeader->srcAddr,
1258  &destIpAddr);
1259 
1260  //Check status code
1261  if(!error)
1262  {
1263  //Use the selected gateway to forward the packet
1264  error = arpResolve(interface, destIpAddr, &ancillary->destMacAddr);
1265  }
1266  else
1267  {
1268  //Number of IP datagrams discarded because no route could be found
1269  //to transmit them to their destination
1270  MIB2_IP_INC_COUNTER32(ipOutNoRoutes, 1);
1271  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutNoRoutes, 1);
1272  }
1273  }
1274 
1275  //Successful address resolution?
1276  if(error == NO_ERROR)
1277  {
1278  //Update IP statistics
1279  ipv4UpdateOutStats(interface, destIpAddr, length);
1280 
1281  //Debug message
1282  TRACE_INFO("Sending IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
1283  //Dump IP header contents for debugging purpose
1284  ipv4DumpHeader(packet);
1285 
1286  //Send Ethernet frame
1287  error = ethSendFrame(interface, &ancillary->destMacAddr,
1288  ETH_TYPE_IPV4, buffer, offset, ancillary);
1289  }
1290  else if(error == ERROR_IN_PROGRESS)
1291  {
1292  //Debug message
1293  TRACE_INFO("Enqueuing IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
1294  //Dump IP header contents for debugging purpose
1295  ipv4DumpHeader(packet);
1296 
1297  //Enqueue packets waiting for address resolution
1298  error = arpEnqueuePacket(interface, destIpAddr, buffer, offset,
1299  ancillary);
1300  }
1301  else
1302  {
1303  //Debug message
1304  TRACE_WARNING("Cannot map IPv4 address to Ethernet address!\r\n");
1305  }
1306  }
1307  else
1308 #endif
1309 #if (PPP_SUPPORT == ENABLED)
1310  //PPP interface?
1311  if(interface->nicDriver != NULL &&
1312  interface->nicDriver->type == NIC_TYPE_PPP)
1313  {
1314  //Update IP statistics
1315  ipv4UpdateOutStats(interface, pseudoHeader->destAddr, length);
1316 
1317  //Debug message
1318  TRACE_INFO("Sending IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
1319  //Dump IP header contents for debugging purpose
1320  ipv4DumpHeader(packet);
1321 
1322  //Send PPP frame
1323  error = pppSendFrame(interface, buffer, offset, PPP_PROTOCOL_IP);
1324  }
1325  else
1326 #endif
1327  //IPv4 interface?
1328  if(interface->nicDriver != NULL &&
1329  interface->nicDriver->type == NIC_TYPE_IPV4)
1330  {
1331  //Update IP statistics
1332  ipv4UpdateOutStats(interface, pseudoHeader->destAddr, length);
1333 
1334  //Debug message
1335  TRACE_INFO("Sending IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
1336  //Dump IP header contents for debugging purpose
1337  ipv4DumpHeader(packet);
1338 
1339  //Send the packet over the specified link
1340  error = nicSendPacket(interface, buffer, offset, ancillary);
1341  }
1342  //Unknown interface type?
1343  else
1344  {
1345  //Report an error
1346  error = ERROR_INVALID_INTERFACE;
1347  }
1348  }
1349 
1350  //Return status code
1351  return error;
1352 }
1353 
1354 
1355 /**
1356  * @brief Join the specified host group
1357  * @param[in] interface Underlying network interface
1358  * @param[in] groupAddr IPv4 address identifying the host group to join
1359  * @return Error code
1360  **/
1361 
1363 {
1364  error_t error;
1365  uint_t i;
1366  Ipv4FilterEntry *entry;
1367  Ipv4FilterEntry *firstFreeEntry;
1368 #if (ETH_SUPPORT == ENABLED)
1369  NetInterface *physicalInterface;
1370  MacAddr macAddr;
1371 #endif
1372 
1373  //The IPv4 address must be a valid multicast address
1375  return ERROR_INVALID_ADDRESS;
1376 
1377 #if (ETH_SUPPORT == ENABLED)
1378  //Point to the physical interface
1379  physicalInterface = nicGetPhysicalInterface(interface);
1380 #endif
1381 
1382  //Initialize error code
1383  error = NO_ERROR;
1384  //Keep track of the first free entry
1385  firstFreeEntry = NULL;
1386 
1387  //Go through the multicast filter table
1388  for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++)
1389  {
1390  //Point to the current entry
1391  entry = &interface->ipv4Context.multicastFilter[i];
1392 
1393  //Valid entry?
1394  if(entry->refCount > 0)
1395  {
1396  //Check whether the table already contains the specified IPv4 address
1397  if(entry->addr == groupAddr)
1398  {
1399  //Increment the reference count
1400  entry->refCount++;
1401  //Successful processing
1402  return NO_ERROR;
1403  }
1404  }
1405  else
1406  {
1407  //Keep track of the first free entry
1408  if(firstFreeEntry == NULL)
1409  firstFreeEntry = entry;
1410  }
1411  }
1412 
1413  //Check whether the multicast filter table is full
1414  if(firstFreeEntry == NULL)
1415  {
1416  //A new entry cannot be added
1417  return ERROR_FAILURE;
1418  }
1419 
1420 #if (ETH_SUPPORT == ENABLED)
1421  //Map the IPv4 multicast address to a MAC-layer address
1423  //Add the corresponding address to the MAC filter table
1424  error = ethAcceptMacAddr(interface, &macAddr);
1425 
1426  //Check status code
1427  if(!error)
1428  {
1429  //Virtual interface?
1430  if(interface != physicalInterface)
1431  {
1432  //Configure the physical interface to accept the MAC address
1433  error = ethAcceptMacAddr(physicalInterface, &macAddr);
1434 
1435  //Any error to report?
1436  if(error)
1437  {
1438  //Clean up side effects
1439  ethDropMacAddr(interface, &macAddr);
1440  }
1441  }
1442  }
1443 #endif
1444 
1445  //MAC filter table successfully updated?
1446  if(!error)
1447  {
1448  //Now we can safely add a new entry to the table
1449  firstFreeEntry->addr = groupAddr;
1450  //Initialize the reference count
1451  firstFreeEntry->refCount = 1;
1452 
1453 #if (IGMP_HOST_SUPPORT == ENABLED)
1454  //Report multicast group membership to the router
1455  igmpHostJoinGroup(interface, firstFreeEntry);
1456 #endif
1457  }
1458 
1459  //Return status code
1460  return error;
1461 }
1462 
1463 
1464 /**
1465  * @brief Leave the specified host group
1466  * @param[in] interface Underlying network interface
1467  * @param[in] groupAddr IPv4 address identifying the host group to leave
1468  * @return Error code
1469  **/
1470 
1472 {
1473  uint_t i;
1474  Ipv4FilterEntry *entry;
1475 #if (ETH_SUPPORT == ENABLED)
1476  NetInterface *physicalInterface;
1477  MacAddr macAddr;
1478 #endif
1479 
1480  //The IPv4 address must be a valid multicast address
1482  return ERROR_INVALID_ADDRESS;
1483 
1484 #if (ETH_SUPPORT == ENABLED)
1485  //Point to the physical interface
1486  physicalInterface = nicGetPhysicalInterface(interface);
1487 #endif
1488 
1489  //Go through the multicast filter table
1490  for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++)
1491  {
1492  //Point to the current entry
1493  entry = &interface->ipv4Context.multicastFilter[i];
1494 
1495  //Valid entry?
1496  if(entry->refCount > 0)
1497  {
1498  //Specified IPv4 address found?
1499  if(entry->addr == groupAddr)
1500  {
1501  //Decrement the reference count
1502  entry->refCount--;
1503 
1504  //Remove the entry if the reference count drops to zero
1505  if(entry->refCount == 0)
1506  {
1507 #if (IGMP_HOST_SUPPORT == ENABLED)
1508  //Report group membership termination
1509  igmpHostLeaveGroup(interface, entry);
1510 #endif
1511 #if (ETH_SUPPORT == ENABLED)
1512  //Map the IPv4 multicast address to a MAC-layer address
1514  //Drop the corresponding address from the MAC filter table
1515  ethDropMacAddr(interface, &macAddr);
1516 
1517  //Virtual interface?
1518  if(interface != physicalInterface)
1519  {
1520  //Drop the corresponding address from the MAC filter table of
1521  //the physical interface
1522  ethDropMacAddr(physicalInterface, &macAddr);
1523  }
1524 #endif
1525  //Remove the multicast address from the list
1526  entry->addr = IPV4_UNSPECIFIED_ADDR;
1527  }
1528 
1529  //Successful processing
1530  return NO_ERROR;
1531  }
1532  }
1533  }
1534 
1535  //The specified IPv4 address does not exist
1536  return ERROR_ADDRESS_NOT_FOUND;
1537 }
1538 
1539 
1540 /**
1541  * @brief Convert a dot-decimal string to a binary IPv4 address
1542  * @param[in] str NULL-terminated string representing the IPv4 address
1543  * @param[out] ipAddr Binary representation of the IPv4 address
1544  * @return Error code
1545  **/
1546 
1548 {
1549  error_t error;
1550  int_t i = 0;
1551  int_t value = -1;
1552 
1553  //Parse input string
1554  while(1)
1555  {
1556  //Decimal digit found?
1557  if(osIsdigit(*str))
1558  {
1559  //First digit to be decoded?
1560  if(value < 0)
1561  {
1562  value = 0;
1563  }
1564 
1565  //Update the value of the current byte
1566  value = (value * 10) + (*str - '0');
1567 
1568  //The resulting value shall be in range 0 to 255
1569  if(value > 255)
1570  {
1571  //The conversion failed
1572  error = ERROR_INVALID_SYNTAX;
1573  break;
1574  }
1575  }
1576  //Dot separator found?
1577  else if(*str == '.' && i < 4)
1578  {
1579  //Each dot must be preceded by a valid number
1580  if(value < 0)
1581  {
1582  //The conversion failed
1583  error = ERROR_INVALID_SYNTAX;
1584  break;
1585  }
1586 
1587  //Save the current byte
1588  ((uint8_t *) ipAddr)[i++] = value;
1589  //Prepare to decode the next byte
1590  value = -1;
1591  }
1592  //End of string detected?
1593  else if(*str == '\0' && i == 3)
1594  {
1595  //The NULL character must be preceded by a valid number
1596  if(value < 0)
1597  {
1598  //The conversion failed
1599  error = ERROR_INVALID_SYNTAX;
1600  }
1601  else
1602  {
1603  //Save the last byte of the IPv4 address
1604  ((uint8_t *) ipAddr)[i] = value;
1605  //The conversion succeeded
1606  error = NO_ERROR;
1607  }
1608 
1609  //We are done
1610  break;
1611  }
1612  //Invalid character...
1613  else
1614  {
1615  //The conversion failed
1616  error = ERROR_INVALID_SYNTAX;
1617  break;
1618  }
1619 
1620  //Point to the next character
1621  str++;
1622  }
1623 
1624  //Return status code
1625  return error;
1626 }
1627 
1628 
1629 /**
1630  * @brief Convert a binary IPv4 address to dot-decimal notation
1631  * @param[in] ipAddr Binary representation of the IPv4 address
1632  * @param[out] str NULL-terminated string representing the IPv4 address
1633  * @return Pointer to the formatted string
1634  **/
1635 
1637 {
1638  uint8_t *p;
1639  static char_t buffer[16];
1640 
1641  //If the NULL pointer is given as parameter, then the internal buffer is used
1642  if(str == NULL)
1643  str = buffer;
1644 
1645  //Cast the address to byte array
1646  p = (uint8_t *) &ipAddr;
1647  //Format IPv4 address
1648  osSprintf(str, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "", p[0], p[1], p[2], p[3]);
1649 
1650  //Return a pointer to the formatted string
1651  return str;
1652 }
1653 
1654 
1655 /**
1656  * @brief Dump IPv4 header for debugging purpose
1657  * @param[in] ipHeader Pointer to the IPv4 header
1658  **/
1659 
1660 void ipv4DumpHeader(const Ipv4Header *ipHeader)
1661 {
1662  //Dump IP header contents
1663  TRACE_DEBUG(" Version = %" PRIu8 "\r\n", ipHeader->version);
1664  TRACE_DEBUG(" Header Length = %" PRIu8 "\r\n", ipHeader->headerLength);
1665  TRACE_DEBUG(" Type Of Service = %" PRIu8 "\r\n", ipHeader->typeOfService);
1666  TRACE_DEBUG(" Total Length = %" PRIu16 "\r\n", ntohs(ipHeader->totalLength));
1667  TRACE_DEBUG(" Identification = %" PRIu16 "\r\n", ntohs(ipHeader->identification));
1668  TRACE_DEBUG(" Flags = 0x%01X\r\n", ntohs(ipHeader->fragmentOffset) >> 13);
1669  TRACE_DEBUG(" Fragment Offset = %" PRIu16 "\r\n", ntohs(ipHeader->fragmentOffset) & 0x1FFF);
1670  TRACE_DEBUG(" Time To Live = %" PRIu8 "\r\n", ipHeader->timeToLive);
1671  TRACE_DEBUG(" Protocol = %" PRIu8 "\r\n", ipHeader->protocol);
1672  TRACE_DEBUG(" Header Checksum = 0x%04" PRIX16 "\r\n", ntohs(ipHeader->headerChecksum));
1673  TRACE_DEBUG(" Src Addr = %s\r\n", ipv4AddrToString(ipHeader->srcAddr, NULL));
1674  TRACE_DEBUG(" Dest Addr = %s\r\n", ipv4AddrToString(ipHeader->destAddr, NULL));
1675 }
1676 
1677 #endif
error_t ipv4ProcessAhHeader(NetInterface *interface, const Ipv4Header *ipv4Header, const NetBuffer *buffer, size_t offset, NetRxAncillary *ancillary)
Process AH protected packet.
Definition: ah.c:60
AH (IP Authentication Header)
error_t arpResolve(NetInterface *interface, Ipv4Addr ipAddr, MacAddr *macAddr)
Address resolution using ARP protocol.
Definition: arp.c:235
error_t arpEnqueuePacket(NetInterface *interface, Ipv4Addr ipAddr, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Enqueue an IPv4 packet waiting for address resolution.
Definition: arp.c:333
void arpFlushCache(NetInterface *interface)
Flush ARP cache.
Definition: arp_cache.c:188
ARP cache management.
void autoIpLinkChangeEvent(AutoIpContext *context)
Callback function for link change event.
Definition: auto_ip_misc.c:270
Helper functions for Auto-IP.
signed int int_t
Definition: compiler_port.h:49
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 htons(value)
Definition: cpu_endian.h:413
#define ntohs(value)
Definition: cpu_endian.h:421
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_WARNING(...)
Definition: debug.h:85
#define TRACE_INFO(...)
Definition: debug.h:95
void dhcpClientLinkChangeEvent(DhcpClientContext *context)
Callback function for link change event.
Helper functions for DHCP client.
uint32_t ttl
Definition: dns_common.h:221
uint8_t fragOffset[3]
Definition: dtls_misc.h:192
error_t
Error codes.
Definition: error.h:43
@ ERROR_IN_PROGRESS
Definition: error.h:213
@ ERROR_INVALID_INTERFACE
Invalid interface.
Definition: error.h:53
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ ERROR_NO_ROUTE
Definition: error.h:219
@ ERROR_PORT_UNREACHABLE
Definition: error.h:85
@ ERROR_MESSAGE_TOO_LONG
Definition: error.h:136
@ ERROR_OUT_OF_RANGE
Definition: error.h:137
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ ERROR_INVALID_HEADER
Definition: error.h:87
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_ADDRESS_NOT_FOUND
Definition: error.h:257
@ ERROR_PROTOCOL_UNREACHABLE
Definition: error.h:84
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t ipv4ProcessEspHeader(NetInterface *interface, const Ipv4Header *ipv4Header, const NetBuffer *buffer, size_t offset, NetRxAncillary *ancillary)
Process ESP protected packet.
Definition: esp.c:61
ESP (IP Encapsulating Security Payload)
error_t ethDropMacAddr(NetInterface *interface, const MacAddr *macAddr)
Remove a unicast/multicast address from the MAC filter table.
Definition: ethernet.c:664
error_t ethSendFrame(NetInterface *interface, const MacAddr *destAddr, uint16_t type, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an Ethernet frame.
Definition: ethernet.c:399
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
error_t ethAcceptMacAddr(NetInterface *interface, const MacAddr *macAddr)
Add a unicast/multicast address to the MAC filter table.
Definition: ethernet.c:594
const MacAddr MAC_BROADCAST_ADDR
Definition: ethernet.c:55
Ethernet.
@ ETH_TYPE_IPV4
Definition: ethernet.h:164
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
MacAddr
Definition: ethernet.h:195
error_t icmpSendErrorMessage(NetInterface *interface, uint8_t type, uint8_t code, uint8_t parameter, const NetBuffer *ipPacket, size_t ipPacketOffset)
Send an ICMP Error message.
Definition: icmp.c:338
void icmpProcessMessage(NetInterface *interface, const Ipv4PseudoHeader *requestPseudoHeader, const NetBuffer *buffer, size_t offset)
Incoming ICMP message processing.
Definition: icmp.c:111
ICMP (Internet Control Message Protocol)
@ ICMP_TYPE_DEST_UNREACHABLE
Definition: icmp.h:54
@ ICMP_CODE_PROTOCOL_UNREACHABLE
Definition: icmp.h:77
@ ICMP_CODE_PORT_UNREACHABLE
Definition: icmp.h:78
void igmpLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: igmp_common.c:123
void igmpProcessMessage(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Process incoming IGMP message.
Definition: igmp_common.c:259
Ipv4Addr groupAddr
Definition: igmp_common.h:171
error_t igmpHostJoinGroup(NetInterface *interface, Ipv4FilterEntry *entry)
Join the specified host group.
Definition: igmp_host.c:87
error_t igmpHostLeaveGroup(NetInterface *interface, Ipv4FilterEntry *entry)
Leave the specified host group.
Definition: igmp_host.c:137
IGMP host.
uint16_t ipCalcChecksumEx(const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP checksum over a multi-part buffer.
Definition: ip.c:619
uint16_t ipCalcChecksum(const void *data, size_t length)
IP checksum calculation.
Definition: ip.c:499
IPv4 and IPv6 common routines.
IP MIB module.
#define IP_MIB_INC_COUNTER64(name, value)
Definition: ip_mib_module.h:47
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
Ipv4Addr ipAddr
Definition: ipcp.h:105
Ipv4Addr destIpAddr
Definition: ipcp.h:80
IPsec (IP security)
error_t ipsecProcessInboundIpv4Packet(NetInterface *interface, const Ipv4Header *ipv4Header, const NetBuffer *buffer, size_t offset)
Inbound IPv4 traffic processing.
Definition: ipsec_inbound.c:50
IPsec processing of inbound IP traffic.
error_t ipsecProcessOutboundIpv4Packet(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, uint16_t fragId, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Outbound IPv4 traffic processing.
IPsec processing of outbound IP traffic.
error_t ipv4GetDefaultGateway(NetInterface *interface, Ipv4Addr *addr)
Retrieve default gateway.
Definition: ipv4.c:434
error_t ipv4GetDefaultGatewayEx(NetInterface *interface, uint_t index, Ipv4Addr *addr)
Retrieve default gateway.
Definition: ipv4.c:449
void ipv4LinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ipv4.c:551
error_t ipv4SetDefaultGateway(NetInterface *interface, Ipv4Addr addr)
Configure default gateway.
Definition: ipv4.c:385
error_t ipv4SetSubnetMaskEx(NetInterface *interface, uint_t index, Ipv4Addr mask)
Configure subnet mask.
Definition: ipv4.c:307
error_t ipv4SetSubnetMask(NetInterface *interface, Ipv4Addr mask)
Configure subnet mask.
Definition: ipv4.c:292
error_t ipv4SendDatagram(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv4 datagram.
Definition: ipv4.c:1004
error_t ipv4SetDnsServer(NetInterface *interface, uint_t index, Ipv4Addr addr)
Configure DNS server.
Definition: ipv4.c:485
error_t ipv4Init(NetInterface *interface)
IPv4 related initialization.
Definition: ipv4.c:79
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1636
error_t ipv4SetHostAddr(NetInterface *interface, Ipv4Addr addr)
Assign host address.
Definition: ipv4.c:153
error_t ipv4SetDefaultTtl(NetInterface *interface, uint8_t ttl)
Set default TTL value for outgoing IPv4 packets.
Definition: ipv4.c:128
error_t ipv4GetHostAddrEx(NetInterface *interface, uint_t index, Ipv4Addr *addr)
Retrieve host address.
Definition: ipv4.c:242
error_t ipv4StringToAddr(const char_t *str, Ipv4Addr *ipAddr)
Convert a dot-decimal string to a binary IPv4 address.
Definition: ipv4.c:1547
void ipv4DumpHeader(const Ipv4Header *ipHeader)
Dump IPv4 header for debugging purpose.
Definition: ipv4.c:1660
error_t ipv4GetSubnetMask(NetInterface *interface, Ipv4Addr *mask)
Retrieve subnet mask.
Definition: ipv4.c:336
error_t ipv4LeaveMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr)
Leave the specified host group.
Definition: ipv4.c:1471
error_t ipv4SetHostAddrEx(NetInterface *interface, uint_t index, Ipv4Addr addr)
Assign host address.
Definition: ipv4.c:168
void ipv4ProcessPacket(NetInterface *interface, Ipv4Header *packet, size_t length, NetRxAncillary *ancillary)
Incoming IPv4 packet processing.
Definition: ipv4.c:602
error_t ipv4JoinMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr)
Join the specified host group.
Definition: ipv4.c:1362
error_t ipv4GetHostAddr(NetInterface *interface, Ipv4Addr *addr)
Retrieve host address.
Definition: ipv4.c:227
error_t ipv4SendPacket(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, uint16_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv4 packet.
Definition: ipv4.c:1090
void ipv4ProcessDatagram(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetRxAncillary *ancillary)
Incoming IPv4 datagram processing.
Definition: ipv4.c:819
error_t ipv4GetDnsServer(NetInterface *interface, uint_t index, Ipv4Addr *addr)
Retrieve DNS server.
Definition: ipv4.c:519
error_t ipv4GetSubnetMaskEx(NetInterface *interface, uint_t index, Ipv4Addr *mask)
Retrieve subnet mask.
Definition: ipv4.c:351
error_t ipv4SetDefaultGatewayEx(NetInterface *interface, uint_t index, Ipv4Addr addr)
Configure default gateway.
Definition: ipv4.c:400
IPv4 (Internet Protocol Version 4)
#define Ipv4PseudoHeader
Definition: ipv4.h:39
@ IPV4_PROTOCOL_IGMP
Definition: ipv4.h:221
@ IPV4_PROTOCOL_AH
Definition: ipv4.h:225
@ IPV4_PROTOCOL_ESP
Definition: ipv4.h:224
@ IPV4_PROTOCOL_UDP
Definition: ipv4.h:223
@ IPV4_PROTOCOL_ICMP
Definition: ipv4.h:220
@ IPV4_PROTOCOL_TCP
Definition: ipv4.h:222
#define IPV4_DEFAULT_TTL
Definition: ipv4.h:62
#define Ipv4Header
Definition: ipv4.h:36
#define IPV4_ADDR_LIST_SIZE
Definition: ipv4.h:69
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:267
@ 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_FLAG_MF
Definition: ipv4.h:209
@ IPV4_OFFSET_MASK
Definition: ipv4.h:210
@ IPV4_FLAG_DF
Definition: ipv4.h:208
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:110
#define ipv4IsMulticastAddr(ipAddr)
Definition: ipv4.h:168
#define IPV4_VERSION
Definition: ipv4.h:89
#define IPV4_MULTICAST_FILTER_SIZE
Definition: ipv4.h:83
#define IPV4_DNS_SERVER_LIST_SIZE
Definition: ipv4.h:76
#define ipv4IsLinkLocalAddr(ipAddr)
Definition: ipv4.h:164
void ipv4ReassembleDatagram(NetInterface *interface, const Ipv4Header *packet, size_t length, NetRxAncillary *ancillary)
IPv4 datagram reassembly algorithm.
Definition: ipv4_frag.c:184
error_t ipv4FragmentDatagram(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, uint16_t id, const NetBuffer *payload, size_t payloadOffset, NetTxAncillary *ancillary)
Fragment an IPv4 datagram into smaller packets.
Definition: ipv4_frag.c:72
void ipv4FlushFragQueue(NetInterface *interface)
Flush IPv4 reassembly queue.
Definition: ipv4_frag.c:661
error_t ipv4CheckSourceAddr(NetInterface *interface, Ipv4Addr ipAddr)
Source IPv4 address filtering.
Definition: ipv4_misc.c:93
void ipv4UpdateOutStats(NetInterface *interface, Ipv4Addr destIpAddr, size_t length)
Update IPv4 output statistics.
Definition: ipv4_misc.c:874
bool_t ipv4IsBroadcastAddr(NetInterface *interface, Ipv4Addr ipAddr)
Check whether an IPv4 address is a broadcast address.
Definition: ipv4_misc.c:471
bool_t ipv4IsLocalHostAddr(Ipv4Addr ipAddr)
Check whether the specified IPv4 is assigned to the host.
Definition: ipv4_misc.c:564
error_t ipv4MapMulticastAddrToMac(Ipv4Addr ipAddr, MacAddr *macAddr)
Map an host group address to a MAC-layer multicast address.
Definition: ipv4_misc.c:770
error_t ipv4AddRouterAlertOption(NetBuffer *buffer, size_t *offset)
Append a Router Alert option to an IPv4 packet.
Definition: ipv4_misc.c:53
void ipv4UpdateErrorStats(NetInterface *interface, error_t error)
Update Ethernet error statistics.
Definition: ipv4_misc.c:928
error_t ipv4SelectDefaultGateway(NetInterface *interface, Ipv4Addr srcAddr, Ipv4Addr *defaultGatewayAddr)
Default gateway selection.
Definition: ipv4_misc.c:391
bool_t ipv4IsOnLink(NetInterface *interface, Ipv4Addr ipAddr)
Check whether an IPv4 address is on-link.
Definition: ipv4_misc.c:433
bool_t ipv4IsTentativeAddr(NetInterface *interface, Ipv4Addr ipAddr)
Check whether an IPv4 address is a tentative address.
Definition: ipv4_misc.c:525
void ipv4UpdateInStats(NetInterface *interface, Ipv4Addr destIpAddr, size_t length)
Update IPv4 input statistics.
Definition: ipv4_misc.c:833
error_t ipv4CheckDestAddr(NetInterface *interface, Ipv4Addr ipAddr)
Destination IPv4 address filtering.
Definition: ipv4_misc.c:117
bool_t ipv4TrapIgmpPacket(Ipv4Header *header)
Trap IGMP packets.
Definition: ipv4_misc.c:803
Helper functions for IPv4.
IPv4 routing.
error_t ipv4ForwardPacket(NetInterface *srcInterface, const NetBuffer *ipPacket, size_t ipPacketOffset)
error_t mdnsResponderStartProbing(MdnsResponderContext *context)
Restart probing process.
mDNS responder (Multicast DNS)
MIB-II module.
#define MIB2_IP_INC_COUNTER32(name, value)
Definition: mib2_module.h:164
Ipv4Addr addr
Definition: nbns_common.h:123
uint8_t p
Definition: ndp.h:300
TCP/IP stack core.
#define NET_INTERFACE_COUNT
Definition: net.h:113
#define NetInterface
Definition: net.h:36
#define netMutex
Definition: net_legacy.h:195
#define netInterface
Definition: net_legacy.h:199
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:415
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
error_t nicSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet to the network controller.
Definition: nic.c:280
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:84
@ NIC_TYPE_LOOPBACK
Loopback interface.
Definition: nic.h:88
@ NIC_TYPE_IPV4
IPv4 interface.
Definition: nic.h:85
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
@ NIC_TYPE_PPP
PPP interface.
Definition: nic.h:84
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osSprintf(dest,...)
Definition: os_port.h:231
#define osIsdigit(c)
Definition: os_port.h:279
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1035
@ PPP_PROTOCOL_IP
Internet Protocol.
Definition: ppp.h:199
error_t rawSocketProcessIpPacket(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Process incoming IP packet.
Definition: raw_socket.c:67
TCP/IP raw sockets.
uint16_t length
Definition: net_mem.h:79
void * address
Definition: net_mem.h:78
IP pseudo header.
Definition: ip.h:99
Ipv4PseudoHeader ipv4Data
Definition: ip.h:104
size_t length
Definition: ip.h:100
IPv4 address entry.
Definition: ipv4.h:343
Ipv4AddrState state
IPv4 address state.
Definition: ipv4.h:345
bool_t conflict
Address conflict detected.
Definition: ipv4.h:346
Ipv4Addr addr
IPv4 address.
Definition: ipv4.h:344
IPv4 context.
Definition: ipv4.h:371
uint16_t identification
IPv4 fragment identification field.
Definition: ipv4.h:377
bool_t isRouter
A flag indicating whether routing is enabled on this interface.
Definition: ipv4.h:373
Ipv4Addr dnsServerList[IPV4_DNS_SERVER_LIST_SIZE]
DNS servers.
Definition: ipv4.h:379
bool_t enableEchoReq
Support for ICMP Echo Request messages.
Definition: ipv4.h:375
uint8_t defaultTtl
Default time-to-live value.
Definition: ipv4.h:374
Ipv4FilterEntry multicastFilter[IPV4_MULTICAST_FILTER_SIZE]
Multicast filter table.
Definition: ipv4.h:380
bool_t enableBroadcastEchoReq
Support for broadcast ICMP Echo Request messages.
Definition: ipv4.h:376
Ipv4FragDesc fragQueue[IPV4_MAX_FRAG_DATAGRAMS]
IPv4 fragment reassembly queue.
Definition: ipv4.h:382
size_t linkMtu
Maximum transmission unit.
Definition: ipv4.h:372
IPv4 multicast filter entry.
Definition: ipv4.h:357
Ipv4Addr addr
Multicast address.
Definition: ipv4.h:358
uint_t refCount
Reference count for the current entry.
Definition: ipv4.h:359
uint_t chunkCount
Definition: net_mem.h:98
uint_t maxChunkCount
Definition: net_mem.h:99
ChunkDesc chunk[1]
Definition: net_mem.h:100
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369
void tcpProcessSegment(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Incoming TCP segment processing.
Definition: tcp_fsm.c:73
TCP finite state machine.
error_t udpProcessDatagram(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Incoming UDP datagram processing.
Definition: udp.c:123
UDP (User Datagram Protocol)
uint8_t mask
Definition: web_socket.h:319