ipv6_routing.c
Go to the documentation of this file.
1 /**
2  * @file ipv6_routing.c
3  * @brief IPv6 routing
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  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL IPV6_TRACE_LEVEL
33 
34 //Dependencies
35 #include <limits.h>
36 #include "core/net.h"
37 #include "core/ip.h"
38 #include "ipv6/ipv6.h"
39 #include "ipv6/ipv6_misc.h"
40 #include "ipv6/ipv6_multicast.h"
41 #include "ipv6/ipv6_routing.h"
42 #include "ipv6/icmpv6.h"
43 #include "ipv6/ndp.h"
44 #include "debug.h"
45 
46 //Check TCP/IP stack configuration
47 #if (IPV6_SUPPORT == ENABLED && IPV6_ROUTING_SUPPORT == ENABLED)
48 
49 
50 /**
51  * @brief Initialize IPv6 routing table
52  * @param[in] context Pointer to the TCP/IP stack context
53  * @return Error code
54  **/
55 
57 {
58  uint_t i;
59 
60  //Clear the routing table
61  for(i = 0; i < IPV6_ROUTING_TABLE_SIZE; i++)
62  {
63  osMemset(&context->ipv6RoutingTable[i], 0, sizeof(Ipv6RoutingTableEntry));
64  }
65 
66  //Successful initialization
67  return NO_ERROR;
68 }
69 
70 
71 /**
72  * @brief Enable routing for the specified interface
73  * @param[in] interface Underlying network interface
74  * @param[in] enable When the flag is set to TRUE, routing is enabled on the
75  * interface and the router can forward packets to or from the interface
76  * @return Error code
77  **/
78 
80 {
81  //Check parameters
82  if(interface == NULL)
84 
85  //Get exclusive access
86  netLock(interface->netContext);
87  //Enable or disable routing
88  interface->ipv6Context.isRouter = enable;
89  //Release exclusive access
90  netUnlock(interface->netContext);
91 
92  //Successful processing
93  return NO_ERROR;
94 }
95 
96 
97 /**
98  * @brief Add a new entry in the IPv6 routing table
99  * @param[in] context Pointer to the TCP/IP stack context
100  * @param[in] prefix Network destination
101  * @param[in] prefixLen Length of the prefix, in bits
102  * @param[in] interface Network interface where to forward the packet
103  * @param[in] nextHop IPv6 address of the next hop
104  * @param[in] metric Metric value
105  * @return Error code
106  **/
107 
109  uint_t prefixLen, NetInterface *interface, const Ipv6Addr *nextHop,
110  uint_t metric)
111 {
112  error_t error;
113  uint_t i;
114  Ipv6RoutingTableEntry *entry;
115  Ipv6RoutingTableEntry *firstFreeEntry;
116 
117  //Check parameters
118  if(context == NULL || prefix == NULL || interface == NULL)
120 
121  //Keep track of the first free entry
122  firstFreeEntry = NULL;
123 
124  //Get exclusive access
125  netLock(context);
126 
127  //Loop through routing table entries
128  for(i = 0; i < IPV6_ROUTING_TABLE_SIZE; i++)
129  {
130  //Point to the current entry
131  entry = &context->ipv6RoutingTable[i];
132 
133  //Valid entry?
134  if(entry->valid)
135  {
136  //Check prefix length
137  if(entry->prefixLen == prefixLen)
138  {
139  //Check whether the current entry matches the specified destination
140  if(ipv6CompPrefix(&entry->prefix, prefix, prefixLen))
141  break;
142  }
143  }
144  else
145  {
146  //Keep track of the first free entry
147  if(firstFreeEntry == NULL)
148  {
149  firstFreeEntry = entry;
150  }
151  }
152  }
153 
154  //If the routing table does not contain the specified destination,
155  //then a new entry should be created
156  if(i >= IPV6_ROUTING_TABLE_SIZE)
157  {
158  entry = firstFreeEntry;
159  }
160 
161  //Check whether the routing table runs out of space
162  if(entry != NULL)
163  {
164  //Network destination
165  entry->prefix = *prefix;
166  entry->prefixLen = prefixLen;
167 
168  //Interface where to forward the packet
169  entry->interface = interface;
170 
171  //Address of the next hop
172  if(nextHop != NULL)
173  {
174  entry->nextHop = *nextHop;
175  }
176  else
177  {
179  }
180 
181  //Metric value
182  entry->metric = metric;
183  //The entry is now valid
184  entry->valid = TRUE;
185 
186  //Successful processing
187  error = NO_ERROR;
188  }
189  else
190  {
191  //The routing table is full
192  error = ERROR_FAILURE;
193  }
194 
195  //Release exclusive access
196  netUnlock(context);
197 
198  //Return status code
199  return error;
200 }
201 
202 
203 /**
204  * @brief Remove an entry from the IPv6 routing table
205  * @param[in] context Pointer to the TCP/IP stack context
206  * @param[in] prefix Network destination
207  * @param[in] prefixLen Length of the prefix, in bits
208  * @return Error code
209  **/
210 
213 {
214  error_t error;
215  uint_t i;
216  Ipv6RoutingTableEntry *entry;
217 
218  //Valid TCP/IP stack context?
219  if(context != NULL)
220  {
221  //Initialize status code
222  error = ERROR_NOT_FOUND;
223 
224  //Get exclusive access
225  netLock(context);
226 
227  //Loop through routing table entries
228  for(i = 0; i < IPV6_ROUTING_TABLE_SIZE; i++)
229  {
230  //Point to the current entry
231  entry = &context->ipv6RoutingTable[i];
232 
233  //Valid entry?
234  if(entry->valid)
235  {
236  //Check prefix length
237  if(entry->prefixLen == prefixLen)
238  {
239  //Check whether the current entry matches the specified destination
240  if(ipv6CompPrefix(&entry->prefix, prefix, prefixLen))
241  {
242  //Delete current entry
243  entry->valid = FALSE;
244  //The route was successfully deleted from the routing table
245  error = NO_ERROR;
246  }
247  }
248  }
249  }
250 
251  //Release exclusive access
252  netUnlock(context);
253  }
254  else
255  {
256  //Report an error
257  error = ERROR_INVALID_PARAMETER;
258  }
259 
260  //Return status code
261  return error;
262 }
263 
264 
265 /**
266  * @brief Delete all routes from the IPv6 routing table
267  * @param[in] context Pointer to the TCP/IP stack context
268  * @return Error code
269  **/
270 
272 {
273  error_t error;
274  uint_t i;
275 
276  //Valid TCP/IP stack context?
277  if(context != NULL)
278  {
279  //Get exclusive access
280  netLock(context);
281 
282  //Clear the routing table
283  for(i = 0; i < IPV6_ROUTING_TABLE_SIZE; i++)
284  {
285  osMemset(&context->ipv6RoutingTable[i], 0,
286  sizeof(Ipv6RoutingTableEntry));
287  }
288 
289  //Release exclusive access
290  netUnlock(context);
291 
292  //Successful processing
293  error = NO_ERROR;
294  }
295  else
296  {
297  //Report an error
298  error = ERROR_INVALID_PARAMETER;
299  }
300 
301  //Return status code
302  return error;
303 }
304 
305 
306 /**
307  * @brief Forward an IPv6 packet
308  * @param[in] srcInterface Network interface on which the packet was received
309  * @param[in] ipPacket Multi-part buffer that holds the IPv6 packet to forward
310  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
311  * @return Error code
312  **/
313 
315  size_t ipPacketOffset)
316 {
317  error_t error;
318  uint_t i;
319  uint_t metric;
321  bool_t match;
322  size_t length;
323  size_t destOffset;
324  NetContext *context;
325  NetInterface *destInterface;
326  NetBuffer *destBuffer;
327  Ipv6Header *ipHeader;
328  Ipv6RoutingTableEntry *entry;
330 #if (ETH_SUPPORT == ENABLED)
331  NetInterface *physicalInterface;
332 #endif
333 
334  //Point to the TCP/IP stack context
335  context = srcInterface->netContext;
336 
337  //If routing is not enabled on the interface, then the router cannot
338  //forward packets from the interface
339  if(!srcInterface->ipv6Context.isRouter)
340  return ERROR_FAILURE;
341 
342  //Silently drop any IP packets received on an interface that has
343  //not been assigned a valid link-local address
345  return ERROR_NOT_CONFIGURED;
346 
347  //Calculate the length of the IPv6 packet
348  length = netBufferGetLength(ipPacket) - ipPacketOffset;
349 
350  //Ensure the packet length is greater than 40 bytes
351  if(length < sizeof(Ipv6Header))
352  return ERROR_INVALID_LENGTH;
353 
354  //Point to the IPv6 header
355  ipHeader = netBufferAt(ipPacket, ipPacketOffset, 0);
356 
357  //Sanity check
358  if(ipHeader == NULL)
359  return ERROR_FAILURE;
360 
361  //An IPv6 packet with a source address of unspecified must never be
362  //forwarded by an IPv6 router (refer to RFC section 3513 2.5.2)
363  if(ipv6CompAddr(&ipHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR))
364  return ERROR_INVALID_ADDRESS;
365 
366  //The unspecified address must not be used as the destination address
367  //of IPv6 packets (refer to RFC section 3513 2.5.2)
368  if(ipv6CompAddr(&ipHeader->destAddr, &IPV6_UNSPECIFIED_ADDR))
369  return ERROR_INVALID_ADDRESS;
370 
371  //An IPv6 packet with a destination address of loopback must never be
372  //forwarded by an IPv6 router (refer to RFC 3513 section 2.5.3)
373  if(ipv6CompAddr(&ipHeader->destAddr, &IPV6_LOOPBACK_ADDR))
374  return ERROR_INVALID_ADDRESS;
375 
376  //Check whether the destination address is a link-local address
377  if(ipv6IsLinkLocalUnicastAddr(&ipHeader->destAddr))
378  {
379  //Forward the packet on the same network interface
380  destInterface = srcInterface;
381  //Next hop
382  destIpAddr = ipHeader->destAddr;
383  }
384  else
385  {
386  //Lowest metric value
387  metric = UINT_MAX;
388  //Longest prefix length
389  prefixLen = 0;
390  //Outgoing network interface
391  destInterface = NULL;
392 
393  //Route determination process
394  for(i = 0; i < IPV6_ROUTING_TABLE_SIZE; i++)
395  {
396  //Point to the current entry
397  entry = &context->ipv6RoutingTable[i];
398 
399  //Valid entry?
400  if(entry->valid && entry->interface != NULL)
401  {
402  //Clear flag
403  match = FALSE;
404 
405  //Do not forward any IP packets to an interface that has not
406  //been assigned a valid link-local address...
408  {
409  //If routing is enabled on the interface, then the router
410  //can forward packets to the interface
411  if(entry->interface->ipv6Context.isRouter)
412  {
413  //Compare the destination address with the current entry for a match
414  if(ipv6CompPrefix(&ipHeader->destAddr, &entry->prefix, entry->prefixLen))
415  {
416  //The longest matching route is the most specific route to the
417  //destination IPv6 address...
418  if(entry->prefixLen > prefixLen)
419  {
420  //Give the current route the higher precedence
421  match = TRUE;
422  }
423  else if(entry->prefixLen == prefixLen)
424  {
425  //If multiple entries with the longest match are found, the
426  //router uses the lowest metric to select the best route
427  if(entry->metric < metric)
428  {
429  //Give the current route the higher precedence
430  match = TRUE;
431  }
432  }
433  }
434  }
435  }
436 
437  //Matching entry?
438  if(match)
439  {
440  //Select the current route
441  metric = entry->metric;
442  prefixLen = entry->prefixLen;
443 
444  //Outgoing interface on which to forward the packet
445  destInterface = entry->interface;
446 
447  //Next hop
449  {
450  destIpAddr = entry->nextHop;
451  }
452  else
453  {
454  destIpAddr = ipHeader->destAddr;
455  }
456  }
457  }
458  }
459  }
460 
461  //No route to the destination?
462  if(destInterface == NULL)
463  {
464  //A Destination Unreachable message should be generated by a router
465  //in response to a packet that cannot be delivered
467  ICMPV6_CODE_NO_ROUTE_TO_DEST, 0, ipPacket, ipPacketOffset);
468 
469  //Exit immediately
470  return ERROR_NO_ROUTE;
471  }
472 
473  //Check whether the length of the IPv6 packet is larger than the link MTU
474  if(length > destInterface->ipv6Context.linkMtu)
475  {
476  //A Packet Too Big must be sent by a router in response to a packet
477  //that it cannot forward because the packet is larger than the MTU
478  //of the outgoing link
480  0, destInterface->ipv6Context.linkMtu, ipPacket, ipPacketOffset);
481 
482  //Exit immediately
483  return ERROR_INVALID_LENGTH;
484  }
485 
486  //Check whether the packet is explicitly addressed to the router itself
487  if(!ipv6CheckDestAddr(destInterface, &ipHeader->destAddr))
488  {
489  //Valid unicast address?
490  if(!ipv6IsMulticastAddr(&ipHeader->destAddr))
491  {
492  //Process IPv6 packet
493  //ipv6ProcessPacket(destInterface, ipPacket, ipPacketOffset);
494  //Exit immediately
495  return NO_ERROR;
496  }
497  }
498 
499  //Check whether the IPv6 packet is about to be sent out the interface
500  //on which it was received
501  if(destInterface == srcInterface)
502  {
503 #if (NDP_SUPPORT == ENABLED)
504  //A router should send a Redirect message whenever it forwards a packet
505  //that is not explicitly addressed to itself in which the source address
506  //identifies a neighbor, and
507  if(ipv6IsOnLink(srcInterface, &ipHeader->srcAddr))
508  {
509  //The router determines that a better first-hop node resides on the
510  //same link as the sending node for the destination address of the
511  //packet being forwarded, and
512  if(ipv6IsOnLink(destInterface, &destIpAddr))
513  {
514  //The destination address of the packet is not a multicast address
515  if(!ipv6IsMulticastAddr(&ipHeader->destAddr))
516  {
517  //Transmit a Redirect message
518  ndpSendRedirect(srcInterface, &destIpAddr, ipPacket, ipPacketOffset);
519  }
520  }
521  }
522 #endif
523  }
524  else
525  {
526  //Check whether the scope of the source address is smaller than the
527  //scope of the destination address
528  if(ipv6GetAddrScope(&ipHeader->srcAddr) < ipv6GetAddrScope(&ipHeader->destAddr))
529  {
530  //A Destination Unreachable message should be generated by a router
531  //in response to a packet that cannot be delivered without leaving
532  //the scope of the source address
534  ICMPV6_CODE_BEYOND_SCOPE_OF_SRC_ADDR, 0, ipPacket, ipPacketOffset);
535 
536  //Exit immediately
537  return ERROR_INVALID_ADDRESS;
538  }
539  }
540 
541  //Hop Limit exceeded in transit?
542  if(ipHeader->hopLimit <= 1)
543  {
544  //If a router receives a packet with a Hop Limit of zero, or if a router
545  //decrements a packet's Hop Limit to zero, it must discard the packet
546  //and originate an ICMPv6 Time Exceeded message
548  ICMPV6_CODE_HOP_LIMIT_EXCEEDED, 0, ipPacket, ipPacketOffset);
549 
550  //Exit immediately
551  return ERROR_FAILURE;
552  }
553 
554  //The Hop-by-Hop Options header, when present, must immediately follow
555  //the IPv6 header. Its presence is indicated by the value zero in the
556  //Next Header field of the IPv6 header
557  if(ipHeader->nextHeader == IPV6_HOP_BY_HOP_OPT_HEADER)
558  {
559  //Point to the extension header
560  size_t headerOffset = ipPacketOffset + sizeof(Ipv6Header);
561 
562  //Calculate the offset of the Next Header field
563  size_t nextHeaderOffset = ipPacketOffset +
564  &ipHeader->nextHeader - (uint8_t *) ipHeader;
565 
566  //The Hop-by-Hop Options header is used to carry optional information
567  //that must be examined by every node along a packet's delivery path
568  error = ipv6ParseHopByHopOptHeader(srcInterface,
569  ipPacket, ipPacketOffset, &headerOffset, &nextHeaderOffset);
570 
571  //Any error while processing the extension header?
572  if(error)
573  return error;
574  }
575 
576  //Allocate a buffer to hold the IPv6 packet
577  destBuffer = ethAllocBuffer(length, &destOffset);
578 
579  //Successful memory allocation?
580  if(destBuffer != NULL)
581  {
582  //Copy IPv6 packet
583  error = netBufferCopy(destBuffer, destOffset, ipPacket, ipPacketOffset,
584  length);
585 
586  //Check status code
587  if(!error)
588  {
589  //Point to the IPv6 header
590  ipHeader = netBufferAt(destBuffer, destOffset, 0);
591  //Every time a router forwards a packet, it decrements the Hop Limit field
592  ipHeader->hopLimit--;
593 
594 #if (ETH_SUPPORT == ENABLED)
595  //Point to the physical interface
596  physicalInterface = nicGetPhysicalInterface(destInterface);
597 
598  //Ethernet interface?
599  if(physicalInterface->nicDriver != NULL &&
600  physicalInterface->nicDriver->type == NIC_TYPE_ETHERNET)
601  {
602  MacAddr destMacAddr;
603  NetTxAncillary ancillary;
604 
605  //Additional options can be passed to the stack along with the packet
606  ancillary = NET_DEFAULT_TX_ANCILLARY;
607 
608  //Destination IPv6 address
610  destIpAddr = ipHeader->destAddr;
611 
612  //Check whether the destination IPv6 address is a multicast address?
614  {
615  //Map IPv6 multicast address to MAC-layer multicast address
616  error = ipv6MapMulticastAddrToMac(&destIpAddr, &destMacAddr);
617  }
618  else
619  {
620  //Resolve host address using Neighbor Discovery protocol
621  error = ndpResolve(destInterface, &destIpAddr, &destMacAddr);
622  }
623 
624  //Successful address resolution?
625  if(!error)
626  {
627  //Debug message
628  TRACE_INFO("Forwarding IPv6 packet to %s (%" PRIuSIZE " bytes)...\r\n",
629  destInterface->name, length);
630  //Dump IP header contents for debugging purpose
631  ipv6DumpHeader(ipHeader);
632 
633  //Send Ethernet frame
634  error = ethSendFrame(destInterface, &destMacAddr, ETH_TYPE_IPV6,
635  destBuffer, destOffset, &ancillary);
636  }
637  //Address resolution in progress?
638  else if(error == ERROR_IN_PROGRESS)
639  {
640  //Debug message
641  TRACE_INFO("Enqueuing IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length);
642  //Dump IP header contents for debugging purpose
643  ipv6DumpHeader(ipHeader);
644 
645  //Enqueue packets waiting for address resolution
646  error = ndpEnqueuePacket(srcInterface, destInterface, &destIpAddr,
647  destBuffer, destOffset, &ancillary);
648  }
649  //Address resolution failed?
650  else
651  {
652  //Debug message
653  TRACE_WARNING("Cannot map IPv6 address to Ethernet address!\r\n");
654  }
655  }
656  else
657 #endif
658 #if (PPP_SUPPORT == ENABLED)
659  //PPP interface?
660  if(destInterface->nicDriver != NULL &&
661  destInterface->nicDriver->type == NIC_TYPE_PPP)
662  {
663  //Debug message
664  TRACE_INFO("Forwarding IPv6 packet to %s (%" PRIuSIZE " bytes)...\r\n",
665  destInterface->name, length);
666  //Dump IP header contents for debugging purpose
667  ipv6DumpHeader(ipHeader);
668 
669  //Send PPP frame
670  error = pppSendFrame(destInterface, destBuffer, destOffset,
672  }
673  else
674 #endif
675  //6LoWPAN interface?
676  if(destInterface->nicDriver != NULL &&
677  destInterface->nicDriver->type == NIC_TYPE_6LOWPAN)
678  {
679  NetTxAncillary ancillary;
680 
681  //Debug message
682  TRACE_INFO("Forwarding IPv6 packet to %s (%" PRIuSIZE " bytes)...\r\n",
683  destInterface->name, length);
684  //Dump IP header contents for debugging purpose
685  ipv6DumpHeader(ipHeader);
686 
687  //Additional options can be passed to the stack along with the packet
688  ancillary = NET_DEFAULT_TX_ANCILLARY;
689 
690  //Send the packet over the specified link
691  error = nicSendPacket(destInterface, destBuffer, destOffset,
692  &ancillary);
693  }
694  else
695  //Unknown interface type?
696  {
697  //Report an error
698  error = ERROR_INVALID_INTERFACE;
699  }
700  }
701 
702  //Free previously allocated memory
703  netBufferFree(destBuffer);
704  }
705  else
706  {
707  //Failed to allocate memory
708  error = ERROR_OUT_OF_MEMORY;
709  }
710 
711  //Return status code
712  return error;
713 }
714 
715 #endif
IPv6 (Internet Protocol Version 6)
@ ICMPV6_TYPE_PACKET_TOO_BIG
Definition: icmpv6.h:72
@ ICMPV6_TYPE_DEST_UNREACHABLE
Definition: icmpv6.h:71
void netUnlock(NetContext *context)
Release exclusive access to the core of the TCP/IP stack.
Definition: net.c:319
#define NetContext
Definition: net.h:36
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:70
@ ERROR_INVALID_INTERFACE
Invalid interface.
Definition: error.h:53
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
Ipv6Addr nextHop
Next hop.
Definition: ipv6_routing.h:68
error_t ndpSendRedirect(NetInterface *interface, const Ipv6Addr *targetAddr, const NetBuffer *ipPacket, size_t ipPacketOffset)
Send a Redirect message.
Definition: ndp.c:2089
#define TRUE
Definition: os_port.h:50
#define Ipv6Header
Definition: ipv6.h:36
error_t ethSendFrame(NetInterface *interface, const MacAddr *destAddr, uint16_t type, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an Ethernet frame.
Definition: ethernet.c:406
Ipv6Addr
Definition: ipv6.h:280
#define IPV6_ROUTING_TABLE_SIZE
Definition: ipv6_routing.h:47
Routing table entry.
Definition: ipv6_routing.h:63
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
IPv6 routing.
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:134
@ ERROR_NOT_CONFIGURED
Definition: error.h:218
Ipv6Addr prefix
uint_t prefixLen
IPv6 prefix length.
Definition: ipv6_routing.h:66
uint8_t ipPacket[]
Definition: ndp.h:431
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:146
IPv6 multicast filtering.
@ ERROR_IN_PROGRESS
Definition: error.h:214
error_t icmpv6SendErrorMessage(NetInterface *interface, uint8_t type, uint8_t code, uint32_t parameter, const NetBuffer *ipPacket, size_t ipPacketOffset)
Send an ICMPv6 Error message.
Definition: icmpv6.c:521
#define FALSE
Definition: os_port.h:46
ICMPv6 (Internet Control Message Protocol Version 6)
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:87
error_t
Error codes.
Definition: error.h:43
void ipv6DumpHeader(const Ipv6Header *ipHeader)
Dump IPv6 header for debugging purpose.
Definition: ipv6.c:2415
@ 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
#define NetInterface
Definition: net.h:40
error_t ipv6CheckDestAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Destination IPv6 address filtering.
Definition: ipv6_misc.c:814
uint_t ipv6GetAddrScope(const Ipv6Addr *ipAddr)
Retrieve the scope of an IPv6 address.
Definition: ipv6_misc.c:1263
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ICMPV6_CODE_HOP_LIMIT_EXCEEDED
Definition: icmpv6.h:109
Helper functions for IPv6.
@ IPV6_HOP_BY_HOP_OPT_HEADER
Definition: ipv6.h:206
error_t ipv6MapMulticastAddrToMac(const Ipv6Addr *ipAddr, MacAddr *macAddr)
Map an IPv6 multicast address to a MAC-layer multicast address.
#define NetTxAncillary
Definition: net_misc.h:36
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
const Ipv6Addr IPV6_LOOPBACK_ADDR
Definition: ipv6.c:69
error_t netBufferCopy(NetBuffer *dest, size_t destOffset, const NetBuffer *src, size_t srcOffset, size_t length)
Copy data between multi-part buffers.
Definition: net_mem.c:522
@ 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
NetInterface * interface
Outgoing network interface.
Definition: ipv6_routing.h:67
bool_t valid
Valid entry.
Definition: ipv6_routing.h:64
MacAddr
Definition: ethernet.h:197
#define ipv6IsLinkLocalUnicastAddr(ipAddr)
Definition: ipv6.h:138
@ ERROR_NO_ROUTE
Definition: error.h:221
error_t ipv6AddRoute(NetContext *context, const Ipv6Addr *prefix, uint_t prefixLen, NetInterface *interface, const Ipv6Addr *nextHop, uint_t metric)
Add a new entry in the IPv6 routing table.
Definition: ipv6_routing.c:108
NDP (Neighbor Discovery Protocol)
@ NIC_TYPE_PPP
PPP interface.
Definition: nic.h:84
#define TRACE_WARNING(...)
Definition: debug.h:93
uint8_t prefixLen
error_t ipv6InitRouting(NetContext *context)
Initialize IPv6 routing table.
Definition: ipv6_routing.c:56
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1036
@ ICMPV6_CODE_BEYOND_SCOPE_OF_SRC_ADDR
Definition: icmpv6.h:97
uint_t metric
Metric value.
Definition: ipv6_routing.h:69
IPv4 and IPv6 common routines.
Ipv6Addr prefix
Destination.
Definition: ipv6_routing.h:65
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
Ipv6AddrState ipv6GetLinkLocalAddrState(NetInterface *interface)
Get the state of the link-local address.
Definition: ipv6.c:330
error_t ipv6EnableRouting(NetInterface *interface, bool_t enable)
Enable routing for the specified interface.
Definition: ipv6_routing.c:79
error_t ipv6DeleteAllRoutes(NetContext *context)
Delete all routes from the IPv6 routing table.
Definition: ipv6_routing.c:271
bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2, size_t length)
Compare IPv6 address prefixes.
Definition: ipv6_misc.c:1218
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_t ipv6DeleteRoute(NetContext *context, const Ipv6Addr *prefix, uint_t prefixLen)
Remove an entry from the IPv6 routing table.
Definition: ipv6_routing.c:211
void netLock(NetContext *context)
Get exclusive access to the core of the TCP/IP stack.
Definition: net.c:307
void * netBufferAt(const NetBuffer *buffer, size_t offset, size_t length)
Returns a pointer to a data segment.
Definition: net_mem.c:418
@ ICMPV6_CODE_NO_ROUTE_TO_DEST
Definition: icmpv6.h:95
error_t ndpResolve(NetInterface *interface, const Ipv6Addr *ipAddr, MacAddr *macAddr)
Address resolution using Neighbor Discovery protocol.
Definition: ndp.c:353
@ IPV6_ADDR_STATE_PREFERRED
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:195
NetBuffer * ethAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an Ethernet frame.
Definition: ethernet.c:784
#define PRIuSIZE
@ NIC_TYPE_6LOWPAN
6LoWPAN interface
Definition: nic.h:87
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
bool_t ipv6IsOnLink(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is on-link.
Definition: ipv6_misc.c:1041
@ NO_ERROR
Success.
Definition: error.h:44
@ ICMPV6_TYPE_TIME_EXCEEDED
Definition: icmpv6.h:73
Debugging facilities.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
Ipv4Addr destIpAddr
Definition: ipcp.h:80