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