ipv4_misc.c
Go to the documentation of this file.
1 /**
2  * @file ipv4_misc.c
3  * @brief Helper functions for IPv4
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL IPV4_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "ipv4/ipv4.h"
37 #include "ipv4/ipv4_misc.h"
38 #include "mibs/mib2_module.h"
39 #include "mibs/ip_mib_module.h"
40 #include "debug.h"
41 
42 //Check TCP/IP stack configuration
43 #if (IPV4_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Append a Router Alert option to an IPv4 packet
48  * @param[in] buffer Multi-part buffer containing the payload
49  * @param[in,out] offset Offset to the first payload byte
50  * @return Error code
51  **/
52 
53 error_t ipv4AddRouterAlertOption(NetBuffer *buffer, size_t *offset)
54 {
55  error_t error;
56  Ipv4Option *option;
57 
58  //Make sure there is enough room to add the option
59  if(*offset >= sizeof(uint32_t))
60  {
61  //Make room for the IPv4 option
62  *offset -= sizeof(uint32_t);
63  //Point to the IPv4 option
64  option = netBufferAt(buffer, *offset);
65 
66  //Format Router Alert option
67  option->type = IPV4_OPTION_RTRALT;
68  option->length = sizeof(uint32_t);
69  option->value[0] = 0;
70  option->value[1] = 0;
71 
72  //Successful processing
73  error = NO_ERROR;
74  }
75  else
76  {
77  //Report an error
79  }
80 
81  //Return status code
82  return error;
83 }
84 
85 
86 /**
87  * @brief Source IPv4 address filtering
88  * @param[in] interface Underlying network interface
89  * @param[in] ipAddr Source IPv4 address to be checked
90  * @return Error code
91  **/
92 
94 {
95  //Broadcast and multicast addresses must not be used as source address
96  //(refer to RFC 1122, section 3.2.1.3)
98  {
99  //Debug message
100  TRACE_WARNING("Wrong source IPv4 address!\r\n");
101  //The source address not is acceptable
102  return ERROR_INVALID_ADDRESS;
103  }
104 
105  //The source address is acceptable
106  return NO_ERROR;
107 }
108 
109 
110 /**
111  * @brief Destination IPv4 address filtering
112  * @param[in] interface Underlying network interface
113  * @param[in] ipAddr Destination IPv4 address to be checked
114  * @return Error code
115  **/
116 
118 {
119  error_t error;
120  uint_t i;
121 
122  //Filter out any invalid addresses
123  error = ERROR_INVALID_ADDRESS;
124 
125  //Broadcast address?
126  if(ipv4IsBroadcastAddr(interface, ipAddr))
127  {
128  //Always accept broadcast address
129  error = NO_ERROR;
130  }
131  //Multicast address?
132  else if(ipv4IsMulticastAddr(ipAddr))
133  {
134  //Go through the multicast filter table
135  for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++)
136  {
137  Ipv4FilterEntry *entry;
138 
139  //Point to the current entry
140  entry = &interface->ipv4Context.multicastFilter[i];
141 
142  //Valid entry?
143  if(entry->refCount > 0)
144  {
145  //Check whether the destination IPv4 address matches
146  //a relevant multicast address
147  if(entry->addr == ipAddr)
148  {
149  //The multicast address is acceptable
150  error = NO_ERROR;
151  //Stop immediately
152  break;
153  }
154  }
155  }
156  }
157  //Unicast address?
158  else
159  {
160  //Loop through the list of IPv4 addresses assigned to the interface
161  for(i = 0; i < IPV4_ADDR_LIST_SIZE; i++)
162  {
163  Ipv4AddrEntry *entry;
164 
165  //Point to the current entry
166  entry = &interface->ipv4Context.addrList[i];
167 
168  //Valid entry?
169  if(entry->state != IPV4_ADDR_STATE_INVALID)
170  {
171  //Check whether the destination address matches a valid unicast
172  //address assigned to the interface
173  if(entry->addr == ipAddr)
174  {
175  //The destination address is acceptable
176  error = NO_ERROR;
177  //We are done
178  break;
179  }
180  }
181  }
182  }
183 
184  //Return status code
185  return error;
186 }
187 
188 
189 /**
190  * @brief IPv4 source address selection
191  *
192  * This function selects the source address and the relevant network interface
193  * to be used in order to join the specified destination address
194  *
195  * @param[in,out] interface A pointer to a valid network interface may be provided as
196  * a hint. The function returns a pointer identifying the interface to be used
197  * @param[in] destAddr Destination IPv4 address
198  * @param[out] srcAddr Local IPv4 address to be used
199  * @return Error code
200  **/
201 
204 {
205  error_t error;
206  uint_t i;
207  uint_t j;
208  NetInterface *currentInterface;
209  NetInterface *bestInterface;
210  Ipv4AddrEntry *currentAddr;
211  Ipv4AddrEntry *bestAddr;
212 
213  //Initialize variables
214  bestInterface = NULL;
215  bestAddr = NULL;
216 
217  //Loop through network interfaces
218  for(i = 0; i < NET_INTERFACE_COUNT; i++)
219  {
220  //Point to the current interface
221  currentInterface = &netInterface[i];
222 
223  //A network interface may be provided as a hint
224  if(*interface != currentInterface && *interface != NULL)
225  {
226  //Select the next interface in the list
227  continue;
228  }
229 
230  //A sort of the candidate source addresses is being performed
231  for(j = 0; j < IPV4_ADDR_LIST_SIZE; j++)
232  {
233  //Point to the current entry
234  currentAddr = &currentInterface->ipv4Context.addrList[j];
235 
236  //Check the state of the address
237  if(currentAddr->state == IPV4_ADDR_STATE_VALID)
238  {
239  //Select the first address as default
240  if(bestAddr == NULL)
241  {
242  //Give the current source address the higher precedence
243  bestInterface = currentInterface;
244  bestAddr = currentAddr;
245 
246  //Select the next address in the list
247  continue;
248  }
249 
250  //Prefer same address
251  if(bestAddr->addr == destAddr)
252  {
253  //Select the next address in the list
254  continue;
255  }
256  else if(currentAddr->addr == destAddr)
257  {
258  //Give the current source address the higher precedence
259  bestInterface = currentInterface;
260  bestAddr = currentAddr;
261 
262  //Select the next address in the list
263  continue;
264  }
265 
266  //Check whether the destination address matches the default gateway
267  if(bestAddr->defaultGateway == destAddr)
268  {
269  //Select the next address in the list
270  continue;
271  }
272  else if(currentAddr->defaultGateway == destAddr)
273  {
274  //Give the current source address the higher precedence
275  bestInterface = currentInterface;
276  bestAddr = currentAddr;
277 
278  //Select the next address in the list
279  continue;
280  }
281 
282  //Prefer appropriate scope
283  if(ipv4GetAddrScope(currentAddr->addr) < ipv4GetAddrScope(bestAddr->addr))
284  {
285  if(ipv4GetAddrScope(currentAddr->addr) >= ipv4GetAddrScope(destAddr))
286  {
287  //Give the current source address the higher precedence
288  bestInterface = currentInterface;
289  bestAddr = currentAddr;
290  }
291 
292  //Select the next address in the list
293  continue;
294  }
295  else if(ipv4GetAddrScope(bestAddr->addr) < ipv4GetAddrScope(currentAddr->addr))
296  {
298  {
299  //Give the current source address the higher precedence
300  bestInterface = currentInterface;
301  bestAddr = currentAddr;
302  }
303 
304  //Select the next address in the list
305  continue;
306  }
307 
308  //If the destination address lies on one of the subnets to which
309  //the host is directly connected, the corresponding source address
310  //may be chosen (refer to RFC 1122, section 3.3.4.3)
311  if(ipv4IsOnSubnet(bestAddr, destAddr))
312  {
313  if(ipv4IsOnSubnet(currentAddr, destAddr))
314  {
315  //Use longest subnet mask
316  if(ipv4GetPrefixLength(currentAddr->subnetMask) >
317  ipv4GetPrefixLength(bestAddr->subnetMask))
318  {
319  //Give the current source address the higher precedence
320  bestInterface = currentInterface;
321  bestAddr = currentAddr;
322  }
323  }
324 
325  //Select the next address in the list
326  continue;
327  }
328  else
329  {
330  if(ipv4IsOnSubnet(currentAddr, destAddr))
331  {
332  //Give the current source address the higher precedence
333  bestInterface = currentInterface;
334  bestAddr = currentAddr;
335 
336  //Select the next address in the list
337  continue;
338  }
339  }
340 
341  //The default gateways may be consulted. If these gateways are
342  //assigned to different interfaces, the interface corresponding
343  //to the gateway with the highest preference may be chosen
344  if(bestAddr->defaultGateway != IPV4_UNSPECIFIED_ADDR)
345  {
346  //Select the next address in the list
347  continue;
348  }
349  else if(currentAddr->defaultGateway != IPV4_UNSPECIFIED_ADDR)
350  {
351  //Give the current source address the higher precedence
352  bestInterface = currentInterface;
353  bestAddr = currentAddr;
354 
355  //Select the next address in the list
356  continue;
357  }
358  }
359  }
360  }
361 
362  //Valid source address?
363  if(bestAddr != NULL)
364  {
365  //Return the out-going interface and the source address to be used
366  *interface = bestInterface;
367  *srcAddr = bestAddr->addr;
368 
369  //Successful source address selection
370  error = NO_ERROR;
371  }
372  else
373  {
374  //Report an error
375  error = ERROR_NO_ADDRESS;
376  }
377 
378  //Return status code
379  return error;
380 }
381 
382 
383 /**
384  * @brief Default gateway selection
385  * @param[in] interface Underlying network interface
386  * @param[in] srcAddr Source IPv4 address
387  * @param[out] defaultGatewayAddr IPv4 address of the gateway
388  * @return Error code
389  **/
390 
392  Ipv4Addr *defaultGatewayAddr)
393 {
394  uint_t i;
395  Ipv4AddrEntry *entry;
396 
397  //Loop through the list of default gateways
398  for(i = 0; i < IPV4_ADDR_LIST_SIZE; i++)
399  {
400  //Point to the current entry
401  entry = &interface->ipv4Context.addrList[i];
402 
403  //Check whether the gateway address is valid
404  if(entry->state == IPV4_ADDR_STATE_VALID &&
406  {
407  //Under the strong ES model, the source address is included as a
408  //parameter in order to select a gateway that is directly reachable
409  //on the corresponding physical interface (refer to RFC 1122,
410  //section 3.3.4.2)
411  if(entry->addr == srcAddr)
412  {
413  //Return the IPv4 address of the default gateway
414  *defaultGatewayAddr = entry->defaultGateway;
415  //Successful default gateway selection
416  return NO_ERROR;
417  }
418  }
419  }
420 
421  //No default gateway found
422  return ERROR_NO_ROUTE;
423 }
424 
425 
426 /**
427  * @brief Check whether an IPv4 address is on-link
428  * @param[in] interface Underlying network interface
429  * @param[in] ipAddr IPv4 address to be checked
430  * @return TRUE if the IPv4 address is on-link, else FALSE
431  **/
432 
434 {
435  uint_t i;
436  bool_t flag;
437  Ipv4AddrEntry *entry;
438 
439  //Initialize flag
440  flag = FALSE;
441 
442  //Loop through the list of IPv4 addresses assigned to the interface
443  for(i = 0; i < IPV4_ADDR_LIST_SIZE && !flag; i++)
444  {
445  //Point to the current entry
446  entry = &interface->ipv4Context.addrList[i];
447 
448  //Valid entry?
449  if(entry->state != IPV4_ADDR_STATE_INVALID)
450  {
451  //Check whether the specified IPv4 address belongs to the same subnet
452  if(ipv4IsOnSubnet(entry, ipAddr))
453  {
454  flag = TRUE;
455  }
456  }
457  }
458 
459  //Return TRUE if the specified IPv4 address is on-link
460  return flag;
461 }
462 
463 
464 /**
465  * @brief Check whether an IPv4 address is a broadcast address
466  * @param[in] interface Underlying network interface
467  * @param[in] ipAddr IPv4 address to be checked
468  * @return TRUE if the IPv4 address is a broadcast address, else FALSE
469  **/
470 
472 {
473  uint_t i;
474  bool_t flag;
475  Ipv4AddrEntry *entry;
476 
477  //Initialize flag
478  flag = FALSE;
479 
480  //Check whether the specified IPv4 address is the broadcast address
482  {
483  flag = TRUE;
484  }
485  else
486  {
487  //Loop through the list of IPv4 addresses assigned to the interface
488  for(i = 0; i < IPV4_ADDR_LIST_SIZE && !flag; i++)
489  {
490  //Point to the current entry
491  entry = &interface->ipv4Context.addrList[i];
492 
493  //Valid entry?
494  if(entry->state != IPV4_ADDR_STATE_INVALID)
495  {
496  //Check whether the specified IPv4 address belongs to the same subnet
497  if(ipv4IsOnSubnet(entry, ipAddr))
498  {
499  //Make sure the subnet mask is not 255.255.255.255
500  if(entry->subnetMask != IPV4_BROADCAST_ADDR)
501  {
502  //Directed broadcast address?
503  if((ipAddr | entry->subnetMask) == IPV4_BROADCAST_ADDR)
504  {
505  flag = TRUE;
506  }
507  }
508  }
509  }
510  }
511  }
512 
513  //Return TRUE if the specified IPv4 address is a broadcast address
514  return flag;
515 }
516 
517 
518 /**
519  * @brief Check whether an IPv4 address is a tentative address
520  * @param[in] interface Underlying network interface
521  * @param[in] ipAddr IPv4 address to be checked
522  * @return TRUE if the IPv4 address is a tentative address, else FALSE
523  **/
524 
526 {
527  uint_t i;
528  bool_t flag;
529  Ipv4AddrEntry *entry;
530 
531  //Initialize flag
532  flag = FALSE;
533 
534  //Loop through the list of IPv4 addresses assigned to the interface
535  for(i = 0; i < IPV4_ADDR_LIST_SIZE && !flag; i++)
536  {
537  //Point to the current entry
538  entry = &interface->ipv4Context.addrList[i];
539 
540  //Tentative address?
541  if(entry->state == IPV4_ADDR_STATE_TENTATIVE)
542  {
543  //Check whether the specified address matches a valid unicast
544  //address assigned to the interface
545  if(entry->addr == ipAddr)
546  {
547  flag = TRUE;
548  }
549  }
550  }
551 
552  //Return TRUE if the specified IPv4 address is a tentative address
553  return flag;
554 }
555 
556 
557 /**
558  * @brief Check whether the specified IPv4 is assigned to the host
559  * @param[in] ipAddr IPv4 address to be checked
560  * @return TRUE if the IPv4 address matches any address assigned to the host,
561  * else FALSE
562  **/
563 
565 {
566  uint_t i;
567  uint_t j;
568  bool_t flag;
569  NetInterface *interface;
570  Ipv4AddrEntry *entry;
571 
572  //Initialize flag
573  flag = FALSE;
574 
575  //Loopback address?
577  {
578  //The 127.0.0.0/8 block is assigned for use as the host loopback address.
579  //A datagram sent by a higher-level protocol to an address anywhere within
580  //this block loops back inside the host (refer to RFC 5735, section 3)
581  flag = TRUE;
582  }
583  else
584  {
585  //Loop through network interfaces
586  for(i = 0; i < NET_INTERFACE_COUNT && !flag; i++)
587  {
588  //Point to the current interface
589  interface = &netInterface[i];
590 
591  //Iterate through the list of addresses assigned to the interface
592  for(j = 0; j < IPV4_ADDR_LIST_SIZE && !flag; j++)
593  {
594  //Point to the current entry
595  entry = &interface->ipv4Context.addrList[j];
596 
597  //Check whether the specified IPv4 address matches any address
598  //assigned to the host
599  if(entry->state == IPV4_ADDR_STATE_VALID &&
600  entry->addr == ipAddr)
601  {
602  flag = TRUE;
603  }
604  }
605  }
606  }
607 
608  //Return TRUE if the specified address matches any address assigned to the host
609  return flag;
610 }
611 
612 
613 /**
614  * @brief Compare IPv4 address prefixes
615  * @param[in] ipAddr1 First IPv4 address
616  * @param[in] ipAddr2 Second IPv4 address
617  * @param[in] length Prefix length
618  * @return TRUE if the prefixes match each other, else FALSE
619  **/
620 
621 bool_t ipv4CompPrefix(Ipv4Addr ipAddr1, Ipv4Addr ipAddr2, size_t length)
622 {
623  uint32_t mask;
624 
625  //Check prefix length
626  if(length == 0)
627  {
628  return TRUE;
629  }
630  else if(length < 32)
631  {
632  //Calculate the mask to be applied
633  mask = ((1 << length) - 1) << (32 - length);
634  //Convert the mask to network byte order
635  mask = htonl(mask);
636  }
637  else if(length == 32)
638  {
639  mask = IPV4_ADDR(255, 255, 255, 255);
640  }
641  else
642  {
643  return FALSE;
644  }
645 
646  //Compare address prefixes
647  return ((ipAddr1 & mask) == (ipAddr2 & mask));
648 }
649 
650 
651 /**
652  * @brief Retrieve the scope of an IPv4 address
653  * @param[in] ipAddr IPv4 address
654  * @return IPv4 address scope
655  **/
656 
658 {
659  uint_t scope;
660 
661  //Broadcast address?
663  {
664  //The broadcast address is never forwarded by the routers connecting
665  //the local network to other networks
667  }
668  //Multicast address?
669  else if(ipv4IsMulticastAddr(ipAddr))
670  {
671  //Local Network Control Block?
673  {
674  //Addresses in the Local Network Control Block are used for protocol
675  //control traffic that is not forwarded off link
677  }
678  //Any other multicast address?
679  else
680  {
681  //Other addresses are assigned global scope
682  scope = IPV4_ADDR_SCOPE_GLOBAL;
683  }
684  }
685  //Unicast address?
686  else
687  {
688  //Loopback address?
690  {
691  //IPv4 loopback addresses, which have the prefix 127.0.0.0/8,
692  //are assigned interface-local scope
694  }
695  //Link-local address?
697  {
698  //IPv4 auto-configuration addresses, which have the prefix
699  //169.254.0.0/16, are assigned link-local scope
701  }
702  //Any other unicast address?
703  else
704  {
705  //Other addresses are assigned global scope
706  scope = IPV4_ADDR_SCOPE_GLOBAL;
707  }
708  }
709 
710  //Return the scope of the specified IPv4 address
711  return scope;
712 }
713 
714 
715 /**
716  * @brief Calculate prefix length for a given subnet mask
717  * @param[in] mask Subnet mask
718  * @return Prefix length
719  **/
720 
722 {
723  uint_t i;
724 
725  //Convert from network byte order to host byte order
726  mask = ntohl(mask);
727 
728  //Count of the number of leading 1 bits in the network mask
729  for(i = 0; i < 32; i++)
730  {
731  //Check the value of the current bit
732  if(!(mask & (1U << (31 - i))))
733  break;
734  }
735 
736  //Return prefix length
737  return i;
738 }
739 
740 
741 /**
742  * @brief Get IPv4 broadcast address
743  * @param[in] interface Pointer to the desired network interface
744  * @param[out] addr IPv4 broadcast address
745  **/
746 
748 {
749  //Check parameters
750  if(interface == NULL || addr == NULL)
752 
753  //The broadcast address is obtained by performing a bitwise OR operation
754  //between the bit complement of the subnet mask and the host IP address
755  *addr = interface->ipv4Context.addrList[0].addr;
756  *addr |= ~interface->ipv4Context.addrList[0].subnetMask;
757 
758  //Successful processing
759  return NO_ERROR;
760 }
761 
762 
763 /**
764  * @brief Map an host group address to a MAC-layer multicast address
765  * @param[in] ipAddr IPv4 host group address
766  * @param[out] macAddr Corresponding MAC-layer multicast address
767  * @return Error code
768  **/
769 
771 {
772  uint8_t *p;
773 
774  //Ensure the specified IPv4 address is a valid host group address
776  return ERROR_INVALID_ADDRESS;
777 
778  //Cast the address to byte array
779  p = (uint8_t *) &ipAddr;
780 
781  //An IP host group address is mapped to an Ethernet multicast address
782  //by placing the low-order 23-bits of the IP address into the low-order
783  //23 bits of the Ethernet multicast address 01-00-5E-00-00-00
784  macAddr->b[0] = 0x01;
785  macAddr->b[1] = 0x00;
786  macAddr->b[2] = 0x5E;
787  macAddr->b[3] = p[1] & 0x7F;
788  macAddr->b[4] = p[2];
789  macAddr->b[5] = p[3];
790 
791  //The specified host group address was successfully
792  //mapped to a MAC-layer address
793  return NO_ERROR;
794 }
795 
796 
797 /**
798  * @brief Trap IGMP packets
799  * @param[in] header Pointer to the IPv4 header
800  * @return TRUE if the IPv4 packet contains an IGMP message, else FALSE
801  **/
802 
804 {
805  bool_t flag;
806 
807  //Initialize flag
808  flag = FALSE;
809 
810  //Make sure the IPv4 packet is not fragmented
811  if((ntohs(header->fragmentOffset) & (IPV4_FLAG_MF | IPV4_OFFSET_MASK)) == 0)
812  {
813  //Valid IGMP message?
814  if(ipv4IsMulticastAddr(header->destAddr) &&
815  header->protocol == IPV4_PROTOCOL_IGMP)
816  {
817  flag = TRUE;
818  }
819  }
820 
821  //Return TRUE if the IPv4 packet contains an IGMP message
822  return flag;
823 }
824 
825 
826 /**
827  * @brief Update IPv4 input statistics
828  * @param[in] interface Underlying network interface
829  * @param[in] destIpAddr Destination IP address
830  * @param[in] length Length of the incoming IP packet
831  **/
832 
834  size_t length)
835 {
836  //Check whether the destination address is a unicast, broadcast or multicast
837  //address
838  if(ipv4IsBroadcastAddr(interface, destIpAddr))
839  {
840  //Number of IP broadcast datagrams transmitted
841  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInBcastPkts, 1);
842  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInBcastPkts, 1);
843  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInBcastPkts, 1);
844  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInBcastPkts, 1);
845  }
847  {
848  //Number of IP multicast datagrams transmitted
849  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInMcastPkts, 1);
850  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInMcastPkts, 1);
851  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInMcastPkts, 1);
852  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInMcastPkts, 1);
853 
854  //Total number of octets transmitted in IP multicast datagrams
855  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInMcastOctets, length);
856  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCInMcastOctets, length);
857  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInMcastOctets, length);
858  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCInMcastOctets, length);
859  }
860  else
861  {
862  //The destination address is a unicast address
863  }
864 }
865 
866 
867 /**
868  * @brief Update IPv4 output statistics
869  * @param[in] interface Underlying network interface
870  * @param[in] destIpAddr Destination IP address
871  * @param[in] length Length of the outgoing IP packet
872  **/
873 
875  size_t length)
876 {
877  //Check whether the destination address is a unicast, broadcast or multicast
878  //address
879  if(ipv4IsBroadcastAddr(interface, destIpAddr))
880  {
881  //Number of IP broadcast datagrams transmitted
882  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutBcastPkts, 1);
883  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutBcastPkts, 1);
884  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutBcastPkts, 1);
885  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutBcastPkts, 1);
886  }
888  {
889  //Number of IP multicast datagrams transmitted
890  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutMcastPkts, 1);
891  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutMcastPkts, 1);
892  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutMcastPkts, 1);
893  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutMcastPkts, 1);
894 
895  //Total number of octets transmitted in IP multicast datagrams
896  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutMcastOctets, length);
897  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutMcastOctets, length);
898  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutMcastOctets, length);
899  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutMcastOctets, length);
900  }
901  else
902  {
903  //The destination address is a unicast address
904  }
905 
906  //Total number of IP datagrams that this entity supplied to the lower
907  //layers for transmission
908  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutTransmits, 1);
909  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutTransmits, 1);
910  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutTransmits, 1);
911  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutTransmits, 1);
912 
913  //Total number of octets in IP datagrams delivered to the lower layers
914  //for transmission
915  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutOctets, length);
916  IP_MIB_INC_COUNTER64(ipv4SystemStats.ipSystemStatsHCOutOctets, length);
917  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutOctets, length);
918  IP_MIB_INC_COUNTER64(ipv4IfStatsTable[interface->index].ipIfStatsHCOutOctets, length);
919 }
920 
921 
922 /**
923  * @brief Update Ethernet error statistics
924  * @param[in] interface Underlying network interface
925  * @param[in] error Status code describing the error
926  **/
927 
929 {
930  //Check error code
931  switch(error)
932  {
934  //Number of input datagrams discarded due to errors in their IP headers
935  MIB2_IP_INC_COUNTER32(ipInHdrErrors, 1);
936  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInHdrErrors, 1);
937  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInHdrErrors, 1);
938  break;
939 
941  //Number of input datagrams discarded because the destination IP address
942  //was not a valid address
943  MIB2_IP_INC_COUNTER32(ipInAddrErrors, 1);
944  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInAddrErrors, 1);
945  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInAddrErrors, 1);
946  break;
947 
949  //Number of locally-addressed datagrams received successfully but discarded
950  //because of an unknown or unsupported protocol
951  MIB2_IP_INC_COUNTER32(ipInUnknownProtos, 1);
952  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInUnknownProtos, 1);
953  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInUnknownProtos, 1);
954  break;
955 
957  //Number of input IP datagrams discarded because the datagram frame
958  //didn't carry enough data
959  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsInTruncatedPkts, 1);
960  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsInTruncatedPkts, 1);
961  break;
962 
963  default:
964  //Just for sanity
965  break;
966  }
967 }
968 
969 #endif
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define ntohl(value)
Definition: cpu_endian.h:422
#define htonl(value)
Definition: cpu_endian.h:414
#define ntohs(value)
Definition: cpu_endian.h:421
Debugging facilities.
#define TRACE_WARNING(...)
Definition: debug.h:85
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ ERROR_NO_ROUTE
Definition: error.h:219
@ ERROR_INVALID_HEADER
Definition: error.h:87
@ ERROR_NO_ADDRESS
Definition: error.h:199
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_PROTOCOL_UNREACHABLE
Definition: error.h:84
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
MacAddr srcAddr
Definition: ethernet.h:220
MacAddr
Definition: ethernet.h:195
IP MIB module.
#define IP_MIB_INC_COUNTER64(name, value)
Definition: ip_mib_module.h:47
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
Ipv4Addr ipAddr
Definition: ipcp.h:105
Ipv4Addr destIpAddr
Definition: ipcp.h:80
IPv4 (Internet Protocol Version 4)
@ IPV4_PROTOCOL_IGMP
Definition: ipv4.h:221
#define IPV4_LOOPBACK_MASK
Definition: ipv4.h:117
#define IPV4_BROADCAST_ADDR
Definition: ipv4.h:112
#define IPV4_LOOPBACK_PREFIX
Definition: ipv4.h:116
#define Ipv4Header
Definition: ipv4.h:36
Ipv4Option
Definition: ipv4.h:327
#define IPV4_LINK_LOCAL_PREFIX
Definition: ipv4.h:120
#define IPV4_ADDR_LIST_SIZE
Definition: ipv4.h:69
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:267
@ IPV4_ADDR_SCOPE_LINK_LOCAL
Definition: ipv4.h:184
@ IPV4_ADDR_SCOPE_INTERFACE_LOCAL
Definition: ipv4.h:183
@ IPV4_ADDR_SCOPE_GLOBAL
Definition: ipv4.h:185
#define IPV4_MULTICAST_LNCB_PREFIX
Definition: ipv4.h:128
#define ipv4IsLoopbackAddr(ipAddr)
Definition: ipv4.h:160
@ IPV4_ADDR_STATE_INVALID
An address that is not assigned to any interface.
Definition: ipv4.h:195
@ IPV4_ADDR_STATE_VALID
An address assigned to an interface whose use is unrestricted.
Definition: ipv4.h:197
@ IPV4_ADDR_STATE_TENTATIVE
An address whose uniqueness on a link is being verified.
Definition: ipv4.h:196
@ IPV4_FLAG_MF
Definition: ipv4.h:209
@ IPV4_OFFSET_MASK
Definition: ipv4.h:210
#define ipv4IsOnSubnet(entry, ipAddr)
Definition: ipv4.h:156
#define IPV4_MULTICAST_LNCB_MASK
Definition: ipv4.h:129
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:110
#define ipv4IsMulticastAddr(ipAddr)
Definition: ipv4.h:168
Ipv4Addr destAddr
Definition: ipv4.h:299
#define IPV4_MULTICAST_FILTER_SIZE
Definition: ipv4.h:83
#define IPV4_LINK_LOCAL_MASK
Definition: ipv4.h:121
#define IPV4_ADDR(a, b, c, d)
Definition: ipv4.h:106
@ IPV4_OPTION_RTRALT
Router Alert.
Definition: ipv4.h:255
error_t ipv4CheckSourceAddr(NetInterface *interface, Ipv4Addr ipAddr)
Source IPv4 address filtering.
Definition: ipv4_misc.c:93
error_t ipv4GetBroadcastAddr(NetInterface *interface, Ipv4Addr *addr)
Get IPv4 broadcast address.
Definition: ipv4_misc.c:747
void ipv4UpdateOutStats(NetInterface *interface, Ipv4Addr destIpAddr, size_t length)
Update IPv4 output statistics.
Definition: ipv4_misc.c:874
bool_t ipv4IsBroadcastAddr(NetInterface *interface, Ipv4Addr ipAddr)
Check whether an IPv4 address is a broadcast address.
Definition: ipv4_misc.c:471
bool_t ipv4IsLocalHostAddr(Ipv4Addr ipAddr)
Check whether the specified IPv4 is assigned to the host.
Definition: ipv4_misc.c:564
error_t ipv4MapMulticastAddrToMac(Ipv4Addr ipAddr, MacAddr *macAddr)
Map an host group address to a MAC-layer multicast address.
Definition: ipv4_misc.c:770
error_t ipv4AddRouterAlertOption(NetBuffer *buffer, size_t *offset)
Append a Router Alert option to an IPv4 packet.
Definition: ipv4_misc.c:53
void ipv4UpdateErrorStats(NetInterface *interface, error_t error)
Update Ethernet error statistics.
Definition: ipv4_misc.c:928
error_t ipv4SelectDefaultGateway(NetInterface *interface, Ipv4Addr srcAddr, Ipv4Addr *defaultGatewayAddr)
Default gateway selection.
Definition: ipv4_misc.c:391
uint_t ipv4GetPrefixLength(Ipv4Addr mask)
Calculate prefix length for a given subnet mask.
Definition: ipv4_misc.c:721
bool_t ipv4CompPrefix(Ipv4Addr ipAddr1, Ipv4Addr ipAddr2, size_t length)
Compare IPv4 address prefixes.
Definition: ipv4_misc.c:621
bool_t ipv4IsOnLink(NetInterface *interface, Ipv4Addr ipAddr)
Check whether an IPv4 address is on-link.
Definition: ipv4_misc.c:433
bool_t ipv4IsTentativeAddr(NetInterface *interface, Ipv4Addr ipAddr)
Check whether an IPv4 address is a tentative address.
Definition: ipv4_misc.c:525
void ipv4UpdateInStats(NetInterface *interface, Ipv4Addr destIpAddr, size_t length)
Update IPv4 input statistics.
Definition: ipv4_misc.c:833
error_t ipv4CheckDestAddr(NetInterface *interface, Ipv4Addr ipAddr)
Destination IPv4 address filtering.
Definition: ipv4_misc.c:117
error_t ipv4SelectSourceAddr(NetInterface **interface, Ipv4Addr destAddr, Ipv4Addr *srcAddr)
IPv4 source address selection.
Definition: ipv4_misc.c:202
uint_t ipv4GetAddrScope(Ipv4Addr ipAddr)
Retrieve the scope of an IPv4 address.
Definition: ipv4_misc.c:657
bool_t ipv4TrapIgmpPacket(Ipv4Header *header)
Trap IGMP packets.
Definition: ipv4_misc.c:803
Helper functions for IPv4.
MIB-II module.
#define MIB2_IP_INC_COUNTER32(name, value)
Definition: mib2_module.h:164
Ipv4Addr addr
Definition: nbns_common.h:123
uint8_t p
Definition: ndp.h:300
TCP/IP stack core.
#define NET_INTERFACE_COUNT
Definition: net.h:113
#define NetInterface
Definition: net.h:36
#define netInterface
Definition: net_legacy.h:199
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:415
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
IPv4 address entry.
Definition: ipv4.h:343
Ipv4Addr subnetMask
Subnet mask.
Definition: ipv4.h:347
Ipv4AddrState state
IPv4 address state.
Definition: ipv4.h:345
Ipv4Addr defaultGateway
Default gateway.
Definition: ipv4.h:348
Ipv4Addr addr
IPv4 address.
Definition: ipv4.h:344
IPv4 multicast filter entry.
Definition: ipv4.h:357
Ipv4Addr addr
Multicast address.
Definition: ipv4.h:358
uint_t refCount
Reference count for the current entry.
Definition: ipv4.h:359
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint8_t length
Definition: tcp.h:368
uint8_t mask
Definition: web_socket.h:319