IPv6 Programmer's Reference
Modes of Operation
Our dual IP layer stack will support three different modes of operation:
- Dual-mode IPv6 with IPv4 (also referred to as “dual IP layer”)
This is done in a way (i.e. conditional compilation using the macros TM_USE_IPV4 and TM_USE_IPV6) that minimizes codespace and dataspace requirements for customers who prefer to run the stack in IPv4-only or IPv6-only modes. The default mode of operation is IPv4-only to be compatible with our current product. We have implemented IPv6 functionality as an option so that if a customer does not buy the IPv6 option, they will not receive the files required to build IPv6 support. Therefore, they will get linker errors if they try to use IPv6. If the user disables both IPv4 and IPv6 support (an invalid configuration) an appropriate error message will be generated at compile time using the #error preprocessor directive. Also, when TM_USE_IPV6 is #define’d, TM_SINGLE_INTERFACE_HOME cannot be #define’d because IPv6 interfaces are multi-homed. When both TM_USE_IPV6 and TM_SINGLE_INTERFACE_HOME are #define’d (an invalid configuration) an appropriate error message will be generated at compile time using the #error preprocessing directive.
Reuse of Existing IPv4 Data Structures
There are many similarities between IPv6 and IPv4 in the sense that IPv6 keeps the best parts of IPv4. Because of this, we try to reuse existing IPv4 internal data structures by making simple changes and extensions to them where applicable. For example, both the Patricia routing tree (which also comprises ARP cache functionality) and the socket tree can be adapted to support IPv6 by expanding the size of the IP address to 128 bits when operating in dual-mode IPv6 with IPv4 (in this case, IPv4-only addresses are stored internally as 128-bit IPv4-mapped IPv6 addresses). As another example, the existing IPv4 interface structure (i.e. ttDeviceEntry) should be straightforward to adapt for IPv6 use by adding new IPv6-specific fields such as the IPv6 interface ID (i.e. dev6InterfaceId), a multi-homed IPv6 address list containing both manually configured as well as stateless auto-configured IPv6 addresses (i.e. dev6IpAddrArray, dev6PrefixLenArray), a list of IPv6 multicast addresses that the interface is listening on (i.e. dev6MldPtr), etc.
To make it clear that specific fields in these shared internal data structures are either IPv4-only or IPv6-only, these fields will be bracketed by the appropriate #ifdef’s for selecting IPv4 or IPv6 functionality, which are TM_USE_IPV4 and TM_USE_IPV6 respectively. An example of a field that is IPv4-only is the existing multi-homed IPv4 address list (i.e. ttDeviceEntry.devIpAddrArray, ttDeviceEntry.devNetMaskArray). In summary, changes to existing IPv4 functionality shall be kept to a minimum, and specifically we do not want any of our changes for IPv6 to increase codespace and dataspace usage when the stack is used in IPv4-only mode.
Naming Standards for New APIs
Any new APIs (both public and internal) which are IPv6-only have names starting with the prefix "tf6" unless the RFC requires otherwise. Any new APIs which support both IPv4 and IPv6 have names starting with the prefix "tf", except for when the new API replaces an existing IPv4-only API. In that case, the name starts with the prefix "tfNg" as described in the next section "Changes to Existing Public APIs". Similar naming conventions are used for macros, type names, and global variables. For example, "TM_6_" is used as the prefix for IPv6-only macros, "TM_" for macros that support both IPv4 and IPv6 except for in the case where it replaces an existing IPv4-only macro in which case the prefix is "TM_NG_", etc. IPv6-specific fields added to existing IPv4 data structures have "6" added at the end of the fieldname prefix if there is a prefix, for example: ttDeviceEntry.dev6IpAddrArray is the list of IPv6 unicast addresses configured on the interface. In a similar manner, "4" may be used at the end of the prefix to indicate IPv4-only, for example: ttRtRadixHeadEntry.rth4DefaultGateway is the routing entry for the IPv4 default gateway.
New Public APIs
RFC 2553 specifies new public BSD socket APIs. Some of these new APIs we won’t implement in phase 1 IPv6, because they require the DNS resolver API to be updated for IPv6 (targeted for phase 2 IPv6), and these APIs are: freeaddrinfo(), freehostent(), gai_strerror(), getaddrinfo(), getipnodebyname(), getipnodebyaddr() and getnameinfo(). The other new BSD socket APIs specified in RFC 2553 we will implement include if_nametoindex(), if_indextoname(), inet_pton() and inet_ntop(). Later, we will implement if_nameindex() and if_freenameindex().
ICMPv6 Neighbor Discovery specifies a means to perform address resolution, which works for other link layers besides Ethernet (i.e. null link-layer). All that is required to use ICMPv6 address resolution with an interface is to configure the link-layer address of that interface. This can be accomplished by calling the new public API tf6InterfaceSetPhysAddr()from the device driver open function. Note that if tf6InterfaceSetPhysAddr() is used instead of drvGetPhyAddrFuncPtr to set the link-layer address, then tf6Eui64SetInterfaceId() should also be called from the device driver open function to set the interface ID.
Because of how IPv6 stateless address auto-configuration works, IPv6 needs access to the interface ID. The interface ID is always 64 bits long (RFC 2373), and is used as the low-order 64 bits of a stateless auto-configured IPv6 address. A new public API tf6Eui64SetInterfaceId() enables the user to configure the interface ID associated with a specific interface, however it should not be called when the interface linklayer type is Ethernet, since in that case the interface ID is automatically derived from the IEEE 48-bit MAC address provided by the user’s driverGetPhysicalAddress function (refer to the drvGetPhysAddrFuncPtr parameter of the function tfAddInterface()). If the interface link-layer type is null link-layer, then tf6Eui64SetInterfaceId() should be called by the user from the device driver open function. If the interface ID is not set before the interface is opened, then IPv6 stateless address auto-configuration will not be performed, which may result in the IPv6 interface not being opened depending on what IPv6 addresses have been manually configured on the interface (i.e. at least one link-local IPv6 address is required). (RFC 2464, RFC 2373)
Because of how scoped IPv6 addresses work, specifically site-local unicast IPv6 addresses, IPv6 needs access to the site identifier. A new API tf6InterfaceSetSiteId() enables the user to configure the site identifier associated with a specific interface. Typically, all interfaces in the node will belong to the same site, therefore we default the site identifier associated with each interface to 0, and do not require the user to call tf6InterfaceSetSiteId() in this case. Refer to section 2.2.1 "Scope ID" for more information on site identifiers.
Since in some cases the user may need to set the scope ID of a local scope IPv6 address to associate it with the specific interface they want to use it with (for example, sending packets to a link-local scope unicast IPv6 address requires specifying the outgoing interface), we provide the API tf6SockaddrSetScopeId() to set the appropriate scope ID to use. This API can be used either with the BSD socket APIs or with Treck APIs (i.e. tf6SockaddrSetScopeId() can be used to assign the scope ID to sockaddr_in6.sin6_scope_id). IPv6 address prefixes encode the scope of the address, which in the case of a unicast IPv6 address is linklocal, site-local or global. Link-local, site-local and global scope unicast addresses are automatically assigned to an interface using stateless address auto-configuration. Additional IPv6 unicast addresses may be manually configured on the interface. Addresses may become deprecated, in which case they should not be used in any new communications. Because there will be more than one local IPv6 address associated with an IPv6 interface, and since there are various criteria (i.e. local versus global scope, preferred versus deprecated status, etc.) governing which are the appropriate local IP addresses to use for communication with a specific destination IP address, we provide a new API tf6GetLocalIpAddress() which enables the application to select an appropriate local IP address. (RFC 2462)
A new API tfCheckOpenInterface() is provided which enables the user to check the status of either IPv4 or IPv6 protocol operation on a specified interface.
A new API tf6SetMcastInterface() is provided which enables the user to set the default interface to use to send IPv6 multicast packets. The application can set the IPV6_MULTICAST_IF option on the socket to override this default interface on a per-socket basis. tfRegisterIpForwCB() functionality needs to be provided for IPv6.
A new API tf6RegisterIpForwCB() is provided for this purpose. tf4NetmaskToPrefixLen() is provided to facilitate porting of existing code to the tfNg APIs. A new API tfSetReachable() is provided so that applications can indicate that a connection is making forward progress. (RFC 2461)
Changes to Existing Public APIs
Because we must not break any existing code that a customer has written, we have made no changes to the public API that are not backwards compatible. Generally, our intent is similar to that described in RFC 2553, which is to provide backwards-compatibility for changes to existing public APIs and when new public APIs are defined, to have these new APIs support both IPv4 and IPv6 where it makes sense. From the standpoint of the existing public API, the primary impact that IPv6 has is due to the expansion of the size of an IP address from 32 bits (IPv4) to 128 bits (IPv6). Unfortunately, the existing type used in the public API to represent an IP address (ttUserIpAddress) does not easily support expansion to 128 bits because it is an integral type rather than a pointer type. Therefore, we are using a new BSD type (sockaddr_storage) to represent an IP address and new APIs that are passed a pointer to this type. Because the existing APIs do not support IPv6 addresses, we have deprecated these existing IPv4-only APIs and recommend that users convert their code to use the new APIs that support both IPv4 and IPv6 addresses. These new APIs that replace existing IPv4-only APIs have names starting with the prefix "tfNg", which is an abbreviation for Treck Function Next Generation. The new APIs call the deprecated APIs as needed.
The existing BSD socket API has been updated in accordance with RFC 2553. This preserves backwards compatibility with existing applications that use the old version of this API.
A new option has been added to tfInterfaceSetOptions() that enables the application to control per interface how many consecutive Neighbor Solicitation messages are sent while performing Duplicate Address Detection on a tentative IPv6 address. (RFC 2462)
The following APIs are deprecated because of the new sockaddr_storage address type supporting both IPv4 and IPv6 addresses. The APIs have been replaced by similarly named Next Generation APIs:
APIs Not Yet Deprecated
Because we have not implemented the equivalent of proxy-ARP in phase 1 IPv6 (targeted for phase 3 IPv6, router), we will not yet deprecate tfAddInterfaceMhomeAddress(), tfAddProxyArpEntry() or tfDelProxyArpEntry().
Because we have not implemented Path MTU Discovery in phase 1 IPv6 (targeted for phase 2 IPv6), we will not yet deprecate tfDisablePathMtuDisc().
Some existing public APIs that take a parameter of type ttUserIpAddress have not been deprecated because they are only used with IPv4. The default gateway functions tfAddDefaultGateway(), tfDelDefaultGateway() and tfGetDefaultGateway() are not deprecated since these functions only make sense to use with IPv4. With IPv6, because of its plug-and-play capabilities (specifically, router discovery), there is no need to have an API for setting the default IPv6 gateway. For testing IPv6 with a router that does not support sending Router Advertisement messages (i.e. testing IPv6 forwarding), the user can effectively override the IPv6 default router list by adding a static route having a prefix length of 3 and a destination IPv6 address of 2000::0 which matches aggregatable global unicast IPv6 addresses.
tfGetBroadcastAddress() is not deprecated because IPv6 does not support broadcast. The DNS APIs we are not looking at for phase 1 IPv6; these will likely be deprecated later when we update the DNS resolver API for IPv6, but not now. This includes tfGetPppDnsIpAddress(). BOOTP and DHCP are protocols specific to IPv4, therefore these APIs will not be deprecated. There will be a DHCPv6 stateful configuration protocol for IPv6 though currently may have draft status.
Additionally, it is out of the scope for Phase 1 IPv6. tfUseCollisionDetection(), tfUserStartArpSend() and tfCancelCollisionDetection() have not been deprecated since they are used by AutoIP and are specific to IPv4. IPv6 provides similar functionality via Duplicate Address Detection, which is part of IPv6 stateless address auto-configuration (refer to RFC 2462), however the only API that IPv6 stateless address auto-configuration requires is a means for the application to set the interface ID (refer to tf6Eui48SetInterfaceId(), tf6Eui64SetInterfaceId()). The scattered send APIs tfIpScatteredSend() and tfSocketScatteredSendTo() are out of scope for phase 1 IPv6.
tfFinishOpenInterface() does not make sense to deprecate. Every IPv6 address configured on the interface, regardless of whether it was manually configured, obtained via stateful configuration (i.e. DHCPv6) or stateless auto-configuration, must go through the process of Duplicate Address Detection (RFC 2462) before tfDeviceStart() can be called to complete configuration of the IPv6 address on the interface. tfFinishOpenInterface() is a means for the user to call the internal API tfDeviceStart(), but since we can't allow a call to tfDeviceStart() until Duplicate Address Detection has completed successfully, it makes no sense to provide this API for IPv6.
Changes to Existing Internal APIs
128-bit IP Addresses
When the stack is run in dual IP layer mode, IPv4-only IP addresses are represented internally as 128-bit IPv4-mapped IPv6 addresses so that we can share existing internal data structures (and associated code) such as the socket tree and the Patricia routing tree between IPv4 and IPv6 implementations. This is accomplished as follows: when TM_USE_IPV6 is enabled, ttIpAddress]] (the internal type used for IPv4 addresses) is defined to be tt6IpAddress. All internal APIs and data structures that reference the type ttIpAddress are impacted by this change (i.e. ttSocketEntry, ttRtCacheEntry, tfSocketLookup, etc.) Internal API optimization, conserve stack space.
When TM_USE_IPV6 is enabled, all parameters of type ttIpAddress are passed as tt6IpAddress, which means that each consumes 128 bits of stack space. These APIs will be conditionally changed via the TM_USE_IPV6 macro to instead take parameters of type ttIpAddressPtr.
Prefix Length versus Netmask
Obviously, it is very inefficient to pass around and store a 128-bit netmask for IPv6 when instead you can use an 8-bit prefix length. Prefix length can take on values ranging from 0 to 128, and it indicates the number of most significant bits set in the netmask.
Dual IP layer mode optimization, IPv4 prefix length stored on interface: Change IPv4 to use prefix length instead of netmask. When the stack is running in dual IP layer mode, an IPv4 netmask (i.e. ttDeviceEntry.devNetMaskArray) is stored for each multi-homed IPv4 address on the interface using 128 bits (i.e. ttIpAddress, which is defined to be tt6IpAddress in this case). This is changed to instead store the 8-bit prefix length (i.e. ttDeviceEntry.dev4PrefixLenArray).
The addition of scoped unicast addressing to IPv6 complicates routing as well as the design of internal data structures which store IPv6 addresses. For example, you can have the same link-local scope unicast IPv6 address assigned to different nodes on different links, and therefore reachable through different interfaces. If the user tries to send a packet to this link-local scope IPv6 address, which interface should the packet go out on? Remember that in this example we are addressing different nodes and not the same node through different interfaces. Therefore, the choice of which outgoing interface to use matters.
To work around this issue, IETF added the field sin6_scope_id to the sockaddr_in6 structure that is part of the BSD socket API for IPv6. According to RFC 2553, this field contains an interface index (i.e. ttDeviceEntry.devIndex, note that this is a 1-based index) if the scope of the unicast IPv6 address is linklocal, and a site identifier (i.e. ttDeviceEntry.dev6SiteId) if the scope is site-local. The use of the field sockaddr_in6.sin6_scope_id is implementation dependent, as long as the value chosen for scope ID is unique at the appropriate scope level so that the combination of scope ID and local scope unicast IPv6 address is unique internal to the node. The user can call tf6SockaddrSetScopeId() to assign the correct value to sockaddr_in6.sin6_scope_id.
A scope identifier may be 0, which refers to the default scope when a valid scope identifier is not known (refer to RFC 2851). We initialize the site identifier of each interface to 0; the user can call the API tf6InterfaceSetSiteId() to set this to a valid non-zero scope identifier for site-local unicast IPv6 addresses associated with a specific interface.
IPv6 Neighbor Cache versus ARP Cache
In our current IPv4 implementation, the ARP Cache is part of the Patricia routing tree. IPv6 will use the ARP Cache to store Neighbor Cache information, however first the ARP Cache entry needs to be modified so that it can handle variable-length link-layer addresses.
Treck supports IPv6 multicast datagrams at the application layer via UDP or RAW sockets. An IPv6 multicast datagram is one that has been sent to an IPv6 address of the form FF00::/8 (see RFC 4291 - IPv6 Addressing Architecture). For example, you would call send() or sendto() with a destination address of FF02:0:0:0:0:0:0:2 (FF02::2) if you wanted to get a message to all routers on the same link as your node.
To receive a multicast datagram, you have to configure a socket to be a member of the multicast group. The multicast group is identified by its IPv6 multicast address and the interface on which you wish to receive the data. A socket may join more than one multicast group. Two such options are provided by Treck for managing your multicast group memberships:
- The Treck Multicast Listener Discovery (MLD) option provides the basic socket functionality for joining and leaving multicast groups.
- The Treck Multicast Listener Discovery version 2 (MLDv2) option provides advanced socket functionality for not only joining and leaving multicast groups but also for filtering the data that you receive based on who sent it. In other words, MLDv2 allows you to mute specific senders that are of no interest to you.
Basically, if you want to join a multicast group, you can call setsockopt() with socket option MCAST_JOIN_GROUP. To leave a group, you can call setsockopt() with socket option MCAST_LEAVE_GROUP. These calls operate with protocol level IPPROTO_IPV6 or IPPROTO_IP, if you are also interested in IPv4 multicast. Refer to the MLD page for details.
If you want to block out certain senders or receive only from certain senders, you can call setsourcefilter(), which joins the specified multicast group and puts a source filter in place. Refer to the MLDv2 page for details.
Privacy Extensions for Stateless Address Autoconfiguration
RFC 4941 describes a method for enhancing node privacy by using temporary global addresses that are randomly generated and periodically regenerated. This feature requires the presence of an IPv6 router on the same subnet to trigger the node's autoconfiguration process by sending the necessary prefix information for autonomous address configuration (RFC 4861, section 4.6.2). Treck supports this feature as follows:
- Compile Time Macros you can define in trsystem.h,
- Treck initialization options set via tfSetTreckOptions() or tfInitTreckOptions(), and
- Interface options set via tfInterfaceSetOptions().
The following configuration macro must be defined in trsystem.h to enable the feature described in this section.
- TM_6_USE_TEMPADDR - Include and enable the code that supports privacy extensions for stateless address autoconfiguration.
Once the code is enabled, the feature can be enabled on an interface (prior to opening the interface) by calling tfInterfaceSetOptions() with option TM_6_DEV_OPTIONS_USE_TEMPADDR. Alternatively, a system-wide default setting can be applied by calling tfSetTreckOptions() or tfInitTreckOptions() with option TM_6_OPTION_USE_TEMPADDR. An interface will inherit the current system-wide default setting when the interface is created with tfAddInterface().
For further details, refer to the Main Article.
Fast Reboot when using Autoconfigured Addresses (example: Wake-on-LAN)
In some cases, it may be necessary to restart the Treck stack and resume communications as quickly as possible. A Wake-on-LAN event after a low power sleep is one example. Reacquiring addresses via DHCPv6 or Router Solicitation and Advertisement can take time and may be unnecessary when a node is restarting from a previously successful autoconfiguration state. The following fast boot options may be used in any combination:
- Manually configure addresses for immediate use while autoconfiguration is in progress (see below). These manually configured addresses exist temporarily, pending autoconfiguration of the same address by DHCPv6 or Router Advertisement. Transferring control of the address to the autoconfiguration state machine is necessary for proper maintenance of address lifetimes and lease renewal.
- Use the DHCPv6 Confirm and Reply message exchange to confirm a user-specified address, bypassing the DHCPv6 server discovery phase (see Main Article).
- Eliminate the address configuration delays related to interface initialization and Duplicate Address Detection (see below).
The code that supports fast reboot by manual address configuration is disabled by default. To enable the code that supports this option, define the following compile time macro in your trsystem.h:
Fast reboot by manual address configuration presupposes that you know what addresses were autoconfigured on an interface prior to rebooting the Treck stack. The following steps provide an example of how to use this option:
- Discover what addresses are autoconfigured on an interface (via DHCPv6 or Router Advertisement) by monitoring the IPv6 Address Configuration Events described on the tfNgOpenInterface() page. In particular, TM_6_DEV_ADDR_CONFIG_COMPLETE, TM_6_DEV_ADDR_INVALIDATED, TM_6_DEV_ADDR_CONFIG_FAILED and TM_6_DEV_ADDR_DUP_DETECTED tell you what addresses have been configured, unconfigured or have encountered a duplicate address on another node.
- Store all valid autoconfigured addresses in non-volatile memory.
- Reboot or power down until awakened by some external event.
- Start Treck as you normally would with tfStartTreck(), etc.
- (Optional, if using DHCPv6) Call tf6UseDhcp() and tf6DhcpSetAddrOption() to initialize DHCPv6 and set your preferred address (the autoconfigured IPv6 address you stored in non-volatile memory).
- When you open your interface this time, set the following tfNgOpenInterface() parameters (if you have more than one address, use tfNgConfigInterface() for additional addresses):
- ipAddrPtr: a pointer to the autoconfigured IPv6 address you stored in non-volatile memory.
- prefixLen: 64, unless you have more accurate information.
- flags: per your requirements.
- ipv6Flags: bitwise OR the TM_6_DEV_IP_FAST_BOOT flag with your other flags (e.g. TM_6_DEV_USER_DHCP).
- buffersPerFrameCount: per your requirements.
- dev6AddrNotifyFuncPtr: a pointer to your callback function.
- multiHomeIndex: 1, 2, 3, etc. (optional, if using tfNgConfigInterface() to configure additional addresses).
- Wait for the TM_6_DEV_ADDR_CONFIG_COMPLETE event for the address that is of interest to you. Your manually configured addresses would have a multiHomeIndex between 0 and (TM_MAX_IPS_PER_IF - 1) (3 by default).
You should receive at least three TM_6_DEV_ADDR_CONFIG_COMPLETE events when each associated address is ready to use: the link-local autoconfigured address for the interface, your manually configured address and eventually, the autoconfiguration of the same address that you manually configured. The first address will allow you to communicate on the local link. You may need to wait for your specific address to become configured if you wish to respond to a Wake-on-LAN event from an off-link source. When autoconfiguration produces a duplicate address on a different multiHomeIndex, you will get a TM_6_DEV_ADDR_INVALIDATED event to tell you that your manually configured address has been replaced by the autoconfigured address. If autoconfiguration produces a different and unexpected address, you should call tfNgUnConfigInterface() to remove your manually configured address because you may have restarted on a different link.
If necessary, you can eliminate the address configuration delays imposed by interface initialization and Duplicate Address Detection. This is strongly discouraged, as it contravenes RFC 4861 and RFC 4862. There are two tfInterfaceSetOptions() options related to address configuration delays (more details on the tfInterfaceSetOptions() page):
|TM_6_DEV_OPTIONS_NO_INIT_DELAY||This option disables the random delay before Treck is allowed to send packets from a newly opened interface. As stated in RFC 4861, "This serves to alleviate congestion when many hosts start up on a link at the same time, such as might happen after recovery from a power failure." Elimination of this delay means that Treck can immediately start Duplicate Address Detection on the interface.|
|TM_6_DEV_OPTIONS_DAD_NO_WAIT||This option disables the delay after sending a Neighbor Solicitation message for the purposes of Duplicate Address Detection. This delay prior to address configuration allows another node with the same address to respond with a Neighbor Advertisement to prevent our node from configuring the address. Elimination of this delay means that the address will be ready for use while it is still theoretically tentative. This option only affects the link-local autoconfigured address and addresses configured with tfNgOpenInterface() options TM_6_DEV_IP_FAST_BOOT or TM_6_DEV_IP_TEMPORARY.|
The code that supports the TM_6_DEV_OPTIONS_DAD_NO_WAIT option is disabled by default. To enable the code that supports this option, define the following compile time macros in your trsystem.h:
#define TM_6_USE_DAD #define TM_6_DAD_ALLOW_NO_WAIT
Treck is only doing a host implementation of IPv6 in phase 1 IPv6.
DNS Resolver API
- A6 queries are not implemented: We are not implementing support for A6 name lookups (part of RFC 2874) in phase 2 IPv6, however we are implementing support for RFC 1886 (AAAA). A6 name lookups are significantly different from our existing IPv4 DNS Resolver implementation; specifically, several round trips may be needed to collect a complete DNS record when using A6. Currently, it is unclear as to if or when RFC 1886 will be deprecated. Also, RFC 2874 specifies a transition mechanism that IPv6 DNS servers can use to populate their AAAA records with the information in their A6 records, so that they can continue to support AAAA name lookups even after they#ve converted over to A6.
- The general versions of getaddrinfo() and getnameinfo() both support a series of features based on service names and port numbers. The goal of this is primarily to combine the functionality of a number of API calls (getservbyname(), gethostbyname(), etc) into a single, versatile, protocol-independent function. However, our implementation is focused on embedded systems, which typically do not have the capability (or desire) to do a getservbyname() (i.e. no filesystem, no /etc/services file, etc). Because of this, none of the service and port number related functions of getaddrinfo and getnameinfo is implemented. This means that the servname parameters are not used, and the following flags are not defined and may not be used: AI_PASSIVE, AI_NUMERICSERV, NI_NOFQDN, NI_NUMERICSERV, NI_NUMERICSCOPE and NI_DGRAM.
- There is currently no API for retrieving IPv6 mail host (MX) records. The DNS code is capable of generating and receiving IPv6 MX records, however they are not stored, since there is not yet an API for the user to retrieve this information. This is a rarely used functionality - to the best of my knowledge, none of our customers currently retrieve IPv4 MX records, even though the capability is there.
BSD Socket APIs
Socket Extension Calls
Treck Initialization Functions
ARP/Routing Table API
PPP Link Layer API
Compile Time Macros
- Disable IPv6 Path MTU Discovery.
- Enable IPv6 fragmentation/reassembly code (enabled by default in trsystem.h).
- Enables DAD (Duplicate Address Detection) code, requires TM_6_USE_MLD to be enabled.
- Enable IPv6 forwarding code (enabled by default in <trsystem.h>)
- Enables MLD (Multicast Listener Discovery) code.
- Enables MLDv2 (Multicast Listener Discovery version 2) code.
- Enables NUD (Neighbor Unreachability Detection) code.
- Enables Prefix Discovery, part of stateless address autoconfiguration.
- RFC 4861 (Neighbor Discovery for IPv6) obsoletes RFC 2461 and removes the following text from section 5.2 for reasons explained in RFC 4943: If the Default Router List is empty, the sender assumes that the destination is on-link. Define this macro in trsystem.h to undo this change and re-enable the on-link assumption code.
- Speed up lookup in the recieve-path of IP aliases configured on the interface. This optimizes for situations where the user has configured many (i.e. >50) IP aliases on a single interface. Enabling this functionality causes a small increase in codespace and dataspace usage.
- May be defined when TM_USE_IPV6 is enabled. This performance macro will reduce codesize. However, you will be restricted to using a single interface.
- Enable IPv4 functionality.
- Enable IPv6 functionality.
- Enable IPv4 forwarding code (enabled by default in <trsystem.h>)
BSD Socket API Macros
- AF_INET6 / PF_INET6
- Refer to RFC 2553. IPv6 address family/protocol family ID.
- Refer to RFC 2553. Max length of interface name. This should correspond to the value of the internal API macro TM_MAX_DEVICE_NAME.
- Refer to RFC 2292. Macro used to test two IPv6 addresses to see if they are equal.
- Refer to RFC 2553. Macro used to test an IPv6 address to see if it is a link-local scope unicast address.
- Refer to RFC 2553. Macro used to test an IPv6 address to see if it is the loopback address.
- Refer to RFC 2553
- Refer to RFC 2553
- Refer to RFC 2553
- Refer to RFC 2553
- Refer to RFC 2553
- Refer to RFC 2553 Macro used to test an IPv6 address to see if it is a multicast address.
- Refer to RFC 2553. Macro used to test an IPv6 address to see if it is a site-local scope unicast address.
- Refer to RFC 2553. Macro used to test an IPv6 address to see if it is the unspecified address (i.e. all 0's).
- Refer to RFC 2553. Macro used to test an IPv6 address to see if it is an IPv4-compatible IPv6 address.
- Refer to RFC 2553. Macro used to test an IPv6 address to see if it represents an IPv4 address (i.e. IPv4-mapped IPv6 address).
- Used at declaration time to initialize an in6_addr structure to the IPv6 wildcard address.
- Used at declaration time to initialize an in6_addr structure to the IPv6 wildcard address.
- Refer to RFC 2553. Length of IPv6 address string.
- Refer to RFC 2553. Length of IPv4 address string.
getaddrinfo() Error Codes
- Address family for nodename not supported.
- Temporary failure in name resolution.
- Invalid value for ai_flags.
- Non-recoverable failure in name resolution.
- ai_family not supported.
- Memory allocation failure.
- No address associated with nodename
- Nodename nor servname provided, or not known
- servname not supported for ai_socktype
- ai_socktype not supported
- system error returned in errno
- highest error code
Flags for addrinfo Structure
- Request for canonical name
- Don't use name resolution
- Return IPv4 addresses in IPv4-mapped format if no native IPv6 are found.
- Return all IPv4 and IPv6 addresses found.
- Return IPv4 addresses only if IPv4 is configured on this device; return IPv6 addresses only if IPv6 is configured on this device.
Flags for getnameinfo()
- Don't do a DNS lookup for this address - just return the address as a numeric string.
- Return an error if the host's name cannot be found.
- Unspecified protocol family
- Unspecified address family
Socket Extension Macros
- IPv6 address configuration event indicates that the IPv6 address at the specified multi-home index was configured on the interface. Refer to the tfNgConfigInterface() parameter dev6AddrNotifyFuncPtr.
- IPv6 address configuration event indicates that the IPv6 address at the specified multi-home index was not configured on the interface because it failed Duplicate Address Detection. Refer to the tfNgConfigInterface() parameter dev6AddrNotifyFuncPtr.
- IPv6 address configuration event indicates that configuration of the IPv6 address at the specified multi-home index has been started. Refer to the tfNgConfigInterface() parameter dev6AddrNotifyFuncPtr.
- IPv6 address configuration event indicates that an IPv6 address has transitioned state from preferred to deprecated. Refer to the tfNgConfigInterface() parameter dev6AddrNotifyFuncPtr.
- IPv6 address configuration event indicates that we detected that a different node is using an IPv6 address that we have already configured on the interface. Note that it is up to the user to specify what recovery, if any, is performed when this event occurs. Refer to the tfNgConfigInterface() parameter dev6AddrNotifyFuncPtr.(RFC 2462)
- IPv6 address configuration event indicates that an IPv6 address has become invalid, and has been removed from the interface. Refer to the tfNgConfigInterface() parameter dev6AddrNotifyFuncPtr.
- Option for tfNgConfigInterface() and tfNgOpenInterface(). IPv6 device flag (i.e.ttDeviceEntry.dev6Flags) that indicates that the network controller hardware does not support filtering of its own multicasts but instead does loopback of its own multicasts. Generally, you don't want to set this flag, since it causes Duplicate Address Detection to not be as robust. On the other hand, if Duplicate Address Detection always fails regardless of what interface ID you set on the interface or what IPv6 address you try to configure, then specifying this flag will likely fix the problem.
- Option for tfNgConfigInterface() and tfNgOpenInterface(). IPv6 device flag (i.e.ttDeviceEntry.dev6Flags) enables optimization of Duplicate Address Detection so that, for IPv6 addresses generated via stateless address autoconfiguration, we only perform Duplicate Address Detection on the link-local scope address. (RFC 2462)
- Option for tfNgConfigInterface() and tfNgOpenInterface(). IPv6 device flag (i.e. ttDeviceEntry.dev6Flags) that enables auto-recovery when the IPv6 interface is disabled. Specifically when a Duplicate Address Detection failure occurs on the auto-configured link-local scope address, and this IPv6 device flag was specified, the stack recovers by setting a random interface ID and reopening the interface for IPv6.
- Option for tfSetTreckOptions(). A boolean used to enable IPv6 forwarding; indicates whether the IPv6 node is operating as a host or as a router. Note that router functionality is not implemented in phase 1 IPv6.
- Option for tfSetTreckOptions(). A boolean used to enable IPv6 fragmentation.
- Option to change the time to wait before increasing an IPv6 PMTU estimate.
- Maximum number of data rows returned by query using a cursor.
- Device flag (i.e. ttDeviceEntry.devFlag) that indicates that the IP routing table must always be consulted when sending a solicited reply packet (i.e. ICMP Echo Reply) to a unicast destination IP address in response to a request packet (i.e. ICMP Echo Request) received on this device, since the outgoing device that the reply must be sent on may be different from the incoming device that the request was received on.