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