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