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