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