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