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