ipv6.c
Go to the documentation of this file.
1 /**
2  * @file ipv6.c
3  * @brief IPv6 (Internet Protocol Version 6)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2022 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  * @section Description
28  *
29  * IP version 6 (IPv6) is a new version of the Internet Protocol, designed
30  * as the successor to IP version 4 (IPv4). Refer to RFC 2460
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 2.2.0
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL IPV6_TRACE_LEVEL
38 
39 //Dependencies
40 #include <string.h>
41 #include "core/net.h"
42 #include "core/ip.h"
43 #include "core/udp.h"
44 #include "core/tcp_fsm.h"
45 #include "core/raw_socket.h"
46 #include "ipv6/ipv6.h"
47 #include "ipv6/ipv6_frag.h"
48 #include "ipv6/ipv6_misc.h"
49 #include "ipv6/ipv6_pmtu.h"
50 #include "ipv6/ipv6_routing.h"
51 #include "ipv6/icmpv6.h"
52 #include "ipv6/mld.h"
53 #include "ipv6/ndp.h"
54 #include "ipv6/ndp_cache.h"
55 #include "ipv6/ndp_misc.h"
57 #include "ipv6/slaac_misc.h"
59 #include "mibs/ip_mib_module.h"
60 #include "debug.h"
61 
62 //Check TCP/IP stack configuration
63 #if (IPV6_SUPPORT == ENABLED)
64 
65 //Unspecified IPv6 address
67  IPV6_ADDR(0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000);
68 
69 //Loopback IPv6 address
71  IPV6_ADDR(0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001);
72 
73 //Link-local All-Nodes IPv6 address
75  IPV6_ADDR(0xFF02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001);
76 
77 //Link-local All-Routers IPv6 address
79  IPV6_ADDR(0xFF02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002);
80 
81 //Link-local IPv6 address prefix
83  IPV6_ADDR(0xFE80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000);
84 
85 //Solicited-node IPv6 address prefix
87  IPV6_ADDR(0xFF02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xFF00, 0x0000);
88 
89 
90 /**
91  * @brief IPv6 related initialization
92  * @param[in] interface Underlying network interface
93  * @return Error code
94  **/
95 
97 {
98  Ipv6Context *context;
99  NetInterface *physicalInterface;
100 
101  //Point to the physical interface
102  physicalInterface = nicGetPhysicalInterface(interface);
103 
104  //Point to the IPv6 context
105  context = &interface->ipv6Context;
106 
107  //Clear the IPv6 context
108  osMemset(context, 0, sizeof(Ipv6Context));
109 
110  //Initialize interface specific variables
111  context->linkMtu = physicalInterface->nicDriver->mtu;
112  context->isRouter = FALSE;
114 
115  //Multicast ICMPv6 Echo Request messages are allowed by default
116  context->enableMulticastEchoReq = TRUE;
117 
118  //Initialize the list of IPv6 addresses assigned to the interface
119  osMemset(context->addrList, 0, sizeof(context->addrList));
120  //Initialize the Prefix List
121  osMemset(context->prefixList, 0, sizeof(context->prefixList));
122  //Initialize the Default Router List
123  osMemset(context->routerList, 0, sizeof(context->routerList));
124  //Initialize the list of DNS servers
125  osMemset(context->dnsServerList, 0, sizeof(context->dnsServerList));
126  //Initialize the multicast filter table
127  osMemset(context->multicastFilter, 0, sizeof(context->multicastFilter));
128 
129 #if (IPV6_FRAG_SUPPORT == ENABLED)
130  //Identification field is used to identify fragments of an original IP datagram
131  context->identification = 0;
132  //Initialize the reassembly queue
133  osMemset(context->fragQueue, 0, sizeof(context->fragQueue));
134 #endif
135 
136  //Successful initialization
137  return NO_ERROR;
138 }
139 
140 
141 /**
142  * @brief Change the MTU of a network interface
143  * @param[in] interface Pointer to the desired network interface
144  * @param[in] mtu Maximum transmit unit
145  * @return Error code
146  **/
147 
148 error_t ipv6SetMtu(NetInterface *interface, size_t mtu)
149 {
150  error_t error;
151  NetInterface *physicalInterface;
152 
153  //Check parameters
154  if(interface == NULL)
156 
157  //Get exclusive access
159 
160  //Point to the physical interface
161  physicalInterface = nicGetPhysicalInterface(interface);
162 
163  //Make sure the specified MTU is greater than or equal to the minimum
164  //IPv6 MTU and does not exceed the maximum MTU of the interface
165  if(mtu >= IPV6_DEFAULT_MTU && mtu <= physicalInterface->nicDriver->mtu)
166  {
167  //Set the MTU to be used
168  interface->ipv6Context.linkMtu = mtu;
169  //Successful processing
170  error = NO_ERROR;
171  }
172  else
173  {
174  //The specified MTU is not valid
175  error = ERROR_OUT_OF_RANGE;
176  }
177 
178  //Release exclusive access
180 
181  //Return status code
182  return error;
183 }
184 
185 
186 /**
187  * @brief Retrieve the MTU for the specified interface
188  * @param[in] interface Pointer to the desired network interface
189  * @param[out] mtu Maximum transmit unit
190  * @return Error code
191  **/
192 
193 error_t ipv6GetMtu(NetInterface *interface, size_t *mtu)
194 {
195  //Check parameters
196  if(interface == NULL || mtu == NULL)
198 
199  //Get exclusive access
201  //Return the current MTU value
202  *mtu = interface->ipv6Context.linkMtu;
203  //Release exclusive access
205 
206  //Successful processing
207  return NO_ERROR;
208 }
209 
210 
211 /**
212  * @brief Assign link-local address
213  * @param[in] interface Pointer to the desired network interface
214  * @param[in] addr Link-local address
215  * @return Error code
216  **/
217 
219 {
220  error_t error;
221 
222  //Get exclusive access
224 
225 #if (NDP_SUPPORT == ENABLED)
226  //Check whether Duplicate Address Detection should be performed
227  if(interface->ndpContext.dupAddrDetectTransmits > 0)
228  {
229  //Use the link-local address as a tentative address
230  error = ipv6SetAddr(interface, 0, addr, IPV6_ADDR_STATE_TENTATIVE,
232  }
233  else
234 #endif
235  {
236  //The use of the link-local address is now unrestricted
237  error = ipv6SetAddr(interface, 0, addr, IPV6_ADDR_STATE_PREFERRED,
239  }
240 
241  //Release exclusive access
243 
244  //Return status code
245  return error;
246 }
247 
248 
249 /**
250  * @brief Retrieve link-local address
251  * @param[in] interface Pointer to the desired network interface
252  * @param[out] addr link-local address
253  * @return Error code
254  **/
255 
257 {
258  Ipv6AddrEntry *entry;
259 
260  //Check parameters
261  if(interface == NULL || addr == NULL)
263 
264  //Get exclusive access
266 
267  //Point to the corresponding entry
268  entry = &interface->ipv6Context.addrList[0];
269 
270  //Check whether the IPv6 address is valid
271  if(entry->state == IPV6_ADDR_STATE_PREFERRED ||
273  {
274  //Get IPv6 address
275  *addr = entry->addr;
276  }
277  else
278  {
279  //Return the unspecified address when no address has been assigned
281  }
282 
283  //Release exclusive access
285 
286  //Successful processing
287  return NO_ERROR;
288 }
289 
290 
291 /**
292  * @brief Get the state of the link-local address
293  * @param[in] interface Pointer to the desired network interface
294  * @return Address state
295  **/
296 
298 {
299  Ipv6AddrState state;
300 
301  //Valid interface?
302  if(interface != NULL)
303  {
304  state = interface->ipv6Context.addrList[0].state;
305  }
306  else
307  {
308  state = IPV6_ADDR_STATE_INVALID;
309  }
310 
311  //Return the state of the link-local address
312  return state;
313 }
314 
315 
316 /**
317  * @brief Assign global address
318  * @param[in] interface Pointer to the desired network interface
319  * @param[in] index Zero-based index
320  * @param[in] addr Global address
321  * @return Error code
322  **/
323 
325 {
326  error_t error;
327 
328  //Get exclusive access
330 
331 #if (NDP_SUPPORT == ENABLED)
332  //Check whether Duplicate Address Detection should be performed
333  if(interface->ndpContext.dupAddrDetectTransmits > 0)
334  {
335  //Use the global address as a tentative address
336  error = ipv6SetAddr(interface, index + 1, addr, IPV6_ADDR_STATE_TENTATIVE,
338  }
339  else
340 #endif
341  {
342  //The use of the global address is now unrestricted
343  error = ipv6SetAddr(interface, index + 1, addr, IPV6_ADDR_STATE_PREFERRED,
345  }
346 
347  //Release exclusive access
349 
350  //Return status code
351  return error;
352 }
353 
354 
355 /**
356  * @brief Retrieve global address
357  * @param[in] interface Pointer to the desired network interface
358  * @param[in] index Zero-based index
359  * @param[out] addr Global address
360  * @return Error code
361  **/
362 
364 {
365  Ipv6AddrEntry *entry;
366 
367  //Check parameters
368  if(interface == NULL || addr == NULL)
370 
371  //Make sure that the index is valid
372  if((index + 1) >= IPV6_ADDR_LIST_SIZE)
373  {
374  //Return the unspecified address when the index is out of range
376  //Report an error
377  return ERROR_OUT_OF_RANGE;
378  }
379 
380  //Get exclusive access
382 
383  //Point to the corresponding entry
384  entry = &interface->ipv6Context.addrList[index + 1];
385 
386  //Check whether the IPv6 address is valid
387  if(entry->state == IPV6_ADDR_STATE_PREFERRED ||
389  {
390  //Get IPv6 address
391  *addr = entry->addr;
392  }
393  else
394  {
395  //Return the unspecified address when no address has been assigned
397  }
398 
399  //Release exclusive access
401 
402  //Successful processing
403  return NO_ERROR;
404 }
405 
406 
407 /**
408  * @brief Get the state of the specified global address
409  * @param[in] interface Pointer to the desired network interface
410  * @param[in] index Zero-based index
411  * @return Address state
412  **/
413 
415 {
416  Ipv6AddrState state;
417 
418  //Valid interface and index?
419  if(interface != NULL && (index + 1) < IPV6_ADDR_LIST_SIZE)
420  {
421  state = interface->ipv6Context.addrList[index + 1].state;
422  }
423  else
424  {
425  state = IPV6_ADDR_STATE_INVALID;
426  }
427 
428  //Return the state of the link-local address
429  return state;
430 }
431 
432 
433 /**
434  * @brief Assign anycast address
435  * @param[in] interface Pointer to the desired network interface
436  * @param[in] index Zero-based index
437  * @param[in] addr Anycast address
438  * @return Error code
439  **/
440 
442 {
443  error_t error;
444  NetInterface *physicalInterface;
445  Ipv6Addr *anycastAddrList;
446  Ipv6Addr solicitedNodeAddr;
447 
448  //Check parameters
449  if(interface == NULL || addr == NULL)
451 
452  //Make sure that the index is valid
453  if(index >= IPV6_ANYCAST_ADDR_LIST_SIZE)
454  return ERROR_OUT_OF_RANGE;
455 
456  //The IPv6 address must be a valid unicast address
458  return ERROR_INVALID_ADDRESS;
459 
460  //Initialize status code
461  error = NO_ERROR;
462 
463  //Get exclusive access
465 
466  //Point to the physical interface
467  physicalInterface = nicGetPhysicalInterface(interface);
468 
469  //Point to the list of anycast addresses assigned to the interface
470  anycastAddrList = interface->ipv6Context.anycastAddrList;
471 
472  //Check whether an anycast address is already assigned
473  if(!ipv6CompAddr(&anycastAddrList[index], &IPV6_UNSPECIFIED_ADDR))
474  {
475  //Ethernet interface?
476  if(physicalInterface->nicDriver != NULL &&
477  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
478  {
479  //Form the Solicited-Node address
480  ipv6ComputeSolicitedNodeAddr(&anycastAddrList[index], &solicitedNodeAddr);
481  //Leave the Solicited-Node multicast group
482  ipv6LeaveMulticastGroup(interface, &solicitedNodeAddr);
483  }
484  }
485 
486  //Assign the specified anycast address to the interface
487  anycastAddrList[index] = *addr;
488 
489  //Check whether the anycast address is valid
491  {
492  //Ethernet interface?
493  if(physicalInterface->nicDriver != NULL &&
494  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
495  {
496  //Form the Solicited-Node address for the link-local address
497  ipv6ComputeSolicitedNodeAddr(addr, &solicitedNodeAddr);
498  //Join the Solicited-Node multicast group for each assigned address
499  error = ipv6JoinMulticastGroup(interface, &solicitedNodeAddr);
500  }
501  }
502 
503  //Release exclusive access
505 
506  //Return status code
507  return error;
508 }
509 
510 
511 /**
512  * @brief Retrieve anycast address
513  * @param[in] interface Pointer to the desired network interface
514  * @param[in] index Zero-based index
515  * @param[out] addr Anycast address
516  * @return Error code
517  **/
518 
520 {
521  //Check parameters
522  if(interface == NULL || addr == NULL)
524 
525  //Make sure that the index is valid
526  if(index >= IPV6_ANYCAST_ADDR_LIST_SIZE)
527  {
528  //Return the unspecified address when the index is out of range
530  //Report an error
531  return ERROR_OUT_OF_RANGE;
532  }
533 
534  //Get exclusive access
536  //Return the corresponding entry
537  *addr = interface->ipv6Context.anycastAddrList[index];
538  //Release exclusive access
540 
541  //Successful processing
542  return NO_ERROR;
543 }
544 
545 
546 /**
547  * @brief Configure IPv6 prefix
548  * @param[in] interface Pointer to the desired network interface
549  * @param[in] index Zero-based index
550  * @param[in] prefix IPv6 prefix
551  * @param[in] length The number of leading bits in the prefix that are valid
552  **/
553 
555  uint_t index, const Ipv6Addr *prefix, uint_t length)
556 {
557  Ipv6PrefixEntry *entry;
558 
559  //Check parameters
560  if(interface == NULL || prefix == NULL)
562 
563  //Make sure that the index is valid
564  if(index >= IPV6_PREFIX_LIST_SIZE)
565  return ERROR_OUT_OF_RANGE;
566 
567  //Make sure the prefix length is valid
568  if(length >= 128)
570 
571  //Get exclusive access
573 
574  //Point to the corresponding entry
575  entry = &interface->ipv6Context.prefixList[index];
576 
577  //Set up IPv6 prefix
578  entry->prefix = *prefix;
579  entry->prefixLen = length;
580 
581  //Check prefix length
582  if(length > 0)
583  {
584  //Set On-link and Autonomous flags
585  entry->onLinkFlag = TRUE;
586  entry->autonomousFlag = FALSE;
587 
588  //Manually assigned prefixes have infinite lifetime
589  entry->validLifetime = INFINITE_DELAY;
591  entry->permanent = TRUE;
592  }
593  else
594  {
595  //Immediately time-out the entry
596  entry->validLifetime = 0;
597  entry->preferredLifetime = 0;
598  entry->permanent = FALSE;
599  }
600 
601  //Release exclusive access
603 
604  //Successful processing
605  return NO_ERROR;
606 }
607 
608 
609 /**
610  * @brief Retrieve IPv6 prefix
611  * @param[in] interface Pointer to the desired network interface
612  * @param[in] index Zero-based index
613  * @param[out] prefix IPv6 prefix
614  * @param[out] length The number of leading bits in the prefix that are valid
615  * @return Error code
616  **/
617 
619  uint_t index, Ipv6Addr *prefix, uint_t *length)
620 {
621  Ipv6PrefixEntry *entry;
622 
623  //Check parameters
624  if(interface == NULL || prefix == NULL)
626 
627  //Make sure that the index is valid
628  if(index >= IPV6_PREFIX_LIST_SIZE)
629  {
630  //Return the ::/0 prefix when the index is out of range
632  *length = 0;
633  //Report an error
634  return ERROR_OUT_OF_RANGE;
635  }
636 
637  //Get exclusive access
639 
640  //Point to the corresponding entry
641  entry = &interface->ipv6Context.prefixList[index];
642 
643  //Check whether the prefix is valid
644  if(entry->validLifetime > 0)
645  {
646  //Get IPv6 prefix
647  *prefix = entry->prefix;
648  *length = entry->prefixLen;
649  }
650  else
651  {
652  //Return the ::/0 prefix when the valid lifetime has expired
654  *length = 0;
655  }
656 
657  //Release exclusive access
659 
660  //Successful processing
661  return NO_ERROR;
662 }
663 
664 
665 /**
666  * @brief Configure default router
667  * @param[in] interface Pointer to the desired network interface
668  * @param[in] index Zero-based index
669  * @param[in] addr Default router address
670  * @return Error code
671  **/
672 
674 {
675  Ipv6RouterEntry *entry;
676 
677  //Check parameters
678  if(interface == NULL || addr == NULL)
680 
681  //Make sure that the index is valid
682  if(index >= IPV6_ROUTER_LIST_SIZE)
683  return ERROR_OUT_OF_RANGE;
684 
685  //The IPv6 address must be a valid unicast address
687  return ERROR_INVALID_ADDRESS;
688 
689  //Get exclusive access
691 
692  //Point to the corresponding entry
693  entry = &interface->ipv6Context.routerList[index];
694 
695  //Set up router address
696  entry->addr = *addr;
697  //Preference value
698  entry->preference = 0;
699 
700  //Valid IPv6 address?
702  {
703  //Manually assigned routers have infinite lifetime
704  entry->lifetime = INFINITE_DELAY;
705  entry->permanent = TRUE;
706  }
707  else
708  {
709  //Immediately time-out the entry
710  entry->lifetime = 0;
711  entry->permanent = FALSE;
712  }
713 
714  //Release exclusive access
716 
717  //Successful processing
718  return NO_ERROR;
719 }
720 
721 
722 /**
723  * @brief Retrieve default router
724  * @param[in] interface Pointer to the desired network interface
725  * @param[in] index Zero-based index
726  * @param[out] addr Default router address
727  * @return Error code
728  **/
729 
731 {
732  Ipv6RouterEntry *entry;
733 
734  //Check parameters
735  if(interface == NULL || addr == NULL)
737 
738  //Make sure that the index is valid
739  if(index >= IPV6_ROUTER_LIST_SIZE)
740  {
741  //Return the unspecified address when the index is out of range
743  //Report an error
744  return ERROR_OUT_OF_RANGE;
745  }
746 
747  //Get exclusive access
749 
750  //Point to the corresponding entry
751  entry = &interface->ipv6Context.routerList[index];
752 
753  //Check the lifetime of the entry
754  if(entry->lifetime > 0)
755  {
756  //Get router address
757  *addr = entry->addr;
758  }
759  else
760  {
761  //Return the unspecified address when the lifetime has expired
763  }
764 
765  //Release exclusive access
767 
768  //Successful processing
769  return NO_ERROR;
770 }
771 
772 
773 /**
774  * @brief Configure DNS server
775  * @param[in] interface Pointer to the desired network interface
776  * @param[in] index This parameter selects between the primary and secondary DNS server
777  * @param[in] addr DNS server address
778  * @return Error code
779  **/
780 
782 {
783  //Check parameters
784  if(interface == NULL || addr == NULL)
786 
787  //Make sure that the index is valid
788  if(index >= IPV6_DNS_SERVER_LIST_SIZE)
789  return ERROR_OUT_OF_RANGE;
790 
791  //The IPv6 address must be a valid unicast address
793  return ERROR_INVALID_ADDRESS;
794 
795  //Get exclusive access
797  //Set up DNS server address
798  interface->ipv6Context.dnsServerList[index] = *addr;
799  //Release exclusive access
801 
802  //Successful processing
803  return NO_ERROR;
804 }
805 
806 
807 /**
808  * @brief Retrieve DNS server
809  * @param[in] interface Pointer to the desired network interface
810  * @param[in] index This parameter selects between the primary and secondary DNS server
811  * @param[out] addr DNS server address
812  * @return Error code
813  **/
814 
816 {
817  //Check parameters
818  if(interface == NULL || addr == NULL)
820 
821  //Make sure that the index is valid
822  if(index >= IPV6_DNS_SERVER_LIST_SIZE)
823  {
824  //Return the unspecified address when the index is out of range
826  //Report an error
827  return ERROR_OUT_OF_RANGE;
828  }
829 
830  //Get exclusive access
832  //Get DNS server address
833  *addr = interface->ipv6Context.dnsServerList[index];
834  //Release exclusive access
836 
837  //Successful processing
838  return NO_ERROR;
839 }
840 
841 
842 /**
843  * @brief Callback function for link change event
844  * @param[in] interface Underlying network interface
845  **/
846 
848 {
849  uint_t i;
850  Ipv6Context *context;
851  Ipv6AddrEntry *entry;
852  NetInterface *physicalInterface;
853 
854  //Point to the physical interface
855  physicalInterface = nicGetPhysicalInterface(interface);
856 
857  //Point to the IPv6 context
858  context = &interface->ipv6Context;
859 
860  //Restore default parameters
861  context->linkMtu = physicalInterface->nicDriver->mtu;
863 
864  //Clear the list of IPv6 addresses
865  ipv6FlushAddrList(interface);
866  //Clear the Prefix List
867  ipv6FlushPrefixList(interface);
868  //Clear the Default Router List
869  ipv6FlushDefaultRouterList(interface);
870 
871 #if (IPV6_FRAG_SUPPORT == ENABLED)
872  //Flush the reassembly queue
873  ipv6FlushFragQueue(interface);
874 #endif
875 
876 #if (MLD_SUPPORT == ENABLED)
877  //Notify MLD of link state changes
878  mldLinkChangeEvent(interface);
879 #endif
880 
881 #if (NDP_SUPPORT == ENABLED)
882  //Notify NDP of link state changes
883  ndpLinkChangeEvent(interface);
884 #endif
885 
886 #if (NDP_ROUTER_ADV_SUPPORT == ENABLED)
887  //Notify the RA service of link state changes
888  ndpRouterAdvLinkChangeEvent(interface->ndpRouterAdvContext);
889 #endif
890 
891 #if (SLAAC_SUPPORT == ENABLED)
892  //Notify the SLAAC service of link state changes
893  slaacLinkChangeEvent(interface->slaacContext);
894 #endif
895 
896 #if (DHCPV6_CLIENT_SUPPORT == ENABLED)
897  //Notify the DHCPv6 client of link state changes
898  dhcpv6ClientLinkChangeEvent(interface->dhcpv6ClientContext);
899 #endif
900 
901  //Go through the list of IPv6 addresses
902  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
903  {
904  //Point to the current entry
905  entry = &context->addrList[i];
906 
907  //Check whether the IPv6 address has been manually assigned
908  if(entry->permanent)
909  {
910 #if (NDP_SUPPORT == ENABLED)
911  //Check whether Duplicate Address Detection should be performed
912  if(interface->ndpContext.dupAddrDetectTransmits > 0)
913  {
914  //Use the IPv6 address as a tentative address
915  ipv6SetAddr(interface, i, &entry->addr, IPV6_ADDR_STATE_TENTATIVE,
917  }
918  else
919 #endif
920  {
921  //The use of the IPv6 address is now unrestricted
922  ipv6SetAddr(interface, i, &entry->addr, IPV6_ADDR_STATE_PREFERRED,
924  }
925  }
926  }
927 }
928 
929 
930 /**
931  * @brief Incoming IPv6 packet processing
932  * @param[in] interface Underlying network interface
933  * @param[in] ipPacket Multi-part buffer that holds the incoming IPv6 packet
934  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
935  * @param[in] ancillary Additional options passed to the stack along with
936  * the packet
937  **/
938 
940  size_t ipPacketOffset, NetRxAncillary *ancillary)
941 {
942  error_t error;
943  size_t i;
944  size_t length;
945  size_t nextHeaderOffset;
946  uint8_t *type;
947  Ipv6Header *ipHeader;
948  IpPseudoHeader pseudoHeader;
949 
950  //Total number of input datagrams received, including those received in error
951  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInReceives, 1);
952  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCInReceives, 1);
953  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInReceives, 1);
954  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCInReceives, 1);
955 
956  //Retrieve the length of the IPv6 packet
958 
959  //Total number of octets received in input IP datagrams
960  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInOctets, length);
961  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCInOctets, length);
962  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInOctets, length);
963  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCInOctets, length);
964 
965  //Ensure the packet length is greater than 40 bytes
966  if(length < sizeof(Ipv6Header))
967  {
968  //Number of input IP datagrams discarded because the datagram frame
969  //didn't carry enough data
970  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInTruncatedPkts, 1);
971  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInTruncatedPkts, 1);
972 
973  //Discard the received packet
974  return;
975  }
976 
977  //Point to the IPv6 header
978  ipHeader = netBufferAt(ipPacket, ipPacketOffset);
979  //Sanity check
980  if(ipHeader == NULL)
981  return;
982 
983  //Debug message
984  TRACE_INFO("IPv6 packet received (%" PRIuSIZE " bytes)...\r\n", length);
985  //Dump IPv6 header contents for debugging purpose
986  ipv6DumpHeader(ipHeader);
987 
988  //Check IP version number
989  if(ipHeader->version != IPV6_VERSION)
990  {
991  //Number of input datagrams discarded due to errors in their IP headers
992  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInHdrErrors, 1);
993  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInHdrErrors, 1);
994 
995  //Discard the received packet
996  return;
997  }
998 
999  //Ensure the payload length is correct before processing the packet
1000  if(ntohs(ipHeader->payloadLen) > (length - sizeof(Ipv6Header)))
1001  {
1002  //Number of input IP datagrams discarded because the datagram frame
1003  //didn't carry enough data
1004  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInTruncatedPkts, 1);
1005  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInTruncatedPkts, 1);
1006 
1007  //Discard the received packet
1008  return;
1009  }
1010 
1011  //Source address filtering
1012  if(ipv6CheckSourceAddr(interface, &ipHeader->srcAddr))
1013  {
1014  //Number of input datagrams discarded due to errors in their IP headers
1015  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInHdrErrors, 1);
1016  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInHdrErrors, 1);
1017 
1018  //Discard the received packet
1019  return;
1020  }
1021 
1022 #if defined(IPV6_PACKET_FORWARD_HOOK)
1023  IPV6_PACKET_FORWARD_HOOK(interface, ipPacket, ipPacketOffset);
1024 #else
1025  //Destination address filtering
1026  if(ipv6CheckDestAddr(interface, &ipHeader->destAddr))
1027  {
1028 #if (IPV6_ROUTING_SUPPORT == ENABLED)
1029  //Forward the packet according to the routing table
1030  ipv6ForwardPacket(interface, ipPacket, ipPacketOffset);
1031 #else
1032  //Number of input datagrams discarded because the destination IP address
1033  //was not a valid address
1034  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInAddrErrors, 1);
1035  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInAddrErrors, 1);
1036 #endif
1037  //We are done
1038  return;
1039  }
1040 #endif
1041 
1042  //Update IP statistics
1043  ipv6UpdateInStats(interface, &ipHeader->destAddr, length);
1044 
1045  //Calculate the effective length of the multi-part buffer
1046  length = ipPacketOffset + sizeof(Ipv6Header) +
1047  ntohs(ipHeader->payloadLen);
1048 
1049  //Adjust the length of the multi-part buffer if necessary
1051 
1052  //Form the IPv6 pseudo header
1053  pseudoHeader.length = sizeof(Ipv6PseudoHeader);
1054  pseudoHeader.ipv6Data.srcAddr = ipHeader->srcAddr;
1055  pseudoHeader.ipv6Data.destAddr = ipHeader->destAddr;
1056  pseudoHeader.ipv6Data.reserved[0] = 0;
1057  pseudoHeader.ipv6Data.reserved[1] = 0;
1058  pseudoHeader.ipv6Data.reserved[2] = 0;
1059 
1060  //Save Hop Limit value
1061  ancillary->ttl = ipHeader->hopLimit;
1062 
1063  //Keep track of Next Header field
1064  nextHeaderOffset = ipPacketOffset + &ipHeader->nextHeader -
1065  (uint8_t *) ipHeader;
1066 
1067  //Point to the first extension header
1068  i = ipPacketOffset + sizeof(Ipv6Header);
1069 
1070  //Parse extension headers
1071  while(i < length)
1072  {
1073  //Retrieve the Next Header field of preceding header
1074  type = netBufferAt(ipPacket, nextHeaderOffset);
1075  //Sanity check
1076  if(type == NULL)
1077  return;
1078 
1079  //Update IPv6 pseudo header
1080  pseudoHeader.ipv6Data.length = htonl(length - i);
1081  pseudoHeader.ipv6Data.nextHeader = *type;
1082 
1083  //Each extension header is identified by the Next Header field of the
1084  //preceding header
1085  switch(*type)
1086  {
1087  //Hop-by-Hop Options header?
1089  //Parse current extension header
1090  error = ipv6ParseHopByHopOptHeader(interface, ipPacket, ipPacketOffset,
1091  &i, &nextHeaderOffset);
1092  //Continue processing
1093  break;
1094 
1095  //Destination Options header?
1096  case IPV6_DEST_OPT_HEADER:
1097  //Parse current extension header
1098  error = ipv6ParseDestOptHeader(interface, ipPacket, ipPacketOffset,
1099  &i, &nextHeaderOffset);
1100  //Continue processing
1101  break;
1102 
1103  //Routing header?
1104  case IPV6_ROUTING_HEADER:
1105  //Parse current extension header
1106  error = ipv6ParseRoutingHeader(interface, ipPacket, ipPacketOffset,
1107  &i, &nextHeaderOffset);
1108  //Continue processing
1109  break;
1110 
1111  //Fragment header?
1112  case IPV6_FRAGMENT_HEADER:
1113 #if (IPV6_FRAG_SUPPORT == ENABLED)
1114  //Parse current extension header
1115  ipv6ParseFragmentHeader(interface, ipPacket, ipPacketOffset,
1116  i, nextHeaderOffset, ancillary);
1117 #endif
1118  //Exit immediately
1119  return;
1120 
1121  //AH header?
1122  case IPV6_AH_HEADER:
1123  //Parse current extension header
1124  error = ipv6ParseAhHeader(interface, ipPacket, ipPacketOffset,
1125  &i, &nextHeaderOffset);
1126  //Continue processing
1127  break;
1128 
1129  //ESP header?
1130  case IPV6_ESP_HEADER:
1131  //Parse current extension header
1132  error = ipv6ParseEspHeader(interface, ipPacket, ipPacketOffset,
1133  &i, &nextHeaderOffset);
1134  //Continue processing
1135  break;
1136 
1137  //ICMPv6 header?
1138  case IPV6_ICMPV6_HEADER:
1139  //Process incoming ICMPv6 message
1140  icmpv6ProcessMessage(interface, &pseudoHeader.ipv6Data, ipPacket,
1141  i, ipHeader->hopLimit);
1142 
1143 #if (RAW_SOCKET_SUPPORT == ENABLED)
1144  //Packets addressed to the tentative address should be silently discarded
1145  if(!ipv6IsTentativeAddr(interface, &ipHeader->destAddr))
1146  {
1147  //Allow raw sockets to process ICMPv6 messages
1148  rawSocketProcessIpPacket(interface, &pseudoHeader, ipPacket, i,
1149  ancillary);
1150  }
1151 #endif
1152  //Exit immediately
1153  return;
1154 
1155 #if (TCP_SUPPORT == ENABLED)
1156  //TCP header?
1157  case IPV6_TCP_HEADER:
1158  //Packets addressed to the tentative address should be silently discarded
1159  if(!ipv6IsTentativeAddr(interface, &ipHeader->destAddr))
1160  {
1161  //Process incoming TCP segment
1162  tcpProcessSegment(interface, &pseudoHeader, ipPacket, i, ancillary);
1163  }
1164  else
1165  {
1166  //Number of input datagrams discarded because the destination IP address
1167  //was not a valid address
1168  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInAddrErrors, 1);
1169  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInAddrErrors, 1);
1170  }
1171 
1172  //Exit immediately
1173  return;
1174 #endif
1175 
1176 #if (UDP_SUPPORT == ENABLED)
1177  //UDP header?
1178  case IPV6_UDP_HEADER:
1179  //Packets addressed to the tentative address should be silently discarded
1180  if(!ipv6IsTentativeAddr(interface, &ipHeader->destAddr))
1181  {
1182  //Process incoming UDP datagram
1183  error = udpProcessDatagram(interface, &pseudoHeader, ipPacket, i,
1184  ancillary);
1185 
1186  //Unreachable port?
1187  if(error == ERROR_PORT_UNREACHABLE)
1188  {
1189  //A destination node should originate a Destination Unreachable
1190  //message with Code 4 in response to a packet for which the
1191  //transport protocol has no listener
1193  ICMPV6_CODE_PORT_UNREACHABLE, 0, ipPacket, ipPacketOffset);
1194  }
1195  }
1196  else
1197  {
1198  //Number of input datagrams discarded because the destination IP address
1199  //was not a valid address
1200  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInAddrErrors, 1);
1201  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInAddrErrors, 1);
1202  }
1203 
1204  //Exit immediately
1205  return;
1206 #endif
1207 
1208  //No next header?
1209  case IPV6_NO_NEXT_HEADER:
1210  //If the payload length field of the IPv6 header indicates the presence of
1211  //octets past the end of the previous header, these octets must be ignored
1212  return;
1213 
1214  //Unrecognized header type?
1215  default:
1216  //Debug message
1217  TRACE_WARNING("Unrecognized Next Header type\r\n");
1218 
1219  //Packets addressed to the tentative address should be silently discarded
1220  if(!ipv6IsTentativeAddr(interface, &ipHeader->destAddr))
1221  {
1222  //Compute the offset of the unrecognized Next Header field within the packet
1223  size_t n = nextHeaderOffset - ipPacketOffset;
1224 
1225  //Send an ICMP Parameter Problem message
1227  ICMPV6_CODE_UNKNOWN_NEXT_HEADER, n, ipPacket, ipPacketOffset);
1228  }
1229  else
1230  {
1231  //Number of input datagrams discarded because the destination IP address
1232  //was not a valid address
1233  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInAddrErrors, 1);
1234  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInAddrErrors, 1);
1235  }
1236 
1237  //Discard incoming packet
1238  return;
1239  }
1240 
1241  //Any error while processing the current extension header?
1242  if(error)
1243  return;
1244  }
1245 }
1246 
1247 
1248 /**
1249  * @brief Parse Hop-by-Hop Options header
1250  * @param[in] interface Underlying network interface
1251  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1252  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1253  * @param[in,out] headerOffset Offset to the Hop-by-Hop Options header
1254  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1255  * @brief Error code
1256  **/
1257 
1259  size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
1260 {
1261  error_t error;
1262  size_t n;
1263  size_t length;
1264  size_t headerLen;
1265  Ipv6HopByHopOptHeader *header;
1266 
1267  //Remaining bytes to process in the IPv6 packet
1268  length = netBufferGetLength(ipPacket) - *headerOffset;
1269 
1270  //Make sure the extension header is valid
1271  if(length < sizeof(Ipv6HopByHopOptHeader))
1272  return ERROR_INVALID_HEADER;
1273 
1274  //Point to the Hop-by-Hop Options header
1275  header = netBufferAt(ipPacket, *headerOffset);
1276  //Sanity check
1277  if(header == NULL)
1278  return ERROR_FAILURE;
1279 
1280  //Calculate the length of the entire header
1281  headerLen = (header->hdrExtLen * 8) + 8;
1282 
1283  //Check header length
1284  if(headerLen > length)
1285  return ERROR_INVALID_HEADER;
1286 
1287  //Debug message
1288  TRACE_DEBUG(" Hop-by-Hop Options header\r\n");
1289 
1290  //The Hop-by-Hop Options header, when present, must immediately follow
1291  //the IPv6 header
1292  if(*headerOffset != (ipPacketOffset + sizeof(Ipv6Header)))
1293  {
1294  //Compute the offset of the unrecognized Next Header field within the packet
1295  n = *nextHeaderOffset - ipPacketOffset;
1296 
1297  //Send an ICMP Parameter Problem message to the source of the packet
1299  ICMPV6_CODE_UNKNOWN_NEXT_HEADER, n, ipPacket, ipPacketOffset);
1300 
1301  //Discard incoming packet
1302  return ERROR_INVALID_HEADER;
1303  }
1304 
1305  //Compute the length of the Options field
1306  n = headerLen - sizeof(Ipv6HopByHopOptHeader);
1307 
1308  //Parse options
1309  error = ipv6ParseOptions(interface, ipPacket, ipPacketOffset,
1310  *headerOffset + sizeof(Ipv6HopByHopOptHeader), n);
1311 
1312  //Any error to report?
1313  if(error)
1314  return error;
1315 
1316  //Keep track of Next Header field
1317  *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header;
1318  //Point to the next extension header
1319  *headerOffset += headerLen;
1320 
1321  //Successful processing
1322  return NO_ERROR;
1323 }
1324 
1325 
1326 /**
1327  * @brief Parse Destination Options header
1328  * @param[in] interface Underlying network interface
1329  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1330  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1331  * @param[in,out] headerOffset Offset to the Destination Options header
1332  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1333  * @brief Error code
1334  **/
1335 
1337  size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
1338 {
1339  error_t error;
1340  size_t n;
1341  size_t length;
1342  size_t headerLen;
1343  Ipv6DestOptHeader *header;
1344 
1345  //Remaining bytes to process in the IPv6 packet
1346  length = netBufferGetLength(ipPacket) - *headerOffset;
1347 
1348  //Make sure the extension header is valid
1349  if(length < sizeof(Ipv6DestOptHeader))
1350  return ERROR_INVALID_HEADER;
1351 
1352  //Point to the Destination Options header
1353  header = netBufferAt(ipPacket, *headerOffset);
1354  //Sanity check
1355  if(header == NULL)
1356  return ERROR_FAILURE;
1357 
1358  //Calculate the length of the entire header
1359  headerLen = (header->hdrExtLen * 8) + 8;
1360 
1361  //Check header length
1362  if(headerLen > length)
1363  return ERROR_INVALID_HEADER;
1364 
1365  //Debug message
1366  TRACE_DEBUG(" Destination Options header\r\n");
1367 
1368  //Compute the length of the Options field
1369  n = headerLen - sizeof(Ipv6DestOptHeader);
1370 
1371  //Parse options
1372  error = ipv6ParseOptions(interface, ipPacket, ipPacketOffset,
1373  *headerOffset + sizeof(Ipv6DestOptHeader), n);
1374 
1375  //Any error to report?
1376  if(error)
1377  return error;
1378 
1379  //Keep track of Next Header field
1380  *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header;
1381  //Point to the next extension header
1382  *headerOffset += headerLen;
1383 
1384  //Successful processing
1385  return NO_ERROR;
1386 }
1387 
1388 
1389 /**
1390  * @brief Parse Routing header
1391  * @param[in] interface Underlying network interface
1392  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1393  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1394  * @param[in,out] headerOffset Offset to the Routing header
1395  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1396  * @brief Error code
1397  **/
1398 
1400  size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
1401 {
1402  size_t n;
1403  size_t length;
1404  size_t headerLen;
1405  Ipv6RoutingHeader *header;
1406 
1407  //Remaining bytes to process in the IPv6 packet
1408  length = netBufferGetLength(ipPacket) - *headerOffset;
1409 
1410  //Make sure the extension header is valid
1411  if(length < sizeof(Ipv6RoutingHeader))
1412  return ERROR_INVALID_HEADER;
1413 
1414  //Point to the Routing header
1415  header = netBufferAt(ipPacket, *headerOffset);
1416  //Sanity check
1417  if(header == NULL)
1418  return ERROR_FAILURE;
1419 
1420  //Calculate the length of the entire header
1421  headerLen = (header->hdrExtLen * 8) + 8;
1422 
1423  //Check header length
1424  if(headerLen > length)
1425  return ERROR_INVALID_HEADER;
1426 
1427  //Debug message
1428  TRACE_DEBUG(" Routing header\r\n");
1429 
1430  //If, while processing a received packet, a node encounters a Routing
1431  //header with an unrecognized Routing Type value, the required behavior
1432  //of the node depends on the value of the Segments Left field
1433  if(header->segmentsLeft != 0)
1434  {
1435  //Retrieve the offset of the Routing header within the packet
1436  n = *headerOffset - ipPacketOffset;
1437  //Compute the exact offset of the Routing Type field
1438  n += (uint8_t *) &header->routingType - (uint8_t *) header;
1439 
1440  //If Segments Left is non-zero, send an ICMP Parameter Problem,
1441  //Code 0, message to the packet's Source Address, pointing to
1442  //the unrecognized Routing Type
1444  ICMPV6_CODE_INVALID_HEADER_FIELD, n, ipPacket, ipPacketOffset);
1445 
1446  //The node must discard the packet
1447  return ERROR_INVALID_TYPE;
1448  }
1449 
1450  //Keep track of Next Header field
1451  *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header;
1452  //Point to the next extension header
1453  *headerOffset += headerLen;
1454 
1455  //Successful processing
1456  return NO_ERROR;
1457 }
1458 
1459 
1460 /**
1461  * @brief Parse AH header
1462  * @param[in] interface Underlying network interface
1463  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1464  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1465  * @param[in,out] headerOffset Offset to the Authentication header
1466  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1467  * @brief Error code
1468  **/
1469 
1471  size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
1472 {
1473  //Debug message
1474  TRACE_DEBUG(" AH header\r\n");
1475  //IPsec is not supported
1476  return ERROR_FAILURE;
1477 }
1478 
1479 
1480 /**
1481  * @brief Parse ESP header
1482  * @param[in] interface Underlying network interface
1483  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1484  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1485  * @param[in,out] headerOffset Offset to the Encapsulating Security Payload header
1486  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1487  * @brief Error code
1488  **/
1489 
1491  size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
1492 {
1493  //Debug message
1494  TRACE_DEBUG(" ESP header\r\n");
1495  //IPsec is not supported
1496  return ERROR_FAILURE;
1497 }
1498 
1499 
1500 /**
1501  * @brief Parse IPv6 options
1502  * @param[in] interface Underlying network interface
1503  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1504  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1505  * @param[in] optionOffset Offset to the first byte of the Options field
1506  * @param[in] optionLen Length of the Options field
1507  * @brief Error code
1508  **/
1509 
1511  size_t ipPacketOffset, size_t optionOffset, size_t optionLen)
1512 {
1513  size_t i;
1514  size_t n;
1515  uint8_t type;
1516  uint8_t action;
1517  uint8_t *options;
1518  Ipv6Option *option;
1519  Ipv6Header *ipHeader;
1520 
1521  //Point to the first byte of the Options field
1522  options = netBufferAt(ipPacket, optionOffset);
1523 
1524  //Sanity check
1525  if(options == NULL)
1526  return ERROR_FAILURE;
1527 
1528  //Parse options
1529  for(i = 0; i < optionLen; )
1530  {
1531  //Point to the current option
1532  option = (Ipv6Option *) (options + i);
1533  //Get option type
1534  type = option->type & IPV6_OPTION_TYPE_MASK;
1535 
1536  //Pad1 option?
1538  {
1539  //Advance data pointer
1540  i++;
1541  }
1542  //PadN option?
1543  else if(type == IPV6_OPTION_TYPE_PADN)
1544  {
1545  //Malformed IPv6 packet?
1546  if((i + sizeof(Ipv6Option)) > optionLen)
1547  return ERROR_INVALID_LENGTH;
1548 
1549  //Advance data pointer
1550  i += sizeof(Ipv6Option) + option->length;
1551  }
1552  //Unrecognized option?
1553  else
1554  {
1555  //Point to the IPv6 header
1556  ipHeader = netBufferAt(ipPacket, ipPacketOffset);
1557 
1558  //Sanity check
1559  if(ipHeader == NULL)
1560  return ERROR_FAILURE;
1561 
1562  //Get the value of the highest-order two bits
1563  action = option->type & IPV6_ACTION_MASK;
1564 
1565  //The highest-order two bits specify the action that must be taken
1566  //if the processing IPv6 node does not recognize the option type
1567  if(action == IPV6_ACTION_SKIP_OPTION)
1568  {
1569  //Skip over this option and continue processing the header
1570  }
1571  else if(action == IPV6_ACTION_DISCARD_PACKET)
1572  {
1573  //Discard the packet
1574  return ERROR_INVALID_OPTION;
1575  }
1576  else if(action == IPV6_ACTION_SEND_ICMP_ERROR_ALL)
1577  {
1578  //Calculate the octet offset within the invoking packet
1579  //where the error was detected
1580  n = optionOffset + i - ipPacketOffset;
1581 
1582  //Send an ICMP Parameter Problem message to the source of the
1583  //packet, regardless of whether or not the destination address
1584  //was a multicast address
1586  ICMPV6_CODE_UNKNOWN_IPV6_OPTION, n, ipPacket, ipPacketOffset);
1587 
1588  //Discard the packet
1589  return ERROR_INVALID_OPTION;
1590  }
1591  else if(action == IPV6_ACTION_SEND_ICMP_ERROR_UNI)
1592  {
1593  //Send an ICMP Parameter Problem message to the source of the
1594  //packet, only if the destination address was not a multicast
1595  //address
1596  if(!ipv6IsMulticastAddr(&ipHeader->destAddr))
1597  {
1598  //Calculate the octet offset within the invoking packet
1599  //where the error was detected
1600  n = optionOffset + i - ipPacketOffset;
1601 
1602  //Send the ICMP Parameter Problem message
1604  ICMPV6_CODE_UNKNOWN_IPV6_OPTION, n, ipPacket, ipPacketOffset);
1605  }
1606 
1607  //Discard the packet
1608  return ERROR_INVALID_OPTION;
1609  }
1610 
1611  //Malformed IPv6 packet?
1612  if((i + sizeof(Ipv6Option)) > optionLen)
1613  return ERROR_INVALID_LENGTH;
1614 
1615  //Advance data pointer
1616  i += sizeof(Ipv6Option) + option->length;
1617  }
1618  }
1619 
1620  //Successful processing
1621  return NO_ERROR;
1622 }
1623 
1624 
1625 /**
1626  * @brief Send an IPv6 datagram
1627  * @param[in] interface Underlying network interface
1628  * @param[in] pseudoHeader IPv6 pseudo header
1629  * @param[in] buffer Multi-part buffer containing the payload
1630  * @param[in] offset Offset to the first byte of the payload
1631  * @param[in] ancillary Additional options passed to the stack along with
1632  * the packet
1633  * @return Error code
1634  **/
1635 
1637  NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
1638 {
1639  error_t error;
1640  size_t length;
1641  size_t pathMtu;
1642 
1643  //Total number of IP datagrams which local IP user-protocols supplied to IP
1644  //in requests for transmission
1645  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsOutRequests, 1);
1646  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCOutRequests, 1);
1647  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsOutRequests, 1);
1648  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCOutRequests, 1);
1649 
1650  //Retrieve the length of payload
1651  length = netBufferGetLength(buffer) - offset;
1652 
1653 #if (IPV6_PMTU_SUPPORT == ENABLED)
1654  //Retrieve the PMTU for the specified destination address
1655  pathMtu = ipv6GetPathMtu(interface, &pseudoHeader->destAddr);
1656 
1657  //The PMTU should not exceed the MTU of the first-hop link
1658  if(pathMtu > interface->ipv6Context.linkMtu)
1659  pathMtu = interface->ipv6Context.linkMtu;
1660 #else
1661  //The PMTU value for the path is assumed to be the MTU of the first-hop link
1662  pathMtu = interface->ipv6Context.linkMtu;
1663 #endif
1664 
1665  //If the payload length is smaller than the PMTU then no fragmentation is
1666  //needed
1667  if((length + sizeof(Ipv6Header)) <= pathMtu)
1668  {
1669  //Send data as is
1670  error = ipv6SendPacket(interface, pseudoHeader, 0, 0, buffer, offset,
1671  ancillary);
1672  }
1673  //If the payload length exceeds the PMTU then the device must fragment the
1674  //data
1675  else
1676  {
1677 #if (IPV6_FRAG_SUPPORT == ENABLED)
1678  //Fragment IP datagram into smaller packets
1679  error = ipv6FragmentDatagram(interface, pseudoHeader, buffer, offset,
1680  pathMtu, ancillary);
1681 #else
1682  //Fragmentation is not supported
1683  error = ERROR_MESSAGE_TOO_LONG;
1684 #endif
1685  }
1686 
1687  //Return status code
1688  return error;
1689 }
1690 
1691 
1692 /**
1693  * @brief Send an IPv6 packet
1694  * @param[in] interface Underlying network interface
1695  * @param[in] pseudoHeader IPv6 pseudo header
1696  * @param[in] fragId Fragment identification field
1697  * @param[in] fragOffset Fragment offset field
1698  * @param[in] buffer Multi-part buffer containing the payload
1699  * @param[in] offset Offset to the first byte of the payload
1700  * @param[in] ancillary Additional options passed to the stack along with
1701  * the packet
1702  * @return Error code
1703  **/
1704 
1706  uint32_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset,
1707  NetTxAncillary *ancillary)
1708 {
1709  error_t error;
1710  size_t length;
1711  Ipv6Header *packet;
1712 #if (ETH_SUPPORT == ENABLED)
1713  NetInterface *physicalInterface;
1714 #endif
1715 
1716  //Calculate the length of the payload
1717  length = netBufferGetLength(buffer) - offset;
1718 
1719  //Add Fragment header?
1720  if(fragOffset != 0)
1721  {
1722  Ipv6FragmentHeader *header;
1723 
1724  //Is there enough space for the IPv6 header and the Fragment header?
1725  if(offset < (sizeof(Ipv6Header) + sizeof(Ipv6FragmentHeader)))
1726  return ERROR_INVALID_PARAMETER;
1727 
1728  //Make room for the Fragment header
1729  offset -= sizeof(Ipv6FragmentHeader);
1730  length += sizeof(Ipv6FragmentHeader);
1731 
1732  //Point to the Fragment header
1733  header = netBufferAt(buffer, offset);
1734  //Format the Fragment header
1735  header->nextHeader = pseudoHeader->nextHeader;
1736  header->reserved = 0;
1737  header->fragmentOffset = htons(fragOffset);
1738  header->identification = htonl(fragId);
1739 
1740  //Make room for the IPv6 header
1741  offset -= sizeof(Ipv6Header);
1742  length += sizeof(Ipv6Header);
1743 
1744  //Point to the IPv6 header
1745  packet = netBufferAt(buffer, offset);
1746  //Properly set the Next Header field
1747  packet->nextHeader = IPV6_FRAGMENT_HEADER;
1748  }
1749  else
1750  {
1751  //Is there enough space for the IPv6 header?
1752  if(offset < sizeof(Ipv6Header))
1753  return ERROR_INVALID_PARAMETER;
1754 
1755  //Make room for the IPv6 header
1756  offset -= sizeof(Ipv6Header);
1757  length += sizeof(Ipv6Header);
1758 
1759  //Point to the IPv6 header
1760  packet = netBufferAt(buffer, offset);
1761  //Properly set the Next Header field
1762  packet->nextHeader = pseudoHeader->nextHeader;
1763  }
1764 
1765  //Format IPv6 header
1766  packet->version = IPV6_VERSION;
1767  packet->trafficClassH = 0;
1768  packet->trafficClassL = 0;
1769  packet->flowLabelH = 0;
1770  packet->flowLabelL = 0;
1771  packet->payloadLen = htons(length - sizeof(Ipv6Header));
1772  packet->hopLimit = ancillary->ttl;
1773  packet->srcAddr = pseudoHeader->srcAddr;
1774  packet->destAddr = pseudoHeader->destAddr;
1775 
1776  //Check whether the Hop Limit value is zero
1777  if(packet->hopLimit == 0)
1778  {
1779  //Use default Hop Limit value
1780  packet->hopLimit = interface->ipv6Context.curHopLimit;
1781  }
1782 
1783 #if (IP_DIFF_SERV_SUPPORT == ENABLED)
1784  //Set DSCP field
1785  packet->trafficClassH = (ancillary->dscp >> 2) & 0x0F;
1786  packet->trafficClassL = (ancillary->dscp << 2) & 0x0C;
1787 #endif
1788 
1789  //Ensure the source address is valid
1790  error = ipv6CheckSourceAddr(interface, &pseudoHeader->srcAddr);
1791  //Invalid source address?
1792  if(error)
1793  return error;
1794 
1795  //Check destination address
1796  if(ipv6CompAddr(&pseudoHeader->destAddr, &IPV6_UNSPECIFIED_ADDR))
1797  {
1798  //The unspecified address must not appear on the public Internet
1799  error = ERROR_INVALID_ADDRESS;
1800  }
1801  else if(ipv6IsLocalHostAddr(&pseudoHeader->destAddr))
1802  {
1803 #if (NET_LOOPBACK_IF_SUPPORT == ENABLED)
1804  uint_t i;
1805 
1806  //Initialize status code
1807  error = ERROR_NO_ROUTE;
1808 
1809  //Loop through network interfaces
1810  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1811  {
1812  //Point to the current interface
1813  interface = &netInterface[i];
1814 
1815  //Loopback interface?
1816  if(interface->nicDriver != NULL &&
1817  interface->nicDriver->type == NIC_TYPE_LOOPBACK)
1818  {
1819  //Forward the packet to the loopback interface
1820  error = nicSendPacket(interface, buffer, offset, ancillary);
1821  break;
1822  }
1823  }
1824 #else
1825  //The loopback address must not appear on the public Internet
1826  error = ERROR_NO_ROUTE;
1827 #endif
1828  }
1829  else
1830  {
1831 #if (ETH_SUPPORT == ENABLED)
1832  //Point to the physical interface
1833  physicalInterface = nicGetPhysicalInterface(interface);
1834 
1835  //Ethernet interface?
1836  if(physicalInterface->nicDriver != NULL &&
1837  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
1838  {
1840  NdpDestCacheEntry *entry;
1841 
1842  //When the sending node has a packet to send, it first examines
1843  //the Destination Cache
1844  entry = ndpFindDestCacheEntry(interface, &pseudoHeader->destAddr);
1845 
1846  //Check whether a matching entry exists
1847  if(entry != NULL)
1848  {
1849  //Retrieve the address of the next-hop
1850  destIpAddr = entry->nextHop;
1851  //Update timestamp
1852  entry->timestamp = osGetSystemTime();
1853  //No error to report
1854  error = NO_ERROR;
1855  }
1856  else
1857  {
1858  //Perform next-hop determination
1859  error = ndpSelectNextHop(interface, &pseudoHeader->destAddr, NULL,
1860  &destIpAddr, ancillary->dontRoute);
1861 
1862  //Check status code
1863  if(error == NO_ERROR)
1864  {
1865  //Create a new Destination Cache entry
1866  entry = ndpCreateDestCacheEntry(interface);
1867 
1868  //Destination cache entry successfully created?
1869  if(entry != NULL)
1870  {
1871  //Destination address
1872  entry->destAddr = pseudoHeader->destAddr;
1873  //Address of the next hop
1874  entry->nextHop = destIpAddr;
1875 
1876  //Initially, the PMTU value for a path is assumed to be the
1877  //MTU of the first-hop link
1878  entry->pathMtu = interface->ipv6Context.linkMtu;
1879 
1880  //Set timestamp
1881  entry->timestamp = osGetSystemTime();
1882  }
1883  }
1884  else if(error == ERROR_NO_ROUTE)
1885  {
1886  //Number of IP datagrams discarded because no route could be found
1887  //to transmit them to their destination
1888  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsOutNoRoutes, 1);
1889  }
1890  }
1891 
1892  //Successful next-hop determination?
1893  if(error == NO_ERROR)
1894  {
1895  //Perform address resolution
1896  if(!macCompAddr(&ancillary->destMacAddr, &MAC_UNSPECIFIED_ADDR))
1897  {
1898  //The destination address is already resolved
1899  error = NO_ERROR;
1900  }
1901  else if(ipv6IsMulticastAddr(&destIpAddr))
1902  {
1903  //Map IPv6 multicast address to MAC-layer multicast address
1905  &ancillary->destMacAddr);
1906  }
1907  else
1908  {
1909  //Resolve host address using Neighbor Discovery protocol
1910  error = ndpResolve(interface, &destIpAddr, &ancillary->destMacAddr);
1911  }
1912 
1913  //Successful address resolution?
1914  if(error == NO_ERROR)
1915  {
1916  //Update IP statistics
1917  ipv6UpdateOutStats(interface, &destIpAddr, length);
1918 
1919  //Debug message
1920  TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
1921  //Dump IP header contents for debugging purpose
1922  ipv6DumpHeader(packet);
1923 
1924  //Send Ethernet frame
1925  error = ethSendFrame(interface, &ancillary->destMacAddr,
1926  ETH_TYPE_IPV6, buffer, offset, ancillary);
1927  }
1928  else if(error == ERROR_IN_PROGRESS)
1929  {
1930  //Debug message
1931  TRACE_INFO("Enqueuing IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
1932  //Dump IP header contents for debugging purpose
1933  ipv6DumpHeader(packet);
1934 
1935  //Enqueue packets waiting for address resolution
1936  error = ndpEnqueuePacket(NULL, interface, &destIpAddr, buffer,
1937  offset, ancillary);
1938  }
1939  else
1940  {
1941  //Debug message
1942  TRACE_WARNING("Cannot map IPv6 address to Ethernet address!\r\n");
1943  }
1944  }
1945  }
1946  else
1947 #endif
1948 #if (PPP_SUPPORT == ENABLED)
1949  //PPP interface?
1950  if(interface->nicDriver != NULL &&
1951  interface->nicDriver->type == NIC_TYPE_PPP)
1952  {
1953  //Update IP statistics
1954  ipv6UpdateOutStats(interface, &pseudoHeader->destAddr, length);
1955 
1956  //Debug message
1957  TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
1958  //Dump IP header contents for debugging purpose
1959  ipv6DumpHeader(packet);
1960 
1961  //Send PPP frame
1962  error = pppSendFrame(interface, buffer, offset, PPP_PROTOCOL_IPV6);
1963  }
1964  else
1965 #endif
1966  //6LoWPAN interface?
1967  if(interface->nicDriver != NULL &&
1968  interface->nicDriver->type == NIC_TYPE_6LOWPAN)
1969  {
1970  //Update IP statistics
1971  ipv6UpdateOutStats(interface, &pseudoHeader->destAddr, length);
1972 
1973  //Debug message
1974  TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
1975  //Dump IP header contents for debugging purpose
1976  ipv6DumpHeader(packet);
1977 
1978  //Send the packet over the specified link
1979  error = nicSendPacket(interface, buffer, offset, ancillary);
1980  }
1981  else
1982  //Unknown interface type?
1983  {
1984  //Report an error
1985  error = ERROR_INVALID_INTERFACE;
1986  }
1987  }
1988 
1989  //Return status code
1990  return error;
1991 }
1992 
1993 
1994 /**
1995  * @brief Join an IPv6 multicast group
1996  * @param[in] interface Underlying network interface
1997  * @param[in] groupAddr IPv6 Multicast address to join
1998  * @return Error code
1999  **/
2000 
2002 {
2003  error_t error;
2004  uint_t i;
2005  Ipv6FilterEntry *entry;
2006  Ipv6FilterEntry *firstFreeEntry;
2007 #if (ETH_SUPPORT == ENABLED)
2008  NetInterface *physicalInterface;
2009  MacAddr macAddr;
2010 #endif
2011 
2012  //The IPv6 address must be a valid multicast address
2014  return ERROR_INVALID_ADDRESS;
2015 
2016 #if (ETH_SUPPORT == ENABLED)
2017  //Point to the physical interface
2018  physicalInterface = nicGetPhysicalInterface(interface);
2019 #endif
2020 
2021  //Initialize error code
2022  error = NO_ERROR;
2023  //Keep track of the first free entry
2024  firstFreeEntry = NULL;
2025 
2026  //Go through the multicast filter table
2027  for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++)
2028  {
2029  //Point to the current entry
2030  entry = &interface->ipv6Context.multicastFilter[i];
2031 
2032  //Valid entry?
2033  if(entry->refCount > 0)
2034  {
2035  //Check whether the table already contains the specified IPv6 address
2036  if(ipv6CompAddr(&entry->addr, groupAddr))
2037  {
2038  //Increment the reference count
2039  entry->refCount++;
2040  //Successful processing
2041  return NO_ERROR;
2042  }
2043  }
2044  else
2045  {
2046  //Keep track of the first free entry
2047  if(firstFreeEntry == NULL)
2048  firstFreeEntry = entry;
2049  }
2050  }
2051 
2052  //Check whether the multicast filter table is full
2053  if(firstFreeEntry == NULL)
2054  {
2055  //A new entry cannot be added
2056  return ERROR_FAILURE;
2057  }
2058 
2059 #if (ETH_SUPPORT == ENABLED)
2060  //Map the IPv6 multicast address to a MAC-layer address
2062 
2063  //Add the corresponding address to the MAC filter table
2064  error = ethAcceptMacAddr(interface, &macAddr);
2065 
2066  //Check status code
2067  if(!error)
2068  {
2069  //Virtual interface?
2070  if(interface != physicalInterface)
2071  {
2072  //Configure the physical interface to accept the MAC address
2073  error = ethAcceptMacAddr(physicalInterface, &macAddr);
2074 
2075  //Any error to report?
2076  if(error)
2077  {
2078  //Clean up side effects
2079  ethDropMacAddr(interface, &macAddr);
2080  }
2081  }
2082  }
2083 #endif
2084 
2085  //MAC filter table successfully updated?
2086  if(!error)
2087  {
2088  //Now we can safely add a new entry to the table
2089  firstFreeEntry->addr = *groupAddr;
2090  //Initialize the reference count
2091  firstFreeEntry->refCount = 1;
2092 
2093 #if (MLD_SUPPORT == ENABLED)
2094  //Start listening to the multicast address
2095  mldStartListening(interface, firstFreeEntry);
2096 #endif
2097  }
2098 
2099  //Return status code
2100  return error;
2101 }
2102 
2103 
2104 /**
2105  * @brief Leave an IPv6 multicast group
2106  * @param[in] interface Underlying network interface
2107  * @param[in] groupAddr IPv6 multicast address to drop
2108  * @return Error code
2109  **/
2110 
2112 {
2113  uint_t i;
2114  Ipv6FilterEntry *entry;
2115 #if (ETH_SUPPORT == ENABLED)
2116  NetInterface *physicalInterface;
2117  MacAddr macAddr;
2118 #endif
2119 
2120  //The IPv6 address must be a valid multicast address
2122  return ERROR_INVALID_ADDRESS;
2123 
2124 #if (ETH_SUPPORT == ENABLED)
2125  //Point to the physical interface
2126  physicalInterface = nicGetPhysicalInterface(interface);
2127 #endif
2128 
2129  //Go through the multicast filter table
2130  for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++)
2131  {
2132  //Point to the current entry
2133  entry = &interface->ipv6Context.multicastFilter[i];
2134 
2135  //Valid entry?
2136  if(entry->refCount > 0)
2137  {
2138  //Specified IPv6 address found?
2139  if(ipv6CompAddr(&entry->addr, groupAddr))
2140  {
2141  //Decrement the reference count
2142  entry->refCount--;
2143 
2144  //Remove the entry if the reference count drops to zero
2145  if(entry->refCount == 0)
2146  {
2147 #if (MLD_SUPPORT == ENABLED)
2148  //Stop listening to the multicast address
2149  mldStopListening(interface, entry);
2150 #endif
2151 #if (ETH_SUPPORT == ENABLED)
2152  //Map the IPv6 multicast address to a MAC-layer address
2154  //Drop the corresponding address from the MAC filter table
2155  ethDropMacAddr(interface, &macAddr);
2156 
2157  //Virtual interface?
2158  if(interface != physicalInterface)
2159  {
2160  //Drop the corresponding address from the MAC filter table of
2161  //the physical interface
2162  ethDropMacAddr(physicalInterface, &macAddr);
2163  }
2164 #endif
2165  //Remove the multicast address from the list
2166  entry->addr = IPV6_UNSPECIFIED_ADDR;
2167  }
2168 
2169  //Successful processing
2170  return NO_ERROR;
2171  }
2172  }
2173  }
2174 
2175  //The specified IPv6 address does not exist
2176  return ERROR_ADDRESS_NOT_FOUND;
2177 }
2178 
2179 
2180 /**
2181  * @brief Convert a string representation of an IPv6 address to a binary IPv6 address
2182  * @param[in] str NULL-terminated string representing the IPv6 address
2183  * @param[out] ipAddr Binary representation of the IPv6 address
2184  * @return Error code
2185  **/
2186 
2188 {
2189  error_t error;
2190  int_t i = 0;
2191  int_t j = -1;
2192  int_t k = 0;
2193  int32_t value = -1;
2194 
2195  //Parse input string
2196  while(1)
2197  {
2198  //Hexadecimal digit found?
2199  if(isxdigit((uint8_t) *str))
2200  {
2201  //First digit to be decoded?
2202  if(value < 0)
2203  value = 0;
2204 
2205  //Update the value of the current 16-bit word
2206  if(osIsdigit(*str))
2207  {
2208  value = (value * 16) + (*str - '0');
2209  }
2210  else if(osIsupper(*str))
2211  {
2212  value = (value * 16) + (*str - 'A' + 10);
2213  }
2214  else
2215  {
2216  value = (value * 16) + (*str - 'a' + 10);
2217  }
2218 
2219  //Check resulting value
2220  if(value > 0xFFFF)
2221  {
2222  //The conversion failed
2223  error = ERROR_INVALID_SYNTAX;
2224  break;
2225  }
2226  }
2227  //"::" symbol found?
2228  else if(!osStrncmp(str, "::", 2))
2229  {
2230  //The "::" can only appear once in an IPv6 address
2231  if(j >= 0)
2232  {
2233  //The conversion failed
2234  error = ERROR_INVALID_SYNTAX;
2235  break;
2236  }
2237 
2238  //The "::" symbol is preceded by a number?
2239  if(value >= 0)
2240  {
2241  //Save the current 16-bit word
2242  ipAddr->w[i++] = htons(value);
2243  //Prepare to decode the next 16-bit word
2244  value = -1;
2245  }
2246 
2247  //Save the position of the "::" symbol
2248  j = i;
2249  //Point to the next character
2250  str++;
2251  }
2252  //":" symbol found?
2253  else if(*str == ':' && i < 8)
2254  {
2255  //Each ":" must be preceded by a valid number
2256  if(value < 0)
2257  {
2258  //The conversion failed
2259  error = ERROR_INVALID_SYNTAX;
2260  break;
2261  }
2262 
2263  //Save the current 16-bit word
2264  ipAddr->w[i++] = htons(value);
2265  //Prepare to decode the next 16-bit word
2266  value = -1;
2267  }
2268  //End of string detected?
2269  else if(*str == '\0' && i == 7 && j < 0)
2270  {
2271  //The NULL character must be preceded by a valid number
2272  if(value < 0)
2273  {
2274  //The conversion failed
2275  error = ERROR_INVALID_SYNTAX;
2276  }
2277  else
2278  {
2279  //Save the last 16-bit word of the IPv6 address
2280  ipAddr->w[i] = htons(value);
2281  //The conversion succeeded
2282  error = NO_ERROR;
2283  }
2284 
2285  //We are done
2286  break;
2287  }
2288  else if(*str == '\0' && i < 7 && j >= 0)
2289  {
2290  //Save the last 16-bit word of the IPv6 address
2291  if(value >= 0)
2292  ipAddr->w[i++] = htons(value);
2293 
2294  //Move the part of the address that follows the "::" symbol
2295  for(k = 0; k < (i - j); k++)
2296  ipAddr->w[7 - k] = ipAddr->w[i - 1 - k];
2297  //A sequence of zeroes can now be written in place of "::"
2298  for(k = 0; k < (8 - i); k++)
2299  ipAddr->w[j + k] = 0;
2300 
2301  //The conversion succeeded
2302  error = NO_ERROR;
2303  break;
2304  }
2305  //Invalid character...
2306  else
2307  {
2308  //The conversion failed
2309  error = ERROR_INVALID_SYNTAX;
2310  break;
2311  }
2312 
2313  //Point to the next character
2314  str++;
2315  }
2316 
2317  //Return status code
2318  return error;
2319 }
2320 
2321 
2322 /**
2323  * @brief Convert a binary IPv6 address to a string representation
2324  *
2325  * Call ipv6AddrToString() to convert an IPv6 address to a text representation. The
2326  * implementation of ipv6AddrToString() function follows RFC 5952 recommendations
2327  *
2328  * @param[in] ipAddr Binary representation of the IPv6 address
2329  * @param[out] str NULL-terminated string representing the IPv6 address
2330  * @return Pointer to the formatted string
2331  **/
2332 
2334 {
2335  static char_t buffer[40];
2336  uint_t i;
2337  uint_t j;
2338  char_t *p;
2339 
2340  //Best run of zeroes
2341  uint_t zeroRunStart = 0;
2342  uint_t zeroRunEnd = 0;
2343 
2344  //If the NULL pointer is given as parameter, then the internal buffer is used
2345  if(str == NULL)
2346  str = buffer;
2347 
2348  //Find the longest run of zeros for "::" short-handing
2349  for(i = 0; i < 8; i++)
2350  {
2351  //Compute the length of the current sequence of zeroes
2352  for(j = i; j < 8 && !ipAddr->w[j]; j++);
2353 
2354  //Keep track of the longest one
2355  if((j - i) > 1 && (j - i) > (zeroRunEnd - zeroRunStart))
2356  {
2357  //The symbol "::" should not be used to shorten just one zero field
2358  zeroRunStart = i;
2359  zeroRunEnd = j;
2360  }
2361  }
2362 
2363  //Format IPv6 address
2364  for(p = str, i = 0; i < 8; i++)
2365  {
2366  //Are we inside the best run of zeroes?
2367  if(i >= zeroRunStart && i < zeroRunEnd)
2368  {
2369  //Append a separator
2370  *(p++) = ':';
2371  //Skip the sequence of zeroes
2372  i = zeroRunEnd - 1;
2373  }
2374  else
2375  {
2376  //Add a separator between each 16-bit word
2377  if(i > 0)
2378  *(p++) = ':';
2379 
2380  //Convert the current 16-bit word to string
2381  p += osSprintf(p, "%" PRIx16, ntohs(ipAddr->w[i]));
2382  }
2383  }
2384 
2385  //A trailing run of zeroes has been found?
2386  if(zeroRunEnd == 8)
2387  *(p++) = ':';
2388 
2389  //Properly terminate the string
2390  *p = '\0';
2391 
2392  //Return a pointer to the formatted string
2393  return str;
2394 }
2395 
2396 
2397 /**
2398  * @brief Dump IPv6 header for debugging purpose
2399  * @param[in] ipHeader IPv6 header
2400  **/
2401 
2402 void ipv6DumpHeader(const Ipv6Header *ipHeader)
2403 {
2404  //Dump IPv6 header contents
2405  TRACE_DEBUG(" Version = %" PRIu8 "\r\n", ipHeader->version);
2406  TRACE_DEBUG(" Traffic Class = %u\r\n", (ipHeader->trafficClassH << 4) | ipHeader->trafficClassL);
2407  TRACE_DEBUG(" Flow Label = 0x%05X\r\n", (ipHeader->flowLabelH << 16) | ntohs(ipHeader->flowLabelL));
2408  TRACE_DEBUG(" Payload Length = %" PRIu16 "\r\n", ntohs(ipHeader->payloadLen));
2409  TRACE_DEBUG(" Next Header = %" PRIu8 "\r\n", ipHeader->nextHeader);
2410  TRACE_DEBUG(" Hop Limit = %" PRIu8 "\r\n", ipHeader->hopLimit);
2411  TRACE_DEBUG(" Src Addr = %s\r\n", ipv6AddrToString(&ipHeader->srcAddr, NULL));
2412  TRACE_DEBUG(" Dest Addr = %s\r\n", ipv6AddrToString(&ipHeader->destAddr, NULL));
2413 }
2414 
2415 #endif
@ IPV6_ADDR_STATE_TENTATIVE
An address whose uniqueness on a link is being verified.
Definition: ipv6.h:168
error_t ethAcceptMacAddr(NetInterface *interface, const MacAddr *macAddr)
Add a unicast/multicast address to the MAC filter table.
Definition: ethernet.c:597
uint8_t length
Definition: coap_common.h:193
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2333
#define htons(value)
Definition: cpu_endian.h:413
IPv6 (Internet Protocol Version 6)
@ IPV6_ESP_HEADER
Definition: ipv6.h:185
@ ICMPV6_TYPE_DEST_UNREACHABLE
Definition: icmpv6.h:53
bool_t enableMulticastEchoReq
Support for multicast ICMPv6 Echo Request messages.
Definition: ipv6.h:463
systime_t lifetime
Router lifetime.
Definition: ipv6.h:433
Ipv6FilterEntry multicastFilter[IPV6_MULTICAST_FILTER_SIZE]
Multicast filter table.
Definition: ipv6.h:469
Ipv6PseudoHeader ipv6Data
Definition: ip.h:106
@ ERROR_OUT_OF_RANGE
Definition: error.h:136
error_t ipv6SetPrefix(NetInterface *interface, uint_t index, const Ipv6Addr *prefix, uint_t length)
Configure IPv6 prefix.
Definition: ipv6.c:554
uint32_t identification
IPv6 fragment identification field.
Definition: ipv6.h:471
void ipv6FlushPrefixList(NetInterface *interface)
Flush the Prefix List.
Definition: ipv6_misc.c:671
Helper functions for NDP (Neighbor Discovery Protocol)
signed int int_t
Definition: compiler_port.h:44
#define netMutex
Definition: net_legacy.h:266
error_t ipv6SendPacket(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, uint32_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 packet.
Definition: ipv6.c:1705
#define IPV6_ADDR(a, b, c, d, e, f, g, h)
Definition: ipv6.h:112
void ipv6UpdateOutStats(NetInterface *interface, const Ipv6Addr *destIpAddr, size_t length)
Update IPv6 output statistics.
Definition: ipv6_misc.c:1502
error_t ipv6SetAnycastAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr)
Assign anycast address.
Definition: ipv6.c:441
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
@ ERROR_INVALID_INTERFACE
Invalid interface.
Definition: error.h:53
uint8_t curHopLimit
Default value for the Hop Limit field.
Definition: ipv6.h:462
systime_t preferredLifetime
Preferred lifetime.
Definition: ipv6.h:420
uint8_t p
Definition: ndp.h:298
error_t nicSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet to the network controller.
Definition: nic.c:280
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
const Ipv6Addr IPV6_SOLICITED_NODE_ADDR_PREFIX
Definition: ipv6.c:86
error_t ipv6ParseDestOptHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
Parse Destination Options header.
Definition: ipv6.c:1336
#define TRUE
Definition: os_port.h:50
NdpDestCacheEntry * ndpFindDestCacheEntry(NetInterface *interface, const Ipv6Addr *destAddr)
Search the Destination Cache for a given destination address.
Definition: ndp_cache.c:446
void tcpProcessSegment(NetInterface *interface, IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, NetRxAncillary *ancillary)
Incoming TCP segment processing.
Definition: tcp_fsm.c:75
Ipv6Addr addr
IPv6 address.
Definition: ipv6.h:397
error_t ipv6GetDefaultRouter(NetInterface *interface, uint_t index, Ipv6Addr *addr)
Retrieve default router.
Definition: ipv6.c:730
@ ERROR_INVALID_HEADER
Definition: error.h:86
#define Ipv6Header
Definition: ipv6.h:36
void ipv6FlushAddrList(NetInterface *interface)
Flush the list of IPv6 addresses.
Definition: ipv6_misc.c:640
error_t ethSendFrame(NetInterface *interface, const MacAddr *destAddr, uint16_t type, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an Ethernet frame.
Definition: ethernet.c:402
@ ICMPV6_CODE_INVALID_HEADER_FIELD
Definition: icmpv6.h:101
bool_t autonomousFlag
Autonomous flag.
Definition: ipv6.h:418
systime_t validLifetime
Valid lifetime.
Definition: ipv6.h:419
size_t ipv6GetPathMtu(NetInterface *interface, const Ipv6Addr *destAddr)
Retrieve the PMTU for the specified path.
Definition: ipv6_pmtu.c:54
#define NET_INTERFACE_COUNT
Definition: net.h:113
bool_t ipv6IsTentativeAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is a tentative address.
Definition: ipv6_misc.c:1109
@ IPV6_OPTION_TYPE_PAD1
Definition: ipv6.h:213
IPv6 routing.
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:121
@ IPV6_ICMPV6_HEADER
Definition: ipv6.h:187
Ipv6Addr prefix
IPv6 prefix information.
Definition: ipv6.h:415
void ipv6ProcessPacket(NetInterface *interface, NetBuffer *ipPacket, size_t ipPacketOffset, NetRxAncillary *ancillary)
Incoming IPv6 packet processing.
Definition: ipv6.c:939
Ipv6Addr destAddr
Destination IPv6 address.
Definition: ndp.h:564
@ IPV6_ACTION_SEND_ICMP_ERROR_ALL
Definition: ipv6.h:227
@ IPV6_ACTION_DISCARD_PACKET
Definition: ipv6.h:226
Ipv6Addr addr
Router address.
Definition: ipv6.h:432
error_t ipv6Init(NetInterface *interface)
IPv6 related initialization.
Definition: ipv6.c:96
Ipv6Addr prefix
#define NDP_INFINITE_LIFETIME
Definition: ndp.h:202
size_t length
Definition: ip.h:99
Helper functions for DHCPv6 client.
error_t ipv6SetGlobalAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr)
Assign global address.
Definition: ipv6.c:324
@ ICMPV6_CODE_UNKNOWN_NEXT_HEADER
Definition: icmpv6.h:102
error_t udpProcessDatagram(NetInterface *interface, IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, NetRxAncillary *ancillary)
Incoming UDP datagram processing.
Definition: udp.c:124
__start_packed struct @6 Ipv6Option
IPv6 option.
#define IPV6_DEFAULT_HOP_LIMIT
Definition: ipv6.h:59
size_t pathMtu
Path MTU.
Definition: ndp.h:566
error_t ipv6GetGlobalAddr(NetInterface *interface, uint_t index, Ipv6Addr *addr)
Retrieve global address.
Definition: ipv6.c:363
IPv6 context.
Definition: ipv6.h:459
@ IPV6_ADDR_STATE_INVALID
An address that is not assigned to any interface.
Definition: ipv6.h:167
error_t ethDropMacAddr(NetInterface *interface, const MacAddr *macAddr)
Remove a unicast/multicast address from the MAC filter table.
Definition: ethernet.c:667
void icmpv6ProcessMessage(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Incoming ICMPv6 message processing.
Definition: icmpv6.c:95
uint8_t ipPacket[]
Definition: ndp.h:429
IP pseudo header.
Definition: ip.h:98
@ NIC_TYPE_LOOPBACK
Loopback interface.
Definition: nic.h:86
error_t ipv6ParseAhHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
Parse AH header.
Definition: ipv6.c:1470
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:133
@ ERROR_IN_PROGRESS
Definition: error.h:212
error_t icmpv6SendErrorMessage(NetInterface *interface, uint8_t type, uint8_t code, uint32_t parameter, const NetBuffer *ipPacket, size_t ipPacketOffset)
Send an ICMPv6 Error message.
Definition: icmpv6.c:470
void ndpLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ndp.c:375
#define IPV6_VERSION
Definition: ipv6.h:107
error_t ipv6GetAnycastAddr(NetInterface *interface, uint_t index, Ipv6Addr *addr)
Retrieve anycast address.
Definition: ipv6.c:519
#define FALSE
Definition: os_port.h:46
__start_packed struct @0 MacAddr
MAC address.
ICMPv6 (Internet Control Message Protocol Version 6)
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define htonl(value)
Definition: cpu_endian.h:414
error_t mldStartListening(NetInterface *interface, Ipv6FilterEntry *entry)
Start listening to the address on the interface.
Definition: mld.c:79
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:84
Ipv6AddrState
IPv6 address state.
Definition: ipv6.h:166
bool_t ipv6IsLocalHostAddr(const Ipv6Addr *ipAddr)
Check whether the specified IPv6 is assigned to the host.
Definition: ipv6_misc.c:1145
char_t type
error_t
Error codes.
Definition: error.h:43
#define netInterface
Definition: net_legacy.h:270
#define osSprintf(dest,...)
Definition: os_port.h:221
__start_packed struct @1 Ipv6HopByHopOptHeader
IPv6 Hop-by-Hop Options header.
#define IP_MIB_INC_COUNTER64(name, value)
Definition: ip_mib_module.h:47
void dhcpv6ClientLinkChangeEvent(Dhcpv6ClientContext *context)
Callback function for link change event.
#define Ipv6PseudoHeader
Definition: ipv6.h:42
@ IPV6_ACTION_SKIP_OPTION
Definition: ipv6.h:225
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ndp.h:567
error_t ipv6GetLinkLocalAddr(NetInterface *interface, Ipv6Addr *addr)
Retrieve link-local address.
Definition: ipv6.c:256
TCP finite state machine.
Prefix list entry.
Definition: ipv6.h:414
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:413
void ipv6DumpHeader(const Ipv6Header *ipHeader)
Dump IPv6 header for debugging purpose.
Definition: ipv6.c:2402
uint8_t value[]
Definition: tcp.h:367
@ IPV6_UDP_HEADER
Definition: ipv6.h:182
@ ERROR_INVALID_ADDRESS
Definition: error.h:102
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
error_t ipv6ForwardPacket(NetInterface *srcInterface, NetBuffer *ipPacket, size_t ipPacketOffset)
Forward an IPv6 packet.
Definition: ipv6_routing.c:267
uint8_t preference
Preference value.
Definition: ipv6.h:434
const Ipv6Addr IPV6_LINK_LOCAL_ALL_NODES_ADDR
Definition: ipv6.c:74
bool_t permanent
Permanently assigned address.
Definition: ipv6.h:402
error_t ipv6SetLinkLocalAddr(NetInterface *interface, const Ipv6Addr *addr)
Assign link-local address.
Definition: ipv6.c:218
__start_packed struct @2 Ipv6DestOptHeader
IPv6 Destination Options header.
@ ICMPV6_CODE_UNKNOWN_IPV6_OPTION
Definition: icmpv6.h:103
Ipv6Addr dnsServerList[IPV6_DNS_SERVER_LIST_SIZE]
DNS servers.
Definition: ipv6.h:468
#define NetRxAncillary
Definition: net_misc.h:40
NdpDestCacheEntry * ndpCreateDestCacheEntry(NetInterface *interface)
Create a new entry in the Destination Cache.
Definition: ndp_cache.c:395
Ipv6AddrEntry addrList[IPV6_ADDR_LIST_SIZE]
IPv6 unicast address list.
Definition: ipv6.h:464
#define NetInterface
Definition: net.h:36
error_t ipv6CheckDestAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Destination IPv6 address filtering.
Definition: ipv6_misc.c:773
void ipv6FlushFragQueue(NetInterface *interface)
Flush IPv6 reassembly queue.
Definition: ipv6_frag.c:719
error_t ipv6FragmentDatagram(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *payload, size_t payloadOffset, size_t pathMtu, NetTxAncillary *ancillary)
Fragment IPv6 datagram into smaller packets.
Definition: ipv6_frag.c:62
@ ERROR_INVALID_LENGTH
Definition: error.h:110
uint8_t options[]
Definition: tcp.h:355
Helper functions for IPv6.
@ IPV6_HOP_BY_HOP_OPT_HEADER
Definition: ipv6.h:180
#define NetTxAncillary
Definition: net_misc.h:36
#define IPV6_MULTICAST_FILTER_SIZE
Definition: ipv6.h:101
uint8_t fragOffset[3]
Definition: dtls_misc.h:190
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:66
void mldLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: mld.c:198
error_t ipv6LeaveMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Leave an IPv6 multicast group.
Definition: ipv6.c:2111
@ ERROR_INVALID_TYPE
Definition: error.h:114
error_t ipv6JoinMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Join an IPv6 multicast group.
Definition: ipv6.c:2001
const Ipv6Addr IPV6_LOOPBACK_ADDR
Definition: ipv6.c:70
#define IPV6_DNS_SERVER_LIST_SIZE
Definition: ipv6.h:94
#define osIsdigit(c)
Definition: os_port.h:263
uint_t refCount
Reference count for the current entry.
Definition: ipv6.h:447
@ PPP_PROTOCOL_IPV6
Internet Protocol version 6.
Definition: ppp.h:200
#define TRACE_INFO(...)
Definition: debug.h:95
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
@ ERROR_MESSAGE_TOO_LONG
Definition: error.h:135
Neighbor and destination cache management.
uint32_t mtu
Definition: icmpv6.h:173
error_t ndpSelectNextHop(NetInterface *interface, const Ipv6Addr *destAddr, const Ipv6Addr *unreachableNextHop, Ipv6Addr *nextHop, bool_t dontRoute)
Next-hop determination.
Definition: ndp_misc.c:505
error_t ipv6SetDnsServer(NetInterface *interface, uint_t index, const Ipv6Addr *addr)
Configure DNS server.
Definition: ipv6.c:781
Ipv6AddrState ipv6GetGlobalAddrState(NetInterface *interface, uint_t index)
Get the state of the specified global address.
Definition: ipv6.c:414
error_t ipv6GetPrefix(NetInterface *interface, uint_t index, Ipv6Addr *prefix, uint_t *length)
Retrieve IPv6 prefix.
Definition: ipv6.c:618
Ipv6Addr addr
Multicast address.
Definition: ipv6.h:446
@ ERROR_NO_ROUTE
Definition: error.h:218
Path MTU Discovery for IPv6.
NDP (Neighbor Discovery Protocol)
TCP/IP raw sockets.
void ipv6FlushDefaultRouterList(NetInterface *interface)
Flush the Default Router List.
Definition: ipv6_misc.c:703
bool_t onLinkFlag
On-link flag.
Definition: ipv6.h:417
#define ntohs(value)
Definition: cpu_endian.h:421
@ NIC_TYPE_PPP
PPP interface.
Definition: nic.h:84
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
Ipv6PrefixEntry prefixList[IPV6_PREFIX_LIST_SIZE]
Prefix list.
Definition: ipv6.h:466
IPv6 fragmentation and reassembly.
bool_t permanent
Permanently assigned prefix.
Definition: ipv6.h:421
#define TRACE_WARNING(...)
Definition: debug.h:85
#define TRACE_DEBUG(...)
Definition: debug.h:107
char char_t
Definition: compiler_port.h:43
uint8_t prefixLen
IPv6 prefix length.
Definition: ipv6.h:416
error_t mldStopListening(NetInterface *interface, Ipv6FilterEntry *entry)
Stop listening to the address on the interface.
Definition: mld.c:128
error_t rawSocketProcessIpPacket(NetInterface *interface, IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, NetRxAncillary *ancillary)
Process incoming IP packet.
Definition: raw_socket.c:68
#define IPV6_ANYCAST_ADDR_LIST_SIZE
Definition: ipv6.h:73
Default router list entry.
Definition: ipv6.h:431
#define IPV6_DEFAULT_MTU
Definition: ipv6.h:109
IPv6 address entry.
Definition: ipv6.h:396
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1022
error_t ipv6ParseEspHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
Parse ESP header.
Definition: ipv6.c:1490
IPv4 and IPv6 common routines.
@ IPV6_TCP_HEADER
Definition: ipv6.h:181
uint8_t n
#define IPV6_ROUTER_LIST_SIZE
Definition: ipv6.h:87
const Ipv6Addr IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR
Definition: ipv6.c:78
IP MIB module.
error_t ndpEnqueuePacket(NetInterface *srcInterface, NetInterface *destInterface, const Ipv6Addr *ipAddr, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Enqueue an IPv6 packet waiting for address resolution.
Definition: ndp.c:196
__start_packed struct @3 Ipv6RoutingHeader
IPv6 Type 0 Routing header.
@ ETH_TYPE_IPV6
Definition: ethernet.h:168
#define IPV6_ADDR_LIST_SIZE
Definition: ipv6.h:66
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
@ IPV6_NO_NEXT_HEADER
Definition: ipv6.h:188
Ipv4Addr groupAddr
Definition: igmp_common.h:169
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
Ipv6FragDesc fragQueue[IPV6_MAX_FRAG_DATAGRAMS]
IPv6 fragment reassembly queue.
Definition: ipv6.h:472
Destination cache entry.
Definition: ndp.h:563
Ipv6AddrState ipv6GetLinkLocalAddrState(NetInterface *interface)
Get the state of the link-local address.
Definition: ipv6.c:297
@ IPV6_OPTION_TYPE_MASK
Definition: ipv6.h:212
error_t ipv6ParseRoutingHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
Parse Routing header.
Definition: ipv6.c:1399
UDP (User Datagram Protocol)
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:320
error_t ipv6SetMtu(NetInterface *interface, size_t mtu)
Change the MTU of a network interface.
Definition: ipv6.c:148
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
@ ICMPV6_CODE_PORT_UNREACHABLE
Definition: icmpv6.h:81
error_t ipv6ComputeSolicitedNodeAddr(const Ipv6Addr *ipAddr, Ipv6Addr *solicitedNodeAddr)
Form a solicited-node address from an IPv6 address.
Definition: ipv6_misc.c:1374
@ ERROR_ADDRESS_NOT_FOUND
Definition: error.h:256
error_t ipv6ParseHopByHopOptHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
Parse Hop-by-Hop Options header.
Definition: ipv6.c:1258
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
#define Ipv6FragmentHeader
Definition: ipv6.h:39
#define osStrncmp(s1, s2, length)
Definition: os_port.h:167
Helper functions for SLAAC.
@ ERROR_INVALID_OPTION
Definition: error.h:97
error_t ndpResolve(NetInterface *interface, const Ipv6Addr *ipAddr, MacAddr *macAddr)
Address resolution using Neighbor Discovery protocol.
Definition: ndp.c:101
error_t ipv6SendDatagram(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 datagram.
Definition: ipv6.c:1636
void ndpRouterAdvLinkChangeEvent(NdpRouterAdvContext *context)
Callback function for link change event.
error_t ipv6StringToAddr(const char_t *str, Ipv6Addr *ipAddr)
Convert a string representation of an IPv6 address to a binary IPv6 address.
Definition: ipv6.c:2187
Ipv4Addr addr
Definition: nbns_common.h:121
error_t ipv6SetDefaultRouter(NetInterface *interface, uint_t index, const Ipv6Addr *addr)
Configure default router.
Definition: ipv6.c:673
bool_t isRouter
A flag indicating whether routing is enabled on this interface.
Definition: ipv6.h:461
void ipv6ParseFragmentHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t fragHeaderOffset, size_t nextHeaderOffset, NetRxAncillary *ancillary)
Parse Fragment header and reassemble original datagram.
Definition: ipv6_frag.c:179
@ IPV6_OPTION_TYPE_PADN
Definition: ipv6.h:214
@ IPV6_ADDR_STATE_PREFERRED
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:169
error_t ipv6GetDnsServer(NetInterface *interface, uint_t index, Ipv6Addr *addr)
Retrieve DNS server.
Definition: ipv6.c:815
bool_t permanent
Permanently assigned router.
Definition: ipv6.h:435
Ipv6AddrState state
IPv6 address state.
Definition: ipv6.h:398
#define IPV6_PREFIX_LIST_SIZE
Definition: ipv6.h:80
void ipv6LinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ipv6.c:847
@ ICMPV6_TYPE_PARAM_PROBLEM
Definition: icmpv6.h:56
#define PRIuSIZE
@ NIC_TYPE_6LOWPAN
6LoWPAN interface
Definition: nic.h:85
unsigned int uint_t
Definition: compiler_port.h:45
@ ERROR_PORT_UNREACHABLE
Definition: error.h:84
Helper functions for router advertisement service.
#define osMemset(p, value, length)
Definition: os_port.h:131
TCP/IP stack core.
@ IPV6_ROUTING_HEADER
Definition: ipv6.h:183
@ IPV6_ADDR_STATE_DEPRECATED
An address assigned to an interface whose use is discouraged.
Definition: ipv6.h:170
error_t ipv6CheckSourceAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Source IPv6 address filtering.
Definition: ipv6_misc.c:750
void slaacLinkChangeEvent(SlaacContext *context)
Callback function for link change event.
Definition: slaac_misc.c:54
const Ipv6Addr IPV6_LINK_LOCAL_ADDR_PREFIX
Definition: ipv6.c:82
error_t ipv6MapMulticastAddrToMac(const Ipv6Addr *ipAddr, MacAddr *macAddr)
Map an IPv6 multicast address to a MAC-layer multicast address.
Definition: ipv6_misc.c:1412
#define osIsupper(c)
Definition: os_port.h:257
__start_packed struct @0 Ipv6Addr
IPv6 network address.
size_t linkMtu
Maximum transmission unit.
Definition: ipv6.h:460
void ipv6UpdateInStats(NetInterface *interface, const Ipv6Addr *destIpAddr, size_t length)
Update IPv6 input statistics.
Definition: ipv6_misc.c:1474
uint8_t ipAddr[4]
Definition: mib_common.h:187
error_t ipv6ParseOptions(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t optionOffset, size_t optionLen)
Parse IPv6 options.
Definition: ipv6.c:1510
@ IPV6_DEST_OPT_HEADER
Definition: ipv6.h:189
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:55
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ IPV6_ACTION_SEND_ICMP_ERROR_UNI
Definition: ipv6.h:228
Ipv6Addr nextHop
IPv6 address of the next-hop neighbor.
Definition: ndp.h:565
#define INFINITE_DELAY
Definition: os_port.h:74
@ IPV6_AH_HEADER
Definition: ipv6.h:186
@ IPV6_ACTION_MASK
Definition: ipv6.h:224
@ IPV6_FRAGMENT_HEADER
Definition: ipv6.h:184
error_t ipv6GetMtu(NetInterface *interface, size_t *mtu)
Retrieve the MTU for the specified interface.
Definition: ipv6.c:193
IPv6 multicast filter entry.
Definition: ipv6.h:445
MLD (Multicast Listener Discovery for IPv6)
Ipv6RouterEntry routerList[IPV6_ROUTER_LIST_SIZE]
Default router list.
Definition: ipv6.h:467
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
systime_t osGetSystemTime(void)
Retrieve system time.
Ipv4Addr destIpAddr
Definition: ipcp.h:78