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