An analysis of the referrers shows that a lot of people visiting this page
don't understand hexadecimal numbers;
An IPv4 address is NOT four decimal numbers, it's one 32 bit number!
A string like '127.0.0.1' is not an IPv4 addres. It merely
represents the actual IPv4 address '01111111000000000000000000000001'.
Other representations of the same address are '2130706433' and
'0x7f000001'.
An IPv6 address is NOT a collection of digits and letters, it's a 128 bit
number! A string like '::1' is not an IPv6 address. It merely represents
the actual IPv6 address.
The whole thing is a bit like René Magritte's painting
'Ceci
n'est pas une pipe' (This is not a pipe); The painting is not a pipe, it
represents a pipe.
Bin | Hex |
---|---|
0000 | 0 |
0001 | 1 |
0010 | 2 |
0011 | 3 |
0100 | 4 |
0101 | 5 |
0110 | 6 |
0111 | 7 |
1000 | 8 |
1001 | 9 |
1010 | a |
1011 | b |
1100 | c |
1101 | d |
1110 | e |
1111 | f |
So that's 2 hex digits to represent 8 bits (a byte), 8 for 32 bits (4 bytes) and
32 for 128 bits (16 bytes).
A group of 4 bits is also known as a nibble (little byte). A group of 4 nibbles
(16 bits or 2 bytes) is sometimes referred to as a 'quad nibble'. EG;
0db8 = 0000 1101 1011 1000
It takes 8 quad nibbles to represent 128 bits.
Hexadecimal numbers are in fact easier to use than decimal numbers. This is because in quad decimal notation (EG 127.0.0.1) each number represents 1 out of 256 possible 8 bit patterns. Whereas in hexadecimal notation, each hex digit represents just 4 bits. This makes things a lot simpler.
For instance, try to find out the binary value for decimal '168'. Wat you need to do is find which powers of two are in there;
Bit | 2ⁿ | Binary | Dec |
---|---|---|---|
0 | 2⁰ | 0000 0001 | 1 |
1 | 2¹ | 0000 0010 | 2 |
2 | 2² | 0000 0100 | 4 |
3 | 2³ | 0000 1000 | 8 |
4 | 2⁴ | 0001 0000 | 16 |
5 | 2⁵ | 0010 0000 | 32 |
6 | 2⁶ | 0100 0000 | 64 |
7 | 2⁷ | 1000 0000 | 128 |
168 ≥ 2⁷ (128), so the biggest number that fits in there is 2⁷. This means that the most significant bit, bit 7 is set;
Decimal Binary 168 - 128 1??? ???? ----- 40
40 < 2⁶ (64), so bit 6 is zero;
10?? ????
40 ≥ 2⁵ (32), so bit 5 is one;
40 - 32 101? ???? ----- 8
8 < 2⁴ (16), so bit 4 is zero;
1010 ????
8 ≥ 2³ (8), so bit 3 is one;
8 - 8 1010 1??? ----- 0
There is nothing left so all the other bits are zero;
1010 1000
Now do the same thing for hex 'a8'. All you need to do is look it up in the table above;
a = 1010 8 = 1000 a8 = 1010 1000
If you want to do this without a table, values 0 to 7 are pretty easy to do by hart;
Hex | Powers of 2 | Binary |
---|---|---|
0 | 0 + 0 + 0 | 000 |
1 | 0 + 0 + 1 | 001 |
2 | 0 + 2 + 0 | 010 |
3 | 0 + 2 + 1 | 011 |
4 | 4 + 0 + 0 | 100 |
5 | 4 + 0 + 1 | 101 |
6 | 4 + 2 + 0 | 110 |
7 | 4 + 2 + 1 | 111 |
For the rest, think of hex values 8 to f as sums of 8 plus 0 to 7;
Hex | Dec | Sum | Powers of 2 | Binary |
---|---|---|---|---|
8 | 8 | 8 + 0 | 8 + 0 + 0 + 0 | 1000 |
9 | 9 | 8 + 1 | 8 + 0 + 0 + 1 | 1001 |
a | 10 | 8 + 2 | 8 + 0 + 2 + 0 | 1010 |
b | 11 | 8 + 3 | 8 + 0 + 2 + 1 | 1011 |
c | 12 | 8 + 4 | 8 + 4 + 0 + 0 | 1100 |
d | 13 | 8 + 5 | 8 + 4 + 0 + 1 | 1101 |
e | 14 | 8 + 6 | 8 + 4 + 2 + 0 | 1110 |
f | 15 | 8 + 7 | 8 + 4 + 2 + 1 | 1111 |
When dealing with host addresses, network addresses and netmasks, doing things hex is a lot easier.
An analysis of the referrers shows that some of you are looking for stuff like
netmasks, CIDR and slash-notation. For instance, what is the netmask of all
addresses from 2001::0 to 2002::0 ?
More about this stuff on this page.
If you want to be a network administrator, you have to understand
binary
(base 2) and hexadecimal
(base 16) systems.
Furthermore you need a thorough understanding of
logic
operators like AND, OR, NOT and XOR.
An analysis of the referrers also shows that a lot of people are looking for the IPv6 equivalent of RFC 1918 and other reserved IPv4 addresses;
IPv4 | IPv6 equivalent |
---|---|
127.0.0.1 | ::1 |
169.254/16 | fe8/10 |
10/8 172.16/12 192.168/16 | fec/10 or fc/7 |
224/4 | ff/8 |
See address types for more information.
One thing which initially confused me was the way IP addresses are often phrased. EG;
2001:db8:1234:abcd:5678:ef90::1/64
This is in fact several statements rolled into one;
Host address: 2001:db8:1234:abcd:5678:ef90::1 Network address: 2001:db8:1234:abcd::0 Netmask: /64
From RFC 2374;
3.1 Aggregatable Global Unicast Address Structure The aggregatable global unicast address format is as follows: | 3| 13 | 8 | 24 | 16 | 64 bits | +--+-----+---+--------+--------+--------------------------------+ |FP| TLA |RES| NLA | SLA | Interface ID | | | ID | | ID | ID | | +--+-----+---+--------+--------+--------------------------------+ <--Public Topology---> Site <--------> Topology <------Interface Identifier-----> Where FP Format Prefix (001) TLA ID Top-Level Aggregation Identifier RES Reserved for future use NLA ID Next-Level Aggregation Identifier SLA ID Site-Level Aggregation Identifier INTERFACE ID Interface Identifier
The top (most left) 48 bits are set by your provider. The next 16 bits are
basically network addresses. That's 2¹⁶=65536 networks! On each network there are
max 2⁶⁴ interface addresses!
A /etc/network/interfaces (Debian Linux) example;
iface eth0 inet6 static pre-up modprobe ipv6 address 2001:db8:1234:1::6 netmask 64 gateway 2001:db8:1234:1::1
Replace '2001:db8:1234' with your own /48.
In my home town 172.16.x.y to 172.31.x.y addresses are used by a large wifi
network. 10.x.y.z addresses are used by the link between my modem and my server,
(which also acts as a gateway and NAT box). This leaves 192.168.x.y addresses
for use on my LAN.
On my LAN I use a subdomain 'int', EG: 'int.example.com'. I simply mapped 'int' to
'ip6' and 192.168.x.y to 2001:db8:1234:x::y. This way IPv6 nameserver zone files
can be easily derived (with a shell script) from IPv4 private net zone files.
So a host with IPv4 address '192.168.1.6' also has IPv6 address
'2001:db8:1234:1::6';
IPv4 | IPv6 | |
---|---|---|
Host name | pc6.int.example.com | pc6.ip6.example.com |
IP address | 192.168.1.6 | 2001:db8:1234:1::6 |
This reduces the number of address from 2⁸⁰ to 2¹⁶ [1], but that's still a lot.
There is also a third hostname which points to both IPv4 and IPv6 addresses
(the RFC1918 addresses are of course invisible to the outside world). So a host
'pc6.example.com' might have both '192.168.1.6' and '2001:db8:1234:1::6' as its
address.
Below an example;
~$ ping4 www.example.com PING www.example.com (192.168.1.1) 56(84) bytes of data. 64 bytes from www.int.example.com (192.168.1.1): icmp_seq=1 ttl=64 time=0.218 ms 64 bytes from www.int.example.com (192.168.1.1): icmp_seq=2 ttl=64 time=0.222 ms 64 bytes from www.int.example.com (192.168.1.1): icmp_seq=3 ttl=64 time=0.216 ms ~$ ping6 www.example.com PING www(www.ip6.example.com) 56 data bytes 64 bytes from www.ip6.example.com: icmp_seq=1 ttl=64 time=0.222 ms 64 bytes from www.ip6.example.com: icmp_seq=2 ttl=64 time=0.220 ms 64 bytes from www.ip6.example.com: icmp_seq=3 ttl=64 time=0.219 ms
[1] Actually 2¹⁶ - 512; In 192.168.x.y, 'y' cannot be 0 or 255. So the IPv4 addresses are 192.168.0.1 to 192.168.255.254. The IPv6 addresses are therefore 2001:db8:1234:0::1 to 2001:db8:1234:ff::fe (assuming 256 networks of max 254 hosts each).
The similar trick can be used for larger address spaces;
For instance, a /8 rfc1918 address;
10.20.30.40
Convert from decimal to hexadecimal;
0a.14.1e.28
Combine bytes into quad nibbles;
0a14 1e28
Insert colon;
0a14:1e28
Prepend prefix;
2001:db8:1234::0a14:1e28
Some more examples;
IPv4 | IPv6 |
---|---|
10.0.0.1 | 2001:db8:1234::0a00:0001 |
10.255.255.254 | 2001:db8:1234::0aff:fffe |
172.16.0.1 | 2001:db8:1234::ac10:0001 |
172.31.255.254 | 2001:db8:1234::ac1f:fffe |
192.168.0.1 | 2001:db8:1234::c0a8:0001 |
192.168.255.254 | 2001:db8:1234::c0a8:fffe |
You may omit the leading zeros from each quad nibble;
IPv4 | IPv6 |
---|---|
10.0.0.1 | 2001:db8:1234::a00:1 |
10.255.255.254 | 2001:db8:1234::aff:fffe |
172.16.0.1 | 2001:db8:1234::ac10:1 |
172.31.255.254 | 2001:db8:1234::ac1f:fffe |
192.168.0.1 | 2001:db8:1234::c0a8:1 |
192.168.255.254 | 2001:db8:1234::c0a8:fffe |
Below a converter.
Submitting two numbers separated by a single dot (ddd.ddd) will use the first
method (xx::xx), four numbers with three dots (ddd.ddd.ddd.ddd) the large range
method (xxxx:xxxx);
WARNING! The stuff above is not to be confused with the functional
equivalent of rfc1918 or other reserved IPv4 addresses.
See
address
types for more information.
I run Bind with views; I have different zone files for the outside world and my
LAN. In the internal zone file are host names like imap, ns, ntp, proxy and
smtp. These hostnames are invisible to the outside world and have both a
(RFC1918) IPv4 and a IPv6 address. Clients on the LAN can choose to connect to
either the IPv4 or the IPv6 address. Likewise daemons like the mailserver,
nameserver, ntpd or web proxy can connect to both IPv4 and IPv6 addresses.
This way IPv4 only clients can connect to IPv6 only servers and vice versa.
As web proxy Squid is used.
For IPv6 NTPD wants hex netmasks. EG;
restrict 192.168.1.0 mask 255.255.255.0 nomodify restrict -6 2001:db8:1234:abcd:: mask ffff:ffff:ffff:ffff:: nomodify
Or;
restrict 192.168.1.0 mask 255.255.255.0 nomodify restrict 2001:db8:1234:abcd:: mask ffff:ffff:ffff:ffff:: nomodify
To compensate for the 3rd: In a script run when the PPP link comes up, put:
# Set IPv6 route to remote end if ! ( ip -6 route | grep -q "${PPP_REMOTE}" ) then ip -6 route add "${PPP_REMOTE}" dev "${PPP_IFACE}" fi
To compensate for the 4th: In a script run when the PPP link comes up, put:
# Set IPv6 default route to remote end if ! ( ip -6 route | grep -q default ) then ip -6 route add default dev "${PPP_IFACE}" fi
Suppose you want to write a little daemon. Something that listens on all interfaces. And no ACLs. No options to make the server IPv4 only or IPv6 only.
The easiest way to implement this is to use a combined IPv4 - IPv6 socket (not all OS-es support this). Creating an IPv6 only listening socket will usually do the trick. If not, use setsockopt() to set 'IPV6_V6ONLY' to '0'. Do this after you set 'addr6.sin6_family' to 'AF_INET6'. A bind to '::' will now also bind to '0.0.0.0'.
If you insist on separate sockets, set 'IPV6_V6ONLY' to '1'.
AFAIK there are no cross platform FOSS GUI web-browsers that support IPv6
link-local addresses. Or rather, they don't support zone-indices. And you
need
zone-indices
to use IPv6 link-local addresses.
Lynx is a
FOSS cross platform web-browser, but it is a text browser and doesn't
support tables.
Still, if you need set set the IP address of an embedded device and you
can only connect to it using an IPv6 link-local address, Lynx is probably
the way to go.
Not found what you were looking for? Have a look at this page.