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