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.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 "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  //Check link state
920  if(!currentInterface->linkState)
921  {
922  //Select the next interface in the list
923  continue;
924  }
925 
926  //A sort of the candidate source addresses is being performed, where a
927  //set of rules define the ordering among addresses (refer to RFC 6724)
928  for(j = 0; j < IPV6_ADDR_LIST_SIZE; j++)
929  {
930  //Point to the current entry
931  currentAddr = &currentInterface->ipv6Context.addrList[j];
932 
933  //Check the state of the address
934  if(currentAddr->state == IPV6_ADDR_STATE_PREFERRED ||
935  currentAddr->state == IPV6_ADDR_STATE_DEPRECATED)
936  {
937  //Select the first address as default
938  if(bestAddr == NULL)
939  {
940  //Give the current source address the higher precedence
941  bestInterface = currentInterface;
942  bestAddr = currentAddr;
943 
944  //Select the next address in the list
945  continue;
946  }
947 
948  //Rule 1: Prefer same address
949  if(ipv6CompAddr(&bestAddr->addr, destAddr))
950  {
951  //Select the next address in the list
952  continue;
953  }
954  else if(ipv6CompAddr(&currentAddr->addr, destAddr))
955  {
956  //Give the current source address the higher precedence
957  bestInterface = currentInterface;
958  bestAddr = currentAddr;
959 
960  //Select the next address in the list
961  continue;
962  }
963 
964  //Rule 2: Prefer appropriate scope
965  if(ipv6GetAddrScope(&currentAddr->addr) < ipv6GetAddrScope(&bestAddr->addr))
966  {
967  if(ipv6GetAddrScope(&currentAddr->addr) >= ipv6GetAddrScope(destAddr))
968  {
969  //Give the current source address the higher precedence
970  bestInterface = currentInterface;
971  bestAddr = currentAddr;
972  }
973 
974  //Select the next address in the list
975  continue;
976  }
977  else if(ipv6GetAddrScope(&bestAddr->addr) < ipv6GetAddrScope(&currentAddr->addr))
978  {
980  {
981  //Give the current source address the higher precedence
982  bestInterface = currentInterface;
983  bestAddr = currentAddr;
984  }
985 
986  //Select the next address in the list
987  continue;
988  }
989 
990  //Rule 3: Avoid deprecated addresses
991  if(bestAddr->state == IPV6_ADDR_STATE_PREFERRED &&
992  currentAddr->state == IPV6_ADDR_STATE_DEPRECATED)
993  {
994  //Select the next address in the list
995  continue;
996  }
997  else if(currentAddr->state == IPV6_ADDR_STATE_PREFERRED &&
998  bestAddr->state == IPV6_ADDR_STATE_DEPRECATED)
999  {
1000  //Give the current source address the higher precedence
1001  bestInterface = currentInterface;
1002  bestAddr = currentAddr;
1003 
1004  //Select the next address in the list
1005  continue;
1006  }
1007 
1008  //Rule 8: Use longest matching prefix
1009  if(ipv6GetCommonPrefixLength(&currentAddr->addr, destAddr) >
1011  {
1012  //Give the current source address the higher precedence
1013  bestInterface = currentInterface;
1014  bestAddr = currentAddr;
1015  }
1016  }
1017  }
1018  }
1019 
1020  //Valid source address?
1021  if(bestAddr != NULL)
1022  {
1023  //Return the out-going interface and the source address to be used
1024  *interface = bestInterface;
1025  *srcAddr = bestAddr->addr;
1026 
1027  //Successful source address selection
1028  error = NO_ERROR;
1029  }
1030  else
1031  {
1032  //Report an error
1033  error = ERROR_NO_ADDRESS;
1034  }
1035 
1036  //Return status code
1037  return error;
1038 }
1039 
1040 
1041 /**
1042  * @brief Check whether an IPv6 address is on-link
1043  * @param[in] interface Underlying network interface
1044  * @param[in] ipAddr IPv6 address to be checked
1045  * @return TRUE if the IPv6 address is on-link, else FALSE
1046  **/
1047 
1049 {
1050  uint_t i;
1051  Ipv6PrefixEntry *entry;
1052 
1053  //Link-local prefix?
1055  {
1056  //The link-local prefix is considered to be on the prefix list with
1057  //an infinite invalidation timer regardless of whether routers are
1058  //advertising a prefix for it
1059  return TRUE;
1060  }
1061 
1062  //Loop through the Prefix List
1063  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
1064  {
1065  //Point to the current entry
1066  entry = &interface->ipv6Context.prefixList[i];
1067 
1068  //Valid prefix?
1069  if(entry->validLifetime > 0)
1070  {
1071  //Check the specified address against the prefix
1072  if(ipv6CompPrefix(ipAddr, &entry->prefix, entry->prefixLen))
1073  {
1074  //The specified IPv6 address is on-link
1075  return TRUE;
1076  }
1077  }
1078  }
1079 
1080  //The specified IPv6 address is off-link
1081  return FALSE;
1082 }
1083 
1084 
1085 /**
1086  * @brief Check whether an IPv6 address is an anycast address
1087  * @param[in] interface Underlying network interface
1088  * @param[in] ipAddr IPv6 address to be checked
1089  * @return TRUE if the IPv6 address is an anycast address, else FALSE
1090  **/
1091 
1093 {
1094  uint_t i;
1095  Ipv6Addr *anycastAddrList;
1096 
1097  //Point to the list of anycast addresses assigned to the interface
1098  anycastAddrList = interface->ipv6Context.anycastAddrList;
1099 
1100  //Loop through the list of IPv6 anycast addresses
1101  for(i = 0; i < IPV6_ANYCAST_ADDR_LIST_SIZE; i++)
1102  {
1103  //Valid entry?
1104  if(!ipv6CompAddr(&anycastAddrList[i], &IPV6_UNSPECIFIED_ADDR))
1105  {
1106  //Check whether the specified address matches a valid anycast
1107  //address assigned to the interface
1108  if(ipv6CompAddr(&anycastAddrList[i], ipAddr))
1109  {
1110  //The specified IPv6 address is an anycast address
1111  return TRUE;
1112  }
1113  }
1114  }
1115 
1116  //The specified IPv6 address is not an anycast address
1117  return FALSE;
1118 }
1119 
1120 
1121 /**
1122  * @brief Check whether an IPv6 address is a tentative address
1123  * @param[in] interface Underlying network interface
1124  * @param[in] ipAddr IPv6 address to be checked
1125  * @return TRUE if the IPv6 address is a tentative address, else FALSE
1126  **/
1127 
1129 {
1130  uint_t i;
1131  Ipv6AddrEntry *entry;
1132 
1133  //Loop through the list of IPv6 unicast addresses
1134  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
1135  {
1136  //Point to the current entry
1137  entry = &interface->ipv6Context.addrList[i];
1138 
1139  //Tentative address?
1140  if(entry->state == IPV6_ADDR_STATE_TENTATIVE)
1141  {
1142  //Check whether the specified address matches a valid unicast
1143  //address assigned to the interface
1144  if(ipv6CompAddr(&entry->addr, ipAddr))
1145  {
1146  //The specified IPv6 address is a tentative address
1147  return TRUE;
1148  }
1149  }
1150  }
1151 
1152  //The specified IPv6 address is not a tentative address
1153  return FALSE;
1154 }
1155 
1156 
1157 /**
1158  * @brief Check whether the specified IPv6 is assigned to the host
1159  * @param[in] context Pointer to the TCP/IP stack context
1160  * @param[in] ipAddr IPv6 address to be checked
1161  * @return TRUE if the IPv6 address matches any address assigned to the host,
1162  * else FALSE
1163  **/
1164 
1166 {
1167  uint_t i;
1168  uint_t j;
1169  bool_t flag;
1170  NetInterface *interface;
1171  Ipv6AddrEntry *entry;
1172 
1173  //Initialize flag
1174  flag = FALSE;
1175 
1176  //Loopback address?
1178  {
1179  //If an application in a host sends packets to this address, the IPv6
1180  //stack will loop these packets back on the same virtual interface
1181  flag = TRUE;
1182  }
1183  else
1184  {
1185  //Loop through network interfaces
1186  for(i = 0; i < context->numInterfaces && !flag; i++)
1187  {
1188  //Point to the current interface
1189  interface = &context->interfaces[i];
1190 
1191  //Iterate through the list of addresses assigned to the interface
1192  for(j = 0; j < IPV6_ADDR_LIST_SIZE && !flag; j++)
1193  {
1194  //Point to the current entry
1195  entry = &interface->ipv6Context.addrList[j];
1196 
1197  //Valid entry?
1198  if(entry->state == IPV6_ADDR_STATE_PREFERRED ||
1200  {
1201  //Check whether the specified IPv6 address matches any address
1202  //assigned to the host
1203  if(ipv6CompAddr(&entry->addr, ipAddr))
1204  {
1205  flag = TRUE;
1206  }
1207  }
1208  }
1209  }
1210  }
1211 
1212  //Return TRUE if the specified address matches any address assigned to the host
1213  return flag;
1214 }
1215 
1216 
1217 /**
1218  * @brief Compare IPv6 address prefixes
1219  * @param[in] ipAddr1 Pointer to the first IPv6 address
1220  * @param[in] ipAddr2 Pointer to the second IPv6 address
1221  * @param[in] length Prefix length
1222  * @return TRUE if the prefixes match each other, else FALSE
1223  **/
1224 
1225 bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2,
1226  size_t length)
1227 {
1228  size_t n;
1229  size_t m;
1230  uint8_t mask;
1231 
1232  //Ensure the prefix length is valid
1233  if(length > 128)
1234  return FALSE;
1235 
1236  //Number of complete bytes
1237  n = length / 8;
1238  //Number of bits in the last byte, if any
1239  m = length % 8;
1240 
1241  //Compare the first part
1242  if(n > 0)
1243  {
1244  if(osMemcmp(ipAddr1, ipAddr2, n))
1245  return FALSE;
1246  }
1247 
1248  //Compare the remaining bits, if any
1249  if(m > 0)
1250  {
1251  //Calculate the mask to be applied
1252  mask = ((1 << m) - 1) << (8 - m);
1253 
1254  //Check remaining bits
1255  if((ipAddr1->b[n] & mask) != (ipAddr2->b[n] & mask))
1256  return FALSE;
1257  }
1258 
1259  //The prefixes match each other
1260  return TRUE;
1261 }
1262 
1263 
1264 /**
1265  * @brief Retrieve the scope of an IPv6 address
1266  * @param[in] ipAddr Pointer to an IPv6 address
1267  * @return IPv6 address scope
1268  **/
1269 
1271 {
1272  uint_t scope;
1273 
1274  //Multicast address?
1276  {
1277  //Retrieve the scope of the multicast address
1279  }
1280  //Loopback address?
1282  {
1283  //The loopback address may be used by a node to send an IPv6 packet
1284  //to itself
1286  }
1287  //Link-local unicast address?
1289  {
1290  //A link-local address is for use on a single link
1292  }
1293  //Site-local unicast address?
1295  {
1296  //A site-local address is for use in a single site
1298  }
1299  //Global address?
1300  else
1301  {
1302  //Global scope
1303  scope = IPV6_ADDR_SCOPE_GLOBAL;
1304  }
1305 
1306  //Return the scope of the specified IPv6 address
1307  return scope;
1308 }
1309 
1310 
1311 /**
1312  * @brief Retrieve the scope of an IPv6 multicast address
1313  * @param[in] ipAddr Pointer to an IPv6 multicast address
1314  * @return IPv6 address scope
1315  **/
1316 
1318 {
1319  uint_t scope;
1320 
1321  //The scope field is a 4-bit value
1322  scope = ipAddr->b[1] & 0x0F;
1323 
1324  //If the scope field contains the reserved value F, an IPv6 packet
1325  //must be treated the same as packets destined to a global multicast
1326  //address (refer to RFC 3513 section 2.7)
1327  if(scope == 0x0F)
1328  {
1329  scope = IPV6_ADDR_SCOPE_GLOBAL;
1330  }
1331 
1332  //Return the scope of the specified IPv6 multicast address
1333  return scope;
1334 }
1335 
1336 
1337 /**
1338  * @brief Compute the length of the longest common prefix
1339  * @param[in] ipAddr1 Pointer to the first IPv6 address
1340  * @param[in] ipAddr2 Pointer to the second IPv6 address
1341  * @return The length of the longest common prefix, in bits
1342  **/
1343 
1345  const Ipv6Addr *ipAddr2)
1346 {
1347  uint_t i;
1348  uint_t j;
1349  uint8_t mask;
1350 
1351  //Clear bit counter
1352  j = 0;
1353 
1354  //Perform a byte-for-byte comparison
1355  for(i = 0; i < sizeof(Ipv6Addr); i++)
1356  {
1357  //Loop as long as prefixes match
1358  if(ipAddr1->b[i] != ipAddr2->b[i])
1359  {
1360  break;
1361  }
1362  }
1363 
1364  //Any mismatch?
1365  if(i < sizeof(Ipv6Addr))
1366  {
1367  //Perform a bit-for-bit comparison
1368  for(j = 0; j < 8; j++)
1369  {
1370  //Calculate the mask to be applied
1371  mask = 1 << (7 - j);
1372 
1373  //Loop as long as prefixes match
1374  if((ipAddr1->b[i] & mask) != (ipAddr2->b[i] & mask))
1375  {
1376  break;
1377  }
1378  }
1379  }
1380 
1381  //Return the length of the longest prefix that the two addresses
1382  //have in common
1383  return i * 8 + j;
1384 }
1385 
1386 
1387 /**
1388  * @brief Form a solicited-node address from an IPv6 address
1389  * @param[in] ipAddr Unicast or anycast address
1390  * @param[out] solicitedNodeAddr Corresponding solicited-node address
1391  * @return Error code
1392  **/
1393 
1395  Ipv6Addr *solicitedNodeAddr)
1396 {
1397  error_t error;
1398 
1399  //Ensure the specified address is a valid unicast or anycast address
1401  {
1402  //Copy the 104-bit prefix
1403  ipv6CopyAddr(solicitedNodeAddr, &IPV6_SOLICITED_NODE_ADDR_PREFIX);
1404 
1405  //Take the low-order 24 bits of the address (unicast or anycast) and
1406  //append those bits to the prefix
1407  solicitedNodeAddr->b[13] = ipAddr->b[13];
1408  solicitedNodeAddr->b[14] = ipAddr->b[14];
1409  solicitedNodeAddr->b[15] = ipAddr->b[15];
1410 
1411  //Successful processing
1412  error = NO_ERROR;
1413  }
1414  else
1415  {
1416  //Report an error
1417  error = ERROR_INVALID_ADDRESS;
1418  }
1419 
1420  //Return status code
1421  return error;
1422 }
1423 
1424 
1425 /**
1426  * @brief Generate a IPv6 link-local address from an interface identifier
1427  * @param[in] interfaceId Interface identifier
1428  * @param[out] ipAddr Corresponding IPv6 link-local address
1429  **/
1430 
1432 {
1433  //A link-local address is formed by combining the well-known link-local
1434  //prefix fe80::/10 with the interface identifier
1435  ipAddr->w[0] = HTONS(0xFE80);
1436  ipAddr->w[1] = HTONS(0x0000);
1437  ipAddr->w[2] = HTONS(0x0000);
1438  ipAddr->w[3] = HTONS(0x0000);
1439  ipAddr->w[4] = interfaceId->w[0];
1440  ipAddr->w[5] = interfaceId->w[1];
1441  ipAddr->w[6] = interfaceId->w[2];
1442  ipAddr->w[7] = interfaceId->w[3];
1443 }
1444 
1445 
1446 /**
1447  * @brief Update IPv6 input statistics
1448  * @param[in] interface Underlying network interface
1449  * @param[in] destIpAddr Destination IP address
1450  * @param[in] length Length of the incoming IP packet
1451  **/
1452 
1454  size_t length)
1455 {
1456  //Check whether the destination address is a unicast or multicast address
1458  {
1459  //Number of IP multicast datagrams transmitted
1460  IPV6_SYSTEM_STATS_INC_COUNTER64(inMcastPkts, 1);
1461  IPV6_IF_STATS_INC_COUNTER64(inMcastPkts, 1);
1462 
1463  //Total number of octets transmitted in IP multicast datagrams
1464  IPV6_SYSTEM_STATS_INC_COUNTER64(inMcastOctets, length);
1465  IPV6_IF_STATS_INC_COUNTER64(inMcastOctets, length);
1466  }
1467 }
1468 
1469 
1470 /**
1471  * @brief Update IPv6 output statistics
1472  * @param[in] interface Underlying network interface
1473  * @param[in] destIpAddr Destination IP address
1474  * @param[in] length Length of the outgoing IP packet
1475  **/
1476 
1478  size_t length)
1479 {
1480  //Check whether the destination address is a unicast or multicast address
1482  {
1483  //Number of IP multicast datagrams transmitted
1484  IPV6_SYSTEM_STATS_INC_COUNTER64(outMcastPkts, 1);
1485  IPV6_IF_STATS_INC_COUNTER64(outMcastPkts, 1);
1486 
1487  //Total number of octets transmitted in IP multicast datagrams
1488  IPV6_SYSTEM_STATS_INC_COUNTER64(outMcastOctets, length);
1489  IPV6_IF_STATS_INC_COUNTER64(outMcastOctets, length);
1490  }
1491 
1492  //Total number of IP datagrams that this entity supplied to the lower layers
1493  //for transmission
1494  IPV6_SYSTEM_STATS_INC_COUNTER64(outTransmits, 1);
1495  IPV6_IF_STATS_INC_COUNTER64(outTransmits, 1);
1496 
1497  //Total number of octets in IP datagrams delivered to the lower layers for
1498  //transmission
1500  IPV6_IF_STATS_INC_COUNTER64(outOctets, length);
1501 }
1502 
1503 #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:355
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:1477
@ 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:1128
#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:1344
#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:1270
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:1431
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:1092
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:1225
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:1394
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:1317
#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:1048
bool_t ipv6IsLocalHostAddr(NetContext *context, const Ipv6Addr *ipAddr)
Check whether the specified IPv6 is assigned to the host.
Definition: ipv6_misc.c:1165
void ipv6UpdateInStats(NetInterface *interface, const Ipv6Addr *destIpAddr, size_t length)
Update IPv6 input statistics.
Definition: ipv6_misc.c:1453
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