NetBurner 3.3.8a
PDF Version
IPv4/IPv6 Dual Stack Guide

Releases prior to 2.8.0 use a type of IPADDR that was a 32-bit number. The most significant change for 2.8.0 and beyond is that the IPADDR type is now an object that can hold IPv4 or IPv6 address information. This document will provide more information on this issue in the IPADDR class section.

Obtaining IPv6 addresses

IPv6 addressing is quite a bit different than IPv4, in which there is typically one IP address per network interface which is assigned by DHCP or set to a static address. In order for an interface to have more than one IP address it can use the Multihome feature. For example, a host's IPv4 AutoIP address.

Link-Local

When using IPv6, all interfaces have multiple IP addresses. For starters there is the ‘link-local’ address (fe80::/64). This is an address that is valid only for the local link that the device is connected to, and is used to negotiate the other addresses for the interface. While it can be used for any communication on the link, it is not a routable address. The link-local address is derived from the MAC address of the interface. As a result it is fixed for a given interface and determined without having to be explicitly set. For example, a device with the mac 00:03:f4:01:23:47 would have the link-local address fe80::203:f4ff:fe01:2347.

Router Auto-Configuration

In addition to the link-local address, IPv6 routers can tell the device to auto-configure based on the router’s assigned prefix. To configure the end address, the device takes a number of bits of the router's prefix (usually 64), and combines this with its auto-configure address (the calculated portion of link-local) to obtain the prefix address. In our previous case, let’s assume a router advertised a prefix of 2001:db8:1:2::. In this case, the full prefix address would be 2001:db8:1:2:203:f4ff:fe01:2347. This applies for all routers on the link that advertise auto-configuration. It’s entirely possible (and reasonable in large corporate networks!) for an interface to have multiple prefix addresses from multiple routers.

DHCPv6

IPv6 addresses can also be assigned by a DHCPv6 server. Like DHCP for IPv4, this is used for assigning addresses to devices, along with passing other information like DNS and NTP servers. It is also possible for routers to notify devices that there is a DHCP server present on the network. In the case where such notification occurs, the NetBurner will automatically configure to obtain the relevant information. There are two types of DHCP servers in IPv6 networks: Information-only and full Stateful Configuration. Information-only servers exist solely to provide additional information about the network, but do not assign IP addresses. These will allow for the auto-configuration of DNS, NTP servers, or other desired information. Full Stateful configuration additionally assigns addresses for use on the device’s link. It is possible to manually start the DHCP client as well, for use on networks without a router.

Static IP Addresses

Finally, if all of these methods are insufficient, it is possible to manually assign and address to the device’s interface as well.

IPADDR Class

The IPADDR type in NetBurner tool releases prior to 2.8.0 was a 32-bit unsigned integer. In order to be able to handle IPv6 addresses with the least impact to existing applications, it is now a C++ object. You will not need to know C++ in order to use these objects. Most function calls will not have to change, and the system will do the appropriate action for both IPv4 and IPv6 addresses. One major change for users that have created custom storage structures that store IPADDRs in UserParams or a file on a file system is that when compiled for IPv6, the IPADDR is now 128 bits instead of 32. This means that unless plans are made for this, reading back stored IPADDRs will cause a problem for the application configuration in previously deployed devices that are updated. One way to address this issue is to use something like a 32-bit storage "key". Whenever reading the configuration structure check that the key in the application matches the key stored in memory. If different, then you must initialize the values. Any time you make a change to the stored information, such as adding a variable, increment the key.

The most significant difference is that while an unsigned 32-bit integer can be checked for a value of 0, an object cannot. For example, many applications check for a static IP address setting with if (EthernetIP == 0). If EthernetIP is now an IPADDR object, the test should now be: if (EthernetIP.IsNull()).

For function parameters that were previously set to 0 to represent a null value, you can use IPADDR::NullIP(). For example, in previous releases a 0 was used for parameter 3, the DNS Server IP address, to tell the system to use the current runtime system DNS IP address value. This will generate an error in the new tools release since the 3rd parameter must be a typed object rather than an integer value. You may also use the INADDR_ANY, which is defined as IPADDR::NullIP() in the system files.

DNSResult = GetHostByName( serverName, &serverIp, 0, TICKS_PER_SECOND * 20 );

Becomes

DNSResult = GetHostByName( serverName, &serverIp, IPADDR::NullIP(), TICKS_PER_SECOND * 20 );

IPADDR Member Functions

C programmers are used to creating structures that contain variables. A very simplistic way to look at a C++ object is that it is a structure that contains both variables and function declarations. These functions are called member functions. They are called using a dot notation instead of calling the function by itself. For example, in prior releases to print an IP address to the debug serial port (stdout) you might use the function: ShowIP(EthernetIP). In the new release this becomes: EthernetIP.printf(). To print to a file descriptor such as a TCP socket, you can use: EthernetIP.fdprintf(fd).

Some common functions are described below in their simplest form. Many of the functions have optional parameters, and experienced C++ programmers may want to know more detailed information, such as which are static and default parameters. Please refer to the NetBurner API documents for more information: IPADDR6

Setting IP Address Values with Member Functions

Member functions are called using a “.” after the object instance name. For example:

IPADDR myIpObject;
myIpObject.SetNull(); // set the IP address to null
Used to hold and manipulate IPv4 and IPv6 addresses in dual stack mode.
Definition: ipv6_addr.h:40
void SetNull()
Set the IP address value of an IPADDR6 object to null.
Definition: ipv6_addr.h:286

Member functions to set an IP address:

  • void SetNull() Set the IP address of an existing IPADDR object to null
  • void SetFromAscii(const char *pStr), Set the IP address to the value of the ASCII representation in the string pointed to by pStr
  • void SetFromIP4(IPADDR4 ip), Set the IP address of an IPADDR4 object from an existing IPADDR4 object

Setting IP Address Values with Static Functions

A “static” function is one that is not attached to any particular instance of an object. They are invoked with a double colon “::”. For example, IPADDR::NullIP() is used to represent an object instance with an IP address of null.

  • static IPADDR6 NullIP(), Return an IPADDR6 object whose IP address is NULL. For example, IPADDR::NullIP();
  • IPADDR AsciiToIp(const char * pStr), Sets the IP address to the value represented by the ASCII string pointed to by pStr. For example, IPADDR myIpAddr = IPADDR::AsciiToIp(“192.168.1.1”);

Reading and Checking IP Address Values

  • bool IsNull(), Returns true if the IP address is null
  • bool IsLoopBack() Returns true if the IP address is the loopback address
  • bool IsMultiCast() Returns true if the IP address is a multicast address
  • bool IsLinkLocal() Returns true if the IP address is the IPv6 link local address. A link local address is of the format
    FE80::/10
    .
  • bool IsEmbeddedIPV4() The same storage space is used to represent an IPv4 or IPv6 address. The function returns true if the address is
    ::FFFF:xx.xx.xx.xx
    , where the x’s represent the IPv4 address.
  • MACADR McastMac() Returns the MAC address for multicasts at this IP address, or null if not a multicast address.

Output an IP Address

  • void printf() Print the IP address value to stdout. The default stdout is the debug serial port
  • void fdprintf(int fd) Print the IP address value to the specified file descriptor
  • int sprintf(char *pStr, int maxl) Sends output to the string pointed to by pStr. maxL = Maximum number of characters to write. Returns the number of characters written.

Domain Name Service (DNS)

The function signature for DNS changes slightly between IPv4 and IPv6. However, if you use the default parameters, your code can be identical in both cases.

The following code example will work in both cases:
GetHostByName(“thename.com”, &resultIP, IPADDR::NullIP(), 10 * TICKS_PER_SECOND);

This will put the IP address of “thename.com” in the resultIP. If you need DNS records other than just the name you can add additional type parameters. The types are:

  • DNS_A, IPv4 address record
  • DNS_CNAME, Canonical name record
  • DNS_MB, Mailbox resource record
  • DNS_MG, Mail group resource record
  • DNS_MX, Mail exchange record
  • DNS_AAAA IPv6 address record

When using DNS in IPv6 you need to decide which address to choose if the server has both an IPv6 and IPv4 address. The function GetHostByName6() has two default value types:

int GetHostByName6( const char *name, // Name to resolve
IPADDR *pResultIP, // Stores resultant IP
const IPADDR &dnsServerIP, // DNS server IP address to use, or IPADDR::NullIP() for system
WORD timeout, // Timeout in system time ticks
WORD TYPE1 = DNS_A, // Defaults to IPv4 address
WORD TYPE2 =DNS_AAAA ); // Defaults to IPv6 address
int GetHostByName6(const char *name, IPADDR *pIpaddr, const IPADDR &dns_server, uint16_t timeout, uint16_t TYPE1=DNS_A, uint16_t TYPE2=DNS_AAAA)
Get the IPv6 address associated with the specified domain name.
Definition: ipv6_dns.cpp:487
#define DNS_AAAA
128-bit IPv6 address
Definition: dns.h:41
#define DNS_A
32-bit IPv4 address
Definition: dns.h:36

The function will first try to get the TYPE1 value. If that fails, it will try to get the TYPE2 value. In the default case as defined in the header file it tries to get an IPv4 address, and if that fails it gets an IPv6. If you want to reverse this priority and try to get the IPV6 first then add the additional types in the function call:

 `GetHostByName(“thename.com”, &resultIP, IPADDR::NullIP(),  10 * TICKS_PER_SECOND, DNS_AAAA, DNS_A);`

Note for OSX Users

At the time of this writing, BSD derived network stacks (including Apple’s OS X) are not able to navigate to link-local addresses in a browser. You must use something refer to as a scope ID.