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  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * The Internet Protocol (IP) provides the functions necessary to deliver a
28  * datagram from a source to a destination over an interconnected system of
29  * networks. Refer to RFC 791 for complete details
30  *
31  * @author Oryx Embedded SARL (www.oryx-embedded.com)
32  * @version 1.9.0
33  **/
34 
35 //Switch to the appropriate trace level
36 #define TRACE_LEVEL IPV4_TRACE_LEVEL
37 
38 //Dependencies
39 #include <string.h>
40 #include <ctype.h>
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.h"
48 #include "ipv4/ipv4.h"
49 #include "ipv4/ipv4_routing.h"
50 #include "ipv4/icmp.h"
51 #include "ipv4/igmp.h"
52 #include "ipv4/auto_ip.h"
53 #include "dhcp/dhcp_client.h"
54 #include "mdns/mdns_responder.h"
55 #include "mibs/mib2_module.h"
56 #include "mibs/ip_mib_module.h"
57 #include "debug.h"
58 
59 //Check TCP/IP stack configuration
60 #if (IPV4_SUPPORT == ENABLED)
61 
62 
63 /**
64  * @brief IPv4 related initialization
65  * @param[in] interface Underlying network interface
66  * @return Error code
67  **/
68 
70 {
71  Ipv4Context *context;
72  NetInterface *physicalInterface;
73 
74  //Point to the physical interface
75  physicalInterface = nicGetPhysicalInterface(interface);
76 
77  //Point to the IPv4 context
78  context = &interface->ipv4Context;
79 
80  //Clear the IPv4 context
81  memset(context, 0, sizeof(Ipv4Context));
82 
83  //Initialize interface specific variables
84  context->linkMtu = physicalInterface->nicDriver->mtu;
85  context->isRouter = FALSE;
86 
87  //Identification field is primarily used to identify
88  //fragments of an original IP datagram
89  context->identification = 0;
90 
91  //Initialize the list of DNS servers
92  memset(context->dnsServerList, 0, sizeof(context->dnsServerList));
93  //Initialize the multicast filter table
94  memset(context->multicastFilter, 0, sizeof(context->multicastFilter));
95 
96 #if (IPV4_FRAG_SUPPORT == ENABLED)
97  //Initialize the reassembly queue
98  memset(context->fragQueue, 0, sizeof(context->fragQueue));
99 #endif
100 
101  //Successful initialization
102  return NO_ERROR;
103 }
104 
105 
106 /**
107  * @brief Assign host address
108  * @param[in] interface Pointer to the desired network interface
109  * @param[in] addr IPv4 host address
110  * @return Error code
111  **/
112 
114 {
115  //Check parameters
116  if(interface == NULL)
118 
119  //The IPv4 address must be a valid unicast address
121  return ERROR_INVALID_ADDRESS;
122 
123  //Get exclusive access
125 
126  //Set up host address
127  interface->ipv4Context.addr = addr;
128  //Clear conflict flag
129  interface->ipv4Context.addrConflict = FALSE;
130 
131  //Check whether the new host address is valid
133  {
134  //The use of the IPv4 address is now unrestricted
135  interface->ipv4Context.addrState = IPV4_ADDR_STATE_VALID;
136  }
137  else
138  {
139  //The IPv4 address is no longer valid
140  interface->ipv4Context.addrState = IPV4_ADDR_STATE_INVALID;
141  }
142 
143 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
144  //Restart mDNS probing process
145  mdnsResponderStartProbing(interface->mdnsResponderContext);
146 #endif
147 
148  //Release exclusive access
150 
151  //Successful processing
152  return NO_ERROR;
153 }
154 
155 
156 /**
157  * @brief Retrieve host address
158  * @param[in] interface Pointer to the desired network interface
159  * @param[out] addr IPv4 host address
160  * @return Error code
161  **/
162 
164 {
165  //Check parameters
166  if(interface == NULL || addr == NULL)
168 
169  //Get exclusive access
171 
172  //Check whether the host address is valid
173  if(interface->ipv4Context.addrState == IPV4_ADDR_STATE_VALID)
174  {
175  //Get IPv4 address
176  *addr = interface->ipv4Context.addr;
177  }
178  else
179  {
180  //Return the unspecified address when no address has been assigned
182  }
183 
184  //Release exclusive access
186 
187  //Successful processing
188  return NO_ERROR;
189 }
190 
191 
192 /**
193  * @brief Configure subnet mask
194  * @param[in] interface Pointer to the desired network interface
195  * @param[in] mask Subnet mask
196  * @return Error code
197  **/
198 
200 {
201  //Check parameters
202  if(interface == NULL)
204 
205  //Get exclusive access
207  //Set up subnet mask
208  interface->ipv4Context.subnetMask = mask;
209  //Release exclusive access
211 
212  //Successful processing
213  return NO_ERROR;
214 }
215 
216 
217 /**
218  * @brief Retrieve subnet mask
219  * @param[in] interface Pointer to the desired network interface
220  * @param[out] mask Subnet mask
221  * @return Error code
222  **/
223 
225 {
226  //Check parameters
227  if(interface == NULL || mask == NULL)
229 
230  //Get exclusive access
232  //Get subnet mask
233  *mask = interface->ipv4Context.subnetMask;
234  //Release exclusive access
236 
237  //Successful processing
238  return NO_ERROR;
239 }
240 
241 
242 /**
243  * @brief Configure default gateway
244  * @param[in] interface Pointer to the desired network interface
245  * @param[in] addr Default gateway address
246  * @return Error code
247  **/
248 
250 {
251  //Check parameters
252  if(interface == NULL)
254 
255  //The IPv4 address must be a valid unicast address
257  return ERROR_INVALID_ADDRESS;
258 
259  //Get exclusive access
261  //Set up default gateway address
262  interface->ipv4Context.defaultGateway = addr;
263  //Release exclusive access
265 
266  //Successful processing
267  return NO_ERROR;
268 }
269 
270 
271 /**
272  * @brief Retrieve default gateway
273  * @param[in] interface Pointer to the desired network interface
274  * @param[out] addr Default gateway address
275  * @return Error code
276  **/
277 
279 {
280  //Check parameters
281  if(interface == NULL || addr == NULL)
283 
284  //Get exclusive access
286  //Get default gateway address
287  *addr = interface->ipv4Context.defaultGateway;
288  //Release exclusive access
290 
291  //Successful processing
292  return NO_ERROR;
293 }
294 
295 
296 /**
297  * @brief Configure DNS server
298  * @param[in] interface Pointer to the desired network interface
299  * @param[in] index This parameter selects between the primary and secondary DNS server
300  * @param[in] addr DNS server address
301  * @return Error code
302  **/
303 
305 {
306  //Check parameters
307  if(interface == NULL)
309 
310  //Make sure that the index is valid
311  if(index >= IPV4_DNS_SERVER_LIST_SIZE)
312  return ERROR_OUT_OF_RANGE;
313 
314  //The IPv4 address must be a valid unicast address
316  return ERROR_INVALID_ADDRESS;
317 
318  //Get exclusive access
320  //Set up DNS server address
321  interface->ipv4Context.dnsServerList[index] = addr;
322  //Release exclusive access
324 
325  //Successful processing
326  return NO_ERROR;
327 }
328 
329 
330 /**
331  * @brief Retrieve DNS server
332  * @param[in] interface Pointer to the desired network interface
333  * @param[in] index This parameter selects between the primary and secondary DNS server
334  * @param[out] addr DNS server address
335  * @return Error code
336  **/
337 
339 {
340  //Check parameters
341  if(interface == NULL || addr == NULL)
343 
344  //Make sure that the index is valid
345  if(index >= IPV4_DNS_SERVER_LIST_SIZE)
346  {
347  //Return the unspecified address when the index is out of range
349  //Report an error
350  return ERROR_OUT_OF_RANGE;
351  }
352 
353  //Get exclusive access
355  //Get DNS server address
356  *addr = interface->ipv4Context.dnsServerList[index];
357  //Release exclusive access
359 
360  //Successful processing
361  return NO_ERROR;
362 }
363 
364 
365 /**
366  * @brief Get IPv4 broadcast address
367  * @param[in] interface Pointer to the desired network interface
368  * @param[out] addr IPv4 broadcast address
369  **/
370 
372 {
373  //Check parameters
374  if(interface == NULL || addr == NULL)
376 
377  //The broadcast address is obtained by performing a bitwise OR operation
378  //between the bit complement of the subnet mask and the host IP address
379  *addr = interface->ipv4Context.addr;
380  *addr |= ~interface->ipv4Context.subnetMask;
381 
382  //Successful processing
383  return NO_ERROR;
384 }
385 
386 
387 /**
388  * @brief Callback function for link change event
389  * @param[in] interface Underlying network interface
390  **/
391 
393 {
394  Ipv4Context *context;
395  NetInterface *physicalInterface;
396 
397  //Point to the physical interface
398  physicalInterface = nicGetPhysicalInterface(interface);
399 
400  //Point to the IPv4 context
401  context = &interface->ipv4Context;
402 
403  //Restore default MTU
404  context->linkMtu = physicalInterface->nicDriver->mtu;
405 
406 #if (ETH_SUPPORT == ENABLED)
407  //Flush ARP cache contents
408  arpFlushCache(interface);
409 #endif
410 
411 #if (IPV4_FRAG_SUPPORT == ENABLED)
412  //Flush the reassembly queue
413  ipv4FlushFragQueue(interface);
414 #endif
415 
416 #if (IGMP_SUPPORT == ENABLED)
417  //Notify IGMP of link state changes
418  igmpLinkChangeEvent(interface);
419 #endif
420 
421 #if (AUTO_IP_SUPPORT == ENABLED)
422  //Notify Auto-IP of link state changes
423  autoIpLinkChangeEvent(interface->autoIpContext);
424 #endif
425 
426 #if (DHCP_CLIENT_SUPPORT == ENABLED)
427  //Notify the DHCP client of link state changes
428  dhcpClientLinkChangeEvent(interface->dhcpClientContext);
429 #endif
430 }
431 
432 
433 /**
434  * @brief Incoming IPv4 packet processing
435  * @param[in] interface Underlying network interface
436  * @param[in] packet Incoming IPv4 packet
437  * @param[in] length Packet length including header and payload
438  **/
439 
440 void ipv4ProcessPacket(NetInterface *interface, Ipv4Header *packet, size_t length)
441 {
442  //Total number of input datagrams received, including those received in error
443  MIB2_INC_COUNTER32(ipGroup.ipInReceives, 1);
444  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInReceives, 1);
445  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInReceives, 1);
446  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInReceives, 1);
447  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInReceives, 1);
448 
449  //Total number of octets received in input IP datagrams
450  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInOctets, length);
451  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInOctets, length);
452  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInOctets, length);
453  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInOctets, length);
454 
455  //Ensure the packet length is greater than 20 bytes
456  if(length < sizeof(Ipv4Header))
457  {
458  //Number of input IP datagrams discarded because the datagram frame
459  //didn't carry enough data
460  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInTruncatedPkts, 1);
461  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInTruncatedPkts, 1);
462 
463  //Discard the received packet
464  return;
465  }
466 
467  //Debug message
468  TRACE_INFO("IPv4 packet received (%" PRIuSIZE " bytes)...\r\n", length);
469  //Dump IP header contents for debugging purpose
470  ipv4DumpHeader(packet);
471 
472  //A packet whose version number is not 4 must be silently discarded
473  if(packet->version != IPV4_VERSION)
474  {
475  //Number of input datagrams discarded due to errors in their IP headers
476  MIB2_INC_COUNTER32(ipGroup.ipInHdrErrors, 1);
477  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInHdrErrors, 1);
478  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInHdrErrors, 1);
479 
480  //Discard the received packet
481  return;
482  }
483 
484  //Valid IPv4 header shall contains more than five 32-bit words
485  if(packet->headerLength < 5)
486  {
487  //Number of input datagrams discarded due to errors in their IP headers
488  MIB2_INC_COUNTER32(ipGroup.ipInHdrErrors, 1);
489  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInHdrErrors, 1);
490  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInHdrErrors, 1);
491 
492  //Discard the received packet
493  return;
494  }
495 
496  //Ensure the total length is correct before processing the packet
497  if(ntohs(packet->totalLength) < (packet->headerLength * 4))
498  {
499  //Number of input datagrams discarded due to errors in their IP headers
500  MIB2_INC_COUNTER32(ipGroup.ipInHdrErrors, 1);
501  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInHdrErrors, 1);
502  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInHdrErrors, 1);
503 
504  //Discard the received packet
505  return;
506  }
507 
508  //Truncated packet?
509  if(length < ntohs(packet->totalLength))
510  {
511  //Number of input IP datagrams discarded because the datagram frame
512  //didn't carry enough data
513  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInTruncatedPkts, 1);
514  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInTruncatedPkts, 1);
515 
516  //Discard the received packet
517  return;
518  }
519 
520  //Source address filtering
521  if(ipv4CheckSourceAddr(interface, packet->srcAddr))
522  {
523  //Number of input datagrams discarded due to errors in their IP headers
524  MIB2_INC_COUNTER32(ipGroup.ipInHdrErrors, 1);
525  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInHdrErrors, 1);
526  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInHdrErrors, 1);
527 
528  //Discard the received packet
529  return;
530  }
531 
532 #if defined(IPV4_PACKET_FORWARD_HOOK)
533  IPV4_PACKET_FORWARD_HOOK(interface, packet, length);
534 #else
535  //Destination address filtering
536  if(ipv4CheckDestAddr(interface, packet->destAddr))
537  {
538 #if (IPV4_ROUTING_SUPPORT == ENABLED)
539  NetBuffer1 buffer;
540 
541  //Unfragmented datagrams fit in a single chunk
542  buffer.chunkCount = 1;
543  buffer.maxChunkCount = 1;
544  buffer.chunk[0].address = packet;
545  buffer.chunk[0].length = length;
546 
547  //Forward the packet according to the routing table
548  ipv4ForwardPacket(interface, (NetBuffer *) &buffer, 0);
549 #else
550  //Number of input datagrams discarded because the destination IP address
551  //was not a valid address
552  MIB2_INC_COUNTER32(ipGroup.ipInAddrErrors, 1);
553  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInAddrErrors, 1);
554  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInAddrErrors, 1);
555 #endif
556  //We are done
557  return;
558  }
559 #endif
560 
561  //Packets addressed to a tentative address should be silently discarded
562  if(ipv4IsTentativeAddr(interface, packet->destAddr))
563  {
564  //Number of input datagrams discarded because the destination IP address
565  //was not a valid address
566  MIB2_INC_COUNTER32(ipGroup.ipInAddrErrors, 1);
567  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInAddrErrors, 1);
568  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInAddrErrors, 1);
569 
570  //Discard the received packet
571  return;
572  }
573 
574  //The host must verify the IP header checksum on every received
575  //datagram and silently discard every datagram that has a bad
576  //checksum (see RFC 1122 3.2.1.2)
577  if(ipCalcChecksum(packet, packet->headerLength * 4) != 0x0000)
578  {
579  //Debug message
580  TRACE_WARNING("Wrong IP header checksum!\r\n");
581 
582  //Number of input datagrams discarded due to errors in their IP headers
583  MIB2_INC_COUNTER32(ipGroup.ipInHdrErrors, 1);
584  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInHdrErrors, 1);
585  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInHdrErrors, 1);
586 
587  //Discard incoming packet
588  return;
589  }
590 
591  //Update IP statistics
592  ipv4UpdateInStats(interface, packet->destAddr, length);
593 
594  //Convert the total length from network byte order
595  length = ntohs(packet->totalLength);
596 
597  //A fragmented packet was received?
598  if(ntohs(packet->fragmentOffset) & (IPV4_FLAG_MF | IPV4_OFFSET_MASK))
599  {
600 #if (IPV4_FRAG_SUPPORT == ENABLED)
601  //Reassemble the original datagram
602  ipv4ReassembleDatagram(interface, packet, length);
603 #endif
604  }
605  else
606  {
607  NetBuffer1 buffer;
608 
609  //Unfragmented datagrams fit in a single chunk
610  buffer.chunkCount = 1;
611  buffer.maxChunkCount = 1;
612  buffer.chunk[0].address = packet;
613  buffer.chunk[0].length = (uint16_t) length;
614 
615  //Pass the IPv4 datagram to the higher protocol layer
616  ipv4ProcessDatagram(interface, (NetBuffer *) &buffer);
617  }
618 }
619 
620 
621 /**
622  * @brief Incoming IPv4 datagram processing
623  * @param[in] interface Underlying network interface
624  * @param[in] buffer Multi-part buffer that holds the incoming IPv4 datagram
625  **/
626 
627 void ipv4ProcessDatagram(NetInterface *interface, const NetBuffer *buffer)
628 {
629  error_t error;
630  size_t offset;
631  size_t length;
632  Ipv4Header *header;
633  IpPseudoHeader pseudoHeader;
634 
635  //Retrieve the length of the IPv4 datagram
636  length = netBufferGetLength(buffer);
637 
638  //Point to the IPv4 header
639  header = netBufferAt(buffer, 0);
640  //Sanity check
641  if(header == NULL)
642  return;
643 
644  //Debug message
645  TRACE_INFO("IPv4 datagram received (%" PRIuSIZE " bytes)...\r\n", length);
646  //Dump IP header contents for debugging purpose
647  ipv4DumpHeader(header);
648 
649  //Get the offset to the payload
650  offset = header->headerLength * 4;
651  //Compute the length of the payload
652  length -= header->headerLength * 4;
653 
654  //Form the IPv4 pseudo header
655  pseudoHeader.length = sizeof(Ipv4PseudoHeader);
656  pseudoHeader.ipv4Data.srcAddr = header->srcAddr;
657  pseudoHeader.ipv4Data.destAddr = header->destAddr;
658  pseudoHeader.ipv4Data.reserved = 0;
659  pseudoHeader.ipv4Data.protocol = header->protocol;
660  pseudoHeader.ipv4Data.length = htons(length);
661 
662 #if defined(IPV4_DATAGRAM_FORWARD_HOOK)
663  IPV4_DATAGRAM_FORWARD_HOOK(interface, &pseudoHeader, buffer, offset);
664 #endif
665 
666  //Check the protocol field
667  switch(header->protocol)
668  {
669  //ICMP protocol?
670  case IPV4_PROTOCOL_ICMP:
671  //Process incoming ICMP message
672  icmpProcessMessage(interface, header->srcAddr, buffer, offset);
673 #if (RAW_SOCKET_SUPPORT == ENABLED)
674  //Allow raw sockets to process ICMP messages
675  rawSocketProcessIpPacket(interface, &pseudoHeader, buffer, offset);
676 #endif
677  //No error to report
678  error = NO_ERROR;
679  //Continue processing
680  break;
681 
682 #if (IGMP_SUPPORT == ENABLED)
683  //IGMP protocol?
684  case IPV4_PROTOCOL_IGMP:
685  //Process incoming IGMP message
686  igmpProcessMessage(interface, buffer, offset);
687 #if (RAW_SOCKET_SUPPORT == ENABLED)
688  //Allow raw sockets to process IGMP messages
689  rawSocketProcessIpPacket(interface, &pseudoHeader, buffer, offset);
690 #endif
691  //No error to report
692  error = NO_ERROR;
693  //Continue processing
694  break;
695 #endif
696 
697 #if (TCP_SUPPORT == ENABLED)
698  //TCP protocol?
699  case IPV4_PROTOCOL_TCP:
700  //Process incoming TCP segment
701  tcpProcessSegment(interface, &pseudoHeader, buffer, offset);
702  //No error to report
703  error = NO_ERROR;
704  //Continue processing
705  break;
706 #endif
707 
708 #if (UDP_SUPPORT == ENABLED)
709  //UDP protocol?
710  case IPV4_PROTOCOL_UDP:
711  //Process incoming UDP datagram
712  error = udpProcessDatagram(interface, &pseudoHeader, buffer, offset);
713  //Continue processing
714  break;
715 #endif
716 
717  //Unknown protocol?
718  default:
719 #if (RAW_SOCKET_SUPPORT == ENABLED)
720  //Allow raw sockets to process IPv4 packets
721  error = rawSocketProcessIpPacket(interface, &pseudoHeader, buffer, offset);
722 #else
723  //Report an error
725 #endif
726  //Continue processing
727  break;
728  }
729 
730  //Unreachable protocol?
731  if(error == ERROR_PROTOCOL_UNREACHABLE)
732  {
733  //Number of locally-addressed datagrams received successfully but discarded
734  //because of an unknown or unsupported protocol
735  MIB2_INC_COUNTER32(ipGroup.ipInUnknownProtos, 1);
736  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInUnknownProtos, 1);
737  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInUnknownProtos, 1);
738 
739  //Send a Destination Unreachable message
741  ICMP_CODE_PROTOCOL_UNREACHABLE, 0, buffer, 0);
742  }
743  else
744  {
745  //Total number of input datagrams successfully delivered to IP
746  //user-protocols
747  MIB2_INC_COUNTER32(ipGroup.ipInDelivers, 1);
748  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInDelivers, 1);
749  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInDelivers, 1);
750  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInDelivers, 1);
751  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInDelivers, 1);
752  }
753 
754  //Unreachable port?
755  if(error == ERROR_PORT_UNREACHABLE)
756  {
757  //Send a Destination Unreachable message
759  ICMP_CODE_PORT_UNREACHABLE, 0, buffer, 0);
760  }
761 }
762 
763 
764 /**
765  * @brief Send an IPv4 datagram
766  * @param[in] interface Underlying network interface
767  * @param[in] pseudoHeader IPv4 pseudo header
768  * @param[in] buffer Multi-part buffer containing the payload
769  * @param[in] offset Offset to the first byte of the payload
770  * @param[in] ttl TTL value. Default Time-To-Live is used when this parameter is zero
771  * @return Error code
772  **/
773 
775  NetBuffer *buffer, size_t offset, uint8_t ttl)
776 {
777  error_t error;
778  size_t length;
779  uint16_t id;
780 
781  //Total number of IP datagrams which local IP user-protocols supplied to IP
782  //in requests for transmission
783  MIB2_INC_COUNTER32(ipGroup.ipOutRequests, 1);
784  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutRequests, 1);
785  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutRequests, 1);
786  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutRequests, 1);
787  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutRequests, 1);
788 
789  //Retrieve the length of payload
790  length = netBufferGetLength(buffer) - offset;
791 
792  //Check whether the TTL value is zero
793  if(ttl == 0)
794  {
795  //Use default Time-To-Live value
797  }
798 
799  //Identification field is primarily used to identify
800  //fragments of an original IP datagram
801  id = interface->ipv4Context.identification++;
802 
803  //If the payload length is smaller than the network
804  //interface MTU then no fragmentation is needed
805  if((length + sizeof(Ipv4Header)) <= interface->ipv4Context.linkMtu)
806  {
807  //Send data as is
808  error = ipv4SendPacket(interface,
809  pseudoHeader, id, 0, buffer, offset, ttl);
810  }
811  //If the payload length exceeds the network interface MTU
812  //then the device must fragment the data
813  else
814  {
815 #if (IPV4_FRAG_SUPPORT == ENABLED)
816  //Fragment IP datagram into smaller packets
817  error = ipv4FragmentDatagram(interface,
818  pseudoHeader, id, buffer, offset, ttl);
819 #else
820  //Fragmentation is not supported
821  error = ERROR_MESSAGE_TOO_LONG;
822 #endif
823  }
824 
825  //Return status code
826  return error;
827 }
828 
829 
830 /**
831  * @brief Send an IPv4 packet
832  * @param[in] interface Underlying network interface
833  * @param[in] pseudoHeader IPv4 pseudo header
834  * @param[in] fragId Fragment identification field
835  * @param[in] fragOffset Fragment offset field
836  * @param[in] buffer Multi-part buffer containing the payload
837  * @param[in] offset Offset to the first byte of the payload
838  * @param[in] ttl Time-To-Live value
839  * @return Error code
840  **/
841 
843  uint16_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset, uint8_t ttl)
844 {
845  error_t error;
846  size_t length;
847  Ipv4Header *packet;
848 #if (ETH_SUPPORT == ENABLED)
849  NetInterface *physicalInterface;
850 #endif
851 
852  //Is there enough space for the IPv4 header?
853  if(offset < sizeof(Ipv4Header))
855 
856  //Make room for the header
857  offset -= sizeof(Ipv4Header);
858  //Calculate the size of the entire packet, including header and data
859  length = netBufferGetLength(buffer) - offset;
860 
861  //Point to the IPv4 header
862  packet = netBufferAt(buffer, offset);
863 
864  //Format IPv4 header
865  packet->version = IPV4_VERSION;
866  packet->headerLength = 5;
867  packet->typeOfService = 0;
868  packet->totalLength = htons(length);
869  packet->identification = htons(fragId);
870  packet->fragmentOffset = htons(fragOffset);
871  packet->timeToLive = ttl;
872  packet->protocol = pseudoHeader->protocol;
873  packet->headerChecksum = 0;
874  packet->srcAddr = pseudoHeader->srcAddr;
875  packet->destAddr = pseudoHeader->destAddr;
876 
877  //Calculate IP header checksum
878  packet->headerChecksum = ipCalcChecksumEx(buffer, offset, packet->headerLength * 4);
879 
880  //Ensure the source address is valid
881  error = ipv4CheckSourceAddr(interface, pseudoHeader->srcAddr);
882  //Invalid source address?
883  if(error)
884  return error;
885 
886  //Destination address is the unspecified address?
887  if(pseudoHeader->destAddr == IPV4_UNSPECIFIED_ADDR)
888  {
889  //Destination address is not acceptable
890  return ERROR_INVALID_ADDRESS;
891  }
892  //Destination address is the loopback address?
893  else if(pseudoHeader->destAddr == IPV4_LOOPBACK_ADDR)
894  {
895  //Check source address
896  if(pseudoHeader->srcAddr != IPV4_LOOPBACK_ADDR)
897  {
898  //Destination address is not acceptable
899  return ERROR_INVALID_ADDRESS;
900  }
901  }
902 
903 #if (ETH_SUPPORT == ENABLED)
904  //Point to the physical interface
905  physicalInterface = nicGetPhysicalInterface(interface);
906 
907  //Ethernet interface?
908  if(physicalInterface->nicDriver != NULL &&
909  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
910  {
912  MacAddr destMacAddr;
913 
914  //Get the destination IPv4 address
915  destIpAddr = pseudoHeader->destAddr;
916 
917  //Destination address is a broadcast address?
918  if(ipv4IsBroadcastAddr(interface, destIpAddr))
919  {
920  //Use of the broadcast MAC address to send the packet
921  destMacAddr = MAC_BROADCAST_ADDR;
922  //No error to report
923  error = NO_ERROR;
924  }
925  //Destination address is a multicast address?
927  {
928  //Map IPv4 multicast address to MAC-layer multicast address
929  error = ipv4MapMulticastAddrToMac(destIpAddr, &destMacAddr);
930  }
931  //Source or destination address is a link-local address?
932  else if(ipv4IsLinkLocalAddr(pseudoHeader->srcAddr) ||
934  {
935  //Packets with a link-local source or destination address are not
936  //routable off the link
937  error = arpResolve(interface, destIpAddr, &destMacAddr);
938  }
939  //Destination host is on the local subnet?
940  else if(ipv4IsOnLocalSubnet(interface, destIpAddr))
941  {
942  //Resolve destination address before sending the packet
943  error = arpResolve(interface, destIpAddr, &destMacAddr);
944  }
945  //Destination host is outside the local subnet?
946  else
947  {
948  //Make sure the default gateway is properly set
949  if(interface->ipv4Context.defaultGateway != IPV4_UNSPECIFIED_ADDR)
950  {
951  //Use the default gateway to forward the packet
952  destIpAddr = interface->ipv4Context.defaultGateway;
953  //Perform address resolution
954  error = arpResolve(interface, destIpAddr, &destMacAddr);
955  }
956  else
957  {
958  //Number of IP datagrams discarded because no route could be found
959  //to transmit them to their destination
960  MIB2_INC_COUNTER32(ipGroup.ipOutNoRoutes, 1);
961  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutNoRoutes, 1);
962 
963  //Report an error
964  error = ERROR_NO_ROUTE;
965  }
966  }
967 
968  //Successful address resolution?
969  if(!error)
970  {
971  //Update IP statistics
972  ipv4UpdateOutStats(interface, destIpAddr, length);
973 
974  //Debug message
975  TRACE_INFO("Sending IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
976  //Dump IP header contents for debugging purpose
977  ipv4DumpHeader(packet);
978 
979  //Send Ethernet frame
980  error = ethSendFrame(interface, &destMacAddr, buffer, offset, ETH_TYPE_IPV4);
981  }
982  //Address resolution is in progress?
983  else if(error == ERROR_IN_PROGRESS)
984  {
985  //Debug message
986  TRACE_INFO("Enqueuing IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
987  //Dump IP header contents for debugging purpose
988  ipv4DumpHeader(packet);
989 
990  //Enqueue packets waiting for address resolution
991  error = arpEnqueuePacket(interface, destIpAddr, buffer, offset);
992  }
993  //Address resolution failed?
994  else
995  {
996  //Debug message
997  TRACE_WARNING("Cannot map IPv4 address to Ethernet address!\r\n");
998  }
999  }
1000  else
1001 #endif
1002 #if (PPP_SUPPORT == ENABLED)
1003  //PPP interface?
1004  if(interface->nicDriver != NULL &&
1005  interface->nicDriver->type == NIC_TYPE_PPP)
1006  {
1007  //Update IP statistics
1008  ipv4UpdateOutStats(interface, pseudoHeader->destAddr, length);
1009 
1010  //Debug message
1011  TRACE_INFO("Sending IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
1012  //Dump IP header contents for debugging purpose
1013  ipv4DumpHeader(packet);
1014 
1015  //Send PPP frame
1016  error = pppSendFrame(interface, buffer, offset, PPP_PROTOCOL_IP);
1017  }
1018  else
1019 #endif
1020  //Unknown interface type?
1021  {
1022  //Report an error
1023  error = ERROR_INVALID_INTERFACE;
1024  }
1025 
1026  //Return status code
1027  return error;
1028 }
1029 
1030 
1031 /**
1032  * @brief Source IPv4 address filtering
1033  * @param[in] interface Underlying network interface
1034  * @param[in] ipAddr Source IPv4 address to be checked
1035  * @return Error code
1036  **/
1037 
1039 {
1040  //Broadcast and multicast addresses must not be used as source
1041  //address (see RFC 1122 3.2.1.3)
1043  {
1044  //Debug message
1045  TRACE_WARNING("Wrong source IPv4 address!\r\n");
1046  //The source address not is acceptable
1047  return ERROR_INVALID_ADDRESS;
1048  }
1049 
1050  //The source address is acceptable
1051  return NO_ERROR;
1052 }
1053 
1054 
1055 /**
1056  * @brief Destination IPv4 address filtering
1057  * @param[in] interface Underlying network interface
1058  * @param[in] ipAddr Destination IPv4 address to be checked
1059  * @return Error code
1060  **/
1061 
1063 {
1064  error_t error;
1065  uint_t i;
1066  Ipv4FilterEntry *entry;
1067 
1068  //Filter out any invalid addresses
1069  error = ERROR_INVALID_ADDRESS;
1070 
1071  //Broadcast address?
1072  if(ipv4IsBroadcastAddr(interface, ipAddr))
1073  {
1074  //Always accept broadcast address
1075  error = NO_ERROR;
1076  }
1077  //Multicast address?
1078  else if(ipv4IsMulticastAddr(ipAddr))
1079  {
1080  //Go through the multicast filter table
1081  for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++)
1082  {
1083  //Point to the current entry
1084  entry = &interface->ipv4Context.multicastFilter[i];
1085 
1086  //Valid entry?
1087  if(entry->refCount > 0)
1088  {
1089  //Check whether the destination IPv4 address matches
1090  //a relevant multicast address
1091  if(entry->addr == ipAddr)
1092  {
1093  //The multicast address is acceptable
1094  error = NO_ERROR;
1095  //Stop immediately
1096  break;
1097  }
1098  }
1099  }
1100  }
1101  //Unicast address?
1102  else
1103  {
1104  //Valid host address?
1105  if(interface->ipv4Context.addrState != IPV4_ADDR_STATE_INVALID)
1106  {
1107  //Check whether the destination address matches the host address
1108  if(interface->ipv4Context.addr == ipAddr)
1109  {
1110  //The destination address is acceptable
1111  error = NO_ERROR;
1112  }
1113  }
1114  }
1115 
1116  //Return status code
1117  return error;
1118 }
1119 
1120 
1121 /**
1122  * @brief IPv4 source address selection
1123  *
1124  * This function selects the source address and the relevant network interface
1125  * to be used in order to join the specified destination address
1126  *
1127  * @param[in,out] interface A pointer to a valid network interface may be provided as
1128  * a hint. The function returns a pointer identifying the interface to be used
1129  * @param[in] destAddr Destination IPv4 address
1130  * @param[out] srcAddr Local IPv4 address to be used
1131  * @return Error code
1132  **/
1133 
1136 {
1137  uint_t i;
1138  NetInterface *currentInterface;
1139  NetInterface *bestInterface;
1140 
1141  //Initialize variables
1142  bestInterface = NULL;
1143 
1144  //Loop through network interfaces
1145  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1146  {
1147  //Point to the current interface
1148  currentInterface = &netInterface[i];
1149 
1150  //A network interface may be provided as a hint...
1151  if(*interface != currentInterface && *interface != NULL)
1152  {
1153  //Select the next interface in the list
1154  continue;
1155  }
1156 
1157  //Check the state of the address
1158  if(currentInterface->ipv4Context.addrState != IPV4_ADDR_STATE_VALID)
1159  {
1160  //Select the next interface in the list
1161  continue;
1162  }
1163 
1164  //Select the first interface as default
1165  if(bestInterface == NULL)
1166  {
1167  //Give the current interface the higher precedence
1168  bestInterface = currentInterface;
1169  //Select the next interface in the list
1170  continue;
1171  }
1172 
1173  //Prefer same address
1174  if(bestInterface->ipv4Context.addr == destAddr)
1175  {
1176  //Select the next interface in the list
1177  continue;
1178  }
1179  else if(currentInterface->ipv4Context.addr == destAddr)
1180  {
1181  //Give the current interface the higher precedence
1182  bestInterface = currentInterface;
1183  //Select the next interface in the list
1184  continue;
1185  }
1186 
1187  //Check whether the destination address matches the default gateway
1188  if(bestInterface->ipv4Context.defaultGateway == destAddr)
1189  {
1190  //Select the next interface in the list
1191  continue;
1192  }
1193  else if(currentInterface->ipv4Context.defaultGateway == destAddr)
1194  {
1195  //Give the current interface the higher precedence
1196  bestInterface = currentInterface;
1197  //Select the next interface in the list
1198  continue;
1199  }
1200 
1201  //Prefer appropriate scope
1202  if(ipv4GetAddrScope(currentInterface->ipv4Context.addr) <
1203  ipv4GetAddrScope(bestInterface->ipv4Context.addr))
1204  {
1205  if(ipv4GetAddrScope(currentInterface->ipv4Context.addr) >=
1207  {
1208  //Give the current interface the higher precedence
1209  bestInterface = currentInterface;
1210  }
1211 
1212  //Select the next interface in the list
1213  continue;
1214  }
1215  else if(ipv4GetAddrScope(bestInterface->ipv4Context.addr) <
1216  ipv4GetAddrScope(currentInterface->ipv4Context.addr))
1217  {
1218  if(ipv4GetAddrScope(bestInterface->ipv4Context.addr) <
1220  {
1221  //Give the current interface the higher precedence
1222  bestInterface = currentInterface;
1223  }
1224 
1225  //Select the next interface in the list
1226  continue;
1227  }
1228 
1229  //Prefer appropriate subnet mask
1230  if(ipv4IsOnLocalSubnet(bestInterface, destAddr))
1231  {
1232  //Select the next interface in the list
1233  continue;
1234  }
1235  else if(ipv4IsOnLocalSubnet(currentInterface, destAddr))
1236  {
1237  //Give the current interface the higher precedence
1238  bestInterface = currentInterface;
1239  //Select the next interface in the list
1240  continue;
1241  }
1242 
1243  //Use longest subnet mask
1244  if(ntohl(currentInterface->ipv4Context.subnetMask) >
1245  ntohl(bestInterface->ipv4Context.subnetMask))
1246  {
1247  //Give the current interface the higher precedence
1248  bestInterface = currentInterface;
1249  }
1250  }
1251 
1252  //Source address selection failed?
1253  if(bestInterface == NULL)
1254  {
1255  //Report an error
1256  return ERROR_NO_ADDRESS;
1257  }
1258 
1259  //Return the out-going interface and the source address to be used
1260  *interface = bestInterface;
1261  *srcAddr = bestInterface->ipv4Context.addr;
1262 
1263  //Successful source address selection
1264  return NO_ERROR;
1265 }
1266 
1267 
1268 /**
1269  * @brief Check whether an IPv4 address is a broadcast address
1270  * @param[in] interface Underlying network interface
1271  * @param[in] ipAddr IPv4 address to be checked
1272  * @return TRUE if the IPv4 address is a broadcast address, else FALSE
1273  **/
1274 
1276 {
1277  //Check whether the specified IPv4 address is the broadcast address
1279  return TRUE;
1280 
1281  //Check whether the specified IPv4 address belongs to the local network
1282  if(ipv4IsOnLocalSubnet(interface, ipAddr))
1283  {
1284  //Make sure the subnet mask is not 255.255.255.255
1285  if(interface->ipv4Context.subnetMask != IPV4_BROADCAST_ADDR)
1286  {
1287  //Directed broadcast address?
1288  if((ipAddr | interface->ipv4Context.subnetMask) == IPV4_BROADCAST_ADDR)
1289  return TRUE;
1290  }
1291  }
1292 
1293  //The specified IPv4 address is not a broadcast address
1294  return FALSE;
1295 }
1296 
1297 
1298 /**
1299  * @brief Retrieve the scope of an IPv4 address
1300  * @param[in] ipAddr IPv4 address
1301  * @return IPv4 address scope
1302  **/
1303 
1305 {
1306  uint_t scope;
1307 
1308  //Broadcast address?
1310  {
1311  //The broadcast address is never forwarded by the routers connecting
1312  //the local network to other networks
1314  }
1315  //Multicast address?
1316  else if(ipv4IsMulticastAddr(ipAddr))
1317  {
1318  //Local Network Control Block?
1320  {
1321  //Addresses in the Local Network Control Block are used for protocol
1322  //control traffic that is not forwarded off link
1324  }
1325  //Any other multicast address?
1326  else
1327  {
1328  //Other addresses are assigned global scope
1329  scope = IPV4_ADDR_SCOPE_GLOBAL;
1330  }
1331  }
1332  //Unicast address?
1333  else
1334  {
1335  //Loopback address?
1337  {
1338  //IPv4 loopback addresses, which have the prefix 127.0.0.0/8,
1339  //are assigned interface-local scope
1341  }
1342  //Link-local address?
1344  {
1345  //IPv4 auto-configuration addresses, which have the prefix
1346  //169.254.0.0/16, are assigned link-local scope
1348  }
1349  //Any other unicast address?
1350  else
1351  {
1352  //Other addresses are assigned global scope
1353  scope = IPV4_ADDR_SCOPE_GLOBAL;
1354  }
1355  }
1356 
1357  //Return the scope of the specified IPv4 address
1358  return scope;
1359 }
1360 
1361 
1362 /**
1363  * @brief Calculate prefix length for a given subnet mask
1364  * @param[in] mask Subnet mask
1365  * @return Prefix length
1366  **/
1367 
1369 {
1370  uint_t i;
1371 
1372  //Convert from network byte order to host byte order
1373  mask = ntohl(mask);
1374 
1375  //Count of the number of leading 1 bits in the network mask
1376  for(i = 0; i < 32; i++)
1377  {
1378  //Check the value of the current bit
1379  if(!(mask & (1 << (31 - i))))
1380  break;
1381  }
1382 
1383  //Return prefix length
1384  return i;
1385 }
1386 
1387 
1388 /**
1389  * @brief Join the specified host group
1390  * @param[in] interface Underlying network interface
1391  * @param[in] groupAddr IPv4 address identifying the host group to join
1392  * @return Error code
1393  **/
1394 
1396 {
1397  error_t error;
1398  uint_t i;
1399  Ipv4FilterEntry *entry;
1400  Ipv4FilterEntry *firstFreeEntry;
1401 #if (ETH_SUPPORT == ENABLED)
1402  NetInterface *physicalInterface;
1403  MacAddr macAddr;
1404 #endif
1405 
1406  //The IPv4 address must be a valid multicast address
1408  return ERROR_INVALID_ADDRESS;
1409 
1410 #if (ETH_SUPPORT == ENABLED)
1411  //Point to the physical interface
1412  physicalInterface = nicGetPhysicalInterface(interface);
1413 #endif
1414 
1415  //Initialize error code
1416  error = NO_ERROR;
1417  //Keep track of the first free entry
1418  firstFreeEntry = NULL;
1419 
1420  //Go through the multicast filter table
1421  for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++)
1422  {
1423  //Point to the current entry
1424  entry = &interface->ipv4Context.multicastFilter[i];
1425 
1426  //Valid entry?
1427  if(entry->refCount > 0)
1428  {
1429  //Check whether the table already contains the specified IPv4 address
1430  if(entry->addr == groupAddr)
1431  {
1432  //Increment the reference count
1433  entry->refCount++;
1434  //Successful processing
1435  return NO_ERROR;
1436  }
1437  }
1438  else
1439  {
1440  //Keep track of the first free entry
1441  if(firstFreeEntry == NULL)
1442  firstFreeEntry = entry;
1443  }
1444  }
1445 
1446  //Check whether the multicast filter table is full
1447  if(firstFreeEntry == NULL)
1448  {
1449  //A new entry cannot be added
1450  return ERROR_FAILURE;
1451  }
1452 
1453 #if (ETH_SUPPORT == ENABLED)
1454  //Map the IPv4 multicast address to a MAC-layer address
1456  //Add the corresponding address to the MAC filter table
1457  error = ethAcceptMacAddr(interface, &macAddr);
1458 
1459  //Check status code
1460  if(!error)
1461  {
1462  //Virtual interface?
1463  if(interface != physicalInterface)
1464  {
1465  //Configure the physical interface to accept the MAC address
1466  error = ethAcceptMacAddr(physicalInterface, &macAddr);
1467 
1468  //Any error to report?
1469  if(error)
1470  {
1471  //Clean up side effects
1472  ethDropMacAddr(interface, &macAddr);
1473  }
1474  }
1475  }
1476 #endif
1477 
1478  //MAC filter table successfully updated?
1479  if(!error)
1480  {
1481  //Now we can safely add a new entry to the table
1482  firstFreeEntry->addr = groupAddr;
1483  //Initialize the reference count
1484  firstFreeEntry->refCount = 1;
1485 
1486 #if (IGMP_SUPPORT == ENABLED)
1487  //Report multicast group membership to the router
1488  igmpJoinGroup(interface, firstFreeEntry);
1489 #endif
1490  }
1491 
1492  //Return status code
1493  return error;
1494 }
1495 
1496 
1497 /**
1498  * @brief Leave the specified host group
1499  * @param[in] interface Underlying network interface
1500  * @param[in] groupAddr IPv4 address identifying the host group to leave
1501  * @return Error code
1502  **/
1503 
1505 {
1506  uint_t i;
1507  Ipv4FilterEntry *entry;
1508 #if (ETH_SUPPORT == ENABLED)
1509  NetInterface *physicalInterface;
1510  MacAddr macAddr;
1511 #endif
1512 
1513  //The IPv4 address must be a valid multicast address
1515  return ERROR_INVALID_ADDRESS;
1516 
1517 #if (ETH_SUPPORT == ENABLED)
1518  //Point to the physical interface
1519  physicalInterface = nicGetPhysicalInterface(interface);
1520 #endif
1521 
1522  //Go through the multicast filter table
1523  for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++)
1524  {
1525  //Point to the current entry
1526  entry = &interface->ipv4Context.multicastFilter[i];
1527 
1528  //Valid entry?
1529  if(entry->refCount > 0)
1530  {
1531  //Specified IPv4 address found?
1532  if(entry->addr == groupAddr)
1533  {
1534  //Decrement the reference count
1535  entry->refCount--;
1536 
1537  //Remove the entry if the reference count drops to zero
1538  if(entry->refCount == 0)
1539  {
1540 #if (IGMP_SUPPORT == ENABLED)
1541  //Report group membership termination
1542  igmpLeaveGroup(interface, entry);
1543 #endif
1544 #if (ETH_SUPPORT == ENABLED)
1545  //Map the IPv4 multicast address to a MAC-layer address
1547  //Drop the corresponding address from the MAC filter table
1548  ethDropMacAddr(interface, &macAddr);
1549 
1550  //Virtual interface?
1551  if(interface != physicalInterface)
1552  {
1553  //Drop the corresponding address from the MAC filter table of
1554  //the physical interface
1555  ethDropMacAddr(physicalInterface, &macAddr);
1556  }
1557 #endif
1558  //Remove the multicast address from the list
1559  entry->addr = IPV4_UNSPECIFIED_ADDR;
1560  }
1561 
1562  //Successful processing
1563  return NO_ERROR;
1564  }
1565  }
1566  }
1567 
1568  //The specified IPv4 address does not exist
1569  return ERROR_ADDRESS_NOT_FOUND;
1570 }
1571 
1572 
1573 /**
1574  * @brief Map an host group address to a MAC-layer multicast address
1575  * @param[in] ipAddr IPv4 host group address
1576  * @param[out] macAddr Corresponding MAC-layer multicast address
1577  * @return Error code
1578  **/
1579 
1581 {
1582  uint8_t *p;
1583 
1584  //Ensure the specified IPv4 address is a valid host group address
1586  return ERROR_INVALID_ADDRESS;
1587 
1588  //Cast the address to byte array
1589  p = (uint8_t *) &ipAddr;
1590 
1591  //An IP host group address is mapped to an Ethernet multicast address
1592  //by placing the low-order 23-bits of the IP address into the low-order
1593  //23 bits of the Ethernet multicast address 01-00-5E-00-00-00
1594  macAddr->b[0] = 0x01;
1595  macAddr->b[1] = 0x00;
1596  macAddr->b[2] = 0x5E;
1597  macAddr->b[3] = p[1] & 0x7F;
1598  macAddr->b[4] = p[2];
1599  macAddr->b[5] = p[3];
1600 
1601  //The specified host group address was successfully
1602  //mapped to a MAC-layer address
1603  return NO_ERROR;
1604 }
1605 
1606 
1607 /**
1608  * @brief Update IPv4 input statistics
1609  * @param[in] interface Underlying network interface
1610  * @param[in] destIpAddr Destination IP address
1611  * @param[in] length Length of the incoming IP packet
1612  **/
1613 
1615 {
1616  //Check whether the destination address is a unicast, broadcast or multicast address
1617  if(ipv4IsBroadcastAddr(interface, destIpAddr))
1618  {
1619  //Number of IP broadcast datagrams transmitted
1620  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInBcastPkts, 1);
1621  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInBcastPkts, 1);
1622  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInBcastPkts, 1);
1623  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInBcastPkts, 1);
1624  }
1626  {
1627  //Number of IP multicast datagrams transmitted
1628  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInMcastPkts, 1);
1629  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInMcastPkts, 1);
1630  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInMcastPkts, 1);
1631  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInMcastPkts, 1);
1632 
1633  //Total number of octets transmitted in IP multicast datagrams
1634  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInMcastOctets, length);
1635  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInMcastOctets, length);
1636  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInMcastOctets, length);
1637  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInMcastOctets, length);
1638  }
1639 }
1640 
1641 
1642 /**
1643  * @brief Update IPv4 output statistics
1644  * @param[in] interface Underlying network interface
1645  * @param[in] destIpAddr Destination IP address
1646  * @param[in] length Length of the outgoing IP packet
1647  **/
1648 
1650 {
1651  //Check whether the destination address is a unicast, broadcast or multicast address
1652  if(ipv4IsBroadcastAddr(interface, destIpAddr))
1653  {
1654  //Number of IP broadcast datagrams transmitted
1655  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutBcastPkts, 1);
1656  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutBcastPkts, 1);
1657  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutBcastPkts, 1);
1658  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutBcastPkts, 1);
1659  }
1661  {
1662  //Number of IP multicast datagrams transmitted
1663  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutMcastPkts, 1);
1664  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutMcastPkts, 1);
1665  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutMcastPkts, 1);
1666  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutMcastPkts, 1);
1667 
1668  //Total number of octets transmitted in IP multicast datagrams
1669  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutMcastOctets, length);
1670  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutMcastOctets, length);
1671  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutMcastOctets, length);
1672  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutMcastOctets, length);
1673  }
1674 
1675  //Total number of IP datagrams that this entity supplied to the lower
1676  //layers for transmission
1677  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutTransmits, 1);
1678  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutTransmits, 1);
1679  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutTransmits, 1);
1680  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutTransmits, 1);
1681 
1682  //Total number of octets in IP datagrams delivered to the lower layers
1683  //for transmission
1684  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutOctets, length);
1685  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutOctets, length);
1686  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutOctets, length);
1687  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutOctets, length);
1688 }
1689 
1690 
1691 /**
1692  * @brief Convert a dot-decimal string to a binary IPv4 address
1693  * @param[in] str NULL-terminated string representing the IPv4 address
1694  * @param[out] ipAddr Binary representation of the IPv4 address
1695  * @return Error code
1696  **/
1697 
1699 {
1700  error_t error;
1701  int_t i = 0;
1702  int_t value = -1;
1703 
1704  //Parse input string
1705  while(1)
1706  {
1707  //Decimal digit found?
1708  if(isdigit((uint8_t) *str))
1709  {
1710  //First digit to be decoded?
1711  if(value < 0)
1712  value = 0;
1713 
1714  //Update the value of the current byte
1715  value = (value * 10) + (*str - '0');
1716 
1717  //The resulting value shall be in range 0 to 255
1718  if(value > 255)
1719  {
1720  //The conversion failed
1721  error = ERROR_INVALID_SYNTAX;
1722  break;
1723  }
1724  }
1725  //Dot separator found?
1726  else if(*str == '.' && i < 4)
1727  {
1728  //Each dot must be preceded by a valid number
1729  if(value < 0)
1730  {
1731  //The conversion failed
1732  error = ERROR_INVALID_SYNTAX;
1733  break;
1734  }
1735 
1736  //Save the current byte
1737  ((uint8_t *) ipAddr)[i++] = value;
1738  //Prepare to decode the next byte
1739  value = -1;
1740  }
1741  //End of string detected?
1742  else if(*str == '\0' && i == 3)
1743  {
1744  //The NULL character must be preceded by a valid number
1745  if(value < 0)
1746  {
1747  //The conversion failed
1748  error = ERROR_INVALID_SYNTAX;
1749  }
1750  else
1751  {
1752  //Save the last byte of the IPv4 address
1753  ((uint8_t *) ipAddr)[i] = value;
1754  //The conversion succeeded
1755  error = NO_ERROR;
1756  }
1757 
1758  //We are done
1759  break;
1760  }
1761  //Invalid character...
1762  else
1763  {
1764  //The conversion failed
1765  error = ERROR_INVALID_SYNTAX;
1766  break;
1767  }
1768 
1769  //Point to the next character
1770  str++;
1771  }
1772 
1773  //Return status code
1774  return error;
1775 }
1776 
1777 
1778 /**
1779  * @brief Convert a binary IPv4 address to dot-decimal notation
1780  * @param[in] ipAddr Binary representation of the IPv4 address
1781  * @param[out] str NULL-terminated string representing the IPv4 address
1782  * @return Pointer to the formatted string
1783  **/
1784 
1786 {
1787  uint8_t *p;
1788  static char_t buffer[16];
1789 
1790  //If the NULL pointer is given as parameter, then the internal buffer is used
1791  if(str == NULL)
1792  str = buffer;
1793 
1794  //Cast the address to byte array
1795  p = (uint8_t *) &ipAddr;
1796  //Format IPv4 address
1797  sprintf(str, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "", p[0], p[1], p[2], p[3]);
1798 
1799  //Return a pointer to the formatted string
1800  return str;
1801 }
1802 
1803 
1804 /**
1805  * @brief Dump IPv4 header for debugging purpose
1806  * @param[in] ipHeader Pointer to the IPv4 header
1807  **/
1808 
1809 void ipv4DumpHeader(const Ipv4Header *ipHeader)
1810 {
1811  //Dump IP header contents
1812  TRACE_DEBUG(" Version = %" PRIu8 "\r\n", ipHeader->version);
1813  TRACE_DEBUG(" Header Length = %" PRIu8 "\r\n", ipHeader->headerLength);
1814  TRACE_DEBUG(" Type Of Service = %" PRIu8 "\r\n", ipHeader->typeOfService);
1815  TRACE_DEBUG(" Total Length = %" PRIu16 "\r\n", ntohs(ipHeader->totalLength));
1816  TRACE_DEBUG(" Identification = %" PRIu16 "\r\n", ntohs(ipHeader->identification));
1817  TRACE_DEBUG(" Flags = 0x%01X\r\n", ntohs(ipHeader->fragmentOffset) >> 13);
1818  TRACE_DEBUG(" Fragment Offset = %" PRIu16 "\r\n", ntohs(ipHeader->fragmentOffset) & 0x1FFF);
1819  TRACE_DEBUG(" Time To Live = %" PRIu8 "\r\n", ipHeader->timeToLive);
1820  TRACE_DEBUG(" Protocol = %" PRIu8 "\r\n", ipHeader->protocol);
1821  TRACE_DEBUG(" Header Checksum = 0x%04" PRIX16 "\r\n", ntohs(ipHeader->headerChecksum));
1822  TRACE_DEBUG(" Src Addr = %s\r\n", ipv4AddrToString(ipHeader->srcAddr, NULL));
1823  TRACE_DEBUG(" Dest Addr = %s\r\n", ipv4AddrToString(ipHeader->destAddr, NULL));
1824 }
1825 
1826 #endif
An address assigned to an interface whose use is unrestricted.
Definition: ipv4.h:184
bool_t ipv4IsBroadcastAddr(NetInterface *interface, Ipv4Addr ipAddr)
Check whether an IPv4 address is a broadcast address.
Definition: ipv4.c:1275
ARP (Address Resolution Protocol)
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:232
error_t ipv4SendDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, uint8_t ttl)
Send an IPv4 datagram.
Definition: ipv4.c:774
void ipv4UpdateOutStats(NetInterface *interface, Ipv4Addr destIpAddr, size_t length)
Update IPv4 output statistics.
Definition: ipv4.c:1649
error_t ipv4SendPacket(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader, uint16_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset, uint8_t ttl)
Send an IPv4 packet.
Definition: ipv4.c:842
void ipv4DumpHeader(const Ipv4Header *ipHeader)
Dump IPv4 header for debugging purpose.
Definition: ipv4.c:1809
#define IPV4_VERSION
Definition: ipv4.h:74
mDNS responder (Multicast DNS)
char char_t
Definition: compiler_port.h:41
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1785
Ipv4Addr groupAddr
Definition: igmp.h:125
#define IP_MIB_INC_COUNTER64(name, value)
Definition: ip_mib_module.h:45
TCP/IP stack core.
void autoIpLinkChangeEvent(AutoIpContext *context)
Callback function for link change event.
Definition: auto_ip.c:440
IPv4 routing.
Debugging facilities.
#define IPV4_MULTICAST_LNCB_MASK
Definition: ipv4.h:114
error_t ipv4GetDefaultGateway(NetInterface *interface, Ipv4Addr *addr)
Retrieve default gateway.
Definition: ipv4.c:278
uint_t chunkCount
Definition: net_mem.h:96
uint8_t p
Definition: ndp.h:295
uint_t maxChunkCount
Definition: net_mem.h:97
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
uint_t ipv4GetAddrScope(Ipv4Addr ipAddr)
Retrieve the scope of an IPv4 address.
Definition: ipv4.c:1304
Generic error code.
Definition: error.h:43
error_t ipv4MapMulticastAddrToMac(Ipv4Addr ipAddr, MacAddr *macAddr)
Map an host group address to a MAC-layer multicast address.
Definition: ipv4.c:1580
void ipv4ProcessDatagram(NetInterface *interface, const NetBuffer *buffer)
Incoming IPv4 datagram processing.
Definition: ipv4.c:627
error_t udpProcessDatagram(NetInterface *interface, IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Incoming UDP datagram processing.
Definition: udp.c:127
MIB-II module.
error_t ipv4SelectSourceAddr(NetInterface **interface, Ipv4Addr destAddr, Ipv4Addr *srcAddr)
IPv4 source address selection.
Definition: ipv4.c:1134
Invalid parameter.
Definition: error.h:45
#define ipv4IsOnLocalSubnet(interface, ipAddr)
Definition: ipv4.h:141
error_t ipv4GetSubnetMask(NetInterface *interface, Ipv4Addr *mask)
Retrieve subnet mask.
Definition: ipv4.c:224
error_t rawSocketProcessIpPacket(NetInterface *interface, IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Process incoming IP packet.
Definition: raw_socket.c:61
#define IPV4_DNS_SERVER_LIST_SIZE
Definition: ipv4.h:61
IPv4 and IPv6 common routines.
Ipv4Addr dnsServerList[IPV4_DNS_SERVER_LIST_SIZE]
DNS servers.
Definition: ipv4.h:327
PPP interface.
Definition: nic.h:70
error_t ipv4Init(NetInterface *interface)
IPv4 related initialization.
Definition: ipv4.c:69
void arpFlushCache(NetInterface *interface)
Flush ARP cache.
Definition: arp.c:72
bool_t isRouter
A flag indicating whether routing is enabled on this interface.
Definition: ipv4.h:320
#define htons(value)
Definition: cpu_endian.h:390
#define MIB2_INC_COUNTER32(name, value)
Definition: mib2_module.h:154
#define IPV4_MULTICAST_LNCB_PREFIX
Definition: ipv4.h:113
#define Ipv4PseudoHeader
Definition: ipv4.h:37
void * address
Definition: net_mem.h:76
#define IPV4_LOOPBACK_ADDR_MASK
Definition: ipv4.h:102
uint_t refCount
Reference count for the current entry.
Definition: ipv4.h:306
void ipv4FlushFragQueue(NetInterface *interface)
Flush IPv4 reassembly queue.
Definition: ipv4_frag.c:616
error_t ipv4GetDnsServer(NetInterface *interface, uint_t index, Ipv4Addr *addr)
Retrieve DNS server.
Definition: ipv4.c:338
error_t ipv4GetHostAddr(NetInterface *interface, Ipv4Addr *addr)
Retrieve host address.
Definition: ipv4.c:163
uint16_t ipCalcChecksum(const void *data, size_t length)
IP checksum calculation.
Definition: ip.c:351
void ipv4LinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ipv4.c:392
#define TRUE
Definition: os_port.h:48
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:230
error_t ipv4GetBroadcastAddr(NetInterface *interface, Ipv4Addr *addr)
Get IPv4 broadcast address.
Definition: ipv4.c:371
#define IPV4_LINK_LOCAL_PREFIX
Definition: ipv4.h:105
uint8_t ipAddr[4]
Definition: mib_common.h:185
#define IPV4_DEFAULT_TTL
Definition: ipv4.h:54
error_t ipv4SetSubnetMask(NetInterface *interface, Ipv4Addr mask)
Configure subnet mask.
Definition: ipv4.c:199
DHCP client (Dynamic Host Configuration Protocol)
void icmpProcessMessage(NetInterface *interface, Ipv4Addr srcIpAddr, const NetBuffer *buffer, size_t offset)
Incoming ICMP message processing.
Definition: icmp.c:54
#define ntohl(value)
Definition: cpu_endian.h:397
Ethernet.
uint8_t mask
Definition: web_socket.h:315
error_t mdnsResponderStartProbing(MdnsResponderContext *context)
Restart probing process.
#define ntohs(value)
Definition: cpu_endian.h:396
error_t ipv4SetDefaultGateway(NetInterface *interface, Ipv4Addr addr)
Configure default gateway.
Definition: ipv4.c:249
signed int int_t
Definition: compiler_port.h:42
size_t length
Definition: ip.h:78
error_t ipv4JoinMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr)
Join the specified host group.
Definition: ipv4.c:1395
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:411
#define ipv4IsLinkLocalAddr(ipAddr)
Definition: ipv4.h:146
An address that is not assigned to any interface.
Definition: ipv4.h:182
error_t arpEnqueuePacket(NetInterface *interface, Ipv4Addr ipAddr, NetBuffer *buffer, size_t offset)
Enqueue an IPv4 packet waiting for address resolution.
Definition: arp.c:339
Invalid interface.
Definition: error.h:51
error_t ipv4CheckSourceAddr(NetInterface *interface, Ipv4Addr ipAddr)
Source IPv4 address filtering.
Definition: ipv4.c:1038
#define NET_INTERFACE_COUNT
Definition: net.h:108
TCP/IP raw sockets.
uint16_t ipCalcChecksumEx(const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP checksum over a multi-part buffer.
Definition: ip.c:471
IPv4 (Internet Protocol Version 4)
ChunkDesc chunk[1]
Definition: net_mem.h:98
Ipv4Addr addr
Multicast address.
Definition: ipv4.h:305
uint32_t ttl
Definition: dns_common.h:203
error_t igmpLeaveGroup(NetInterface *interface, Ipv4FilterEntry *entry)
Leave the specified host group.
Definition: igmp.c:131
uint8_t fragOffset[3]
Definition: dtls_misc.h:180
void igmpProcessMessage(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Process incoming IGMP message.
Definition: igmp.c:278
error_t ethDropMacAddr(NetInterface *interface, const MacAddr *macAddr)
Remove a unicast/multicast address from the MAC filter table.
Definition: ethernet.c:803
error_t ipv4ForwardPacket(NetInterface *srcInterface, const NetBuffer *ipPacket, size_t ipPacketOffset)
error_t arpResolve(NetInterface *interface, Ipv4Addr ipAddr, MacAddr *macAddr)
Address resolution using ARP protocol.
Definition: arp.c:248
Auto-IP (Dynamic Configuration of IPv4 Link-Local Addresses)
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
void igmpLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: igmp.c:205
NetInterface netInterface[NET_INTERFACE_COUNT]
Definition: net.c:74
const MacAddr MAC_BROADCAST_ADDR
Definition: ethernet.c:55
error_t ipv4LeaveMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr)
Leave the specified host group.
Definition: ipv4.c:1504
uint16_t id
Definition: dns_common.h:156
IGMP (Internet Group Management Protocol)
error_t ethSendFrame(NetInterface *interface, const MacAddr *destAddr, NetBuffer *buffer, size_t offset, uint16_t type)
Send an Ethernet frame.
Definition: ethernet.c:476
IP MIB module.
uint_t ipv4GetPrefixLength(Ipv4Addr mask)
Calculate prefix length for a given subnet mask.
Definition: ipv4.c:1368
error_t ipv4FragmentDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader, uint16_t id, const NetBuffer *payload, size_t payloadOffset, uint8_t timeToLive)
Fragment an IPv4 datagram into smaller packets.
Definition: ipv4_frag.c:69
#define TRACE_INFO(...)
Definition: debug.h:86
void ipv4UpdateInStats(NetInterface *interface, Ipv4Addr destIpAddr, size_t length)
Update IPv4 input statistics.
Definition: ipv4.c:1614
error_t ethAcceptMacAddr(NetInterface *interface, const MacAddr *macAddr)
Add a unicast/multicast address to the MAC filter table.
Definition: ethernet.c:733
Ethernet interface.
Definition: nic.h:69
Success.
Definition: error.h:42
error_t ipv4SetHostAddr(NetInterface *interface, Ipv4Addr addr)
Assign host address.
Definition: ipv4.c:113
uint16_t length
Definition: net_mem.h:77
error_t
Error codes.
Definition: error.h:40
#define IPV4_LINK_LOCAL_MASK
Definition: ipv4.h:106
#define TRACE_WARNING(...)
Definition: debug.h:78
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:44
error_t ipv4SetDnsServer(NetInterface *interface, uint_t index, Ipv4Addr addr)
Configure DNS server.
Definition: ipv4.c:304
void ipv4ReassembleDatagram(NetInterface *interface, const Ipv4Header *packet, size_t length)
IPv4 datagram reassembly algorithm.
Definition: ipv4_frag.c:176
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:85
Ipv4Addr destIpAddr
Definition: ipcp.h:76
unsigned int uint_t
Definition: compiler_port.h:43
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
__start_packed struct @112 MacAddr
MAC address.
#define PRIuSIZE
Definition: compiler_port.h:72
uint16_t identification
IPv4 fragment identification field.
Definition: ipv4.h:321
#define NetInterface
Definition: net.h:34
Internet Protocol.
Definition: ppp.h:197
#define ipv4IsMulticastAddr(ipAddr)
Definition: ipv4.h:150
#define IPV4_LOOPBACK_ADDR
Definition: ipv4.h:100
uint8_t value[]
Definition: dtls_misc.h:141
MacAddr srcAddr
Definition: ethernet.h:181
IP pseudo header.
Definition: ip.h:76
#define Ipv4Header
Definition: ipv4.h:34
ICMP (Internet Control Message Protocol)
void dhcpClientLinkChangeEvent(DhcpClientContext *context)
Callback function for link change event.
Definition: dhcp_client.c:354
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:95
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1004
#define IPV4_MULTICAST_FILTER_SIZE
Definition: ipv4.h:68
OsMutex netMutex
Definition: net.c:70
IPv4 context.
Definition: ipv4.h:317
size_t linkMtu
Maximum transmission unit.
Definition: ipv4.h:319
Ipv4PseudoHeader ipv4Data
Definition: ip.h:82
uint8_t length
Definition: dtls_misc.h:140
error_t ipv4CheckDestAddr(NetInterface *interface, Ipv4Addr ipAddr)
Destination IPv4 address filtering.
Definition: ipv4.c:1062
error_t igmpJoinGroup(NetInterface *interface, Ipv4FilterEntry *entry)
Join the specified host group.
Definition: igmp.c:81
IPv4 multicast filter entry.
Definition: ipv4.h:303
#define FALSE
Definition: os_port.h:44
TCP finite state machine.
Ipv4FragDesc fragQueue[IPV4_MAX_FRAG_DATAGRAMS]
IPv4 fragment reassembly queue.
Definition: ipv4.h:330
#define IPV4_LOOPBACK_ADDR_PREFIX
Definition: ipv4.h:101
int bool_t
Definition: compiler_port.h:47
Ipv4FilterEntry multicastFilter[IPV4_MULTICAST_FILTER_SIZE]
Multicast filter table.
Definition: ipv4.h:328
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
UDP (User Datagram Protocol)
void ipv4ProcessPacket(NetInterface *interface, Ipv4Header *packet, size_t length)
Incoming IPv4 packet processing.
Definition: ipv4.c:440
void tcpProcessSegment(NetInterface *interface, IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Incoming TCP segment processing.
Definition: tcp_fsm.c:70
Ipv4Addr addr
Definition: nbns_common.h:119
MacAddr destAddr
Definition: ethernet.h:180
#define IPV4_BROADCAST_ADDR
Definition: ipv4.h:97
error_t ipv4StringToAddr(const char_t *str, Ipv4Addr *ipAddr)
Convert a dot-decimal string to a binary IPv4 address.
Definition: ipv4.c:1698
#define TRACE_DEBUG(...)
Definition: debug.h:98
#define ipv4IsTentativeAddr(interface, ipAddr)
Definition: ipv4.h:154