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-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @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.4.4
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  //Debug message
1279  TRACE_WARNING("Unrecognized Next Header type\r\n");
1280 
1281  //Packets addressed to the tentative address should be silently discarded
1282  if(!ipv6IsTentativeAddr(interface, &ipHeader->destAddr))
1283  {
1284  //Compute the offset of the unrecognized Next Header field within the packet
1285  size_t n = nextHeaderOffset - ipPacketOffset;
1286 
1287  //Send an ICMP Parameter Problem message
1289  ICMPV6_CODE_UNKNOWN_NEXT_HEADER, n, ipPacket, ipPacketOffset);
1290  }
1291  else
1292  {
1293  //Number of input datagrams discarded because the destination IP address
1294  //was not a valid address
1295  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsInAddrErrors, 1);
1296  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsInAddrErrors, 1);
1297  }
1298 
1299  //Discard incoming packet
1300  return;
1301  }
1302 
1303  //Any error while processing the current extension header?
1304  if(error)
1305  return;
1306  }
1307 }
1308 
1309 
1310 /**
1311  * @brief Parse Hop-by-Hop Options header
1312  * @param[in] interface Underlying network interface
1313  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1314  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1315  * @param[in,out] headerOffset Offset to the Hop-by-Hop Options header
1316  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1317  * @brief Error code
1318  **/
1319 
1321  const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset,
1322  size_t *nextHeaderOffset)
1323 {
1324  error_t error;
1325  size_t n;
1326  size_t length;
1327  size_t headerLen;
1328  Ipv6HopByHopOptHeader *header;
1329 
1330  //Remaining bytes to process in the IPv6 packet
1331  length = netBufferGetLength(ipPacket) - *headerOffset;
1332 
1333  //Make sure the extension header is valid
1334  if(length < sizeof(Ipv6HopByHopOptHeader))
1335  return ERROR_INVALID_HEADER;
1336 
1337  //Point to the Hop-by-Hop Options header
1338  header = netBufferAt(ipPacket, *headerOffset, 0);
1339  //Sanity check
1340  if(header == NULL)
1341  return ERROR_FAILURE;
1342 
1343  //Calculate the length of the entire header
1344  headerLen = (header->hdrExtLen * 8) + 8;
1345 
1346  //Check header length
1347  if(headerLen > length)
1348  return ERROR_INVALID_HEADER;
1349 
1350  //Debug message
1351  TRACE_DEBUG(" Hop-by-Hop Options header\r\n");
1352 
1353  //The Hop-by-Hop Options header, when present, must immediately follow
1354  //the IPv6 header
1355  if(*headerOffset != (ipPacketOffset + sizeof(Ipv6Header)))
1356  {
1357  //Compute the offset of the unrecognized Next Header field within the packet
1358  n = *nextHeaderOffset - ipPacketOffset;
1359 
1360  //Send an ICMP Parameter Problem message to the source of the packet
1362  ICMPV6_CODE_UNKNOWN_NEXT_HEADER, n, ipPacket, ipPacketOffset);
1363 
1364  //Discard incoming packet
1365  return ERROR_INVALID_HEADER;
1366  }
1367 
1368  //Compute the length of the Options field
1369  n = headerLen - sizeof(Ipv6HopByHopOptHeader);
1370 
1371  //Parse options
1372  error = ipv6ParseOptions(interface, ipPacket, ipPacketOffset,
1373  *headerOffset + sizeof(Ipv6HopByHopOptHeader), n);
1374 
1375  //Any error to report?
1376  if(error)
1377  return error;
1378 
1379  //Keep track of Next Header field
1380  *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header;
1381  //Point to the next extension header
1382  *headerOffset += headerLen;
1383 
1384  //Successful processing
1385  return NO_ERROR;
1386 }
1387 
1388 
1389 /**
1390  * @brief Parse Destination Options header
1391  * @param[in] interface Underlying network interface
1392  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1393  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1394  * @param[in,out] headerOffset Offset to the Destination Options header
1395  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1396  * @brief Error code
1397  **/
1398 
1400  const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset,
1401  size_t *nextHeaderOffset)
1402 {
1403  error_t error;
1404  size_t n;
1405  size_t length;
1406  size_t headerLen;
1407  Ipv6DestOptHeader *header;
1408 
1409  //Remaining bytes to process in the IPv6 packet
1410  length = netBufferGetLength(ipPacket) - *headerOffset;
1411 
1412  //Make sure the extension header is valid
1413  if(length < sizeof(Ipv6DestOptHeader))
1414  return ERROR_INVALID_HEADER;
1415 
1416  //Point to the Destination Options header
1417  header = netBufferAt(ipPacket, *headerOffset, 0);
1418  //Sanity check
1419  if(header == NULL)
1420  return ERROR_FAILURE;
1421 
1422  //Calculate the length of the entire header
1423  headerLen = (header->hdrExtLen * 8) + 8;
1424 
1425  //Check header length
1426  if(headerLen > length)
1427  return ERROR_INVALID_HEADER;
1428 
1429  //Debug message
1430  TRACE_DEBUG(" Destination Options header\r\n");
1431 
1432  //Compute the length of the Options field
1433  n = headerLen - sizeof(Ipv6DestOptHeader);
1434 
1435  //Parse options
1436  error = ipv6ParseOptions(interface, ipPacket, ipPacketOffset,
1437  *headerOffset + sizeof(Ipv6DestOptHeader), n);
1438 
1439  //Any error to report?
1440  if(error)
1441  return error;
1442 
1443  //Keep track of Next Header field
1444  *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header;
1445  //Point to the next extension header
1446  *headerOffset += headerLen;
1447 
1448  //Successful processing
1449  return NO_ERROR;
1450 }
1451 
1452 
1453 /**
1454  * @brief Parse Routing header
1455  * @param[in] interface Underlying network interface
1456  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1457  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1458  * @param[in,out] headerOffset Offset to the Routing header
1459  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1460  * @brief Error code
1461  **/
1462 
1464  const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset,
1465  size_t *nextHeaderOffset)
1466 {
1467  size_t n;
1468  size_t length;
1469  size_t headerLen;
1470  Ipv6RoutingHeader *header;
1471 
1472  //Remaining bytes to process in the IPv6 packet
1473  length = netBufferGetLength(ipPacket) - *headerOffset;
1474 
1475  //Make sure the extension header is valid
1476  if(length < sizeof(Ipv6RoutingHeader))
1477  return ERROR_INVALID_HEADER;
1478 
1479  //Point to the Routing header
1480  header = netBufferAt(ipPacket, *headerOffset, 0);
1481  //Sanity check
1482  if(header == NULL)
1483  return ERROR_FAILURE;
1484 
1485  //Calculate the length of the entire header
1486  headerLen = (header->hdrExtLen * 8) + 8;
1487 
1488  //Check header length
1489  if(headerLen > length)
1490  return ERROR_INVALID_HEADER;
1491 
1492  //Debug message
1493  TRACE_DEBUG(" Routing header\r\n");
1494 
1495  //If, while processing a received packet, a node encounters a Routing
1496  //header with an unrecognized Routing Type value, the required behavior
1497  //of the node depends on the value of the Segments Left field
1498  if(header->segmentsLeft != 0)
1499  {
1500  //Retrieve the offset of the Routing header within the packet
1501  n = *headerOffset - ipPacketOffset;
1502  //Compute the exact offset of the Routing Type field
1503  n += (uint8_t *) &header->routingType - (uint8_t *) header;
1504 
1505  //If Segments Left is non-zero, send an ICMP Parameter Problem,
1506  //Code 0, message to the packet's Source Address, pointing to
1507  //the unrecognized Routing Type
1509  ICMPV6_CODE_INVALID_HEADER_FIELD, n, ipPacket, ipPacketOffset);
1510 
1511  //The node must discard the packet
1512  return ERROR_INVALID_TYPE;
1513  }
1514 
1515  //Keep track of Next Header field
1516  *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header;
1517  //Point to the next extension header
1518  *headerOffset += headerLen;
1519 
1520  //Successful processing
1521  return NO_ERROR;
1522 }
1523 
1524 
1525 /**
1526  * @brief Parse AH header
1527  * @param[in] interface Underlying network interface
1528  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1529  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1530  * @param[in,out] headerOffset Offset to the Authentication header
1531  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1532  * @brief Error code
1533  **/
1534 
1536  size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
1537 {
1538  //Debug message
1539  TRACE_DEBUG(" AH header\r\n");
1540 
1541  //IPsec is not supported
1542  return ERROR_FAILURE;
1543 }
1544 
1545 
1546 /**
1547  * @brief Parse ESP header
1548  * @param[in] interface Underlying network interface
1549  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1550  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1551  * @param[in,out] headerOffset Offset to the Encapsulating Security Payload header
1552  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1553  * @brief Error code
1554  **/
1555 
1557  size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
1558 {
1559  //Debug message
1560  TRACE_DEBUG(" ESP header\r\n");
1561 
1562  //IPsec is not supported
1563  return ERROR_FAILURE;
1564 }
1565 
1566 
1567 /**
1568  * @brief Parse IPv6 options
1569  * @param[in] interface Underlying network interface
1570  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1571  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1572  * @param[in] optionOffset Offset to the first byte of the Options field
1573  * @param[in] optionLen Length of the Options field
1574  * @brief Error code
1575  **/
1576 
1578  size_t ipPacketOffset, size_t optionOffset, size_t optionLen)
1579 {
1580  size_t i;
1581  size_t n;
1582  uint8_t type;
1583  uint8_t action;
1584  uint8_t *options;
1585  Ipv6Option *option;
1586  Ipv6Header *ipHeader;
1587 
1588  //Point to the first byte of the Options field
1589  options = netBufferAt(ipPacket, optionOffset, 0);
1590 
1591  //Sanity check
1592  if(options == NULL)
1593  return ERROR_FAILURE;
1594 
1595  //Parse options
1596  for(i = 0; i < optionLen; )
1597  {
1598  //Point to the current option
1599  option = (Ipv6Option *) (options + i);
1600  //Get option type
1601  type = option->type & IPV6_OPTION_TYPE_MASK;
1602 
1603  //Pad1 option?
1605  {
1606  //Advance data pointer
1607  i++;
1608  }
1609  //PadN option?
1610  else if(type == IPV6_OPTION_TYPE_PADN)
1611  {
1612  //Malformed IPv6 packet?
1613  if((i + sizeof(Ipv6Option)) > optionLen)
1614  return ERROR_INVALID_LENGTH;
1615 
1616  //Advance data pointer
1617  i += sizeof(Ipv6Option) + option->length;
1618  }
1619  //Unrecognized option?
1620  else
1621  {
1622  //Point to the IPv6 header
1623  ipHeader = netBufferAt(ipPacket, ipPacketOffset, 0);
1624 
1625  //Sanity check
1626  if(ipHeader == NULL)
1627  return ERROR_FAILURE;
1628 
1629  //Get the value of the highest-order two bits
1630  action = option->type & IPV6_ACTION_MASK;
1631 
1632  //The highest-order two bits specify the action that must be taken
1633  //if the processing IPv6 node does not recognize the option type
1634  if(action == IPV6_ACTION_SKIP_OPTION)
1635  {
1636  //Skip over this option and continue processing the header
1637  }
1638  else if(action == IPV6_ACTION_DISCARD_PACKET)
1639  {
1640  //Discard the packet
1641  return ERROR_INVALID_OPTION;
1642  }
1643  else if(action == IPV6_ACTION_SEND_ICMP_ERROR_ALL)
1644  {
1645  //Calculate the octet offset within the invoking packet
1646  //where the error was detected
1647  n = optionOffset + i - ipPacketOffset;
1648 
1649  //Send an ICMP Parameter Problem message to the source of the
1650  //packet, regardless of whether or not the destination address
1651  //was a multicast address
1653  ICMPV6_CODE_UNKNOWN_IPV6_OPTION, n, ipPacket, ipPacketOffset);
1654 
1655  //Discard the packet
1656  return ERROR_INVALID_OPTION;
1657  }
1658  else if(action == IPV6_ACTION_SEND_ICMP_ERROR_UNI)
1659  {
1660  //Send an ICMP Parameter Problem message to the source of the
1661  //packet, only if the destination address was not a multicast
1662  //address
1663  if(!ipv6IsMulticastAddr(&ipHeader->destAddr))
1664  {
1665  //Calculate the octet offset within the invoking packet
1666  //where the error was detected
1667  n = optionOffset + i - ipPacketOffset;
1668 
1669  //Send the ICMP Parameter Problem message
1671  ICMPV6_CODE_UNKNOWN_IPV6_OPTION, n, ipPacket, ipPacketOffset);
1672  }
1673 
1674  //Discard the packet
1675  return ERROR_INVALID_OPTION;
1676  }
1677 
1678  //Malformed IPv6 packet?
1679  if((i + sizeof(Ipv6Option)) > optionLen)
1680  return ERROR_INVALID_LENGTH;
1681 
1682  //Advance data pointer
1683  i += sizeof(Ipv6Option) + option->length;
1684  }
1685  }
1686 
1687  //Successful processing
1688  return NO_ERROR;
1689 }
1690 
1691 
1692 /**
1693  * @brief Send an IPv6 datagram
1694  * @param[in] interface Underlying network interface
1695  * @param[in] pseudoHeader IPv6 pseudo header
1696  * @param[in] buffer Multi-part buffer containing the payload
1697  * @param[in] offset Offset to the first byte of the payload
1698  * @param[in] ancillary Additional options passed to the stack along with
1699  * the packet
1700  * @return Error code
1701  **/
1702 
1704  const Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset,
1705  NetTxAncillary *ancillary)
1706 {
1707  error_t error;
1708  size_t length;
1709  size_t pathMtu;
1710 
1711  //Total number of IP datagrams which local IP user-protocols supplied to IP
1712  //in requests for transmission
1713  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsOutRequests, 1);
1714  IP_MIB_INC_COUNTER64(ipv6SystemStats.ipSystemStatsHCOutRequests, 1);
1715  IP_MIB_INC_COUNTER32(ipv6IfStatsTable[interface->index].ipIfStatsOutRequests, 1);
1716  IP_MIB_INC_COUNTER64(ipv6IfStatsTable[interface->index].ipIfStatsHCOutRequests, 1);
1717 
1718  //Retrieve the length of payload
1719  length = netBufferGetLength(buffer) - offset;
1720 
1721 #if (IPV6_PMTU_SUPPORT == ENABLED)
1722  //Retrieve the PMTU for the specified destination address
1723  pathMtu = ipv6GetPathMtu(interface, &pseudoHeader->destAddr);
1724 
1725  //The PMTU should not exceed the MTU of the first-hop link
1726  if(pathMtu > interface->ipv6Context.linkMtu)
1727  {
1728  pathMtu = interface->ipv6Context.linkMtu;
1729  }
1730 #else
1731  //The PMTU value for the path is assumed to be the MTU of the first-hop link
1732  pathMtu = interface->ipv6Context.linkMtu;
1733 #endif
1734 
1735  //Check the length of the payload
1736  if((length + sizeof(Ipv6Header)) <= pathMtu)
1737  {
1738  //If the payload length is smaller than the PMTU then no fragmentation
1739  //is needed
1740  error = ipv6SendPacket(interface, pseudoHeader, 0, 0, buffer, offset,
1741  ancillary);
1742  }
1743  else
1744  {
1745 #if (IPV6_FRAG_SUPPORT == ENABLED)
1746  //This flag defines a mechanism to turn off fragmentation
1747  if(!ancillary->dontFrag)
1748  {
1749  //If the payload length exceeds the PMTU then the device must fragment
1750  //the data
1751  error = ipv6FragmentDatagram(interface, pseudoHeader, buffer, offset,
1752  pathMtu, ancillary);
1753  }
1754  else
1755 #endif
1756  {
1757  //When the data size is larger than the MTU of the outgoing interface,
1758  //the packet will be discarded
1759  error = ERROR_MESSAGE_TOO_LONG;
1760  }
1761  }
1762 
1763  //Return status code
1764  return error;
1765 }
1766 
1767 
1768 /**
1769  * @brief Send an IPv6 packet
1770  * @param[in] interface Underlying network interface
1771  * @param[in] pseudoHeader IPv6 pseudo header
1772  * @param[in] fragId Fragment identification field
1773  * @param[in] fragOffset Fragment offset field
1774  * @param[in] buffer Multi-part buffer containing the payload
1775  * @param[in] offset Offset to the first byte of the payload
1776  * @param[in] ancillary Additional options passed to the stack along with
1777  * the packet
1778  * @return Error code
1779  **/
1780 
1782  const Ipv6PseudoHeader *pseudoHeader, uint32_t fragId, size_t fragOffset,
1783  NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
1784 {
1785  error_t error;
1786  uint8_t nextHeader;
1787  size_t length;
1788  Ipv6Header *packet;
1789 #if (ETH_SUPPORT == ENABLED)
1790  NetInterface *physicalInterface;
1791 #endif
1792 
1793  //Get the value of the Next Header field
1794  nextHeader = pseudoHeader->nextHeader;
1795 
1796  //The Hop-by-Hop Options header is used to carry optional information that
1797  //must be examined by every node along a packet's delivery path
1798  if(ancillary->routerAlert)
1799  {
1800  //Format Hop-by-Hop Options header
1801  error = ipv6FormatHopByHopOptHeader(&nextHeader, buffer, &offset);
1802  //Any error to report?
1803  if(error)
1804  return error;
1805  }
1806 
1807  //The Fragment header is used by an IPv6 source to send a packet larger than
1808  //would fit in the path MTU to its destination
1809  if(fragOffset != 0)
1810  {
1811  //Format Fragment header
1812  error = ipv6FormatFragmentHeader(fragId, fragOffset, &nextHeader, buffer,
1813  &offset);
1814  //Any error to report?
1815  if(error)
1816  return error;
1817  }
1818 
1819  //Make sure there is sufficient space for the IPv6 header
1820  if(offset < sizeof(Ipv6Header))
1821  return ERROR_INVALID_PARAMETER;
1822 
1823  //Make room for the IPv6 header
1824  offset -= sizeof(Ipv6Header);
1825  //Calculate the size of the entire packet, including header and data
1826  length = netBufferGetLength(buffer) - offset;
1827 
1828  //Point to the IPv6 header
1829  packet = netBufferAt(buffer, offset, 0);
1830 
1831  //Format IPv6 header
1832  packet->version = IPV6_VERSION;
1833  packet->trafficClassH = (ancillary->tos >> 4) & 0x0F;
1834  packet->trafficClassL = ancillary->tos & 0x0F;
1835  packet->flowLabelH = 0;
1836  packet->flowLabelL = 0;
1837  packet->payloadLen = htons(length - sizeof(Ipv6Header));
1838  packet->nextHeader = nextHeader;
1839  packet->hopLimit = ancillary->ttl;
1840  packet->srcAddr = pseudoHeader->srcAddr;
1841  packet->destAddr = pseudoHeader->destAddr;
1842 
1843  //Check whether the Hop Limit value is zero
1844  if(packet->hopLimit == 0)
1845  {
1846  //Use default Hop Limit value
1847  packet->hopLimit = interface->ipv6Context.curHopLimit;
1848  }
1849 
1850  //Ensure the source address is valid
1851  error = ipv6CheckSourceAddr(interface, &pseudoHeader->srcAddr);
1852  //Invalid source address?
1853  if(error)
1854  return error;
1855 
1856  //Check destination address
1857  if(ipv6CompAddr(&pseudoHeader->destAddr, &IPV6_UNSPECIFIED_ADDR))
1858  {
1859  //The unspecified address must not appear on the public Internet
1860  error = ERROR_INVALID_ADDRESS;
1861  }
1862  else if(ipv6IsLocalHostAddr(&pseudoHeader->destAddr))
1863  {
1864 #if (NET_LOOPBACK_IF_SUPPORT == ENABLED)
1865  uint_t i;
1866 
1867  //Initialize status code
1868  error = ERROR_NO_ROUTE;
1869 
1870  //Loop through network interfaces
1871  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1872  {
1873  //Point to the current interface
1874  interface = &netInterface[i];
1875 
1876  //Loopback interface?
1877  if(interface->nicDriver != NULL &&
1878  interface->nicDriver->type == NIC_TYPE_LOOPBACK)
1879  {
1880  //Forward the packet to the loopback interface
1881  error = nicSendPacket(interface, buffer, offset, ancillary);
1882  break;
1883  }
1884  }
1885 #else
1886  //The loopback address must not appear on the public Internet
1887  error = ERROR_NO_ROUTE;
1888 #endif
1889  }
1890  else
1891  {
1892 #if (ETH_SUPPORT == ENABLED)
1893  //Point to the physical interface
1894  physicalInterface = nicGetPhysicalInterface(interface);
1895 
1896  //Ethernet interface?
1897  if(physicalInterface->nicDriver != NULL &&
1898  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
1899  {
1901  NdpDestCacheEntry *entry;
1902 
1903  //When the sending node has a packet to send, it first examines
1904  //the Destination Cache
1905  entry = ndpFindDestCacheEntry(interface, &pseudoHeader->destAddr);
1906 
1907  //Check whether a matching entry exists
1908  if(entry != NULL)
1909  {
1910  //Retrieve the address of the next-hop
1911  destIpAddr = entry->nextHop;
1912  //Update timestamp
1913  entry->timestamp = osGetSystemTime();
1914  //No error to report
1915  error = NO_ERROR;
1916  }
1917  else
1918  {
1919  //Perform next-hop determination
1920  error = ndpSelectNextHop(interface, &pseudoHeader->destAddr, NULL,
1921  &destIpAddr, ancillary->dontRoute);
1922 
1923  //Check status code
1924  if(error == NO_ERROR)
1925  {
1926  //Create a new Destination Cache entry
1927  entry = ndpCreateDestCacheEntry(interface);
1928 
1929  //Destination cache entry successfully created?
1930  if(entry != NULL)
1931  {
1932  //Destination address
1933  entry->destAddr = pseudoHeader->destAddr;
1934  //Address of the next hop
1935  entry->nextHop = destIpAddr;
1936 
1937  //Initially, the PMTU value for a path is assumed to be the
1938  //MTU of the first-hop link
1939  entry->pathMtu = interface->ipv6Context.linkMtu;
1940 
1941  //Set timestamp
1942  entry->timestamp = osGetSystemTime();
1943  }
1944  }
1945  else if(error == ERROR_NO_ROUTE)
1946  {
1947  //Number of IP datagrams discarded because no route could be found
1948  //to transmit them to their destination
1949  IP_MIB_INC_COUNTER32(ipv6SystemStats.ipSystemStatsOutNoRoutes, 1);
1950  }
1951  }
1952 
1953  //Successful next-hop determination?
1954  if(error == NO_ERROR)
1955  {
1956  //Perform address resolution
1957  if(!macCompAddr(&ancillary->destMacAddr, &MAC_UNSPECIFIED_ADDR))
1958  {
1959  //The destination address is already resolved
1960  error = NO_ERROR;
1961  }
1962  else if(ipv6IsMulticastAddr(&destIpAddr))
1963  {
1964  //Map IPv6 multicast address to MAC-layer multicast address
1966  &ancillary->destMacAddr);
1967  }
1968  else
1969  {
1970  //Resolve host address using Neighbor Discovery protocol
1971  error = ndpResolve(interface, &destIpAddr, &ancillary->destMacAddr);
1972  }
1973 
1974  //Successful address resolution?
1975  if(error == NO_ERROR)
1976  {
1977  //Update IP statistics
1978  ipv6UpdateOutStats(interface, &destIpAddr, length);
1979 
1980  //Debug message
1981  TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
1982  //Dump IP header contents for debugging purpose
1983  ipv6DumpHeader(packet);
1984 
1985  //Send Ethernet frame
1986  error = ethSendFrame(interface, &ancillary->destMacAddr,
1987  ETH_TYPE_IPV6, buffer, offset, ancillary);
1988  }
1989  else if(error == ERROR_IN_PROGRESS)
1990  {
1991  //Debug message
1992  TRACE_INFO("Enqueuing IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
1993  //Dump IP header contents for debugging purpose
1994  ipv6DumpHeader(packet);
1995 
1996  //Enqueue packets waiting for address resolution
1997  error = ndpEnqueuePacket(NULL, interface, &destIpAddr, buffer,
1998  offset, ancillary);
1999  }
2000  else
2001  {
2002  //Debug message
2003  TRACE_WARNING("Cannot map IPv6 address to Ethernet address!\r\n");
2004  }
2005  }
2006  }
2007  else
2008 #endif
2009 #if (PPP_SUPPORT == ENABLED)
2010  //PPP interface?
2011  if(interface->nicDriver != NULL &&
2012  interface->nicDriver->type == NIC_TYPE_PPP)
2013  {
2014  //Update IP statistics
2015  ipv6UpdateOutStats(interface, &pseudoHeader->destAddr, length);
2016 
2017  //Debug message
2018  TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
2019  //Dump IP header contents for debugging purpose
2020  ipv6DumpHeader(packet);
2021 
2022  //Send PPP frame
2023  error = pppSendFrame(interface, buffer, offset, PPP_PROTOCOL_IPV6);
2024  }
2025  else
2026 #endif
2027  //6LoWPAN interface?
2028  if(interface->nicDriver != NULL &&
2029  interface->nicDriver->type == NIC_TYPE_6LOWPAN)
2030  {
2031  //Update IP statistics
2032  ipv6UpdateOutStats(interface, &pseudoHeader->destAddr, length);
2033 
2034  //Debug message
2035  TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
2036  //Dump IP header contents for debugging purpose
2037  ipv6DumpHeader(packet);
2038 
2039  //Send the packet over the specified link
2040  error = nicSendPacket(interface, buffer, offset, ancillary);
2041  }
2042  //Unknown interface type?
2043  else
2044  {
2045  //Report an error
2046  error = ERROR_INVALID_INTERFACE;
2047  }
2048  }
2049 
2050  //Return status code
2051  return error;
2052 }
2053 
2054 
2055 /**
2056  * @brief Format Hop-by-Hop Options header
2057  * @param[in,out] nextHeader Value of the Next Header field
2058  * @param[in] buffer Multi-part buffer containing the payload
2059  * @param[in,out] offset Offset to the first payload byte
2060  * @return Error code
2061  **/
2062 
2064  size_t *offset)
2065 {
2066  error_t error;
2067  Ipv6HopByHopOptHeader *header;
2068  Ipv6Option *option;
2069 
2070  //Make sure there is sufficient space for the Fragment header, the IPv6
2071  //Router Alert option and the PadN option
2072  if(*offset >= (sizeof(Ipv6HopByHopOptHeader) +
2073  sizeof(Ipv6RouterAlertOption) + sizeof(Ipv6Option)))
2074  {
2075  //Make room for the header
2076  *offset -= sizeof(Ipv6HopByHopOptHeader) + sizeof(Ipv6RouterAlertOption) +
2077  sizeof(Ipv6Option);
2078 
2079  //Point to the header
2080  header = netBufferAt(buffer, *offset, 0);
2081 
2082  //Format Hop-by-Hop Options header
2083  header->nextHeader = *nextHeader;
2084  header->hdrExtLen = 0;
2085 
2086  //Point to the first option
2087  option = (Ipv6Option *) header->options;
2088 
2089  //Format IPv6 Router Alert option
2090  option->type = IPV6_OPTION_TYPE_ROUTER_ALERT;
2091  option->length = sizeof(uint16_t);
2092  option->data[0] = 0;
2093  option->data[1] = 0;
2094 
2095  //Pad out the containing header to a multiple of 8 octets in length
2096  option = (Ipv6Option *) (header->options + sizeof(Ipv6RouterAlertOption));
2097 
2098  //The PadN option is used to insert two or more octets of padding into
2099  //the Options area of a header
2100  option->type = IPV6_OPTION_TYPE_PADN;
2101  option->length = 0;
2102 
2103  //Update the value of the Next Header field
2105 
2106  //Successful processing
2107  error = NO_ERROR;
2108  }
2109  else
2110  {
2111  //Report an error
2112  error = ERROR_INVALID_PARAMETER;
2113  }
2114 
2115  //Return status code
2116  return error;
2117 }
2118 
2119 
2120 /**
2121  * @brief Format Fragment header
2122  * @param[in] fragId Fragment identification field
2123  * @param[in] fragOffset Fragment offset field
2124  * @param[in,out] nextHeader Value of the Next Header field
2125  * @param[in] buffer Multi-part buffer containing the payload
2126  * @param[in,out] offset Offset to the first payload byte
2127  * @return Error code
2128  **/
2129 
2131  uint8_t *nextHeader, NetBuffer *buffer, size_t *offset)
2132 {
2133  error_t error;
2134  Ipv6FragmentHeader *header;
2135 
2136  //Make sure there is sufficient space for the Fragment header
2137  if(*offset >= sizeof(Ipv6FragmentHeader))
2138  {
2139  //Make room for the header
2140  *offset -= sizeof(Ipv6FragmentHeader);
2141  //Point to the header
2142  header = netBufferAt(buffer, *offset, 0);
2143 
2144  //Format Fragment header
2145  header->nextHeader = *nextHeader;
2146  header->reserved = 0;
2147  header->fragmentOffset = htons(fragOffset);
2148  header->identification = htonl(fragId);
2149 
2150  //Update the value of the Next Header field
2152 
2153  //Successful processing
2154  error = NO_ERROR;
2155  }
2156  else
2157  {
2158  //Report an error
2159  error = ERROR_INVALID_PARAMETER;
2160  }
2161 
2162  //Return status code
2163  return error;
2164 }
2165 
2166 
2167 /**
2168  * @brief Convert a string representation of an IPv6 address to a binary IPv6 address
2169  * @param[in] str NULL-terminated string representing the IPv6 address
2170  * @param[out] ipAddr Binary representation of the IPv6 address
2171  * @return Error code
2172  **/
2173 
2175 {
2176  error_t error;
2177  int_t i = 0;
2178  int_t j = -1;
2179  int_t k = 0;
2180  int32_t value = -1;
2181 
2182  //Parse input string
2183  while(1)
2184  {
2185  //Hexadecimal digit found?
2186  if(isxdigit((uint8_t) *str))
2187  {
2188  //First digit to be decoded?
2189  if(value < 0)
2190  {
2191  value = 0;
2192  }
2193 
2194  //Update the value of the current 16-bit word
2195  if(osIsdigit(*str))
2196  {
2197  value = (value * 16) + (*str - '0');
2198  }
2199  else if(osIsupper(*str))
2200  {
2201  value = (value * 16) + (*str - 'A' + 10);
2202  }
2203  else
2204  {
2205  value = (value * 16) + (*str - 'a' + 10);
2206  }
2207 
2208  //Check resulting value
2209  if(value > 0xFFFF)
2210  {
2211  //The conversion failed
2212  error = ERROR_INVALID_SYNTAX;
2213  break;
2214  }
2215  }
2216  //"::" symbol found?
2217  else if(osStrncmp(str, "::", 2) == 0)
2218  {
2219  //The "::" can only appear once in an IPv6 address
2220  if(j >= 0)
2221  {
2222  //The conversion failed
2223  error = ERROR_INVALID_SYNTAX;
2224  break;
2225  }
2226 
2227  //The "::" symbol is preceded by a number?
2228  if(value >= 0)
2229  {
2230  //Save the current 16-bit word
2231  ipAddr->w[i++] = htons(value);
2232  //Prepare to decode the next 16-bit word
2233  value = -1;
2234  }
2235 
2236  //Save the position of the "::" symbol
2237  j = i;
2238  //Point to the next character
2239  str++;
2240  }
2241  //":" symbol found?
2242  else if(*str == ':' && i < 8)
2243  {
2244  //Each ":" must be preceded by a valid number
2245  if(value < 0)
2246  {
2247  //The conversion failed
2248  error = ERROR_INVALID_SYNTAX;
2249  break;
2250  }
2251 
2252  //Save the current 16-bit word
2253  ipAddr->w[i++] = htons(value);
2254  //Prepare to decode the next 16-bit word
2255  value = -1;
2256  }
2257  //End of string detected?
2258  else if(*str == '\0' && i == 7 && j < 0)
2259  {
2260  //The NULL character must be preceded by a valid number
2261  if(value < 0)
2262  {
2263  //The conversion failed
2264  error = ERROR_INVALID_SYNTAX;
2265  }
2266  else
2267  {
2268  //Save the last 16-bit word of the IPv6 address
2269  ipAddr->w[i] = htons(value);
2270  //The conversion succeeded
2271  error = NO_ERROR;
2272  }
2273 
2274  //We are done
2275  break;
2276  }
2277  else if(*str == '\0' && i < 7 && j >= 0)
2278  {
2279  //Save the last 16-bit word of the IPv6 address
2280  if(value >= 0)
2281  {
2282  ipAddr->w[i++] = htons(value);
2283  }
2284 
2285  //Move the part of the address that follows the "::" symbol
2286  for(k = 0; k < (i - j); k++)
2287  {
2288  ipAddr->w[7 - k] = ipAddr->w[i - 1 - k];
2289  }
2290 
2291  //A sequence of zeroes can now be written in place of "::"
2292  for(k = 0; k < (8 - i); k++)
2293  {
2294  ipAddr->w[j + k] = 0;
2295  }
2296 
2297  //The conversion succeeded
2298  error = NO_ERROR;
2299  break;
2300  }
2301  //Invalid character...
2302  else
2303  {
2304  //The conversion failed
2305  error = ERROR_INVALID_SYNTAX;
2306  break;
2307  }
2308 
2309  //Point to the next character
2310  str++;
2311  }
2312 
2313  //Return status code
2314  return error;
2315 }
2316 
2317 
2318 /**
2319  * @brief Convert a binary IPv6 address to a string representation
2320  *
2321  * Call ipv6AddrToString() to convert an IPv6 address to a text representation. The
2322  * implementation of ipv6AddrToString() function follows RFC 5952 recommendations
2323  *
2324  * @param[in] ipAddr Binary representation of the IPv6 address
2325  * @param[out] str NULL-terminated string representing the IPv6 address
2326  * @return Pointer to the formatted string
2327  **/
2328 
2330 {
2331  static char_t buffer[40];
2332  uint_t i;
2333  uint_t j;
2334  char_t *p;
2335 
2336  //Best run of zeroes
2337  uint_t zeroRunStart = 0;
2338  uint_t zeroRunEnd = 0;
2339 
2340  //If the NULL pointer is given as parameter, then the internal buffer is used
2341  if(str == NULL)
2342  str = buffer;
2343 
2344  //Find the longest run of zeros for "::" short-handing
2345  for(i = 0; i < 8; i++)
2346  {
2347  //Compute the length of the current sequence of zeroes
2348  for(j = i; j < 8 && !ipAddr->w[j]; j++)
2349  {
2350  }
2351 
2352  //Keep track of the longest one
2353  if((j - i) > 1 && (j - i) > (zeroRunEnd - zeroRunStart))
2354  {
2355  //The symbol "::" should not be used to shorten just one zero field
2356  zeroRunStart = i;
2357  zeroRunEnd = j;
2358  }
2359  }
2360 
2361  //Format IPv6 address
2362  for(p = str, i = 0; i < 8; i++)
2363  {
2364  //Are we inside the best run of zeroes?
2365  if(i >= zeroRunStart && i < zeroRunEnd)
2366  {
2367  //Append a separator
2368  *(p++) = ':';
2369  //Skip the sequence of zeroes
2370  i = zeroRunEnd - 1;
2371  }
2372  else
2373  {
2374  //Add a separator between each 16-bit word
2375  if(i > 0)
2376  *(p++) = ':';
2377 
2378  //Convert the current 16-bit word to string
2379  p += osSprintf(p, "%" PRIx16, ntohs(ipAddr->w[i]));
2380  }
2381  }
2382 
2383  //A trailing run of zeroes has been found?
2384  if(zeroRunEnd == 8)
2385  *(p++) = ':';
2386 
2387  //Properly terminate the string
2388  *p = '\0';
2389 
2390  //Return a pointer to the formatted string
2391  return str;
2392 }
2393 
2394 
2395 /**
2396  * @brief Dump IPv6 header for debugging purpose
2397  * @param[in] ipHeader IPv6 header
2398  **/
2399 
2400 void ipv6DumpHeader(const Ipv6Header *ipHeader)
2401 {
2402  //Dump IPv6 header contents
2403  TRACE_DEBUG(" Version = %" PRIu8 "\r\n", ipHeader->version);
2404  TRACE_DEBUG(" Traffic Class = %u\r\n", (ipHeader->trafficClassH << 4) | ipHeader->trafficClassL);
2405  TRACE_DEBUG(" Flow Label = 0x%05X\r\n", (ipHeader->flowLabelH << 16) | ntohs(ipHeader->flowLabelL));
2406  TRACE_DEBUG(" Payload Length = %" PRIu16 "\r\n", ntohs(ipHeader->payloadLen));
2407  TRACE_DEBUG(" Next Header = %" PRIu8 "\r\n", ipHeader->nextHeader);
2408  TRACE_DEBUG(" Hop Limit = %" PRIu8 "\r\n", ipHeader->hopLimit);
2409  TRACE_DEBUG(" Src Addr = %s\r\n", ipv6AddrToString(&ipHeader->srcAddr, NULL));
2410  TRACE_DEBUG(" Dest Addr = %s\r\n", ipv6AddrToString(&ipHeader->destAddr, NULL));
2411 }
2412 
2413 #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:2329
#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:1781
@ 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:137
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:49
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:2063
error_t ipv6ParseDestOptHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
Parse Destination Options header.
Definition: ipv6.c:1399
#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:2130
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:114
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:1535
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:139
IPv6 multicast filtering.
@ ERROR_IN_PROGRESS
Definition: error.h:213
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:506
void ndpLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ndp.c:541
#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
#define osSprintf(dest,...)
Definition: os_port.h:231
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:2400
@ 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:285
@ PPP_PROTOCOL_IPV6
Internet Protocol version 6.
Definition: ppp.h:200
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
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:136
@ 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:220
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:85
#define TRACE_DEBUG(...)
Definition: debug.h:107
char char_t
Definition: compiler_port.h:48
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:1556
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:1703
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:360
@ 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:1463
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:369
#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:1320
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
#define Ipv6FragmentHeader
Definition: ipv6.h:39
uint8_t options[]
Definition: tcp.h:357
#define osStrncmp(s1, s2, length)
Definition: os_port.h:177
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:260
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:2174
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:50
@ ERROR_PORT_UNREACHABLE
Definition: error.h:85
Helper functions for router advertisement service.
#define osMemset(p, value, length)
Definition: os_port.h:135
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:279
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:1577
@ 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