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