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