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-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.0
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 "debug.h"
43 
44 //Check TCP/IP stack configuration
45 #if (IPV6_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Update IPv6 address state
50  * @param[in] entry Pointer to an IPv6 address entry
51  * @param[in] newState New state to switch to
52  **/
53 
55 {
56  //Any state change?
57  if(newState != entry->state)
58  {
59 #if defined(IPV6_CHANGE_ADDR_STATE_HOOK)
60  IPV6_CHANGE_ADDR_STATE_HOOK(entry, newState);
61 #endif
62 
63  //Switch to the new state
64  entry->state = newState;
65  }
66 }
67 
68 
69 /**
70  * @brief Get the state of the specified IPv6 address
71  * @param[in] interface Underlying network interface
72  * @param[in] addr IPv6 address
73  * @return Address state
74  **/
75 
77 {
78  uint_t i;
79  Ipv6AddrEntry *entry;
80 
81  //Loop through the list of IPv6 addresses assigned to the interface
82  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
83  {
84  //Point to the current entry
85  entry = &interface->ipv6Context.addrList[i];
86 
87  //Valid IPv6 address?
88  if(entry->state != IPV6_ADDR_STATE_INVALID)
89  {
90  //Check whether the current entry matches the specified address
91  if(ipv6CompAddr(&entry->addr, addr))
92  {
93  //Return the state of the IPv6 address
94  return entry->state;
95  }
96  }
97  }
98 
99  //The specified IPv6 address is not valid
101 }
102 
103 
104 /**
105  * @brief Set IPv6 address and address state
106  * @param[in] interface Pointer to the desired network interface
107  * @param[in] index Zero-based index
108  * @param[in] addr IPv6 address
109  * @param[in] state State of the IPv6 address
110  * @param[in] validLifetime Valid lifetime
111  * @param[in] preferredLifetime Preferred lifetime
112  * @param[in] permanent Permanently assigned address
113  * @return Error code
114  **/
115 
119 {
120  error_t error;
121  NetInterface *physicalInterface;
122  Ipv6AddrEntry *entry;
123  Ipv6Addr solicitedNodeAddr;
124 
125  //Check parameters
126  if(interface == NULL || addr == NULL)
128 
129  //Make sure that the index is valid
130  if(index >= IPV6_ADDR_LIST_SIZE)
131  return ERROR_OUT_OF_RANGE;
132 
133  //The IPv6 address must be a valid unicast address
135  return ERROR_INVALID_ADDRESS;
136 
137  //Initialize status code
138  error = NO_ERROR;
139 
140  //Point to the physical interface
141  physicalInterface = nicGetPhysicalInterface(interface);
142 
143  //Point to the corresponding entry
144  entry = &interface->ipv6Context.addrList[index];
145 
146  //Check whether an IPv6 address is already assigned
147  if(!ipv6CompAddr(&entry->addr, &IPV6_UNSPECIFIED_ADDR))
148  {
149  //Check the state of the IPv6 address
150  if(entry->state != IPV6_ADDR_STATE_INVALID)
151  {
152  //Ethernet interface?
153  if(physicalInterface->nicDriver != NULL &&
154  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
155  {
156  //Form the Solicited-Node address
157  ipv6ComputeSolicitedNodeAddr(&entry->addr, &solicitedNodeAddr);
158  //Leave the Solicited-Node multicast group
159  ipv6LeaveMulticastGroup(interface, &solicitedNodeAddr);
160  }
161  }
162  }
163 
164  //The current IPv6 address is no more valid
166  entry->validLifetime = 0;
167  entry->preferredLifetime = 0;
168  entry->permanent = FALSE;
169 
170  //Assign the new IPv6 address
171  entry->addr = *addr;
172 
173  //Check whether the new IPv6 address is valid
175  {
176  //Check the state of the IPv6 address
177  if(state != IPV6_ADDR_STATE_INVALID)
178  {
179  //Ethernet interface?
180  if(physicalInterface->nicDriver != NULL &&
181  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
182  {
183  //Form the Solicited-Node address for the link-local address
184  ipv6ComputeSolicitedNodeAddr(addr, &solicitedNodeAddr);
185  //Join the Solicited-Node multicast group for each assigned address
186  error = ipv6JoinMulticastGroup(interface, &solicitedNodeAddr);
187  }
188  //6LoWPAN interface?
189  else if(interface->nicDriver != NULL &&
190  interface->nicDriver->type == NIC_TYPE_6LOWPAN)
191  {
192  //There is no need to join the solicited-node multicast address,
193  //since nobody multicasts Neighbor Solicitations in this type of
194  //network (refer to RFC 6775 section 5.2)
195  }
196  }
197 
198  //Check status code
199  if(!error)
200  {
201  //Set the state of the IPv6 address
202  ipv6ChangeAddrState(entry, state);
203 
204  //Clear duplicate flag
205  entry->duplicate = FALSE;
206 
207  //Save preferred and valid lifetimes
209  entry->validLifetime = validLifetime;
210 
211  //Set time stamp
212  entry->timestamp = osGetSystemTime();
213 
214  //Initialize DAD related variables
215  entry->dadTimeout = 0;
216  entry->dadRetransmitCount = 0;
217  }
218 
219  //This flag tells whether the IPv6 address should be permanently assigned
220  entry->permanent = permanent;
221  }
222 
223 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
224  //Restart mDNS probing process
225  mdnsResponderStartProbing(interface->mdnsResponderContext);
226 #endif
227 
228  //Return status code
229  return error;
230 }
231 
232 
233 /**
234  * @brief Add a new entry to the list of IPv6 addresses
235  * @param[in] interface Underlying network interface
236  * @param[in] addr IPv6 address
237  * @param[in] validLifetime Valid lifetime, in seconds
238  * @param[in] preferredLifetime Preferred lifetime, in seconds
239  **/
240 
241 void ipv6AddAddr(NetInterface *interface, const Ipv6Addr *addr,
242  uint32_t validLifetime, uint32_t preferredLifetime)
243 {
244  uint_t i;
245  Ipv6AddrEntry *entry;
246 
247  //Check the valid lifetime
249  {
250  //The length of time in seconds that the address is valid
251  if(validLifetime < (MAX_DELAY / 1000))
252  {
253  validLifetime *= 1000;
254  }
255  else
256  {
258  }
259  }
260  else
261  {
262  //A value of all one bits (0xffffffff) represents infinity
264  }
265 
266  //Check the preferred lifetime
268  {
269  //The length of time in seconds that the address remains preferred
270  if(preferredLifetime < (MAX_DELAY / 1000))
271  {
272  preferredLifetime *= 1000;
273  }
274  else
275  {
277  }
278  }
279  else
280  {
281  //A value of all one bits (0xffffffff) represents infinity
283  }
284 
285  //Loop through the list of IPv6 addresses assigned to the interface
286  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
287  {
288  //Point to the current entry
289  entry = &interface->ipv6Context.addrList[i];
290 
291  //Check the state of the IPv6 address
292  if(entry->state == IPV6_ADDR_STATE_PREFERRED ||
294  {
295  //Check whether the current entry matches the specified address
296  if(ipv6CompAddr(&entry->addr, addr))
297  {
298  //The IPv6 address should be preserved if it has been manually assigned
299  if(!entry->permanent)
300  {
301  //Update the lifetimes of the entry
302  entry->validLifetime = validLifetime;
304 
305  //Save current time
306  entry->timestamp = osGetSystemTime();
307  //Update the state of the IPv6 address
309  }
310 
311  //Exit immediately
312  return;
313  }
314  }
315  }
316 
317  //If no matching entry was found, then try to create a new entry
318  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
319  {
320  //Point to the current entry
321  entry = &interface->ipv6Context.addrList[i];
322 
323  //Check the state of the IPv6 address
324  if(entry->state == IPV6_ADDR_STATE_INVALID)
325  {
326  //The IPv6 address should be preserved if it has been manually assigned
327  if(!entry->permanent)
328  {
329 #if (NDP_SUPPORT == ENABLED)
330  //Check whether Duplicate Address Detection should be performed
331  if(interface->ndpContext.dupAddrDetectTransmits > 0)
332  {
333  //Use the IPv6 address as a tentative address
336  }
337  else
338 #endif
339  {
340  //The use of the IPv6 address is now unrestricted
343  }
344 
345  //Exit immediately
346  return;
347  }
348  }
349  }
350 }
351 
352 
353 /**
354  * @brief Remove an entry from the list of IPv6 addresses
355  * @param[in] interface Underlying network interface
356  * @param[in] addr IPv6 address
357  **/
358 
359 void ipv6RemoveAddr(NetInterface *interface, const Ipv6Addr *addr)
360 {
361  uint_t i;
362  Ipv6AddrEntry *entry;
363 
364  //Loop through the list of IPv6 addresses assigned to the interface
365  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
366  {
367  //Point to the current entry
368  entry = &interface->ipv6Context.addrList[i];
369 
370  //Valid IPv6 address?
371  if(entry->validLifetime)
372  {
373  //Check whether the current entry matches the specified address
374  if(ipv6CompAddr(&entry->addr, addr))
375  {
376  //The IPv6 address should be preserved if it has been manually assigned
377  if(!entry->permanent)
378  {
379  //Remove the IPv6 address from the list
380  ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
382  }
383  }
384  }
385  }
386 }
387 
388 
389 /**
390  * @brief Add a new entry to the Prefix List
391  * @param[in] interface Underlying network interface
392  * @param[in] prefix IPv6 prefix
393  * @param[in] length The number of leading bits in the prefix that are valid
394  * @param[in] onLinkFlag On-link flag
395  * @param[in] autonomousFlag Autonomous flag
396  * @param[in] validLifetime Valid lifetime, in seconds
397  * @param[in] preferredLifetime Preferred lifetime, in seconds
398  **/
399 
400 void ipv6AddPrefix(NetInterface *interface, const Ipv6Addr *prefix,
401  uint_t length, bool_t onLinkFlag, bool_t autonomousFlag,
402  uint32_t validLifetime, uint32_t preferredLifetime)
403 {
404  uint_t i;
405  Ipv6PrefixEntry *entry;
406  Ipv6PrefixEntry *firstFreeEntry;
407 
408  //Initialize variables
409  entry = NULL;
410  firstFreeEntry = NULL;
411 
412  //Loop through the Prefix List
413  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
414  {
415  //Point to the current entry
416  entry = &interface->ipv6Context.prefixList[i];
417 
418  //Valid prefix?
419  if(entry->validLifetime)
420  {
421  //Compare prefix length against the specified value
422  if(entry->prefixLen == length)
423  {
424  //Check whether the current entry matches the specified prefix
425  if(ipv6CompPrefix(&entry->prefix, prefix, length))
426  break;
427  }
428  }
429  else
430  {
431  //The IPv6 prefix should be preserved if it has been manually assigned
432  if(!entry->permanent)
433  {
434  //Keep track of the first free entry
435  if(firstFreeEntry == NULL)
436  {
437  firstFreeEntry = entry;
438  }
439  }
440  }
441  }
442 
443  //No matching entry found?
444  if(i >= IPV6_PREFIX_LIST_SIZE)
445  entry = firstFreeEntry;
446 
447  //Update the entry if necessary
448  if(entry != NULL)
449  {
450  //The IPv6 prefix should be preserved if it has been manually assigned
451  if(!entry->permanent)
452  {
453  //Save the IPv6 prefix
454  entry->prefix = *prefix;
455  entry->prefixLen = length;
456 
457  //Save On-link and Autonomous flags
458  entry->onLinkFlag = onLinkFlag;
459  entry->autonomousFlag = autonomousFlag;
460 
461  //Check the valid lifetime
463  {
464  //The length of time in seconds that the prefix is valid
465  //for the purpose of on-link determination
466  if(validLifetime < (MAX_DELAY / 1000))
467  {
468  entry->validLifetime = validLifetime * 1000;
469  }
470  else
471  {
472  entry->validLifetime = MAX_DELAY;
473  }
474  }
475  else
476  {
477  //A value of all one bits (0xffffffff) represents infinity
478  entry->validLifetime = INFINITE_DELAY;
479  }
480 
481  //Check the preferred lifetime
483  {
484  //The length of time in seconds that addresses generated from the
485  //prefix via stateless address autoconfiguration remain preferred
486  if(preferredLifetime < (MAX_DELAY / 1000))
487  {
488  entry->preferredLifetime = preferredLifetime * 1000;
489  }
490  else
491  {
492  entry->preferredLifetime = MAX_DELAY;
493  }
494  }
495  else
496  {
497  //A value of all one bits (0xffffffff) represents infinity
499  }
500 
501  //Save current time
502  entry->timestamp = osGetSystemTime();
503  }
504  }
505 }
506 
507 
508 /**
509  * @brief Remove an entry from the Prefix List
510  * @param[in] interface Underlying network interface
511  * @param[in] prefix IPv6 prefix
512  * @param[in] length The number of leading bits in the prefix that are valid
513  **/
514 
516  uint_t length)
517 {
518  uint_t i;
519  Ipv6PrefixEntry *entry;
520 
521  //Loop through the Prefix List
522  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
523  {
524  //Point to the current entry
525  entry = &interface->ipv6Context.prefixList[i];
526 
527  //Valid prefix?
528  if(entry->validLifetime)
529  {
530  //Compare prefix length against the specified value
531  if(entry->prefixLen == length)
532  {
533  //Check whether the current entry matches the specified prefix
534  if(ipv6CompPrefix(&entry->prefix, prefix, length))
535  {
536  //The IPv6 prefix should be preserved if it has been manually assigned
537  if(!entry->permanent)
538  {
539  //When removing an entry from the Prefix List, there is no need
540  //to purge any entries from the Destination or Neighbor Caches
541  entry->prefix = IPV6_UNSPECIFIED_ADDR;
542  entry->prefixLen = 0;
543  entry->validLifetime = 0;
544  }
545  }
546  }
547  }
548  }
549 }
550 
551 
552 /**
553  * @brief Add a new entry to the Default Router List
554  * @param[in] interface Underlying network interface
555  * @param[in] addr IPv6 address of the router
556  * @param[in] lifetime Router lifetime, in seconds
557  * @param[in] preference Preference value
558  **/
559 
561  uint16_t lifetime, uint8_t preference)
562 {
563  uint_t i;
564  Ipv6RouterEntry *entry;
565  Ipv6RouterEntry *firstFreeEntry;
566 
567  //Initialize variables
568  entry = NULL;
569  firstFreeEntry = NULL;
570 
571  //Loop through the Default Router List
572  for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
573  {
574  //Point to the current entry
575  entry = &interface->ipv6Context.routerList[i];
576 
577  //Check the lifetime associated with the default router
578  if(entry->lifetime)
579  {
580  //Check whether the current entry matches the specified router address
581  if(ipv6CompAddr(&entry->addr, addr))
582  break;
583  }
584  else
585  {
586  //The router address should be preserved if it has been manually assigned
587  if(!entry->permanent)
588  {
589  //Keep track of the first free entry
590  if(firstFreeEntry == NULL)
591  {
592  firstFreeEntry = entry;
593  }
594  }
595  }
596  }
597 
598  //No matching entry found?
599  if(i >= IPV6_ROUTER_LIST_SIZE)
600  entry = firstFreeEntry;
601 
602  //Update the entry if necessary
603  if(entry != NULL)
604  {
605  //The router address should be preserved if it has been manually assigned
606  if(!entry->permanent)
607  {
608  //Save the IPv6 address of the router
609  entry->addr = *addr;
610  //The lifetime associated with the default router
611  entry->lifetime = lifetime * 1000;
612  //Save preference value
613  entry->preference = preference;
614  //Save current time
615  entry->timestamp = osGetSystemTime();
616  }
617  }
618 }
619 
620 
621 /**
622  * @brief Remove an entry from the Default Router List
623  * @param[in] interface Underlying network interface
624  * @param[in] addr IPv6 address of the router to be removed from the list
625  **/
626 
628 {
629  uint_t i;
630  bool_t flag;
631  Ipv6RouterEntry *entry;
632 
633  //This flag will be set if any entry has been removed from
634  //the Default Router List
635  flag = FALSE;
636 
637  //Loop through the Default Router List
638  for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
639  {
640  //Point to the current entry
641  entry = &interface->ipv6Context.routerList[i];
642 
643  //Check the lifetime associated with the default router
644  if(entry->lifetime)
645  {
646  //Check whether the current entry matches the specified router address
647  if(ipv6CompAddr(&entry->addr, addr))
648  {
649  //The router address should be preserved if it has been manually assigned
650  if(!entry->permanent)
651  {
652  //Immediately time-out the entry
653  entry->addr = IPV6_UNSPECIFIED_ADDR;
654  entry->lifetime = 0;
655 
656  //Set flag
657  flag = TRUE;
658  }
659  }
660  }
661  }
662 
663  //Check whether an entry has been removed from the list
664  if(flag)
665  {
666 #if (NDP_SUPPORT == ENABLED)
667  //When removing a router from the Default Router list, the node must
668  //update the Destination Cache in such a way that all entries using
669  //the router perform next-hop determination again
670  ndpFlushDestCache(interface);
671 #endif
672  }
673 }
674 
675 
676 /**
677  * @brief Flush the list of IPv6 addresses
678  * @param[in] interface Underlying network interface
679  **/
680 
682 {
683  uint_t i;
684  Ipv6AddrEntry *entry;
685 
686  //Go through the list of IPv6 addresses
687  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
688  {
689  //Point to the current entry
690  entry = &interface->ipv6Context.addrList[i];
691 
692  //Valid IPv6 address?
693  if(entry->validLifetime > 0)
694  {
695  //The IPv6 address should be preserved if it has been manually assigned
696  if(!entry->permanent)
697  {
698  //The IPv6 address is not longer valid
699  ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
701  }
702  }
703  }
704 }
705 
706 
707 /**
708  * @brief Flush the Prefix List
709  * @param[in] interface Underlying network interface
710  **/
711 
713 {
714  uint_t i;
715  Ipv6PrefixEntry *entry;
716 
717  //Go through the Prefix List
718  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
719  {
720  //Point to the current entry
721  entry = &interface->ipv6Context.prefixList[i];
722 
723  //Valid IPv6 prefix?
724  if(entry->validLifetime > 0)
725  {
726  //The IPv6 prefix should be preserved if it has been manually assigned
727  if(!entry->permanent)
728  {
729  //Remove the entry from the Prefix List
730  entry->prefix = IPV6_UNSPECIFIED_ADDR;
731  entry->prefixLen = 0;
732  entry->validLifetime = 0;
733  }
734  }
735  }
736 }
737 
738 
739 /**
740  * @brief Flush the Default Router List
741  * @param[in] interface Underlying network interface
742  **/
743 
745 {
746  uint_t i;
747  Ipv6RouterEntry *entry;
748 
749  //Go through the Default Router List
750  for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
751  {
752  //Point to the current entry
753  entry = &interface->ipv6Context.routerList[i];
754 
755  //Valid entry?
756  if(entry->lifetime > 0)
757  {
758  //The router address should be preserved if it has been manually assigned
759  if(!entry->permanent)
760  {
761  //Clear the current entry
762  entry->addr = IPV6_UNSPECIFIED_ADDR;
763  //Remove the entry from the Default Router List
764  entry->lifetime = 0;
765  }
766  }
767  }
768 }
769 
770 
771 /**
772  * @brief Flush the list of DNS servers
773  * @param[in] interface Underlying network interface
774  **/
775 
777 {
778  //Clear the list of DNS servers
779  osMemset(interface->ipv6Context.dnsServerList, 0,
780  sizeof(interface->ipv6Context.dnsServerList));
781 }
782 
783 
784 /**
785  * @brief Source IPv6 address filtering
786  * @param[in] interface Underlying network interface
787  * @param[in] ipAddr Source IPv6 address to be checked
788  * @return Error code
789  **/
790 
792 {
793  //Multicast addresses cannot be used as source address
795  {
796  //Debug message
797  TRACE_WARNING("Wrong source IPv6 address!\r\n");
798  //The source address not is acceptable
799  return ERROR_INVALID_ADDRESS;
800  }
801 
802  //The source address is acceptable
803  return NO_ERROR;
804 }
805 
806 
807 /**
808  * @brief Destination IPv6 address filtering
809  * @param[in] interface Underlying network interface
810  * @param[in] ipAddr Destination IPv6 address to be checked
811  * @return Error code
812  **/
813 
815 {
816  error_t error;
817  uint_t i;
818 
819  //Filter out any invalid addresses
820  error = ERROR_INVALID_ADDRESS;
821 
822  //Loop through the list of IPv6 unicast addresses
823  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
824  {
825  Ipv6AddrEntry *entry;
826 
827  //Point to the current entry
828  entry = &interface->ipv6Context.addrList[i];
829 
830  //Valid entry?
831  if(entry->state != IPV6_ADDR_STATE_INVALID)
832  {
833  //Check whether the destination address matches a valid unicast
834  //address assigned to the interface
835  if(ipv6CompAddr(&entry->addr, ipAddr))
836  {
837  //The destination address is acceptable
838  error = NO_ERROR;
839  //We are done
840  break;
841  }
842  }
843  }
844 
845  //Check status code
846  if(error == ERROR_INVALID_ADDRESS)
847  {
848  Ipv6Addr *anycastAddrList;
849 
850  //Point to the list of anycast addresses assigned to the interface
851  anycastAddrList = interface->ipv6Context.anycastAddrList;
852 
853  //Loop through the list of IPv6 anycast addresses
854  for(i = 0; i < IPV6_ANYCAST_ADDR_LIST_SIZE; i++)
855  {
856  //Valid entry?
857  if(!ipv6CompAddr(&anycastAddrList[i], &IPV6_UNSPECIFIED_ADDR))
858  {
859  //Check whether the destination address matches a valid anycast
860  //address assigned to the interface
861  if(ipv6CompAddr(&anycastAddrList[i], ipAddr))
862  {
863  //The destination address is acceptable
864  error = NO_ERROR;
865  //We are done
866  break;
867  }
868  }
869  }
870  }
871 
872  //Return status code
873  return error;
874 }
875 
876 
877 /**
878  * @brief IPv6 source address selection
879  *
880  * This function selects the source address and the relevant network interface
881  * to be used in order to join the specified destination address
882  *
883  * @param[in] context Pointer to the TCP/IP stack context
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 < context->numInterfaces; i++)
908  {
909  //Point to the current interface
910  currentInterface = &context->interfaces[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] context Pointer to the TCP/IP stack context
1153  * @param[in] ipAddr IPv6 address to be checked
1154  * @return TRUE if the IPv6 address matches any address assigned to the host,
1155  * else FALSE
1156  **/
1157 
1159 {
1160  uint_t i;
1161  uint_t j;
1162  bool_t flag;
1163  NetInterface *interface;
1164  Ipv6AddrEntry *entry;
1165 
1166  //Initialize flag
1167  flag = FALSE;
1168 
1169  //Loopback address?
1171  {
1172  //If an application in a host sends packets to this address, the IPv6
1173  //stack will loop these packets back on the same virtual interface
1174  flag = TRUE;
1175  }
1176  else
1177  {
1178  //Loop through network interfaces
1179  for(i = 0; i < context->numInterfaces && !flag; i++)
1180  {
1181  //Point to the current interface
1182  interface = &context->interfaces[i];
1183 
1184  //Iterate through the list of addresses assigned to the interface
1185  for(j = 0; j < IPV6_ADDR_LIST_SIZE && !flag; j++)
1186  {
1187  //Point to the current entry
1188  entry = &interface->ipv6Context.addrList[j];
1189 
1190  //Valid entry?
1191  if(entry->state == IPV6_ADDR_STATE_PREFERRED ||
1193  {
1194  //Check whether the specified IPv6 address matches any address
1195  //assigned to the host
1196  if(ipv6CompAddr(&entry->addr, ipAddr))
1197  {
1198  flag = TRUE;
1199  }
1200  }
1201  }
1202  }
1203  }
1204 
1205  //Return TRUE if the specified address matches any address assigned to the host
1206  return flag;
1207 }
1208 
1209 
1210 /**
1211  * @brief Compare IPv6 address prefixes
1212  * @param[in] ipAddr1 Pointer to the first IPv6 address
1213  * @param[in] ipAddr2 Pointer to the second IPv6 address
1214  * @param[in] length Prefix length
1215  * @return TRUE if the prefixes match each other, else FALSE
1216  **/
1217 
1218 bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2,
1219  size_t length)
1220 {
1221  size_t n;
1222  size_t m;
1223  uint8_t mask;
1224 
1225  //Ensure the prefix length is valid
1226  if(length > 128)
1227  return FALSE;
1228 
1229  //Number of complete bytes
1230  n = length / 8;
1231  //Number of bits in the last byte, if any
1232  m = length % 8;
1233 
1234  //Compare the first part
1235  if(n > 0)
1236  {
1237  if(osMemcmp(ipAddr1, ipAddr2, n))
1238  return FALSE;
1239  }
1240 
1241  //Compare the remaining bits, if any
1242  if(m > 0)
1243  {
1244  //Calculate the mask to be applied
1245  mask = ((1 << m) - 1) << (8 - m);
1246 
1247  //Check remaining bits
1248  if((ipAddr1->b[n] & mask) != (ipAddr2->b[n] & mask))
1249  return FALSE;
1250  }
1251 
1252  //The prefixes match each other
1253  return TRUE;
1254 }
1255 
1256 
1257 /**
1258  * @brief Retrieve the scope of an IPv6 address
1259  * @param[in] ipAddr Pointer to an IPv6 address
1260  * @return IPv6 address scope
1261  **/
1262 
1264 {
1265  uint_t scope;
1266 
1267  //Multicast address?
1269  {
1270  //Retrieve the scope of the multicast address
1272  }
1273  //Loopback address?
1275  {
1276  //The loopback address may be used by a node to send an IPv6 packet
1277  //to itself
1279  }
1280  //Link-local unicast address?
1282  {
1283  //A link-local address is for use on a single link
1285  }
1286  //Site-local unicast address?
1288  {
1289  //A site-local address is for use in a single site
1291  }
1292  //Global address?
1293  else
1294  {
1295  //Global scope
1296  scope = IPV6_ADDR_SCOPE_GLOBAL;
1297  }
1298 
1299  //Return the scope of the specified IPv6 address
1300  return scope;
1301 }
1302 
1303 
1304 /**
1305  * @brief Retrieve the scope of an IPv6 multicast address
1306  * @param[in] ipAddr Pointer to an IPv6 multicast address
1307  * @return IPv6 address scope
1308  **/
1309 
1311 {
1312  uint_t scope;
1313 
1314  //The scope field is a 4-bit value
1315  scope = ipAddr->b[1] & 0x0F;
1316 
1317  //If the scope field contains the reserved value F, an IPv6 packet
1318  //must be treated the same as packets destined to a global multicast
1319  //address (refer to RFC 3513 section 2.7)
1320  if(scope == 0x0F)
1321  {
1322  scope = IPV6_ADDR_SCOPE_GLOBAL;
1323  }
1324 
1325  //Return the scope of the specified IPv6 multicast address
1326  return scope;
1327 }
1328 
1329 
1330 /**
1331  * @brief Compute the length of the longest common prefix
1332  * @param[in] ipAddr1 Pointer to the first IPv6 address
1333  * @param[in] ipAddr2 Pointer to the second IPv6 address
1334  * @return The length of the longest common prefix, in bits
1335  **/
1336 
1338  const Ipv6Addr *ipAddr2)
1339 {
1340  uint_t i;
1341  uint_t j;
1342  uint8_t mask;
1343 
1344  //Clear bit counter
1345  j = 0;
1346 
1347  //Perform a byte-for-byte comparison
1348  for(i = 0; i < sizeof(Ipv6Addr); i++)
1349  {
1350  //Loop as long as prefixes match
1351  if(ipAddr1->b[i] != ipAddr2->b[i])
1352  {
1353  break;
1354  }
1355  }
1356 
1357  //Any mismatch?
1358  if(i < sizeof(Ipv6Addr))
1359  {
1360  //Perform a bit-for-bit comparison
1361  for(j = 0; j < 8; j++)
1362  {
1363  //Calculate the mask to be applied
1364  mask = 1 << (7 - j);
1365 
1366  //Loop as long as prefixes match
1367  if((ipAddr1->b[i] & mask) != (ipAddr2->b[i] & mask))
1368  {
1369  break;
1370  }
1371  }
1372  }
1373 
1374  //Return the length of the longest prefix that the two addresses
1375  //have in common
1376  return i * 8 + j;
1377 }
1378 
1379 
1380 /**
1381  * @brief Form a solicited-node address from an IPv6 address
1382  * @param[in] ipAddr Unicast or anycast address
1383  * @param[out] solicitedNodeAddr Corresponding solicited-node address
1384  * @return Error code
1385  **/
1386 
1388  Ipv6Addr *solicitedNodeAddr)
1389 {
1390  error_t error;
1391 
1392  //Ensure the specified address is a valid unicast or anycast address
1394  {
1395  //Copy the 104-bit prefix
1396  ipv6CopyAddr(solicitedNodeAddr, &IPV6_SOLICITED_NODE_ADDR_PREFIX);
1397 
1398  //Take the low-order 24 bits of the address (unicast or anycast) and
1399  //append those bits to the prefix
1400  solicitedNodeAddr->b[13] = ipAddr->b[13];
1401  solicitedNodeAddr->b[14] = ipAddr->b[14];
1402  solicitedNodeAddr->b[15] = ipAddr->b[15];
1403 
1404  //Successful processing
1405  error = NO_ERROR;
1406  }
1407  else
1408  {
1409  //Report an error
1410  error = ERROR_INVALID_ADDRESS;
1411  }
1412 
1413  //Return status code
1414  return error;
1415 }
1416 
1417 
1418 /**
1419  * @brief Generate a IPv6 link-local address from an interface identifier
1420  * @param[in] interfaceId Interface identifier
1421  * @param[out] ipAddr Corresponding IPv6 link-local address
1422  **/
1423 
1425 {
1426  //A link-local address is formed by combining the well-known link-local
1427  //prefix fe80::/10 with the interface identifier
1428  ipAddr->w[0] = HTONS(0xFE80);
1429  ipAddr->w[1] = HTONS(0x0000);
1430  ipAddr->w[2] = HTONS(0x0000);
1431  ipAddr->w[3] = HTONS(0x0000);
1432  ipAddr->w[4] = interfaceId->w[0];
1433  ipAddr->w[5] = interfaceId->w[1];
1434  ipAddr->w[6] = interfaceId->w[2];
1435  ipAddr->w[7] = interfaceId->w[3];
1436 }
1437 
1438 
1439 /**
1440  * @brief Update IPv6 input statistics
1441  * @param[in] interface Underlying network interface
1442  * @param[in] destIpAddr Destination IP address
1443  * @param[in] length Length of the incoming IP packet
1444  **/
1445 
1447  size_t length)
1448 {
1449  //Check whether the destination address is a unicast or multicast address
1451  {
1452  //Number of IP multicast datagrams transmitted
1453  IPV6_SYSTEM_STATS_INC_COUNTER64(inMcastPkts, 1);
1454  IPV6_IF_STATS_INC_COUNTER64(inMcastPkts, 1);
1455 
1456  //Total number of octets transmitted in IP multicast datagrams
1457  IPV6_SYSTEM_STATS_INC_COUNTER64(inMcastOctets, length);
1458  IPV6_IF_STATS_INC_COUNTER64(inMcastOctets, length);
1459  }
1460 }
1461 
1462 
1463 /**
1464  * @brief Update IPv6 output statistics
1465  * @param[in] interface Underlying network interface
1466  * @param[in] destIpAddr Destination IP address
1467  * @param[in] length Length of the outgoing IP packet
1468  **/
1469 
1471  size_t length)
1472 {
1473  //Check whether the destination address is a unicast or multicast address
1475  {
1476  //Number of IP multicast datagrams transmitted
1477  IPV6_SYSTEM_STATS_INC_COUNTER64(outMcastPkts, 1);
1478  IPV6_IF_STATS_INC_COUNTER64(outMcastPkts, 1);
1479 
1480  //Total number of octets transmitted in IP multicast datagrams
1481  IPV6_SYSTEM_STATS_INC_COUNTER64(outMcastOctets, length);
1482  IPV6_IF_STATS_INC_COUNTER64(outMcastOctets, length);
1483  }
1484 
1485  //Total number of IP datagrams that this entity supplied to the lower layers
1486  //for transmission
1487  IPV6_SYSTEM_STATS_INC_COUNTER64(outTransmits, 1);
1488  IPV6_IF_STATS_INC_COUNTER64(outTransmits, 1);
1489 
1490  //Total number of octets in IP datagrams delivered to the lower layers for
1491  //transmission
1493  IPV6_IF_STATS_INC_COUNTER64(outOctets, length);
1494 }
1495 
1496 #endif
@ IPV6_ADDR_STATE_TENTATIVE
An address whose uniqueness on a link is being verified.
Definition: ipv6.h:194
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ipv6.h:480
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:560
systime_t lifetime
Router lifetime.
Definition: ipv6.h:477
#define NetContext
Definition: net.h:36
#define IPV6_IF_STATS_INC_COUNTER64(name, value)
Definition: ipv6.h:158
@ ERROR_NO_ADDRESS
Definition: error.h:200
int bool_t
Definition: compiler_port.h:63
@ ERROR_OUT_OF_RANGE
Definition: error.h:138
Ipv4Addr destAddr
Definition: ipv4.h:354
void ipv6FlushPrefixList(NetInterface *interface)
Flush the Prefix List.
Definition: ipv6_misc.c:712
Eui64
Definition: ethernet.h:212
void ipv6UpdateOutStats(NetInterface *interface, const Ipv6Addr *destIpAddr, size_t length)
Update IPv6 output statistics.
Definition: ipv6_misc.c:1470
@ IPV6_ADDR_SCOPE_INTERFACE_LOCAL
Definition: ipv6.h:178
void ipv6RemovePrefix(NetInterface *interface, const Ipv6Addr *prefix, uint_t length)
Remove an entry from the Prefix List.
Definition: ipv6_misc.c:515
void ipv6RemoveDefaultRouter(NetInterface *interface, const Ipv6Addr *addr)
Remove an entry from the Default Router List.
Definition: ipv6_misc.c:627
systime_t preferredLifetime
Preferred lifetime.
Definition: ipv6.h:464
uint_t dadRetransmitCount
Retransmission counter for Duplicate Address Detection.
Definition: ipv6.h:449
const Ipv6Addr IPV6_SOLICITED_NODE_ADDR_PREFIX
Definition: ipv6.c:85
void ipv6ChangeAddrState(Ipv6AddrEntry *entry, Ipv6AddrState newState)
Update IPv6 address state.
Definition: ipv6_misc.c:54
#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:76
Ipv6Addr addr
IPv6 address.
Definition: ipv6.h:441
systime_t preferredLifetime
Preferred lifetime.
Definition: ipv6.h:445
void ipv6FlushAddrList(NetInterface *interface)
Flush the list of IPv6 addresses.
Definition: ipv6_misc.c:681
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ipv6.h:466
Ipv6Addr
Definition: ipv6.h:280
#define IPV6_SYSTEM_STATS_INC_COUNTER64(name, value)
Definition: ipv6.h:156
bool_t autonomousFlag
Autonomous flag.
Definition: ipv6.h:462
systime_t validLifetime
Valid lifetime.
Definition: ipv6.h:463
#define osMemcmp(p1, p2, length)
Definition: os_port.h:156
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:134
Ipv6Addr prefix
IPv6 prefix information.
Definition: ipv6.h:459
Ipv6Addr addr
Router address.
Definition: ipv6.h:476
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:193
#define ipv6IsSiteLocalUnicastAddr(ipAddr)
Definition: ipv6.h:142
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:146
IPv6 multicast filtering.
uint_t ipv6GetCommonPrefixLength(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2)
Compute the length of the longest common prefix.
Definition: ipv6_misc.c:1337
#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:776
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:87
Ipv6AddrState
IPv6 address state.
Definition: ipv6.h:192
error_t
Error codes.
Definition: error.h:43
error_t ipv6JoinMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Join an IPv6 multicast group.
uint32_t validLifetime
systime_t dadTimeout
Timeout value for Duplicate Address Detection.
Definition: ipv6.h:448
Prefix list entry.
Definition: ipv6.h:458
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
uint8_t preference
Preference value.
Definition: ipv6.h:478
bool_t permanent
Permanently assigned address.
Definition: ipv6.h:446
#define NetInterface
Definition: net.h:40
error_t ipv6CheckDestAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Destination IPv6 address filtering.
Definition: ipv6_misc.c:814
uint_t ipv6GetAddrScope(const Ipv6Addr *ipAddr)
Retrieve the scope of an IPv6 address.
Definition: ipv6_misc.c:1263
Helper functions for IPv6.
@ IPV6_ADDR_SCOPE_GLOBAL
Definition: ipv6.h:183
uint8_t mask
Definition: web_socket.h:319
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
const Ipv6Addr IPV6_LOOPBACK_ADDR
Definition: ipv6.c:69
bool_t duplicate
The address is a duplicate.
Definition: ipv6.h:443
Eui64 interfaceId
Definition: ipv6cp.h:71
uint8_t length
Definition: tcp.h:375
@ IPV6_ADDR_SCOPE_LINK_LOCAL
Definition: ipv6.h:179
void ipv6RemoveAddr(NetInterface *interface, const Ipv6Addr *addr)
Remove an entry from the list of IPv6 addresses.
Definition: ipv6_misc.c:359
Neighbor and destination cache management.
#define ipv6IsLinkLocalUnicastAddr(ipAddr)
Definition: ipv6.h:138
NDP (Neighbor Discovery Protocol)
void ipv6FlushDefaultRouterList(NetInterface *interface)
Flush the Default Router List.
Definition: ipv6_misc.c:744
bool_t onLinkFlag
On-link flag.
Definition: ipv6.h:461
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:116
bool_t permanent
Permanently assigned prefix.
Definition: ipv6.h:465
#define TRACE_WARNING(...)
Definition: debug.h:93
uint8_t prefixLen
IPv6 prefix length.
Definition: ipv6.h:460
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:241
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:130
#define IPV6_ANYCAST_ADDR_LIST_SIZE
Definition: ipv6.h:79
Default router list entry.
Definition: ipv6.h:475
IPv6 address entry.
Definition: ipv6.h:440
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:93
#define IPV6_ADDR_LIST_SIZE
Definition: ipv6.h:72
void ipv6GenerateLinkLocalAddr(const Eui64 *interfaceId, Ipv6Addr *ipAddr)
Generate a IPv6 link-local address from an interface identifier.
Definition: ipv6_misc.c:1424
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:1218
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:400
error_t ipv6ComputeSolicitedNodeAddr(const Ipv6Addr *ipAddr, Ipv6Addr *solicitedNodeAddr)
Form a solicited-node address from an IPv6 address.
Definition: ipv6_misc.c:1387
systime_t validLifetime
Valid lifetime.
Definition: ipv6.h:444
@ IPV6_ADDR_SCOPE_SITE_LOCAL
Definition: ipv6.h:181
Ipv4Addr ipAddr
Definition: ipcp.h:105
Ipv4Addr addr
Definition: nbns_common.h:141
#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:195
bool_t permanent
Permanently assigned router.
Definition: ipv6.h:479
Ipv6AddrState state
IPv6 address state.
Definition: ipv6.h:442
uint_t ipv6GetMulticastAddrScope(const Ipv6Addr *ipAddr)
Retrieve the scope of an IPv6 multicast address.
Definition: ipv6_misc.c:1310
#define IPV6_PREFIX_LIST_SIZE
Definition: ipv6.h:86
@ 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:196
error_t ipv6CheckSourceAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Source IPv6 address filtering.
Definition: ipv6_misc.c:791
bool_t ipv6IsOnLink(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is on-link.
Definition: ipv6_misc.c:1041
bool_t ipv6IsLocalHostAddr(NetContext *context, const Ipv6Addr *ipAddr)
Check whether the specified IPv6 is assigned to the host.
Definition: ipv6_misc.c:1158
void ipv6UpdateInStats(NetInterface *interface, const Ipv6Addr *destIpAddr, size_t length)
Update IPv6 input statistics.
Definition: ipv6_misc.c:1446
error_t mdnsResponderStartProbing(MdnsResponderContext *context)
Restart probing process.
error_t ipv6SelectSourceAddr(NetContext *context, NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:891
@ 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:447
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