Chapter 4. Storage of IP Addresses

Once your application accepts an IPv6 address via an input field or an API or retrieves it from DNS, how does your app actually store that address?

And, given that we will be working with dual-stack systems for quite some time, can your application handle both an IPv4 and an IPv6 address?

Memory Locations

Consider, for instance, memory locations. With IPv4, you have a rigid 32-bit address. Is your application only allocating a fixed size in memory? What happens when you try to insert the 128-bit IPv6 address into that memory location? Will you have a buffer overflow?

Similarly, in reading from a memory location, have you again addressed the fact that IPv6 addresses may have a variable length, depending on whether address compression was used?

In a dual-stack environment, are you allocating memory space for two addresses, so that you can store both an IPv4 and an IPv6 address?

Databases

As with memory locations, you need to look at your database tables where you store IP addresses. Is the field you use to store IPv4 addresses big enough to handle the much larger IPv6 addresses? Do you need to modify any components of your application that interact with the database to address the larger size?

In reading or writing to the database, do you again need to compensate for the variable length of IPv6 addresses? With IPv4, you always knew you had four octets that were represented by decimal numbers. If you applied a format to the results retrieved from your database, it was incredibly trivial to do using IPv4. It’s a nice, fixed format.

However, with IPv6 the address could be as short as:

::1

or as long as:

2001:db8:3f4d:ccdd:4179:880a:f00d:5511

Can your routines that read or write to your database handle this variability?

Configuration Files

Similarly, text-based configuration files have the same issues, regardless of whether they are written by the application or manually edited by users. Are the components of your app that read from or write to any configuration files able to work with IPv6 addresses? Can they handle the variable IPv6 address length?

Configuration files also have another issue you need to think about, namely:

Are there hardcoded IP addresses lurking in the configuration file?

Think of the many times you have browsed through an application’s config file and seen instances of hardcoded IP addresses. It could be something as basic as a default address, or it could be an IP address inside of a URL. As a simple example, consider a configuration file that references localhost as 127.0.0.1 in IPv4. In IPv6, localhost is ::1. Do you need to update the configuration file? Can the configuration file reference both an IPv4 and an IPv6 value?

As another example, take a look at the httpd.conf file used by Apache web servers. To indicate that Apache should listen on a specific IPv4 address, a Listen directive is included in the file:

Listen 198.51.100.55

With IPv6, you need to change the Listen directive to have the IPv6 address in square brackets:

Listen [2001:db8:3145::100]

You can, of course, include a port number after either address. For a dual-stack system where you want the Apache server to listen on both IPv4 and IPv6 addresses, you need to include both Listen directives:

Listen 198.51.100.55
Listen [2001:db8:3145::100]

Similarly, when configuring a <VirtualHost> directive, you might use an IPv4 address as shown here:

<VirtualHost 198.51.100.55>
ServerAdmin webadmin@example.com
DocumentRoot /var/www/html
ServerName www.example.com
</VirtualHost>

For IPv6, the file would need to be updated with the IPv6 address (note again the square bracket notation):

<VirtualHost [2001:db8:3145::100]>
ServerAdmin webadmin@example.com
DocumentRoot /var/www/html
ServerName www.example.com
</VirtualHost>

Again, similar to the Listen directive, if you want a VirtualHost directive to apply to both an IPv4 and IPv6 address, you need to have multiple VirtualHost directives, although both could simply point to the identical information.

How would your application handle storing IP addresses in a configuration file?

  • Would someone need to edit your configuration file to change addresses from IPv4 to IPv6?

  • How do you address providing both an IPv4 and IPv6 address?

  • Have you checked all the components of your application that reference the configuration file to see if they can read both styles of IP addresses? And can they deal with having both addresses in a dual-stack environment?

To this last point, you do need to consider that dual-stack systems will undoubtedly be around for quite a long time and you may therefore need to be sure you can store multiple IP addresses, whereas in the past you might have been able to store only a single address.

Case Sensitivity and Leading Zero Suppression

Regardless of how you are storing the IPv6 address, remember the case-sensitivity issue raised earlier. Unlike the all-numeric IPv4 addresses, IPv6 addresses can contain text in the form of the letters a–f. However, the specification for IPv6 addresses does not mandate whether those letters are uppercase or lowercase, and so you must assume that users of your application may provide IPv6 addresses using either case (or even a mixture).

RFC 5952 recommends that IPv6 addresses be entered entirely in lowercase and, for the sake of simplicity, you may want to simply have a routine that normalizes all incoming IPv6 addresses to lowercase before they are stored in memory, a database, or configuration files. Of course, given that some of those storage media may be able to be altered through another means (such as a system administrator editing a configuration file), you may want to also have your application normalize all IPv6 addresses to lowercase when reading from where the IPv6 address was stored.

Similarly, the IPv6 address specification allows for an address to either include or not include leading zeroes. These two addresses are identical:

2001:db8:10ff::ae:2
2001:0db8:10ff::00ae:0002

In fact, you could remove the zero compression and show the address in its full form:

2001:0db8:10ff:0000:0000:0000:00ae:0002

If you store the address in this longer form and then go to compare it later to the same address in a shorter form, your comparison routine needs to take into account these possible variations.

Again RFC 5952 makes some recommendations here and specifies that leading zeroes must be suppressed and the zero compression indicator (“::”) be used whenever possible (except for the case where there is only one zero, in which case the compression indicator should not be used). Given all of this, the recommended address for your app to store of the ones shown here would be:

2001:db8:10ff::ae:2

Your application needs to consider these points when storing the IPv6 address—and also when reading the IPv6 address in from storage. Will you normalize IPv6 addresses to a standard format? Do you need to for your application? If you are doing any kind of comparisons, it would definitely make sense. If you are simply connecting to a network address, you may not need to go through this extra work.

Just a wee bit more complicated than IPv4, eh?

Get Migrating Applications to IPv6 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.