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