In most cases, if you enter 0 for an IP address it will expand to 0.0.0.0. Likewise, 127.1 will expand to 127.0.0.1. Why? Magic.
But really, why do these shortcuts exist and how do they work? It can’t be as simple as adding zeros, if it was 127.1 would more logically expand to 127.1.0.0.
The familiar dotted-quad notation (AKA “dot-decimal notation”) is purely a human readable convenience. Each quad represents an octet, an 8 bit number. The four octets can then be combined into a 32 bit number which is the actual IP address.
Under the hood, integer IP addresses are always used. They are space efficient and reduce calculating networks from netmasks to applying a bitmask. If you’ve every entered a subnet mask in hex form (0xffffff00), you might have a sense of this.
To convert a dotted-quad into an integer, we need to put each octet in
to the correct position in the integer. The first octet needs to go in
bits 25 through 32, the second in 17 through 24 and so on. This is
done with the
Left Bitwise Shift Operator
<< in most languages.
Let’s take Google well known 22.214.171.124 DNS server address:
134744072 looks like nothing and yet:
It’s not that simple
The conversion explains why 0 works, the integer version of 0.0.0.0 is 0:
But what about 127.1? How does it know where to put the zeros?
inet_aton() treats addresses differently depending on
the how many dot separated numbers there are.
As we have seen, one number is the full integer IP address.
If there are two numbers, as in 127.1, the first number is the first octet and the second is a integer that fills in the remaining 24 bits. In the case of 127.1 it’s:
Which is the same as:
(And aren’t you glad you aren’t typing 2130706433 to get to localhost?)
A variation of this logic is applied in the case were three numbers are provided, the first two are octets and the third is the remaining 16 bits. Google’s 126.96.36.199 can be written as 8.8.2056
Why does this exist?
Why on Earth would
inet_aton() take such on construction? It’s
not actually clear from the documentation, but I have a theory.
First consider that an IP address has two parts, the network and the host. In the dotted-quad format, given 192.168.0.1, the first three octets are the network, “192.168.0” and the last the host, “1”.
At the time
inet_aton() was written, it was very common to
receive Class B (/16)
network allocations. Given the Class B network 10.10.0.0/16, your
first 255 addresses would be 10.10.0.1 to 10.10.0.255 (.0.255 is not
a broadcast address) with the 256th host being 10.10.1.0 (.1.0 is
not a network address). However, if you used a dotted-triplet you
could start at 10.10.1, continue through 10.10.256 all the way up to
10.10.65534. As with the dotted-quad, the last octet is the host and
the rest is the network.
I don’t think this form was ever common and stopped making sense when subnetting became the norm. Yet, it exists and, if nothing else, can save you a little typing.
Here’s a C program to explore the various notations. Most
modern languages provide
inet_aton() either direct or indirectly, as
there is something right about doing this in C.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
Now you can amaze and confuse your friends with inscrutable integer IP addresses.