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