ipv6_misc.c
Go to the documentation of this file.
1 /**
2  * @file ipv6_misc.c
3  * @brief Helper functions for IPv6
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL IPV6_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "ipv6/ipv6.h"
37 #include "ipv6/ipv6_multicast.h"
38 #include "ipv6/ipv6_misc.h"
39 #include "ipv6/ndp.h"
40 #include "ipv6/ndp_cache.h"
41 #include "mdns/mdns_responder.h"
42 #include "mibs/ip_mib_module.h"
43 #include "debug.h"
44 
45 //Check TCP/IP stack configuration
46 #if (IPV6_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Update IPv6 address state
51  * @param[in] entry Pointer to an IPv6 address entry
52  * @param[in] newState New state to switch to
53  **/
54 
56 {
57  //Any state change?
58  if(newState != entry->state)
59  {
60 #if defined(IPV6_CHANGE_ADDR_STATE_HOOK)
61  IPV6_CHANGE_ADDR_STATE_HOOK(entry, newState);
62 #endif
63 
64  //Switch to the new state
65  entry->state = newState;
66  }
67 }
68 
69 
70 /**
71  * @brief Get the state of the specified IPv6 address
72  * @param[in] interface Underlying network interface
73  * @param[in] addr IPv6 address
74  * @return Address state
75  **/
76 
78 {
79  uint_t i;
80  Ipv6AddrEntry *entry;
81 
82  //Loop through the list of IPv6 addresses assigned to the interface
83  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
84  {
85  //Point to the current entry
86  entry = &interface->ipv6Context.addrList[i];
87 
88  //Valid IPv6 address?
89  if(entry->state != IPV6_ADDR_STATE_INVALID)
90  {
91  //Check whether the current entry matches the specified address
92  if(ipv6CompAddr(&entry->addr, addr))
93  {
94  //Return the state of the IPv6 address
95  return entry->state;
96  }
97  }
98  }
99 
100  //The specified IPv6 address is not valid
102 }
103 
104 
105 /**
106  * @brief Set IPv6 address and address state
107  * @param[in] interface Pointer to the desired network interface
108  * @param[in] index Zero-based index
109  * @param[in] addr IPv6 address
110  * @param[in] state State of the IPv6 address
111  * @param[in] validLifetime Valid lifetime
112  * @param[in] preferredLifetime Preferred lifetime
113  * @param[in] permanent Permanently assigned address
114  * @return Error code
115  **/
116 
120 {
121  error_t error;
122  NetInterface *physicalInterface;
123  Ipv6AddrEntry *entry;
124  Ipv6Addr solicitedNodeAddr;
125 
126  //Check parameters
127  if(interface == NULL || addr == NULL)
129 
130  //Make sure that the index is valid
131  if(index >= IPV6_ADDR_LIST_SIZE)
132  return ERROR_OUT_OF_RANGE;
133 
134  //The IPv6 address must be a valid unicast address
136  return ERROR_INVALID_ADDRESS;
137 
138  //Initialize status code
139  error = NO_ERROR;
140 
141  //Point to the physical interface
142  physicalInterface = nicGetPhysicalInterface(interface);
143 
144  //Point to the corresponding entry
145  entry = &interface->ipv6Context.addrList[index];
146 
147  //Check whether an IPv6 address is already assigned
148  if(!ipv6CompAddr(&entry->addr, &IPV6_UNSPECIFIED_ADDR))
149  {
150  //Check the state of the IPv6 address
151  if(entry->state != IPV6_ADDR_STATE_INVALID)
152  {
153  //Ethernet interface?
154  if(physicalInterface->nicDriver != NULL &&
155  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
156  {
157  //Form the Solicited-Node address
158  ipv6ComputeSolicitedNodeAddr(&entry->addr, &solicitedNodeAddr);
159  //Leave the Solicited-Node multicast group
160  ipv6LeaveMulticastGroup(interface, &solicitedNodeAddr);
161  }
162  }
163  }
164 
165  //The current IPv6 address is no more valid
167  entry->validLifetime = 0;
168  entry->preferredLifetime = 0;
169  entry->permanent = FALSE;
170 
171  //Assign the new IPv6 address
172  entry->addr = *addr;
173 
174  //Check whether the new IPv6 address is valid
176  {
177  //Check the state of the IPv6 address
178  if(state != IPV6_ADDR_STATE_INVALID)
179  {
180  //Ethernet interface?
181  if(physicalInterface->nicDriver != NULL &&
182  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
183  {
184  //Form the Solicited-Node address for the link-local address
185  ipv6ComputeSolicitedNodeAddr(addr, &solicitedNodeAddr);
186  //Join the Solicited-Node multicast group for each assigned address
187  error = ipv6JoinMulticastGroup(interface, &solicitedNodeAddr);
188  }
189  //6LoWPAN interface?
190  else if(interface->nicDriver != NULL &&
191  interface->nicDriver->type == NIC_TYPE_6LOWPAN)
192  {
193  //There is no need to join the solicited-node multicast address,
194  //since nobody multicasts Neighbor Solicitations in this type of
195  //network (refer to RFC 6775 section 5.2)
196  }
197  }
198 
199  //Check status code
200  if(!error)
201  {
202  //Set the state of the IPv6 address
203  ipv6ChangeAddrState(entry, state);
204 
205  //Clear duplicate flag
206  entry->duplicate = FALSE;
207 
208  //Save preferred and valid lifetimes
210  entry->validLifetime = validLifetime;
211 
212  //Set time stamp
213  entry->timestamp = osGetSystemTime();
214 
215  //Initialize DAD related variables
216  entry->dadTimeout = 0;
217  entry->dadRetransmitCount = 0;
218  }
219 
220  //This flag tells whether the IPv6 address should be permanently assigned
221  entry->permanent = permanent;
222  }
223 
224 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
225  //Restart mDNS probing process
226  mdnsResponderStartProbing(interface->mdnsResponderContext);
227 #endif
228 
229  //Return status code
230  return error;
231 }
232 
233 
234 /**
235  * @brief Add a new entry to the list of IPv6 addresses
236  * @param[in] interface Underlying network interface
237  * @param[in] addr IPv6 address
238  * @param[in] validLifetime Valid lifetime, in seconds
239  * @param[in] preferredLifetime Preferred lifetime, in seconds
240  **/
241 
242 void ipv6AddAddr(NetInterface *interface, const Ipv6Addr *addr,
243  uint32_t validLifetime, uint32_t preferredLifetime)
244 {
245  uint_t i;
246  Ipv6AddrEntry *entry;
247 
248  //Check the valid lifetime
250  {
251  //The length of time in seconds that the address is valid
252  if(validLifetime < (MAX_DELAY / 1000))
253  {
254  validLifetime *= 1000;
255  }
256  else
257  {
259  }
260  }
261  else
262  {
263  //A value of all one bits (0xffffffff) represents infinity
265  }
266 
267  //Check the preferred lifetime
269  {
270  //The length of time in seconds that the address remains preferred
271  if(preferredLifetime < (MAX_DELAY / 1000))
272  {
273  preferredLifetime *= 1000;
274  }
275  else
276  {
278  }
279  }
280  else
281  {
282  //A value of all one bits (0xffffffff) represents infinity
284  }
285 
286  //Loop through the list of IPv6 addresses assigned to the interface
287  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
288  {
289  //Point to the current entry
290  entry = &interface->ipv6Context.addrList[i];
291 
292  //Check the state of the IPv6 address
293  if(entry->state == IPV6_ADDR_STATE_PREFERRED ||
295  {
296  //Check whether the current entry matches the specified address
297  if(ipv6CompAddr(&entry->addr, addr))
298  {
299  //The IPv6 address should be preserved if it has been manually assigned
300  if(!entry->permanent)
301  {
302  //Update the lifetimes of the entry
303  entry->validLifetime = validLifetime;
305 
306  //Save current time
307  entry->timestamp = osGetSystemTime();
308  //Update the state of the IPv6 address
310  }
311 
312  //Exit immediately
313  return;
314  }
315  }
316  }
317 
318  //If no matching entry was found, then try to create a new entry
319  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
320  {
321  //Point to the current entry
322  entry = &interface->ipv6Context.addrList[i];
323 
324  //Check the state of the IPv6 address
325  if(entry->state == IPV6_ADDR_STATE_INVALID)
326  {
327  //The IPv6 address should be preserved if it has been manually assigned
328  if(!entry->permanent)
329  {
330 #if (NDP_SUPPORT == ENABLED)
331  //Check whether Duplicate Address Detection should be performed
332  if(interface->ndpContext.dupAddrDetectTransmits > 0)
333  {
334  //Use the IPv6 address as a tentative address
337  }
338  else
339 #endif
340  {
341  //The use of the IPv6 address is now unrestricted
344  }
345 
346  //Exit immediately
347  return;
348  }
349  }
350  }
351 }
352 
353 
354 /**
355  * @brief Remove an entry from the list of IPv6 addresses
356  * @param[in] interface Underlying network interface
357  * @param[in] addr IPv6 address
358  **/
359 
360 void ipv6RemoveAddr(NetInterface *interface, const Ipv6Addr *addr)
361 {
362  uint_t i;
363  Ipv6AddrEntry *entry;
364 
365  //Loop through the list of IPv6 addresses assigned to the interface
366  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
367  {
368  //Point to the current entry
369  entry = &interface->ipv6Context.addrList[i];
370 
371  //Valid IPv6 address?
372  if(entry->validLifetime)
373  {
374  //Check whether the current entry matches the specified address
375  if(ipv6CompAddr(&entry->addr, addr))
376  {
377  //The IPv6 address should be preserved if it has been manually assigned
378  if(!entry->permanent)
379  {
380  //Remove the IPv6 address from the list
381  ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
383  }
384  }
385  }
386  }
387 }
388 
389 
390 /**
391  * @brief Add a new entry to the Prefix List
392  * @param[in] interface Underlying network interface
393  * @param[in] prefix IPv6 prefix
394  * @param[in] length The number of leading bits in the prefix that are valid
395  * @param[in] onLinkFlag On-link flag
396  * @param[in] autonomousFlag Autonomous flag
397  * @param[in] validLifetime Valid lifetime, in seconds
398  * @param[in] preferredLifetime Preferred lifetime, in seconds
399  **/
400 
401 void ipv6AddPrefix(NetInterface *interface, const Ipv6Addr *prefix,
402  uint_t length, bool_t onLinkFlag, bool_t autonomousFlag,
403  uint32_t validLifetime, uint32_t preferredLifetime)
404 {
405  uint_t i;
406  Ipv6PrefixEntry *entry;
407  Ipv6PrefixEntry *firstFreeEntry;
408 
409  //Initialize variables
410  entry = NULL;
411  firstFreeEntry = NULL;
412 
413  //Loop through the Prefix List
414  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
415  {
416  //Point to the current entry
417  entry = &interface->ipv6Context.prefixList[i];
418 
419  //Valid prefix?
420  if(entry->validLifetime)
421  {
422  //Compare prefix length against the specified value
423  if(entry->prefixLen == length)
424  {
425  //Check whether the current entry matches the specified prefix
426  if(ipv6CompPrefix(&entry->prefix, prefix, length))
427  break;
428  }
429  }
430  else
431  {
432  //The IPv6 prefix should be preserved if it has been manually assigned
433  if(!entry->permanent)
434  {
435  //Keep track of the first free entry
436  if(firstFreeEntry == NULL)
437  {
438  firstFreeEntry = entry;
439  }
440  }
441  }
442  }
443 
444  //No matching entry found?
445  if(i >= IPV6_PREFIX_LIST_SIZE)
446  entry = firstFreeEntry;
447 
448  //Update the entry if necessary
449  if(entry != NULL)
450  {
451  //The IPv6 prefix should be preserved if it has been manually assigned
452  if(!entry->permanent)
453  {
454  //Save the IPv6 prefix
455  entry->prefix = *prefix;
456  entry->prefixLen = length;
457 
458  //Save On-link and Autonomous flags
459  entry->onLinkFlag = onLinkFlag;
460  entry->autonomousFlag = autonomousFlag;
461 
462  //Check the valid lifetime
464  {
465  //The length of time in seconds that the prefix is valid
466  //for the purpose of on-link determination
467  if(validLifetime < (MAX_DELAY / 1000))
468  {
469  entry->validLifetime = validLifetime * 1000;
470  }
471  else
472  {
473  entry->validLifetime = MAX_DELAY;
474  }
475  }
476  else
477  {
478  //A value of all one bits (0xffffffff) represents infinity
479  entry->validLifetime = INFINITE_DELAY;
480  }
481 
482  //Check the preferred lifetime
484  {
485  //The length of time in seconds that addresses generated from the
486  //prefix via stateless address autoconfiguration remain preferred
487  if(preferredLifetime < (MAX_DELAY / 1000))
488  {
489  entry->preferredLifetime = preferredLifetime * 1000;
490  }
491  else
492  {
493  entry->preferredLifetime = MAX_DELAY;
494  }
495  }
496  else
497  {
498  //A value of all one bits (0xffffffff) represents infinity
500  }
501 
502  //Save current time
503  entry->timestamp = osGetSystemTime();
504  }
505  }
506 }
507 
508 
509 /**
510  * @brief Remove an entry from the Prefix List
511  * @param[in] interface Underlying network interface
512  * @param[in] prefix IPv6 prefix
513  * @param[in] length The number of leading bits in the prefix that are valid
514  **/
515 
517  uint_t length)
518 {
519  uint_t i;
520  Ipv6PrefixEntry *entry;
521 
522  //Loop through the Prefix List
523  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
524  {
525  //Point to the current entry
526  entry = &interface->ipv6Context.prefixList[i];
527 
528  //Valid prefix?
529  if(entry->validLifetime)
530  {
531  //Compare prefix length against the specified value
532  if(entry->prefixLen == length)
533  {
534  //Check whether the current entry matches the specified prefix
535  if(ipv6CompPrefix(&entry->prefix, prefix, length))
536  {
537  //The IPv6 prefix should be preserved if it has been manually assigned
538  if(!entry->permanent)
539  {
540  //When removing an entry from the Prefix List, there is no need
541  //to purge any entries from the Destination or Neighbor Caches
542  entry->prefix = IPV6_UNSPECIFIED_ADDR;
543  entry->prefixLen = 0;
544  entry->validLifetime = 0;
545  }
546  }
547  }
548  }
549  }
550 }
551 
552 
553 /**
554  * @brief Add a new entry to the Default Router List
555  * @param[in] interface Underlying network interface
556  * @param[in] addr IPv6 address of the router
557  * @param[in] lifetime Router lifetime, in seconds
558  * @param[in] preference Preference value
559  **/
560 
562  uint16_t lifetime, uint8_t preference)
563 {
564  uint_t i;
565  Ipv6RouterEntry *entry;
566  Ipv6RouterEntry *firstFreeEntry;
567 
568  //Initialize variables
569  entry = NULL;
570  firstFreeEntry = NULL;
571 
572  //Loop through the Default Router List
573  for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
574  {
575  //Point to the current entry
576  entry = &interface->ipv6Context.routerList[i];
577 
578  //Check the lifetime associated with the default router
579  if(entry->lifetime)
580  {
581  //Check whether the current entry matches the specified router address
582  if(ipv6CompAddr(&entry->addr, addr))
583  break;
584  }
585  else
586  {
587  //The router address should be preserved if it has been manually assigned
588  if(!entry->permanent)
589  {
590  //Keep track of the first free entry
591  if(firstFreeEntry == NULL)
592  {
593  firstFreeEntry = entry;
594  }
595  }
596  }
597  }
598 
599  //No matching entry found?
600  if(i >= IPV6_ROUTER_LIST_SIZE)
601  entry = firstFreeEntry;
602 
603  //Update the entry if necessary
604  if(entry != NULL)
605  {
606  //The router address should be preserved if it has been manually assigned
607  if(!entry->permanent)
608  {
609  //Save the IPv6 address of the router
610  entry->addr = *addr;
611  //The lifetime associated with the default router
612  entry->lifetime = lifetime * 1000;
613  //Save preference value
614  entry->preference = preference;
615  //Save current time
616  entry->timestamp = osGetSystemTime();
617  }
618  }
619 }
620 
621 
622 /**
623  * @brief Remove an entry from the Default Router List
624  * @param[in] interface Underlying network interface
625  * @param[in] addr IPv6 address of the router to be removed from the list
626  **/
627 
629 {
630  uint_t i;
631  bool_t flag;
632  Ipv6RouterEntry *entry;
633 
634  //This flag will be set if any entry has been removed from
635  //the Default Router List
636  flag = FALSE;
637 
638  //Loop through the Default Router List
639  for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
640  {
641  //Point to the current entry
642  entry = &interface->ipv6Context.routerList[i];
643 
644  //Check the lifetime associated with the default router
645  if(entry->lifetime)
646  {
647  //Check whether the current entry matches the specified router address
648  if(ipv6CompAddr(&entry->addr, addr))
649  {
650  //The router address should be preserved if it has been manually assigned
651  if(!entry->permanent)
652  {
653  //Immediately time-out the entry
654  entry->addr = IPV6_UNSPECIFIED_ADDR;
655  entry->lifetime = 0;
656 
657  //Set flag
658  flag = TRUE;
659  }
660  }
661  }
662  }
663 
664  //Check whether an entry has been removed from the list
665  if(flag)
666  {
667 #if (NDP_SUPPORT == ENABLED)
668  //When removing a router from the Default Router list, the node must
669  //update the Destination Cache in such a way that all entries using
670  //the router perform next-hop determination again
671  ndpFlushDestCache(interface);
672 #endif
673  }
674 }
675 
676 
677 /**
678  * @brief Flush the list of IPv6 addresses
679  * @param[in] interface Underlying network interface
680  **/
681 
683 {
684  uint_t i;
685  Ipv6AddrEntry *entry;
686 
687  //Go through the list of IPv6 addresses
688  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
689  {
690  //Point to the current entry
691  entry = &interface->ipv6Context.addrList[i];
692 
693  //Valid IPv6 address?
694  if(entry->validLifetime > 0)
695  {
696  //The IPv6 address should be preserved if it has been manually assigned
697  if(!entry->permanent)
698  {
699  //The IPv6 address is not longer valid
700  ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
702  }
703  }
704  }
705 }
706 
707 
708 /**
709  * @brief Flush the Prefix List
710  * @param[in] interface Underlying network interface
711  **/
712 
714 {
715  uint_t i;
716  Ipv6PrefixEntry *entry;
717 
718  //Go through the Prefix List
719  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
720  {
721  //Point to the current entry
722  entry = &interface->ipv6Context.prefixList[i];
723 
724  //Valid IPv6 prefix?
725  if(entry->validLifetime > 0)
726  {
727  //The IPv6 prefix should be preserved if it has been manually assigned
728  if(!entry->permanent)
729  {
730  //Remove the entry from the Prefix List
731  entry->prefix = IPV6_UNSPECIFIED_ADDR;
732  entry->prefixLen = 0;
733  entry->validLifetime = 0;
734  }
735  }
736  }
737 }
738 
739 
740 /**
741  * @brief Flush the Default Router List
742  * @param[in] interface Underlying network interface
743  **/
744 
746 {
747  uint_t i;
748  Ipv6RouterEntry *entry;
749 
750  //Go through the Default Router List
751  for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
752  {
753  //Point to the current entry
754  entry = &interface->ipv6Context.routerList[i];
755 
756  //Valid entry?
757  if(entry->lifetime > 0)
758  {
759  //The router address should be preserved if it has been manually assigned
760  if(!entry->permanent)
761  {
762  //Clear the current entry
763  entry->addr = IPV6_UNSPECIFIED_ADDR;
764  //Remove the entry from the Default Router List
765  entry->lifetime = 0;
766  }
767  }
768  }
769 }
770 
771 
772 /**
773  * @brief Flush the list of DNS servers
774  * @param[in] interface Underlying network interface
775  **/
776 
778 {
779  //Clear the list of DNS servers
780  osMemset(interface->ipv6Context.dnsServerList, 0,
781  sizeof(interface->ipv6Context.dnsServerList));
782 }
783 
784 
785 /**
786  * @brief Source IPv6 address filtering
787  * @param[in] interface Underlying network interface
788  * @param[in] ipAddr Source IPv6 address to be checked
789  * @return Error code
790  **/
791 
793 {
794  //Multicast addresses cannot be used as source address
796  {
797  //Debug message
798  TRACE_WARNING("Wrong source IPv6 address!\r\n");
799  //The source address not is acceptable
800  return ERROR_INVALID_ADDRESS;
801  }
802 
803  //The source address is acceptable
804  return NO_ERROR;
805 }
806 
807 
808 /**
809  * @brief Destination IPv6 address filtering
810  * @param[in] interface Underlying network interface
811  * @param[in] ipAddr Destination IPv6 address to be checked
812  * @return Error code
813  **/
814 
816 {
817  error_t error;
818  uint_t i;
819 
820  //Filter out any invalid addresses
821  error = ERROR_INVALID_ADDRESS;
822 
823  //Loop through the list of IPv6 unicast addresses
824  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
825  {
826  Ipv6AddrEntry *entry;
827 
828  //Point to the current entry
829  entry = &interface->ipv6Context.addrList[i];
830 
831  //Valid entry?
832  if(entry->state != IPV6_ADDR_STATE_INVALID)
833  {
834  //Check whether the destination address matches a valid unicast
835  //address assigned to the interface
836  if(ipv6CompAddr(&entry->addr, ipAddr))
837  {
838  //The destination address is acceptable
839  error = NO_ERROR;
840  //We are done
841  break;
842  }
843  }
844  }
845 
846  //Check status code
847  if(error == ERROR_INVALID_ADDRESS)
848  {
849  Ipv6Addr *anycastAddrList;
850 
851  //Point to the list of anycast addresses assigned to the interface
852  anycastAddrList = interface->ipv6Context.anycastAddrList;
853 
854  //Loop through the list of IPv6 anycast addresses
855  for(i = 0; i < IPV6_ANYCAST_ADDR_LIST_SIZE; i++)
856  {
857  //Valid entry?
858  if(!ipv6CompAddr(&anycastAddrList[i], &IPV6_UNSPECIFIED_ADDR))
859  {
860  //Check whether the destination address matches a valid anycast
861  //address assigned to the interface
862  if(ipv6CompAddr(&anycastAddrList[i], ipAddr))
863  {
864  //The destination address is acceptable
865  error = NO_ERROR;
866  //We are done
867  break;
868  }
869  }
870  }
871  }
872 
873  //Return status code
874  return error;
875 }
876 
877 
878 /**
879  * @brief IPv6 source address selection
880  *
881  * This function selects the source address and the relevant network interface
882  * to be used in order to join the specified destination address
883  *
884  * @param[in,out] interface A pointer to a valid network interface may be provided as
885  * a hint. The function returns a pointer identifying the interface to be used
886  * @param[in] destAddr Destination IPv6 address
887  * @param[out] srcAddr Local IPv6 address to be used
888  * @return Error code
889  **/
890 
893 {
894  error_t error;
895  uint_t i;
896  uint_t j;
897  NetInterface *currentInterface;
898  NetInterface *bestInterface;
899  Ipv6AddrEntry *currentAddr;
900  Ipv6AddrEntry *bestAddr;
901 
902  //Initialize variables
903  bestInterface = NULL;
904  bestAddr = NULL;
905 
906  //Loop through network interfaces
907  for(i = 0; i < NET_INTERFACE_COUNT; i++)
908  {
909  //Point to the current interface
910  currentInterface = &netInterface[i];
911 
912  //A network interface may be provided as a hint
913  if(*interface != currentInterface && *interface != NULL)
914  {
915  //Select the next interface in the list
916  continue;
917  }
918 
919  //A sort of the candidate source addresses is being performed, where a
920  //set of rules define the ordering among addresses (refer to RFC 6724)
921  for(j = 0; j < IPV6_ADDR_LIST_SIZE; j++)
922  {
923  //Point to the current entry
924  currentAddr = &currentInterface->ipv6Context.addrList[j];
925 
926  //Check the state of the address
927  if(currentAddr->state == IPV6_ADDR_STATE_PREFERRED ||
928  currentAddr->state == IPV6_ADDR_STATE_DEPRECATED)
929  {
930  //Select the first address as default
931  if(bestAddr == NULL)
932  {
933  //Give the current source address the higher precedence
934  bestInterface = currentInterface;
935  bestAddr = currentAddr;
936 
937  //Select the next address in the list
938  continue;
939  }
940 
941  //Rule 1: Prefer same address
942  if(ipv6CompAddr(&bestAddr->addr, destAddr))
943  {
944  //Select the next address in the list
945  continue;
946  }
947  else if(ipv6CompAddr(&currentAddr->addr, destAddr))
948  {
949  //Give the current source address the higher precedence
950  bestInterface = currentInterface;
951  bestAddr = currentAddr;
952 
953  //Select the next address in the list
954  continue;
955  }
956 
957  //Rule 2: Prefer appropriate scope
958  if(ipv6GetAddrScope(&currentAddr->addr) < ipv6GetAddrScope(&bestAddr->addr))
959  {
960  if(ipv6GetAddrScope(&currentAddr->addr) >= ipv6GetAddrScope(destAddr))
961  {
962  //Give the current source address the higher precedence
963  bestInterface = currentInterface;
964  bestAddr = currentAddr;
965  }
966 
967  //Select the next address in the list
968  continue;
969  }
970  else if(ipv6GetAddrScope(&bestAddr->addr) < ipv6GetAddrScope(&currentAddr->addr))
971  {
973  {
974  //Give the current source address the higher precedence
975  bestInterface = currentInterface;
976  bestAddr = currentAddr;
977  }
978 
979  //Select the next address in the list
980  continue;
981  }
982 
983  //Rule 3: Avoid deprecated addresses
984  if(bestAddr->state == IPV6_ADDR_STATE_PREFERRED &&
985  currentAddr->state == IPV6_ADDR_STATE_DEPRECATED)
986  {
987  //Select the next address in the list
988  continue;
989  }
990  else if(currentAddr->state == IPV6_ADDR_STATE_PREFERRED &&
991  bestAddr->state == IPV6_ADDR_STATE_DEPRECATED)
992  {
993  //Give the current source address the higher precedence
994  bestInterface = currentInterface;
995  bestAddr = currentAddr;
996 
997  //Select the next address in the list
998  continue;
999  }
1000 
1001  //Rule 8: Use longest matching prefix
1002  if(ipv6GetCommonPrefixLength(&currentAddr->addr, destAddr) >
1004  {
1005  //Give the current source address the higher precedence
1006  bestInterface = currentInterface;
1007  bestAddr = currentAddr;
1008  }
1009  }
1010  }
1011  }
1012 
1013  //Valid source address?
1014  if(bestAddr != NULL)
1015  {
1016  //Return the out-going interface and the source address to be used
1017  *interface = bestInterface;
1018  *srcAddr = bestAddr->addr;
1019 
1020  //Successful source address selection
1021  error = NO_ERROR;
1022  }
1023  else
1024  {
1025  //Report an error
1026  error = ERROR_NO_ADDRESS;
1027  }
1028 
1029  //Return status code
1030  return error;
1031 }
1032 
1033 
1034 /**
1035  * @brief Check whether an IPv6 address is on-link
1036  * @param[in] interface Underlying network interface
1037  * @param[in] ipAddr IPv6 address to be checked
1038  * @return TRUE if the IPv6 address is on-link, else FALSE
1039  **/
1040 
1042 {
1043  uint_t i;
1044  Ipv6PrefixEntry *entry;
1045 
1046  //Link-local prefix?
1048  {
1049  //The link-local prefix is considered to be on the prefix list with
1050  //an infinite invalidation timer regardless of whether routers are
1051  //advertising a prefix for it
1052  return TRUE;
1053  }
1054 
1055  //Loop through the Prefix List
1056  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
1057  {
1058  //Point to the current entry
1059  entry = &interface->ipv6Context.prefixList[i];
1060 
1061  //Valid prefix?
1062  if(entry->validLifetime > 0)
1063  {
1064  //Check the specified address against the prefix
1065  if(ipv6CompPrefix(ipAddr, &entry->prefix, entry->prefixLen))
1066  {
1067  //The specified IPv6 address is on-link
1068  return TRUE;
1069  }
1070  }
1071  }
1072 
1073  //The specified IPv6 address is off-link
1074  return FALSE;
1075 }
1076 
1077 
1078 /**
1079  * @brief Check whether an IPv6 address is an anycast address
1080  * @param[in] interface Underlying network interface
1081  * @param[in] ipAddr IPv6 address to be checked
1082  * @return TRUE if the IPv6 address is an anycast address, else FALSE
1083  **/
1084 
1086 {
1087  uint_t i;
1088  Ipv6Addr *anycastAddrList;
1089 
1090  //Point to the list of anycast addresses assigned to the interface
1091  anycastAddrList = interface->ipv6Context.anycastAddrList;
1092 
1093  //Loop through the list of IPv6 anycast addresses
1094  for(i = 0; i < IPV6_ANYCAST_ADDR_LIST_SIZE; i++)
1095  {
1096  //Valid entry?
1097  if(!ipv6CompAddr(&anycastAddrList[i], &IPV6_UNSPECIFIED_ADDR))
1098  {
1099  //Check whether the specified address matches a valid anycast
1100  //address assigned to the interface
1101  if(ipv6CompAddr(&anycastAddrList[i], ipAddr))
1102  {
1103  //The specified IPv6 address is an anycast address
1104  return TRUE;
1105  }
1106  }
1107  }
1108 
1109  //The specified IPv6 address is not an anycast address
1110  return FALSE;
1111 }
1112 
1113 
1114 /**
1115  * @brief Check whether an IPv6 address is a tentative address
1116  * @param[in] interface Underlying network interface
1117  * @param[in] ipAddr IPv6 address to be checked
1118  * @return TRUE if the IPv6 address is a tentative address, else FALSE
1119  **/
1120 
1122 {
1123  uint_t i;
1124  Ipv6AddrEntry *entry;
1125 
1126  //Loop through the list of IPv6 unicast addresses
1127  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
1128  {
1129  //Point to the current entry
1130  entry = &interface->ipv6Context.addrList[i];
1131 
1132  //Tentative address?
1133  if(entry->state == IPV6_ADDR_STATE_TENTATIVE)
1134  {
1135  //Check whether the specified address matches a valid unicast
1136  //address assigned to the interface
1137  if(ipv6CompAddr(&entry->addr, ipAddr))
1138  {
1139  //The specified IPv6 address is a tentative address
1140  return TRUE;
1141  }
1142  }
1143  }
1144 
1145  //The specified IPv6 address is not a tentative address
1146  return FALSE;
1147 }
1148 
1149 
1150 /**
1151  * @brief Check whether the specified IPv6 is assigned to the host
1152  * @param[in] ipAddr IPv6 address to be checked
1153  * @return TRUE if the IPv6 address matches any address assigned to the host,
1154  * else FALSE
1155  **/
1156 
1158 {
1159  uint_t i;
1160  uint_t j;
1161  bool_t flag;
1162  NetInterface *interface;
1163  Ipv6AddrEntry *entry;
1164 
1165  //Initialize flag
1166  flag = FALSE;
1167 
1168  //Loopback address?
1170  {
1171  //If an application in a host sends packets to this address, the IPv6
1172  //stack will loop these packets back on the same virtual interface
1173  flag = TRUE;
1174  }
1175  else
1176  {
1177  //Loop through network interfaces
1178  for(i = 0; i < NET_INTERFACE_COUNT && !flag; i++)
1179  {
1180  //Point to the current interface
1181  interface = &netInterface[i];
1182 
1183  //Iterate through the list of addresses assigned to the interface
1184  for(j = 0; j < IPV6_ADDR_LIST_SIZE && !flag; j++)
1185  {
1186  //Point to the current entry
1187  entry = &interface->ipv6Context.addrList[j];
1188 
1189  //Valid entry?
1190  if(entry->state == IPV6_ADDR_STATE_PREFERRED ||
1192  {
1193  //Check whether the specified IPv6 address matches any address
1194  //assigned to the host
1195  if(ipv6CompAddr(&entry->addr, ipAddr))
1196  {
1197  flag = TRUE;
1198  }
1199  }
1200  }
1201  }
1202  }
1203 
1204  //Return TRUE if the specified address matches any address assigned to the host
1205  return flag;
1206 }
1207 
1208 
1209 /**
1210  * @brief Compare IPv6 address prefixes
1211  * @param[in] ipAddr1 Pointer to the first IPv6 address
1212  * @param[in] ipAddr2 Pointer to the second IPv6 address
1213  * @param[in] length Prefix length
1214  * @return TRUE if the prefixes match each other, else FALSE
1215  **/
1216 
1217 bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2,
1218  size_t length)
1219 {
1220  size_t n;
1221  size_t m;
1222  uint8_t mask;
1223 
1224  //Ensure the prefix length is valid
1225  if(length > 128)
1226  return FALSE;
1227 
1228  //Number of complete bytes
1229  n = length / 8;
1230  //Number of bits in the last byte, if any
1231  m = length % 8;
1232 
1233  //Compare the first part
1234  if(n > 0)
1235  {
1236  if(osMemcmp(ipAddr1, ipAddr2, n))
1237  return FALSE;
1238  }
1239 
1240  //Compare the remaining bits, if any
1241  if(m > 0)
1242  {
1243  //Calculate the mask to be applied
1244  mask = ((1 << m) - 1) << (8 - m);
1245 
1246  //Check remaining bits
1247  if((ipAddr1->b[n] & mask) != (ipAddr2->b[n] & mask))
1248  return FALSE;
1249  }
1250 
1251  //The prefixes match each other
1252  return TRUE;
1253 }
1254 
1255 
1256 /**
1257  * @brief Retrieve the scope of an IPv6 address
1258  * @param[in] ipAddr Pointer to an IPv6 address
1259  * @return IPv6 address scope
1260  **/
1261 
1263 {
1264  uint_t scope;
1265 
1266  //Multicast address?
1268  {
1269  //Retrieve the scope of the multicast address
1271  }
1272  //Loopback address?
1274  {
1275  //The loopback address may be used by a node to send an IPv6 packet
1276  //to itself
1278  }
1279  //Link-local unicast address?
1281  {
1282  //A link-local address is for use on a single link
1284  }
1285  //Site-local unicast address?
1287  {
1288  //A site-local address is for use in a single site
1290  }
1291  //Global address?
1292  else
1293  {
1294  //Global scope
1295  scope = IPV6_ADDR_SCOPE_GLOBAL;
1296  }
1297 
1298  //Return the scope of the specified IPv6 address
1299  return scope;
1300 }
1301 
1302 
1303 /**
1304  * @brief Retrieve the scope of an IPv6 multicast address
1305  * @param[in] ipAddr Pointer to an IPv6 multicast address
1306  * @return IPv6 address scope
1307  **/
1308 
1310 {
1311  uint_t scope;
1312 
1313  //The scope field is a 4-bit value
1314  scope = ipAddr->b[1] & 0x0F;
1315 
1316  //If the scope field contains the reserved value F, an IPv6 packet
1317  //must be treated the same as packets destined to a global multicast
1318  //address (refer to RFC 3513 section 2.7)
1319  if(scope == 0x0F)
1320  {
1321  scope = IPV6_ADDR_SCOPE_GLOBAL;
1322  }
1323 
1324  //Return the scope of the specified IPv6 multicast address
1325  return scope;
1326 }
1327 
1328 
1329 /**
1330  * @brief Compute the length of the longest common prefix
1331  * @param[in] ipAddr1 Pointer to the first IPv6 address
1332  * @param[in] ipAddr2 Pointer to the second IPv6 address
1333  * @return The length of the longest common prefix, in bits
1334  **/
1335 
1337  const Ipv6Addr *ipAddr2)
1338 {
1339  uint_t i;
1340  uint_t j;
1341  uint8_t mask;
1342 
1343  //Clear bit counter
1344  j = 0;
1345 
1346  //Perform a byte-for-byte comparison
1347  for(i = 0; i < sizeof(Ipv6Addr); i++)
1348  {
1349  //Loop as long as prefixes match
1350  if(ipAddr1->b[i] != ipAddr2->b[i])
1351  {
1352  break;
1353  }
1354  }
1355 
1356  //Any mismatch?
1357  if(i < sizeof(Ipv6Addr))
1358  {
1359  //Perform a bit-for-bit comparison
1360  for(j = 0; j < 8; j++)
1361  {
1362  //Calculate the mask to be applied
1363  mask = 1 << (7 - j);
1364 
1365  //Loop as long as prefixes match
1366  if((ipAddr1->b[i] & mask) != (ipAddr2->b[i] & mask))
1367  {
1368  break;
1369  }
1370  }
1371  }
1372 
1373  //Return the length of the longest prefix that the two addresses
1374  //have in common
1375  return i * 8 + j;
1376 }
1377 
1378 
1379 /**
1380  * @brief Form a solicited-node address from an IPv6 address
1381  * @param[in] ipAddr Unicast or anycast address
1382  * @param[out] solicitedNodeAddr Corresponding solicited-node address
1383  * @return Error code
1384  **/
1385 
1387  Ipv6Addr *solicitedNodeAddr)
1388 {
1389  error_t error;
1390 
1391  //Ensure the specified address is a valid unicast or anycast address
1393  {
1394  //Copy the 104-bit prefix
1395  ipv6CopyAddr(solicitedNodeAddr, &IPV6_SOLICITED_NODE_ADDR_PREFIX);
1396 
1397  //Take the low-order 24 bits of the address (unicast or anycast) and
1398  //append those bits to the prefix
1399  solicitedNodeAddr->b[13] = ipAddr->b[13];
1400  solicitedNodeAddr->b[14] = ipAddr->b[14];
1401  solicitedNodeAddr->b[15] = ipAddr->b[15];
1402 
1403  //Successful processing
1404  error = NO_ERROR;
1405  }
1406  else
1407  {
1408  //Report an error
1409  error = ERROR_INVALID_ADDRESS;
1410  }
1411 
1412  //Return status code
1413  return error;
1414 }
1415 
1416 
1417 /**
1418  * @brief Generate a IPv6 link-local address from an interface identifier
1419  * @param[in] interfaceId Interface identifier
1420  * @param[out] ipAddr Corresponding IPv6 link-local address
1421  **/
1422 
1424 {
1425  //A link-local address is formed by combining the well-known link-local
1426  //prefix fe80::/10 with the interface identifier
1427  ipAddr->w[0] = HTONS(0xFE80);
1428  ipAddr->w[1] = HTONS(0x0000);
1429  ipAddr->w[2] = HTONS(0x0000);
1430  ipAddr->w[3] = HTONS(0x0000);
1431  ipAddr->w[4] = interfaceId->w[0];
1432  ipAddr->w[5] = interfaceId->w[1];
1433  ipAddr->w[6] = interfaceId->w[2];
1434  ipAddr->w[7] = interfaceId->w[3];
1435 }
1436 
1437 
1438 /**
1439  * @brief Update IPv6 input statistics
1440  * @param[in] interface Underlying network interface
1441  * @param[in] destIpAddr Destination IP address
1442  * @param[in] length Length of the incoming IP packet
1443  **/
1444 
1446  size_t length)
1447 {
1448  //Check whether the destination address is a unicast or multicast address
1450  {
1451  //Number of IP multicast datagrams transmitted
1452  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInMcastPkts, 1);
1453  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCInMcastPkts, 1);
1454  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInMcastPkts, 1);
1455  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCInMcastPkts, 1);
1456 
1457  //Total number of octets transmitted in IP multicast datagrams
1458  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInMcastOctets, length);
1459  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCInMcastOctets, length);
1460  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInMcastOctets, length);
1461  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCInMcastOctets, length);
1462  }
1463 }
1464 
1465 
1466 /**
1467  * @brief Update IPv6 output statistics
1468  * @param[in] interface Underlying network interface
1469  * @param[in] destIpAddr Destination IP address
1470  * @param[in] length Length of the outgoing IP packet
1471  **/
1472 
1474  size_t length)
1475 {
1476  //Check whether the destination address is a unicast or multicast address
1478  {
1479  //Number of IP multicast datagrams transmitted
1480  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsOutMcastPkts, 1);
1481  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCOutMcastPkts, 1);
1482  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsOutMcastPkts, 1);
1483  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCOutMcastPkts, 1);
1484 
1485  //Total number of octets transmitted in IP multicast datagrams
1486  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsOutMcastOctets, length);
1487  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCOutMcastOctets, length);
1488  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsOutMcastOctets, length);
1489  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCOutMcastOctets, length);
1490  }
1491 
1492  //Total number of IP datagrams that this entity supplied to the lower
1493  //layers for transmission
1494  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsOutTransmits, 1);
1495  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCOutTransmits, 1);
1496  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsOutTransmits, 1);
1497  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCOutTransmits, 1);
1498 
1499  //Total number of octets in IP datagrams delivered to the lower layers
1500  //for transmission
1501  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsOutOctets, length);
1502  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCOutOctets, length);
1503  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsOutOctets, length);
1504  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCOutOctets, length);
1505 }
1506 
1507 #endif
@ IPV6_ADDR_STATE_TENTATIVE
An address whose uniqueness on a link is being verified.
Definition: ipv6.h:174
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ipv6.h:460
IPv6 (Internet Protocol Version 6)
void ipv6AddDefaultRouter(NetInterface *interface, const Ipv6Addr *addr, uint16_t lifetime, uint8_t preference)
Add a new entry to the Default Router List.
Definition: ipv6_misc.c:561
systime_t lifetime
Router lifetime.
Definition: ipv6.h:457
@ ERROR_NO_ADDRESS
Definition: error.h:200
int bool_t
Definition: compiler_port.h:61
@ ERROR_OUT_OF_RANGE
Definition: error.h:138
Ipv4Addr destAddr
Definition: ipv4.h:330
void ipv6FlushPrefixList(NetInterface *interface)
Flush the Prefix List.
Definition: ipv6_misc.c:713
Eui64
Definition: ethernet.h:212
void ipv6UpdateOutStats(NetInterface *interface, const Ipv6Addr *destIpAddr, size_t length)
Update IPv6 output statistics.
Definition: ipv6_misc.c:1473
@ IPV6_ADDR_SCOPE_INTERFACE_LOCAL
Definition: ipv6.h:158
void ipv6RemovePrefix(NetInterface *interface, const Ipv6Addr *prefix, uint_t length)
Remove an entry from the Prefix List.
Definition: ipv6_misc.c:516
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
void ipv6RemoveDefaultRouter(NetInterface *interface, const Ipv6Addr *addr)
Remove an entry from the Default Router List.
Definition: ipv6_misc.c:628
systime_t preferredLifetime
Preferred lifetime.
Definition: ipv6.h:444
uint_t dadRetransmitCount
Retransmission counter for Duplicate Address Detection.
Definition: ipv6.h:429
const Ipv6Addr IPV6_SOLICITED_NODE_ADDR_PREFIX
Definition: ipv6.c:86
void ipv6ChangeAddrState(Ipv6AddrEntry *entry, Ipv6AddrState newState)
Update IPv6 address state.
Definition: ipv6_misc.c:55
#define TRUE
Definition: os_port.h:50
uint32_t preferredLifetime
Ipv6AddrState ipv6GetAddrState(NetInterface *interface, const Ipv6Addr *addr)
Get the state of the specified IPv6 address.
Definition: ipv6_misc.c:77
Ipv6Addr addr
IPv6 address.
Definition: ipv6.h:421
systime_t preferredLifetime
Preferred lifetime.
Definition: ipv6.h:425
void ipv6FlushAddrList(NetInterface *interface)
Flush the list of IPv6 addresses.
Definition: ipv6_misc.c:682
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ipv6.h:446
Ipv6Addr
Definition: ipv6.h:260
bool_t autonomousFlag
Autonomous flag.
Definition: ipv6.h:442
systime_t validLifetime
Valid lifetime.
Definition: ipv6.h:443
#define osMemcmp(p1, p2, length)
Definition: os_port.h:156
#define NET_INTERFACE_COUNT
Definition: net.h:115
bool_t ipv6IsTentativeAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is a tentative address.
Definition: ipv6_misc.c:1121
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:127
Ipv6Addr prefix
IPv6 prefix information.
Definition: ipv6.h:439
Ipv6Addr addr
Router address.
Definition: ipv6.h:456
uint32_t lifetime
Definition: ndp.h:480
Ipv6Addr prefix
#define NDP_INFINITE_LIFETIME
Definition: ndp.h:202
@ IPV6_ADDR_STATE_INVALID
An address that is not assigned to any interface.
Definition: ipv6.h:173
#define ipv6IsSiteLocalUnicastAddr(ipAddr)
Definition: ipv6.h:135
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:139
IPv6 multicast filtering.
uint_t ipv6GetCommonPrefixLength(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2)
Compute the length of the longest common prefix.
Definition: ipv6_misc.c:1336
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
void ipv6FlushDnsServerList(NetInterface *interface)
Flush the list of DNS servers.
Definition: ipv6_misc.c:777
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:85
Ipv6AddrState
IPv6 address state.
Definition: ipv6.h:172
bool_t ipv6IsLocalHostAddr(const Ipv6Addr *ipAddr)
Check whether the specified IPv6 is assigned to the host.
Definition: ipv6_misc.c:1157
error_t
Error codes.
Definition: error.h:43
#define netInterface
Definition: net_legacy.h:199
error_t ipv6JoinMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Join an IPv6 multicast group.
#define IP_MIB_INC_COUNTER64(name, value)
Definition: ip_mib_module.h:47
uint32_t validLifetime
systime_t dadTimeout
Timeout value for Duplicate Address Detection.
Definition: ipv6.h:428
error_t ipv6SelectSourceAddr(NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:891
Prefix list entry.
Definition: ipv6.h:438
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
uint8_t preference
Preference value.
Definition: ipv6.h:458
bool_t permanent
Permanently assigned address.
Definition: ipv6.h:426
#define NetInterface
Definition: net.h:36
error_t ipv6CheckDestAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Destination IPv6 address filtering.
Definition: ipv6_misc.c:815
uint_t ipv6GetAddrScope(const Ipv6Addr *ipAddr)
Retrieve the scope of an IPv6 address.
Definition: ipv6_misc.c:1262
Helper functions for IPv6.
@ IPV6_ADDR_SCOPE_GLOBAL
Definition: ipv6.h:163
uint8_t mask
Definition: web_socket.h:319
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:66
const Ipv6Addr IPV6_LOOPBACK_ADDR
Definition: ipv6.c:70
bool_t duplicate
The address is a duplicate.
Definition: ipv6.h:423
Eui64 interfaceId
Definition: ipv6cp.h:71
uint8_t length
Definition: tcp.h:375
@ IPV6_ADDR_SCOPE_LINK_LOCAL
Definition: ipv6.h:159
void ipv6RemoveAddr(NetInterface *interface, const Ipv6Addr *addr)
Remove an entry from the list of IPv6 addresses.
Definition: ipv6_misc.c:360
Neighbor and destination cache management.
#define ipv6IsLinkLocalUnicastAddr(ipAddr)
Definition: ipv6.h:131
NDP (Neighbor Discovery Protocol)
void ipv6FlushDefaultRouterList(NetInterface *interface)
Flush the Default Router List.
Definition: ipv6_misc.c:745
bool_t onLinkFlag
On-link flag.
Definition: ipv6.h:441
uint32_t systime_t
System time.
error_t ipv6SetAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr, Ipv6AddrState state, systime_t validLifetime, systime_t preferredLifetime, bool_t permanent)
Set IPv6 address and address state.
Definition: ipv6_misc.c:117
bool_t permanent
Permanently assigned prefix.
Definition: ipv6.h:445
#define TRACE_WARNING(...)
Definition: debug.h:93
uint8_t prefixLen
IPv6 prefix length.
Definition: ipv6.h:440
void ndpFlushDestCache(NetInterface *interface)
Flush Destination Cache.
Definition: ndp_cache.c:532
void ipv6AddAddr(NetInterface *interface, const Ipv6Addr *addr, uint32_t validLifetime, uint32_t preferredLifetime)
Add a new entry to the list of IPv6 addresses.
Definition: ipv6_misc.c:242
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:123
#define IPV6_ANYCAST_ADDR_LIST_SIZE
Definition: ipv6.h:72
Default router list entry.
Definition: ipv6.h:455
IPv6 address entry.
Definition: ipv6.h:420
uint8_t m
Definition: ndp.h:304
#define HTONS(value)
Definition: cpu_endian.h:410
uint8_t n
#define IPV6_ROUTER_LIST_SIZE
Definition: ipv6.h:86
IP MIB module.
#define IPV6_ADDR_LIST_SIZE
Definition: ipv6.h:65
void ipv6GenerateLinkLocalAddr(const Eui64 *interfaceId, Ipv6Addr *ipAddr)
Generate a IPv6 link-local address from an interface identifier.
Definition: ipv6_misc.c:1423
error_t ipv6LeaveMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Leave an IPv6 multicast group.
bool_t ipv6IsAnycastAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is an anycast address.
Definition: ipv6_misc.c:1085
MacAddr srcAddr
Definition: ethernet.h:222
bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2, size_t length)
Compare IPv6 address prefixes.
Definition: ipv6_misc.c:1217
void ipv6AddPrefix(NetInterface *interface, const Ipv6Addr *prefix, uint_t length, bool_t onLinkFlag, bool_t autonomousFlag, uint32_t validLifetime, uint32_t preferredLifetime)
Add a new entry to the Prefix List.
Definition: ipv6_misc.c:401
error_t ipv6ComputeSolicitedNodeAddr(const Ipv6Addr *ipAddr, Ipv6Addr *solicitedNodeAddr)
Form a solicited-node address from an IPv6 address.
Definition: ipv6_misc.c:1386
systime_t validLifetime
Valid lifetime.
Definition: ipv6.h:424
@ IPV6_ADDR_SCOPE_SITE_LOCAL
Definition: ipv6.h:161
Ipv4Addr ipAddr
Definition: ipcp.h:105
Ipv4Addr addr
Definition: nbns_common.h:123
#define MAX_DELAY
Definition: os_port.h:77
@ IPV6_ADDR_STATE_PREFERRED
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:175
bool_t permanent
Permanently assigned router.
Definition: ipv6.h:459
Ipv6AddrState state
IPv6 address state.
Definition: ipv6.h:422
uint_t ipv6GetMulticastAddrScope(const Ipv6Addr *ipAddr)
Retrieve the scope of an IPv6 multicast address.
Definition: ipv6_misc.c:1309
#define IPV6_PREFIX_LIST_SIZE
Definition: ipv6.h:79
@ NIC_TYPE_6LOWPAN
6LoWPAN interface
Definition: nic.h:87
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
@ IPV6_ADDR_STATE_DEPRECATED
An address assigned to an interface whose use is discouraged.
Definition: ipv6.h:176
error_t ipv6CheckSourceAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Source IPv6 address filtering.
Definition: ipv6_misc.c:792
bool_t ipv6IsOnLink(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is on-link.
Definition: ipv6_misc.c:1041
void ipv6UpdateInStats(NetInterface *interface, const Ipv6Addr *destIpAddr, size_t length)
Update IPv6 input statistics.
Definition: ipv6_misc.c:1445
error_t mdnsResponderStartProbing(MdnsResponderContext *context)
Restart probing process.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define INFINITE_DELAY
Definition: os_port.h:75
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ipv6.h:427
mDNS responder (Multicast DNS)
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
systime_t osGetSystemTime(void)
Retrieve system time.
Ipv4Addr destIpAddr
Definition: ipcp.h:80