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