a Collection of Small Hints and Tools
There are quite a few occasions on which one has to do more or less complex calculations on IPv6 addresses. This page gives you a few hints on how to perform those calculations.
In an IPv6 address like 2001:db8:1:2::3/64 the part before the slash (/) is the address itself and the part behind the slash is the associated network mask. The mask is the amount of bits from the left of the address that belong to the so called network ID or prefix, while all remaining bits to the right belong to the host ID.
Network masks have several purposes:
When used to configure a network interface the mask tells the system what other addresses can potentially be found on that network link. For example the address and mask above would tell the system that the local interface has the address 2001:db8:1:2::3 and other hosts on the same link will have addresses out of the range 2001:db8:1:2:*:*:*:*.
When used to configure a routing table the mask is used to tell the system how many bits on the left of the address are significant for this route. For example telling the system to route 2001:db8::/32 to a specifc gateway will create a route that will match packets to 2001:db8::1 and 2001:db8:ffff:1:2:3:4:5, but not packets to 2002:aabb:ccdd::33.
A network mask can be any decimal number 0 (match any IP) and 128 (match exactly this one IP). Per convention network masks are usually put on multiples of 4 bits - this makes network and host IDs easier to understand. For example:
Most network interface types have a default network mask of /64, so that the 64 left bits belong to the whole network link and the right 64 bits are used to differentiate between the nodes connected to this link - so unless you encounter one of the more unusual network configurations, you will only see network masks between /0 and /64 in steps of 4 and the mask /128 to express host-only.
Most networks on an organisational level are hierarchic - this is also expressed by the network masks that will be encountered in those networks. Most organisations will start with a /48 prefix (eg. 2001:db8:1234::/48), that they get from their upstream provider and sub-divide this network until they reach the link or node level.
Let's assume we need to make a network plan for a campus with eight buildings, each building has two to four independent entrances and each entrance has up to ten floors above it. One possibility to structure the network would be to distribute connectivity from the central IT building to each other building, from each buildings main entrance to the other entrances and from there to each floor, putting a small router on each of those distribution points.
We start with 2001:db8:1234::/48 which our provider routes to our central connectivity hub at IT and follow the cable-tree. One possibility would be to give each building a /56 prefix - 2001:db8:0::/56 for infrastructure, 2001:db8:1234:100::/56 for IT, 2001:db8:200::/56 for research building 1, ..., 2001:db8:1234:700::/56 for the management and finances building.
Using /56 on this level gives us the freedom to simply hand out more /56 networks if new buildings are built or existing buildings extended, if we used /52 on this level we would have only 16 main networks and would have to restructure the network when building number 17 is constructed.
Let's consider the management and finances building as an example. There are four entrances: upper management, production management, research and development, and public relations and marketing. Obviously those branches need a good network separation or for example marketing would continuously spy and bicker on research to give them a cool new feature. So each entrance gets a router-firewall and a /60 subnet - 2001:db8:1234:800::/60 for the router network itself, 2001:db8:1234:810/60 for upper management, 2001:db8:1234:820::/60 for production management, 2001:db8:1234:830::/60 for research, and 2001:db8:1234:840::/60 for marketing/PR.
The building has four floors - at the research branch of management the first floor is the finances branch that budgets the research and the other floors house the research management (properly separated from their employees, so the researchers can think freely). We can continue the network sub-classing with reserving 2001:db8:1234:840::/64 for infrastructure, giving floor 1 the prefix 2001:db8:1234:841::/64, floor 2 the prefix 2001:db8:1234:842::/64, etc.pp. with each floor having one switched link.
To make things more interesting the research building has more than 16 entrances: one for researching novel cup-cake-forms and one for researching novel flavours, one for flour research, several for research bakeries, etc.pp. This makes it difficult to service the building with just one /56 prefix. We need to separate the building into several sub-buildings with one /56 prefix each - eg. 2001:db8:1234:200::/56 for the south half of the building, 2001:db8:1234:300::/56 for the north half. We could deliver connectivity over two cables (one for each /56) or simply over one cable and set up two routes over it or even aggregate the route into 2001:db8:1234:200::/55.
On a socket level it is possible to use an IPv6 network socket to receive and handle IPv4 traffic. While normal users and administrators don't usually see much of this behaviour, it makes lives considerably easier for programmers: they only need to support the IPv6 socket interface to handle both IPv6 and IPv4 and they can save one socket if their program needs to listen on both protocol families.
More specifically any IPv6 based program listening on the IPv6 ANY address ("::") will also receive IPv4 traffic (if the host and interface supports it) and any IPv6-based client program can use an IPv4 mapped address to contact an IPv4-based server program.
IPv6-mapped IPv4 addresses simply map the 32bits of the IPv4 address to the right-most 32 bits of the IPv6 address structure and fill the other 96 bits with zeroes. For example the IPv6-mapped address for 10.1.2.3 would be ::0a01:0203/96. So if an IPv6 server received traffic from there it would see ::a01:203 as the source address of the packet and also use it as target in its response.
Calculating these mapped addresses is an easy matter of converting dotted decimal notation to hexadecimal notation, which can be done with built-in shell tools. For example the conversion of 192.168.11.22 to IPv6-mapped could be done like this:
bash$ printf "::%x%02x:%x%02x\n" `echo 192.168.11.22|tr . " "` ::c0a8:b16
The printf utility uses the same format as the printf function in the C programming language - the "%x" place holder converts a number given as parameter to hexadecimal notation, the "%02x" additionally pads it with 0's to at least 2 characters.
Alternatively many systems allow a mixed notation like "::192.168.11.22", but not all programs and operating systems understand these mixed notation addresses.
Similar to IPv6-mapped addresses a conversion between a global IPv4 address and a 6to4 tunnel prefix requires the transformation between dotted decimal and hexadecimal:
bash$ printf "2002:%x%02x:%x%02x::/48\n" `echo 192.168.11.22|tr . " "` 2002:c0a8:b16::/48
Please note that the example address above will not work in a regular setup, since it is a private address and not globally routable.
You can find a few utilities here (checkout with subversion):
svn co https://silmor.de/svn/misc/ip6calc
The ip4toip6 utility can be used to convert all local IPv4 addresses up IPv6-mapped addresses and 6to4 prefixes.
The ip6calc utility can be used to calculate network and host IDs from a full IP-address plus mask, as well as calculating sub-classed networks - eg. for combining a dynamic provider-assigned /48-prefix with the local network numbers to create the actual local /64 network prefixes.