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.6
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, sizeof(Ipv6Header));
1019  //Malformed IPv6 packet?
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, sizeof(uint8_t));
1140  //Malformed IPv6 packet?
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  Ipv6HopByHopOptHeader *header;
1341 
1342  //Point to the Hop-by-Hop Options header
1343  header = netBufferAt(ipPacket, *headerOffset, sizeof(Ipv6HopByHopOptHeader));
1344  //Malformed extension header?
1345  if(header == NULL)
1346  return ERROR_FAILURE;
1347 
1348  //Calculate the length of the extension header
1349  length = (header->hdrExtLen * 8) + 8;
1350 
1351  //Check the length of the extension header
1352  header = netBufferAt(ipPacket, *headerOffset, length);
1353  //Malformed extension header?
1354  if(header == NULL)
1355  return ERROR_FAILURE;
1356 
1357  //Debug message
1358  TRACE_DEBUG(" Hop-by-Hop Options header\r\n");
1359 
1360  //The Hop-by-Hop Options header, when present, must immediately follow the
1361  //IPv6 header
1362  if(*headerOffset != (ipPacketOffset + sizeof(Ipv6Header)))
1363  {
1364  //Compute the offset of the unrecognized Next Header field within the
1365  //packet
1366  n = *nextHeaderOffset - ipPacketOffset;
1367 
1368  //Send an ICMP Parameter Problem message to the source of the packet
1370  ICMPV6_CODE_UNKNOWN_NEXT_HEADER, n, ipPacket, ipPacketOffset);
1371 
1372  //Discard incoming packet
1373  return ERROR_INVALID_HEADER;
1374  }
1375 
1376  //Compute the length of the Options field
1377  n = length - sizeof(Ipv6HopByHopOptHeader);
1378 
1379  //Parse options
1380  error = ipv6ParseOptions(interface, ipPacket, ipPacketOffset,
1381  *headerOffset + sizeof(Ipv6HopByHopOptHeader), n);
1382 
1383  //Any error to report?
1384  if(error)
1385  return error;
1386 
1387  //Keep track of Next Header field
1388  *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header;
1389  //Point to the next extension header
1390  *headerOffset += length;
1391 
1392  //Successful processing
1393  return NO_ERROR;
1394 }
1395 
1396 
1397 /**
1398  * @brief Parse Destination Options header
1399  * @param[in] interface Underlying network interface
1400  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1401  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1402  * @param[in,out] headerOffset Offset to the Destination Options header
1403  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1404  * @brief Error code
1405  **/
1406 
1408  const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset,
1409  size_t *nextHeaderOffset)
1410 {
1411  error_t error;
1412  size_t n;
1413  size_t length;
1414  Ipv6DestOptHeader *header;
1415 
1416  //Point to the Destination Options header
1417  header = netBufferAt(ipPacket, *headerOffset, sizeof(Ipv6DestOptHeader));
1418  //Malformed extension header?
1419  if(header == NULL)
1420  return ERROR_FAILURE;
1421 
1422  //Calculate the length of the extension header
1423  length = (header->hdrExtLen * 8) + 8;
1424 
1425  //Check the length of the extension header
1426  header = netBufferAt(ipPacket, *headerOffset, length);
1427  //Malformed extension header?
1428  if(header == NULL)
1429  return ERROR_FAILURE;
1430 
1431  //Debug message
1432  TRACE_DEBUG(" Destination Options header\r\n");
1433 
1434  //Compute the length of the Options field
1435  n = length - sizeof(Ipv6DestOptHeader);
1436 
1437  //Parse options
1438  error = ipv6ParseOptions(interface, ipPacket, ipPacketOffset,
1439  *headerOffset + sizeof(Ipv6DestOptHeader), n);
1440 
1441  //Any error to report?
1442  if(error)
1443  return error;
1444 
1445  //Keep track of Next Header field
1446  *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header;
1447  //Point to the next extension header
1448  *headerOffset += length;
1449 
1450  //Successful processing
1451  return NO_ERROR;
1452 }
1453 
1454 
1455 /**
1456  * @brief Parse Routing header
1457  * @param[in] interface Underlying network interface
1458  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1459  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1460  * @param[in,out] headerOffset Offset to the Routing header
1461  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1462  * @brief Error code
1463  **/
1464 
1466  const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset,
1467  size_t *nextHeaderOffset)
1468 {
1469  size_t n;
1470  size_t length;
1471  Ipv6RoutingHeader *header;
1472 
1473  //Point to the Routing header
1474  header = netBufferAt(ipPacket, *headerOffset, sizeof(Ipv6RoutingHeader));
1475  //Malformed extension header?
1476  if(header == NULL)
1477  return ERROR_FAILURE;
1478 
1479  //Calculate the length of the extension header
1480  length = (header->hdrExtLen * 8) + 8;
1481 
1482  //Check the length of the extension header
1483  header = netBufferAt(ipPacket, *headerOffset, length);
1484  //Malformed extension header?
1485  if(header == NULL)
1486  return ERROR_FAILURE;
1487 
1488  //Debug message
1489  TRACE_DEBUG(" Routing header\r\n");
1490 
1491  //If, while processing a received packet, a node encounters a Routing header
1492  //with an unrecognized Routing Type value, the required behavior of the node
1493  //depends on the value of the Segments Left field
1494  if(header->segmentsLeft != 0)
1495  {
1496  //Retrieve the offset of the Routing header within the packet
1497  n = *headerOffset - ipPacketOffset;
1498  //Compute the exact offset of the Routing Type field
1499  n += (uint8_t *) &header->routingType - (uint8_t *) header;
1500 
1501  //If Segments Left is non-zero, send an ICMP Parameter Problem, Code 0,
1502  //message to the packet's Source Address, pointing to the unrecognized
1503  //Routing Type
1505  ICMPV6_CODE_INVALID_HEADER_FIELD, n, ipPacket, ipPacketOffset);
1506 
1507  //The node must discard the packet
1508  return ERROR_INVALID_TYPE;
1509  }
1510 
1511  //Keep track of Next Header field
1512  *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header;
1513  //Point to the next extension header
1514  *headerOffset += length;
1515 
1516  //Successful processing
1517  return NO_ERROR;
1518 }
1519 
1520 
1521 /**
1522  * @brief Parse AH header
1523  * @param[in] interface Underlying network interface
1524  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1525  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1526  * @param[in,out] headerOffset Offset to the Authentication header
1527  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1528  * @brief Error code
1529  **/
1530 
1532  size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
1533 {
1534  //Debug message
1535  TRACE_DEBUG(" AH header\r\n");
1536 
1537  //IPsec is not supported
1538  return ERROR_FAILURE;
1539 }
1540 
1541 
1542 /**
1543  * @brief Parse ESP header
1544  * @param[in] interface Underlying network interface
1545  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1546  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1547  * @param[in,out] headerOffset Offset to the Encapsulating Security Payload header
1548  * @param[in,out] nextHeaderOffset Offset to the Next Header field
1549  * @brief Error code
1550  **/
1551 
1553  size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
1554 {
1555  //Debug message
1556  TRACE_DEBUG(" ESP header\r\n");
1557 
1558  //IPsec is not supported
1559  return ERROR_FAILURE;
1560 }
1561 
1562 
1563 /**
1564  * @brief Parse IPv6 options
1565  * @param[in] interface Underlying network interface
1566  * @param[in] ipPacket Multi-part buffer containing the IPv6 packet
1567  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
1568  * @param[in] optionsOffset Offset to the first byte of the Options field
1569  * @param[in] optionsLen Length of the Options field
1570  * @brief Error code
1571  **/
1572 
1574  size_t ipPacketOffset, size_t optionsOffset, size_t optionsLen)
1575 {
1576  size_t i;
1577  size_t n;
1578  uint8_t type;
1579  uint8_t action;
1580  uint8_t *options;
1581  Ipv6Option *option;
1582  Ipv6Header *ipHeader;
1583 
1584  //Point to the first byte of the Options field
1585  options = netBufferAt(ipPacket, optionsOffset, optionsLen);
1586  //Malformed IPv6 packet?
1587  if(options == NULL)
1588  return ERROR_FAILURE;
1589 
1590  //Parse options
1591  for(i = 0; i < optionsLen; )
1592  {
1593  //Point to the current option
1594  option = (Ipv6Option *) (options + i);
1595  //Get option type
1596  type = option->type & IPV6_OPTION_TYPE_MASK;
1597 
1598  //Pad1 option?
1600  {
1601  //Advance data pointer
1602  i++;
1603  }
1604  //PadN option?
1605  else if(type == IPV6_OPTION_TYPE_PADN)
1606  {
1607  //Malformed IPv6 packet?
1608  if((i + sizeof(Ipv6Option)) > optionsLen)
1609  return ERROR_INVALID_LENGTH;
1610 
1611  //Advance data pointer
1612  i += sizeof(Ipv6Option) + option->length;
1613  }
1614  //Unrecognized option?
1615  else
1616  {
1617  //Point to the IPv6 header
1618  ipHeader = netBufferAt(ipPacket, ipPacketOffset, sizeof(Ipv6Header));
1619  //Malformed IPv6 packet?
1620  if(ipHeader == NULL)
1621  return ERROR_FAILURE;
1622 
1623  //Get the value of the highest-order two bits
1624  action = option->type & IPV6_ACTION_MASK;
1625 
1626  //The highest-order two bits specify the action that must be taken
1627  //if the processing IPv6 node does not recognize the option type
1628  if(action == IPV6_ACTION_SKIP_OPTION)
1629  {
1630  //Skip over this option and continue processing the header
1631  }
1632  else if(action == IPV6_ACTION_DISCARD_PACKET)
1633  {
1634  //Discard the packet
1635  return ERROR_INVALID_OPTION;
1636  }
1637  else if(action == IPV6_ACTION_SEND_ICMP_ERROR_ALL)
1638  {
1639  //Calculate the octet offset within the invoking packet
1640  //where the error was detected
1641  n = optionsOffset + i - ipPacketOffset;
1642 
1643  //Send an ICMP Parameter Problem message to the source of the
1644  //packet, regardless of whether or not the destination address
1645  //was a multicast address
1647  ICMPV6_CODE_UNKNOWN_IPV6_OPTION, n, ipPacket, ipPacketOffset);
1648 
1649  //Discard the packet
1650  return ERROR_INVALID_OPTION;
1651  }
1652  else if(action == IPV6_ACTION_SEND_ICMP_ERROR_UNI)
1653  {
1654  //Send an ICMP Parameter Problem message to the source of the
1655  //packet, only if the destination address was not a multicast
1656  //address
1657  if(!ipv6IsMulticastAddr(&ipHeader->destAddr))
1658  {
1659  //Calculate the octet offset within the invoking packet
1660  //where the error was detected
1661  n = optionsOffset + i - ipPacketOffset;
1662 
1663  //Send the ICMP Parameter Problem message
1665  ICMPV6_CODE_UNKNOWN_IPV6_OPTION, n, ipPacket, ipPacketOffset);
1666  }
1667 
1668  //Discard the packet
1669  return ERROR_INVALID_OPTION;
1670  }
1671 
1672  //Malformed IPv6 packet?
1673  if((i + sizeof(Ipv6Option)) > optionsLen)
1674  return ERROR_INVALID_LENGTH;
1675 
1676  //Advance data pointer
1677  i += sizeof(Ipv6Option) + option->length;
1678  }
1679  }
1680 
1681  //Successful processing
1682  return NO_ERROR;
1683 }
1684 
1685 
1686 /**
1687  * @brief Send an IPv6 datagram
1688  * @param[in] interface Underlying network interface
1689  * @param[in] pseudoHeader IPv6 pseudo header
1690  * @param[in] buffer Multi-part buffer containing the payload
1691  * @param[in] offset Offset to the first byte of the payload
1692  * @param[in] ancillary Additional options passed to the stack along with
1693  * the packet
1694  * @return Error code
1695  **/
1696 
1698  const Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset,
1699  NetTxAncillary *ancillary)
1700 {
1701  error_t error;
1702  size_t length;
1703  size_t pathMtu;
1704 
1705  //Total number of IP datagrams which local IP user-protocols supplied to IP
1706  //in requests for transmission
1707  IPV6_SYSTEM_STATS_INC_COUNTER64(outRequests, 1);
1708  IPV6_IF_STATS_INC_COUNTER64(outRequests, 1);
1709 
1710  //Retrieve the length of payload
1711  length = netBufferGetLength(buffer) - offset;
1712 
1713 #if (IPV6_PMTU_SUPPORT == ENABLED)
1714  //Retrieve the PMTU for the specified destination address
1715  pathMtu = ipv6GetPathMtu(interface, &pseudoHeader->destAddr);
1716 
1717  //The PMTU should not exceed the MTU of the first-hop link
1718  if(pathMtu > interface->ipv6Context.linkMtu)
1719  {
1720  pathMtu = interface->ipv6Context.linkMtu;
1721  }
1722 #else
1723  //The PMTU value for the path is assumed to be the MTU of the first-hop link
1724  pathMtu = interface->ipv6Context.linkMtu;
1725 #endif
1726 
1727  //Check the length of the payload
1728  if((length + sizeof(Ipv6Header)) <= pathMtu)
1729  {
1730  //If the payload length is smaller than the PMTU then no fragmentation
1731  //is needed
1732  error = ipv6SendPacket(interface, pseudoHeader, 0, 0, buffer, offset,
1733  ancillary);
1734  }
1735  else
1736  {
1737 #if (IPV6_FRAG_SUPPORT == ENABLED)
1738  //This flag defines a mechanism to turn off fragmentation
1739  if(!ancillary->dontFrag)
1740  {
1741  //If the payload length exceeds the PMTU then the device must fragment
1742  //the data
1743  error = ipv6FragmentDatagram(interface, pseudoHeader, buffer, offset,
1744  pathMtu, ancillary);
1745  }
1746  else
1747 #endif
1748  {
1749  //When the data size is larger than the MTU of the outgoing interface,
1750  //the packet will be discarded
1751  error = ERROR_MESSAGE_TOO_LONG;
1752  }
1753  }
1754 
1755  //Return status code
1756  return error;
1757 }
1758 
1759 
1760 /**
1761  * @brief Send an IPv6 packet
1762  * @param[in] interface Underlying network interface
1763  * @param[in] pseudoHeader IPv6 pseudo header
1764  * @param[in] fragId Fragment identification field
1765  * @param[in] fragOffset Fragment offset field
1766  * @param[in] buffer Multi-part buffer containing the payload
1767  * @param[in] offset Offset to the first byte of the payload
1768  * @param[in] ancillary Additional options passed to the stack along with
1769  * the packet
1770  * @return Error code
1771  **/
1772 
1774  const Ipv6PseudoHeader *pseudoHeader, uint32_t fragId, size_t fragOffset,
1775  NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
1776 {
1777  error_t error;
1778  uint8_t nextHeader;
1779  size_t length;
1780  Ipv6Header *packet;
1781  NetContext *context;
1782 #if (ETH_SUPPORT == ENABLED)
1783  NetInterface *physicalInterface;
1784 #endif
1785 
1786  //Point to the TCP/IP stack context
1787  context = interface->netContext;
1788 
1789  //Get the value of the Next Header field
1790  nextHeader = pseudoHeader->nextHeader;
1791 
1792  //The Hop-by-Hop Options header is used to carry optional information that
1793  //must be examined by every node along a packet's delivery path
1794  if(ancillary->routerAlert)
1795  {
1796  //Format Hop-by-Hop Options header
1797  error = ipv6FormatHopByHopOptHeader(&nextHeader, buffer, &offset);
1798  //Any error to report?
1799  if(error)
1800  return error;
1801  }
1802 
1803  //The Fragment header is used by an IPv6 source to send a packet larger than
1804  //would fit in the path MTU to its destination
1805  if(fragOffset != 0)
1806  {
1807  //Format Fragment header
1808  error = ipv6FormatFragmentHeader(fragId, fragOffset, &nextHeader, buffer,
1809  &offset);
1810  //Any error to report?
1811  if(error)
1812  return error;
1813  }
1814 
1815  //Make sure there is sufficient space for the IPv6 header
1816  if(offset < sizeof(Ipv6Header))
1817  return ERROR_INVALID_PARAMETER;
1818 
1819  //Make room for the IPv6 header
1820  offset -= sizeof(Ipv6Header);
1821  //Calculate the size of the entire packet, including header and data
1822  length = netBufferGetLength(buffer) - offset;
1823 
1824  //Point to the IPv6 header
1825  packet = netBufferAt(buffer, offset, 0);
1826 
1827  //Format IPv6 header
1828  packet->version = IPV6_VERSION;
1829  packet->trafficClassH = (ancillary->tos >> 4) & 0x0F;
1830  packet->trafficClassL = ancillary->tos & 0x0F;
1831  packet->flowLabelH = 0;
1832  packet->flowLabelL = 0;
1833  packet->payloadLen = htons(length - sizeof(Ipv6Header));
1834  packet->nextHeader = nextHeader;
1835  packet->hopLimit = ancillary->ttl;
1836  packet->srcAddr = pseudoHeader->srcAddr;
1837  packet->destAddr = pseudoHeader->destAddr;
1838 
1839  //Check whether the Hop Limit value is zero
1840  if(packet->hopLimit == 0)
1841  {
1842  //Use default Hop Limit value
1843  packet->hopLimit = interface->ipv6Context.curHopLimit;
1844  }
1845 
1846  //Ensure the source address is valid
1847  error = ipv6CheckSourceAddr(interface, &pseudoHeader->srcAddr);
1848  //Invalid source address?
1849  if(error)
1850  return error;
1851 
1852  //Check destination address
1853  if(ipv6CompAddr(&pseudoHeader->destAddr, &IPV6_UNSPECIFIED_ADDR))
1854  {
1855  //The unspecified address must not appear on the public Internet
1856  error = ERROR_INVALID_ADDRESS;
1857  }
1858  else if(ipv6IsLocalHostAddr(context, &pseudoHeader->destAddr))
1859  {
1860 #if (NET_LOOPBACK_IF_SUPPORT == ENABLED)
1861  uint_t i;
1862 
1863  //Initialize status code
1864  error = ERROR_NO_ROUTE;
1865 
1866  //Loop through network interfaces
1867  for(i = 0; i < context->numInterfaces; i++)
1868  {
1869  //Point to the current interface
1870  interface = &context->interfaces[i];
1871 
1872  //Loopback interface?
1873  if(interface->nicDriver != NULL &&
1874  interface->nicDriver->type == NIC_TYPE_LOOPBACK)
1875  {
1876  //Forward the packet to the loopback interface
1877  error = nicSendPacket(interface, buffer, offset, ancillary);
1878  break;
1879  }
1880  }
1881 #else
1882  //The loopback address must not appear on the public Internet
1883  error = ERROR_NO_ROUTE;
1884 #endif
1885  }
1886  else
1887  {
1888 #if (ETH_SUPPORT == ENABLED)
1889  //Point to the physical interface
1890  physicalInterface = nicGetPhysicalInterface(interface);
1891 
1892  //Ethernet interface?
1893  if(physicalInterface->nicDriver != NULL &&
1894  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
1895  {
1897  NdpDestCacheEntry *entry;
1898 
1899  //When the sending node has a packet to send, it first examines
1900  //the Destination Cache
1901  entry = ndpFindDestCacheEntry(interface, &pseudoHeader->destAddr);
1902 
1903  //Check whether a matching entry exists
1904  if(entry != NULL)
1905  {
1906  //Retrieve the address of the next-hop
1907  destIpAddr = entry->nextHop;
1908  //Update timestamp
1909  entry->timestamp = osGetSystemTime();
1910  //No error to report
1911  error = NO_ERROR;
1912  }
1913  else
1914  {
1915  //Perform next-hop determination
1916  error = ndpSelectNextHop(interface, &pseudoHeader->destAddr, NULL,
1917  &destIpAddr, ancillary->dontRoute);
1918 
1919  //Check status code
1920  if(error == NO_ERROR)
1921  {
1922  //Create a new Destination Cache entry
1923  entry = ndpCreateDestCacheEntry(interface);
1924 
1925  //Destination cache entry successfully created?
1926  if(entry != NULL)
1927  {
1928  //Destination address
1929  entry->destAddr = pseudoHeader->destAddr;
1930  //Address of the next hop
1931  entry->nextHop = destIpAddr;
1932 
1933  //Initially, the PMTU value for a path is assumed to be the
1934  //MTU of the first-hop link
1935  entry->pathMtu = interface->ipv6Context.linkMtu;
1936 
1937  //Set timestamp
1938  entry->timestamp = osGetSystemTime();
1939  }
1940  }
1941  else if(error == ERROR_NO_ROUTE)
1942  {
1943  //Number of IP datagrams discarded because no route could be found
1944  //to transmit them to their destination
1945  IPV6_SYSTEM_STATS_INC_COUNTER32(outNoRoutes, 1);
1946  }
1947  }
1948 
1949  //Successful next-hop determination?
1950  if(error == NO_ERROR)
1951  {
1952  //Perform address resolution
1953  if(!macCompAddr(&ancillary->destMacAddr, &MAC_UNSPECIFIED_ADDR))
1954  {
1955  //The destination address is already resolved
1956  error = NO_ERROR;
1957  }
1958  else if(ipv6IsMulticastAddr(&destIpAddr))
1959  {
1960  //Map IPv6 multicast address to MAC-layer multicast address
1962  &ancillary->destMacAddr);
1963  }
1964  else
1965  {
1966  //Resolve host address using Neighbor Discovery protocol
1967  error = ndpResolve(interface, &destIpAddr, &ancillary->destMacAddr);
1968  }
1969 
1970  //Successful address resolution?
1971  if(error == NO_ERROR)
1972  {
1973  //Update IP statistics
1974  ipv6UpdateOutStats(interface, &destIpAddr, length);
1975 
1976  //Debug message
1977  TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
1978  //Dump IP header contents for debugging purpose
1979  ipv6DumpHeader(packet);
1980 
1981  //Send Ethernet frame
1982  error = ethSendFrame(interface, &ancillary->destMacAddr,
1983  ETH_TYPE_IPV6, buffer, offset, ancillary);
1984  }
1985  else if(error == ERROR_IN_PROGRESS)
1986  {
1987  //Debug message
1988  TRACE_INFO("Enqueuing IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
1989  //Dump IP header contents for debugging purpose
1990  ipv6DumpHeader(packet);
1991 
1992  //Enqueue packets waiting for address resolution
1993  error = ndpEnqueuePacket(NULL, interface, &destIpAddr, buffer,
1994  offset, ancillary);
1995  }
1996  else
1997  {
1998  //Debug message
1999  TRACE_WARNING("Cannot map IPv6 address to Ethernet address!\r\n");
2000  }
2001  }
2002  }
2003  else
2004 #endif
2005 #if (PPP_SUPPORT == ENABLED)
2006  //PPP interface?
2007  if(interface->nicDriver != NULL &&
2008  interface->nicDriver->type == NIC_TYPE_PPP)
2009  {
2010  //Update IP statistics
2011  ipv6UpdateOutStats(interface, &pseudoHeader->destAddr, length);
2012 
2013  //Debug message
2014  TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
2015  //Dump IP header contents for debugging purpose
2016  ipv6DumpHeader(packet);
2017 
2018  //Send PPP frame
2019  error = pppSendFrame(interface, buffer, offset, PPP_PROTOCOL_IPV6);
2020  }
2021  else
2022 #endif
2023  //6LoWPAN interface?
2024  if(interface->nicDriver != NULL &&
2025  interface->nicDriver->type == NIC_TYPE_6LOWPAN)
2026  {
2027  //Update IP statistics
2028  ipv6UpdateOutStats(interface, &pseudoHeader->destAddr, length);
2029 
2030  //Debug message
2031  TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
2032  //Dump IP header contents for debugging purpose
2033  ipv6DumpHeader(packet);
2034 
2035  //Send the packet over the specified link
2036  error = nicSendPacket(interface, buffer, offset, ancillary);
2037  }
2038  //Unknown interface type?
2039  else
2040  {
2041  //Report an error
2042  error = ERROR_INVALID_INTERFACE;
2043  }
2044  }
2045 
2046  //Return status code
2047  return error;
2048 }
2049 
2050 
2051 /**
2052  * @brief Format Hop-by-Hop Options header
2053  * @param[in,out] nextHeader Value of the Next Header field
2054  * @param[in] buffer Multi-part buffer containing the payload
2055  * @param[in,out] offset Offset to the first payload byte
2056  * @return Error code
2057  **/
2058 
2060  size_t *offset)
2061 {
2062  error_t error;
2063  Ipv6HopByHopOptHeader *header;
2064  Ipv6Option *option;
2065 
2066  //Make sure there is sufficient space for the Fragment header, the IPv6
2067  //Router Alert option and the PadN option
2068  if(*offset >= (sizeof(Ipv6HopByHopOptHeader) +
2069  sizeof(Ipv6RouterAlertOption) + sizeof(Ipv6Option)))
2070  {
2071  //Make room for the header
2072  *offset -= sizeof(Ipv6HopByHopOptHeader) + sizeof(Ipv6RouterAlertOption) +
2073  sizeof(Ipv6Option);
2074 
2075  //Point to the header
2076  header = netBufferAt(buffer, *offset, 0);
2077 
2078  //Format Hop-by-Hop Options header
2079  header->nextHeader = *nextHeader;
2080  header->hdrExtLen = 0;
2081 
2082  //Point to the first option
2083  option = (Ipv6Option *) header->options;
2084 
2085  //Format IPv6 Router Alert option
2086  option->type = IPV6_OPTION_TYPE_ROUTER_ALERT;
2087  option->length = sizeof(uint16_t);
2088  option->data[0] = 0;
2089  option->data[1] = 0;
2090 
2091  //Pad out the containing header to a multiple of 8 octets in length
2092  option = (Ipv6Option *) (header->options + sizeof(Ipv6RouterAlertOption));
2093 
2094  //The PadN option is used to insert two or more octets of padding into
2095  //the Options area of a header
2096  option->type = IPV6_OPTION_TYPE_PADN;
2097  option->length = 0;
2098 
2099  //Update the value of the Next Header field
2101 
2102  //Successful processing
2103  error = NO_ERROR;
2104  }
2105  else
2106  {
2107  //Report an error
2108  error = ERROR_INVALID_PARAMETER;
2109  }
2110 
2111  //Return status code
2112  return error;
2113 }
2114 
2115 
2116 /**
2117  * @brief Format Fragment header
2118  * @param[in] fragId Fragment identification field
2119  * @param[in] fragOffset Fragment offset field
2120  * @param[in,out] nextHeader Value of the Next Header field
2121  * @param[in] buffer Multi-part buffer containing the payload
2122  * @param[in,out] offset Offset to the first payload byte
2123  * @return Error code
2124  **/
2125 
2127  uint8_t *nextHeader, NetBuffer *buffer, size_t *offset)
2128 {
2129  error_t error;
2130  Ipv6FragmentHeader *header;
2131 
2132  //Make sure there is sufficient space for the Fragment header
2133  if(*offset >= sizeof(Ipv6FragmentHeader))
2134  {
2135  //Make room for the header
2136  *offset -= sizeof(Ipv6FragmentHeader);
2137  //Point to the header
2138  header = netBufferAt(buffer, *offset, 0);
2139 
2140  //Format Fragment header
2141  header->nextHeader = *nextHeader;
2142  header->reserved = 0;
2143  header->fragmentOffset = htons(fragOffset);
2144  header->identification = htonl(fragId);
2145 
2146  //Update the value of the Next Header field
2148 
2149  //Successful processing
2150  error = NO_ERROR;
2151  }
2152  else
2153  {
2154  //Report an error
2155  error = ERROR_INVALID_PARAMETER;
2156  }
2157 
2158  //Return status code
2159  return error;
2160 }
2161 
2162 
2163 /**
2164  * @brief Convert a string representation of an IPv6 address to a binary IPv6 address
2165  * @param[in] str NULL-terminated string representing the IPv6 address
2166  * @param[out] ipAddr Binary representation of the IPv6 address
2167  * @return Error code
2168  **/
2169 
2171 {
2172  error_t error;
2173  int_t i = 0;
2174  int_t j = -1;
2175  int_t k = 0;
2176  int32_t value = -1;
2177 
2178  //Parse input string
2179  while(1)
2180  {
2181  //Hexadecimal digit found?
2182  if(isxdigit((uint8_t) *str))
2183  {
2184  //First digit to be decoded?
2185  if(value < 0)
2186  {
2187  value = 0;
2188  }
2189 
2190  //Update the value of the current 16-bit word
2191  if(osIsdigit(*str))
2192  {
2193  value = (value * 16) + (*str - '0');
2194  }
2195  else if(osIsupper(*str))
2196  {
2197  value = (value * 16) + (*str - 'A' + 10);
2198  }
2199  else
2200  {
2201  value = (value * 16) + (*str - 'a' + 10);
2202  }
2203 
2204  //Check resulting value
2205  if(value > 0xFFFF)
2206  {
2207  //The conversion failed
2208  error = ERROR_INVALID_SYNTAX;
2209  break;
2210  }
2211  }
2212  //"::" symbol found?
2213  else if(osStrncmp(str, "::", 2) == 0)
2214  {
2215  //The "::" can only appear once in an IPv6 address
2216  if(j >= 0)
2217  {
2218  //The conversion failed
2219  error = ERROR_INVALID_SYNTAX;
2220  break;
2221  }
2222 
2223  //The "::" symbol is preceded by a number?
2224  if(value >= 0)
2225  {
2226  //Save the current 16-bit word
2227  ipAddr->w[i++] = htons(value);
2228  //Prepare to decode the next 16-bit word
2229  value = -1;
2230  }
2231 
2232  //Save the position of the "::" symbol
2233  j = i;
2234  //Point to the next character
2235  str++;
2236  }
2237  //":" symbol found?
2238  else if(*str == ':' && i < 8)
2239  {
2240  //Each ":" must be preceded by a valid number
2241  if(value < 0)
2242  {
2243  //The conversion failed
2244  error = ERROR_INVALID_SYNTAX;
2245  break;
2246  }
2247 
2248  //Save the current 16-bit word
2249  ipAddr->w[i++] = htons(value);
2250  //Prepare to decode the next 16-bit word
2251  value = -1;
2252  }
2253  //End of string detected?
2254  else if(*str == '\0' && i == 7 && j < 0)
2255  {
2256  //The NULL character must be preceded by a valid number
2257  if(value < 0)
2258  {
2259  //The conversion failed
2260  error = ERROR_INVALID_SYNTAX;
2261  }
2262  else
2263  {
2264  //Save the last 16-bit word of the IPv6 address
2265  ipAddr->w[i] = htons(value);
2266  //The conversion succeeded
2267  error = NO_ERROR;
2268  }
2269 
2270  //We are done
2271  break;
2272  }
2273  else if(*str == '\0' && i < 7 && j >= 0)
2274  {
2275  //Save the last 16-bit word of the IPv6 address
2276  if(value >= 0)
2277  {
2278  ipAddr->w[i++] = htons(value);
2279  }
2280 
2281  //Move the part of the address that follows the "::" symbol
2282  for(k = 0; k < (i - j); k++)
2283  {
2284  ipAddr->w[7 - k] = ipAddr->w[i - 1 - k];
2285  }
2286 
2287  //A sequence of zeroes can now be written in place of "::"
2288  for(k = 0; k < (8 - i); k++)
2289  {
2290  ipAddr->w[j + k] = 0;
2291  }
2292 
2293  //The conversion succeeded
2294  error = NO_ERROR;
2295  break;
2296  }
2297  //Invalid character...
2298  else
2299  {
2300  //The conversion failed
2301  error = ERROR_INVALID_SYNTAX;
2302  break;
2303  }
2304 
2305  //Point to the next character
2306  str++;
2307  }
2308 
2309  //Return status code
2310  return error;
2311 }
2312 
2313 
2314 /**
2315  * @brief Convert a binary IPv6 address to a string representation
2316  *
2317  * Call ipv6AddrToString() to convert an IPv6 address to a text representation. The
2318  * implementation of ipv6AddrToString() function follows RFC 5952 recommendations
2319  *
2320  * @param[in] ipAddr Binary representation of the IPv6 address
2321  * @param[out] str NULL-terminated string representing the IPv6 address
2322  * @return Pointer to the formatted string
2323  **/
2324 
2326 {
2327  static char_t buffer[40];
2328  uint_t i;
2329  uint_t j;
2330  char_t *p;
2331 
2332  //Best run of zeroes
2333  uint_t zeroRunStart = 0;
2334  uint_t zeroRunEnd = 0;
2335 
2336  //If the NULL pointer is given as parameter, then the internal buffer is used
2337  if(str == NULL)
2338  str = buffer;
2339 
2340  //Find the longest run of zeros for "::" short-handing
2341  for(i = 0; i < 8; i++)
2342  {
2343  //Compute the length of the current sequence of zeroes
2344  for(j = i; j < 8 && !ipAddr->w[j]; j++)
2345  {
2346  }
2347 
2348  //Keep track of the longest one
2349  if((j - i) > 1 && (j - i) > (zeroRunEnd - zeroRunStart))
2350  {
2351  //The symbol "::" should not be used to shorten just one zero field
2352  zeroRunStart = i;
2353  zeroRunEnd = j;
2354  }
2355  }
2356 
2357  //Format IPv6 address
2358  for(p = str, i = 0; i < 8; i++)
2359  {
2360  //Are we inside the best run of zeroes?
2361  if(i >= zeroRunStart && i < zeroRunEnd)
2362  {
2363  //Append a separator
2364  *(p++) = ':';
2365  //Skip the sequence of zeroes
2366  i = zeroRunEnd - 1;
2367  }
2368  else
2369  {
2370  //Add a separator between each 16-bit word
2371  if(i > 0)
2372  *(p++) = ':';
2373 
2374  //Convert the current 16-bit word to string
2375  p += osSprintf(p, "%" PRIx16, ntohs(ipAddr->w[i]));
2376  }
2377  }
2378 
2379  //A trailing run of zeroes has been found?
2380  if(zeroRunEnd == 8)
2381  *(p++) = ':';
2382 
2383  //Properly terminate the string
2384  *p = '\0';
2385 
2386  //Return a pointer to the formatted string
2387  return str;
2388 }
2389 
2390 
2391 /**
2392  * @brief Dump IPv6 header for debugging purpose
2393  * @param[in] ipHeader IPv6 header
2394  **/
2395 
2396 void ipv6DumpHeader(const Ipv6Header *ipHeader)
2397 {
2398  //Dump IPv6 header contents
2399  TRACE_DEBUG(" Version = %" PRIu8 "\r\n", ipHeader->version);
2400  TRACE_DEBUG(" Traffic Class = %u\r\n", (ipHeader->trafficClassH << 4) | ipHeader->trafficClassL);
2401  TRACE_DEBUG(" Flow Label = 0x%05X\r\n", (ipHeader->flowLabelH << 16) | ntohs(ipHeader->flowLabelL));
2402  TRACE_DEBUG(" Payload Length = %" PRIu16 "\r\n", ntohs(ipHeader->payloadLen));
2403  TRACE_DEBUG(" Next Header = %" PRIu8 "\r\n", ipHeader->nextHeader);
2404  TRACE_DEBUG(" Hop Limit = %" PRIu8 "\r\n", ipHeader->hopLimit);
2405  TRACE_DEBUG(" Src Addr = %s\r\n", ipv6AddrToString(&ipHeader->srcAddr, NULL));
2406  TRACE_DEBUG(" Dest Addr = %s\r\n", ipv6AddrToString(&ipHeader->destAddr, NULL));
2407 }
2408 
2409 #endif
@ IPV6_ADDR_STATE_TENTATIVE
An address whose uniqueness on a link is being verified.
Definition: ipv6.h:196
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2325
#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:1773
@ IPV6_ESP_HEADER
Definition: ipv6.h:213
@ ICMPV6_TYPE_DEST_UNREACHABLE
Definition: icmpv6.h:71
bool_t enableMulticastEchoReq
Support for multicast ICMPv6 Echo Request messages.
Definition: ipv6.h:524
systime_t lifetime
Router lifetime.
Definition: ipv6.h:479
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:530
#define NetContext
Definition: net.h:36
#define IPV6_IF_STATS_INC_COUNTER64(name, value)
Definition: ipv6.h:160
error_t ipv6ParseOptions(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t optionsOffset, size_t optionsLen)
Parse IPv6 options.
Definition: ipv6.c:1573
@ 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:532
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:400
#define IPV6_ADDR(a, b, c, d, e, f, g, h)
Definition: ipv6.h:127
void ipv6UpdateOutStats(NetInterface *interface, const Ipv6Addr *destIpAddr, size_t length)
Update IPv6 output statistics.
Definition: ipv6_misc.c:1477
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:522
systime_t preferredLifetime
Preferred lifetime.
Definition: ipv6.h:466
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:2059
error_t ipv6ParseDestOptHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
Parse Destination Options header.
Definition: ipv6.c:1407
#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:443
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:2126
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:282
@ ICMPV6_CODE_INVALID_HEADER_FIELD
Definition: icmpv6.h:119
#define IPV6_SYSTEM_STATS_INC_COUNTER64(name, value)
Definition: ipv6.h:158
bool_t autonomousFlag
Autonomous flag.
Definition: ipv6.h:464
uint8_t defaultHopLimit
Default Hop Limit value.
Definition: ipv6.h:521
uint8_t type
Definition: coap_common.h:176
systime_t validLifetime
Valid lifetime.
Definition: ipv6.h:465
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:1128
@ IPV6_OPTION_TYPE_PAD1
Definition: ipv6.h:241
IPv6 routing.
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:136
Ipv6DestOptHeader
Definition: ipv6.h:333
@ IPV6_ICMPV6_HEADER
Definition: ipv6.h:215
error_t udpProcessDatagram(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Incoming UDP datagram processing.
Definition: udp.c:121
Ipv6Addr prefix
IPv6 prefix information.
Definition: ipv6.h:461
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:257
@ IPV6_ACTION_DISCARD_PACKET
Definition: ipv6.h:256
Ipv6Addr addr
Router address.
Definition: ipv6.h:478
error_t ipv6Init(NetInterface *interface)
IPv6 related initialization.
Definition: ipv6.c:95
Ipv6Addr prefix
#define NDP_INFINITE_LIFETIME
Definition: ndp.h:202
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:157
#define IPV6_DEFAULT_HOP_LIMIT
Definition: ipv6.h:67
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:518
@ IPV6_ADDR_STATE_INVALID
An address that is not assigned to any interface.
Definition: ipv6.h:195
uint8_t ipPacket[]
Definition: ndp.h:431
void mldLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: mld_common.c:115
@ 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:1531
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:148
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:518
void ndpLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ndp.c:635
#define IPV6_VERSION
Definition: ipv6.h:122
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:194
error_t
Error codes.
Definition: error.h:43
@ ERROR_PROTOCOL_UNREACHABLE
Definition: error.h:84
#define osSprintf(dest,...)
Definition: os_port.h:237
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:44
@ IPV6_ACTION_SKIP_OPTION
Definition: ipv6.h:255
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:460
void ipv6DumpHeader(const Ipv6Header *ipHeader)
Dump IPv6 header for debugging purpose.
Definition: ipv6.c:2396
@ IPV6_UDP_HEADER
Definition: ipv6.h:210
@ 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:480
const Ipv6Addr IPV6_LINK_LOCAL_ALL_NODES_ADDR
Definition: ipv6.c:73
bool_t permanent
Permanently assigned address.
Definition: ipv6.h:448
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:529
#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:525
#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:720
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint8_t nextHeader
Definition: ipv6.h:304
Helper functions for IPv6.
@ IPV6_HOP_BY_HOP_OPT_HEADER
Definition: ipv6.h:208
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:197
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:102
#define osIsdigit(c)
Definition: os_port.h:291
@ 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:244
Neighbor and destination cache management.
uint8_t hopLimit
Definition: ipv6.h:305
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:463
#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:527
IPv6 fragmentation and reassembly.
bool_t permanent
Permanently assigned prefix.
Definition: ipv6.h:467
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:412
uint8_t prefixLen
IPv6 prefix length.
Definition: ipv6.h:462
#define IPV6_ANYCAST_ADDR_LIST_SIZE
Definition: ipv6.h:81
Default router list entry.
Definition: ipv6.h:477
#define IPV6_DEFAULT_MTU
Definition: ipv6.h:124
IPv6 address entry.
Definition: ipv6.h:442
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1034
error_t ipv6ParseEspHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
Parse ESP header.
Definition: ipv6.c:1552
IPv4 and IPv6 common routines.
@ IPV6_TCP_HEADER
Definition: ipv6.h:209
uint8_t n
#define IPV6_ROUTER_LIST_SIZE
Definition: ipv6.h:95
const Ipv6Addr IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR
Definition: ipv6.c:77
#define IpPseudoHeader
Definition: ip.h:36
error_t ipv6SendDatagram(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 datagram.
Definition: ipv6.c:1697
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:74
@ IPV6_NO_NEXT_HEADER
Definition: ipv6.h:216
Ipv6FragDesc fragQueue[IPV6_MAX_FRAG_DATAGRAMS]
IPv6 fragment reassembly queue.
Definition: ipv6.h:533
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:240
error_t ipv6ParseRoutingHeader(NetInterface *interface, const NetBuffer *ipPacket, size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset)
Parse Routing header.
Definition: ipv6.c:1465
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:1394
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:40
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:183
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:2170
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:520
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:242
#define IPV6_IF_STATS_INC_COUNTER32(name, value)
Definition: ipv6.h:159
@ IPV6_ADDR_STATE_PREFERRED
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:197
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:481
Ipv6AddrState state
IPv6 address state.
Definition: ipv6.h:444
Ipv6RoutingHeader
Definition: ipv6.h:348
#define IPV6_PREFIX_LIST_SIZE
Definition: ipv6.h:88
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:141
TCP/IP stack core.
@ IPV6_ROUTING_HEADER
Definition: ipv6.h:211
@ IPV6_ADDR_STATE_DEPRECATED
An address assigned to an interface whose use is discouraged.
Definition: ipv6.h:198
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:285
size_t linkMtu
Maximum transmission unit.
Definition: ipv6.h:519
bool_t ipv6IsLocalHostAddr(NetContext *context, const Ipv6Addr *ipAddr)
Check whether the specified IPv6 is assigned to the host.
Definition: ipv6_misc.c:1165
void ipv6UpdateInStats(NetInterface *interface, const Ipv6Addr *destIpAddr, size_t length)
Update IPv6 input statistics.
Definition: ipv6_misc.c:1453
@ IPV6_DEST_OPT_HEADER
Definition: ipv6.h:217
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:258
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:214
bool_t enableEchoReq
Support for ICMPv6 Echo Request messages.
Definition: ipv6.h:523
@ IPV6_ACTION_MASK
Definition: ipv6.h:254
@ IPV6_FRAGMENT_HEADER
Definition: ipv6.h:212
error_t ipv6GetMtu(NetInterface *interface, size_t *mtu)
Retrieve the MTU for the specified interface.
Definition: ipv6.c:194
Ipv6HopByHopOptHeader
Definition: ipv6.h:321
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:528
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
systime_t osGetSystemTime(void)
Retrieve system time.
Ipv4Addr destIpAddr
Definition: ipcp.h:80