IPv6 Router Discovery
Table of Contents >> Optional Protocols
Neighbor Discovery is an important aspect of IPv6 that includes Router Discovery—the ability of an IPv6 host to learn information about the local network to which it is connected.
RFC 4861, Neighbor Discovery for IP Version 6, and RFC 4862, IPv6 Stateless Address Autoconfiguration, provide a protocol by which one node (the router) can configure another (the host).
Treck does not provide a complete router solution but there are occasions when a Treck application needs to send a Router Advertisement message to configure one or more hosts on its network. This, and related features, are described below.
Contents
Code Configuration
All features described on this page use IPv6 and require that you uncomment the following compile time macro in trsystem.h.
#define TM_USE_IPV6
A router application would also need to forward packets from one network to another. Configuring IP forwarding is discussed in Appendix A.
A router application might also need to filter packets. The IPv6 Filtering API is discussed on the Programmer's Reference page.
Router Discovery Events
The features described in this section do not send any messages. They simply allow an application to be notified when a router discovery event occurs.
No Router Available
Treck IPv6 will automatically discover routers by sending several router solicitation messages when an interface is opened. If the feature described below is enabled and there is no response, your application will be notified when Treck stops soliciting for routers.
If you requested router-controlled DHCPv6 when you opened the interface (with the TM_6_DEV_USER_DHCP_RTR_CTRLD flag), you will not receive this event. In this case, Treck will launch the DHCPv6 Client, instead.
To enable this notification, uncomment the following compile time macro in trsystem.h.
#define TM_6_RTR_SOL_FAIL_CB
Should the condition ever occur, a TM_6_DEV_ADDR_RTR_SOL_FAILED event will be sent to the function pointer, dev6AddrNotifyFuncPtr, you supplied when you called tfNgOpenInterface() or tfNgConfigInterface().
| This is a timeout condition. The notification happens within the context of your tfTimerExecute() call. |
Router Solicitation Received
IPv6 hosts broadcast Router Solicitation messages to locate routers and to obtain configuration information after reboot. IPv6 routers receive router solicitation messages and respond with router advertisement messages. This feature allows an application to view each router solicitation message that is received on an interface and gather statistics or provide custom router functionality (i.e., not supported by Treck).
Uncomment the following compile time macro in trsystem.h to compile the code for this feature.
#define TM_6_RTR_SOL_RECV_CB
Call tf6RegisterRouterSolCB() to register an application function to be called with a pointer to the message.
Router Advertisement Received
IPv6 routers send Router Advertisement messages to IPv6 hosts that use the information to send messages beyond the local network. Router advertisement messages can contain various options, including packet size limit and IPv6 address prefix information. This feature allows an application to view each router advertisement message that is received on an interface and extract information from options that Treck does not support.
Uncomment the following compile time macro in trsystem.h to compile the code for this feature.
#define TM_6_RTR_ADV_RECV_CB
Call tf6RegisterRouterAdvCB() to register an application function to be called with a pointer to the message.
Sending Router Advertisements
Use this feature to configure an interface to send Router Advertisement messages. One might use this feature for a network that: 1) had no existing IPv6 router but needed to communicate beyond the local network, and 2) had hosts that could not be manually configured with IPv6 addresses and routes. Refer to RFC 4861, Neighbor Discovery for IP version 6 (IPv6), for details of the process.
Code Configuration
Uncomment the following compile time macro in trsystem.h to compile the code for this feature. Refer to the Function API subsection below for additional configuration requirements.
#define TM_6_RTR_ADV_SEND_MOD
Uncomment the following compile time macro in trsystem.h if you need IPv6 Router Advertisement Options for DNS Configuration described in RFC 8106. Hosts may not support DNS parameters sent by way of router advertisement. Typically, DNS information, like the DNS server address, is sent in a DHCPv6 message.
#define TM_6_RTR_ADV_SEND_MOD_DNS
Function API
When TM_6_RTR_ADV_SEND_MOD is defined, the functions below can be used to send router advertisement messages from an interface. Interfaces will not send router advertisements unless configured.
- tf6RouterAdvConfig()
- Configure an interface to send router advertisements. This can also be used to stop router advertisements for an interface that was previously configured to send them.
- tf6RouterAdvDefaults()
- Get the Router Advertisement default values, as recommended in RFC 4861.
- tf6RouterAdvPrefixDefaults()
- Get the Prefix Option default values, as recommended in RFC 4861.
Protocol Constants
The following constants are defined as macros in trsocket.h. Router constants are copied from RFC 4861, Section 10. Limits for Router Configuration Variables are copied from RFC 4861, Section 6.2.1.
It's not recommended, but you can override any or all of the following values by defining the macro yourself, e.g. in trsystem.h.
Router Advertisement Protocol Constants Name Units Value Description TM_6_RTR_ADV_MAX_INTERVAL seconds 16 The maximum interval when sending the first few unsolicited Router Advertisement messages. TM_6_RTR_ADV_MAX_INITIAL transmissions 3 The number of unsolicited Router Advertisement messages to send, initially. TM_6_RTR_ADV_MIN_DELAY seconds 3 The minimum delay between consecutive Router Advertisement messages. TM_6_RTR_ADV_MAX_DELAY milliseconds 500 After receiving a Router Solicitation message, the Router Advertisement response is delayed a random amount in the range 0 to TM_6_RTR_ADV_MAX_DELAY. TM_6_RTR_ADV_MAX_INTV_MIN seconds 4 The lower limit for MaxRtrAdvInterval (Router Configuration Variable). TM_6_RTR_ADV_MAX_INTV_MAX seconds 1,800 The upper limit for MaxRtrAdvInterval. TM_6_RTR_ADV_MIN_INTV_MIN seconds 3 The lower limit for MinRtrAdvInterval (Router Configuration Variable). TM_6_RTR_ADV_MIN_INTV_MAX fraction 3/4 The upper limit for MinRtrAdvInterval, specified as a percentage of MaxRtrAdvInterval, e.g. 75/100. Parentheses must be omitted to preserve the order of operations, e.g. (MaxRtrAdvInterval * 3 / 4) is non-zero but (MaxRtrAdvInterval * (3 / 4)) will always be zero. TM_6_RTR_ADV_REACHABLE_MAX milliseconds 3,600,000 (1 hour) The upper limit for AdvReachableTime (Router Configuration Variable). TM_6_RTR_ADV_LIFETIME_MAX seconds 9000 The upper limit for AdvDefaultLifetime (Router Configuration Variable).
Example
The following code skeleton is presented as an example of functions tf6RouterAdvConfig(), tf6RouterAdvDefaults(), tf6RouterAdvPrefixDefaults(), tfNgOpenInterface(), tfCheckOpenInterface(), tfSetTreckOptions() and structures ttRouterAdvParam and ttRouterAdvPrefixParam.
struct sockaddr_storage zeroAddr; ttUserInterface innerHandle; ttUserInterface outerHandle; ttRouterAdvParam raParam; ttRouterAdvPrefixParam pfxParam[1]; int errorCode; static const char * raDnsAddr[] = {"2001:db8::123", "2001:db8::456"}; static const char * raDnsSearch[] = {"treck.com", "treck.net"}; /* Create a link-local IPv6 address, only */ memset(&zeroAddr, 0, sizeof(zeroAddr)); zeroAddr.ss_len = sizeof(zeroAddr); zeroAddr.ss_family = AF_INET6; /* Allow Treck to forward IPv6 packets */ errorCode = tfSetTreckOptions(TM_6_OPTION_IP_FORWARDING, 1); assert(errorCode == TM_ENOERROR); /* Open the interface for the public network */ errorCode = tfNgOpenInterface(outerHandle, &zeroAddr, 128, TM_DEV_IP_FORW_ENB, TM_6_DEV_IP_FORW_ENB, 1, myOuterOpenCallback); while (errorCode == TM_EINPROGRESS) { os_sleep(1); errorCode = tfCheckOpenInterface(outerHandle, AF_INET6); } assert(errorCode == TM_ENOERROR); /* Open the interface for the private network */ errorCode = tfNgOpenInterface(innerHandle, &zeroAddr, 128, TM_DEV_IP_FORW_ENB, TM_6_DEV_IP_FORW_ENB, 1, myInnerOpenCallback); while (errorCode == TM_EINPROGRESS) { os_sleep(1); errorCode = tfCheckOpenInterface(innerHandle, AF_INET6); } assert(errorCode == TM_ENOERROR); #ifdef TM_6_RTR_ADV_SEND_MOD /* Get the default Router Advertisement values */ errorCode = tf6RouterAdvDefaults(&raParam); assert(errorCode == TM_ENOERROR); errorCode = tf6RouterAdvPrefixDefaults(&pfxParam[0]); assert(errorCode == TM_ENOERROR); /* Customize the parameters to our network */ raParam.raAdvFlags |= TM_6_RA_FL_OTHER; /* Fetch DHCPv6 parameters */ raParam.raAdvPrefixCount = 1; /* One prefix option */ raParam.raAdvPrefixArray = pfxParam; pfxParam[0].raAdvPrefixStr = "2001:db8:0:7::"; /* 64-bit prefix used by local hosts */ #ifdef TM_6_RTR_ADV_SEND_MOD_DNS raParam.raAdvRDNSS.raDnsCount = 2; /* Two DNS servers */ raParam.raAdvRDNSS.raDnsStrArray = raDnsAddr; raParam.raAdvDNSSL.raDnsCount = 2; /* Two search domains */ raParam.raAdvDNSSL.raDnsStrArray = raDnsSearch; #endif /* TM_6_RTR_ADV_SEND_MOD_DNS */ /* Start sending Router Advertisements on the private network */ errorCode = tf6RouterAdvConfig(innerHandle, &raParam); assert(errorCode == TM_ENOERROR); #endif /* TM_6_RTR_ADV_SEND_MOD */
Function Calls
- tf6RegisterRouterAdvCB()
- tf6RegisterRouterSolCB()
- tf6RouterAdvConfig()
- tf6RouterAdvDefaults()
- tf6RouterAdvPrefixDefaults()