Rack of Ethernet switches.

How to Understand IP Addresses and Subnets

A "Just Enough" Guide to Network Details

IP addresses and associated details like subnet masks used to be esoteric concepts. Only technical specialists saw these details. But now IP addresses are casually mentioned. Stories about criminal investigation or geopolitical intrigue describe attributing actions through records of IP addresses. Pop-up ads associated with BitTorrent file-sharing warn you to "mask your IP."

The Internet used to consist of nothing but research institutions plus a few of the most technically oriented parts of the U.S. Government. Now most people are on the Internet. The percentage and total number are both higher when you consider that mobile phones use IP.

"IP" stands for "Internet Protocol". The TCP/IP suite won the evolutionary process of network protocol development. If you're on the Internet, you're running IP. Not Novell Netware's IPX/SPX, or Banyan VINES, or the actual OSI protocols, or anything else.

Meanwhile we all have to do our own troubleshooting from time to time. We try to make sense of things like this:

Linux $ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: p3p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:13:3b:12:6f:a9 brd ff:ff:ff:ff:ff:ff
    inet 10.1.1.100/24 brd 10.1.1.255 scope global p3p1
       valid_lft forever preferred_lft forever
    inet6 fc00::213:3bff:fe12:6fa9/64 scope global dynamic mngtmpaddr
       valid_lft 86131sec preferred_lft 14131sec
    inet6 fc00::1:0:0:1/64 scope global dynamic mngtmpaddr
       valid_lft 86131sec preferred_lft 14131sec
    inet6 fe80::213:3bff:fe12:6fa9/64 scope link
       valid_lft forever preferred_lft forever
3: p7p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:13:3b:12:6f:aa brd ff:ff:ff:ff:ff:ff
    inet 73.103.82.147/21 brd 255.255.255.255 scope global p7p1
       valid_lft forever preferred_lft forever
    inet6 2001:558:600d:39:300a:e052:e108:949/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::213:3bff:fe12:6faa/64 scope link
       valid_lft forever preferred_lft forever
4: wlp10s0u2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether c8:3a:35:cf:3b:b9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.101/24 brd 192.168.1.255 scope global wlp10s0u2
       valid_lft forever preferred_lft forever
    inet6 fe80::ca3a:35ff:fecf:3bb9/64 scope link
       valid_lft forever preferred_lft forever

$ ip route
default via 73.103.80.1 dev p7p1 metric 5
10.1.1.0/24 dev p3p1 proto kernel scope link src 10.1.1.100
73.103.80.0/21 dev p7p1 proto kernel scope link src 73.103.82.147 metric 5
169.254.0.0/16 dev p7p1 scope link metric 5
169.254.0.0/16 dev wlp10s0u2 scope link metric 35
169.254.0.0/16 dev p3p1 scope link metric 1002
192.168.1.0/24 dev wlp10s0u2 proto kernel scope link src 192.168.1.101 metric 35

I'll show you how to understand that!

So, let's start with IP addresses and then move on from there.

IP Addresses

An IP address is a string of bits.

I'm going to explain just IP version 4, or IPv4, to start with. That is, I'll explain about IP addresses, and subnet masks, and subnet design, and some other pieces, entirely in terms of the relatively simple IPv4.

Then at the end, I'll show you how those work with IPv6. And as it turns out... It's exactly the same!

32-bit Addresses

So, an IP address is a 32-bit pattern. A sequence of 32 bits, each of them either a zero or one.

This addressing system was developed in the late 1970s. Most computers already dealt with data in 8-bit chunks or bytes. 32 is a multiple of 8. In addition, 32 itself is a power of two. Finally, a 32-bit field provides 232 or 4,294,967,296 possible patterns, or addresses.

Starry-eyed dreamers at the time speculated that this Internet thing being dreamed up might, one day, have a few thousand nodes. So, 32-bit addresses providing over 4 billion possible addresses would be way more than we could ever need. Yes, that was very much like Bill Gates saying that 640 kilobytes of memory (that is, 0.00064 GB) was more than anyone would ever need.

You could represent that pattern in several different ways. However, most of them are rather unfriendly to us humans. For example, the computer I'm using right now has this IP address:
11000000101010001111111000010010

That's really the address. Computers store data in memory as bits, they process data in programs as bits. Computers like binary.

But, we humans don't! Let's see, what are some possibly friendlier alternatives?. I could convert the 32-bit string into an integer in base 10:
3,232,300,562

That doesn't make my human eyes go cross-eyed trying to read it the way the 32 bits did. However, a specific integer well over 3 billion isn't exactly handy. And, as I'll show you soon, there are multiple levels of detail I would like to take advantage of, but I can't with one giant base-10 integer.

What about hexadecimal, or base 16? That's a little better as it's shorter and it somewhat supports those multiple levels I mentioned. But if you aren't an assembler programmer, most people don't find base 16 to be a friendly format:
0xC0A8FE12

The Internet Protocol was developed in the late 1970s, and a document from 1981 formally defines the same IP protocol and addresses we use today. We also still use its compromise solution for representing IP addresses. We start with the original 32-bit pattern:
11000000101010000000000101100110

Now break that into 8-bit chunks:
11000000 10101000 00000001 01100110

Finally, convert each 8-bit chunk into a base-10 number, and connect those with dots. Since they're based on 8-bit chunks, each of the four numbers must lie within the range of 0 through 255:
192.168.1.102

People call that dotted decimal or dotted quad notation.

Like I said, it's a compromise. They're familiar base 10 numbers, there are only 4 of them, and they can't get very large. This makes many things much easier for humans, like communicating one over the phone, or seeing one on the screen and accurately writing it down.

But like other compromises that make easy things even easier (for example, the computer mouse), dotted quad can get in the way of more advanced and quite necessary things, as we'll see in a bit.

But for now, it's what we have.

Where Versus Which

As I mentioned, we want to deal with addresses at multiple levels of detail. The clever design of this lets the Internet grow to a complexity far beyond what its original inventors expected.

The word Internet is a shortcut for "Internetwork", a word invented to mean a large-scale network made up of inter-connected smaller networks, where each smaller network has multiple hosts attached.

Some hosts are connected to multiple networks and can forward packets between them. These forwarding hosts, which we call routers, allow communication between hosts connected to different networks.

The first part of the address is called the netid and it answers the question "Where is this host?" Or, put another way, "On which network?"

The routers use the netid to decide how to forward a packet hop by hop by hop across the Internet to its destination.

The rest of the address is called the hostid and it answers the question "On that network, which host?" The hostid is used for the very last hop.

So, coloring the netid yellow and the hostid blue, the IP address is something like this:
1011...netid...10010001...hostid...1101
The whole thing is 32 bits long. The first so many are the netid, and the rest are the hostid.

But where does it split? I said "the first so many", but how many exactly?

It's however many you want it to be, whatever best solves your specific problem!

Deciding exactly where to split netid versus hostid gets into subnets, which I'll get to shortly. But first...

Slash Notation

Since there's no default answer to the length of the netid, we need to indicate where we're splitting the address.

How Not To Do It

We used to think of a binary netmask, a 32-bit pattern where 1 meant "part of the netid" and 0 meant "not the netid" or "part of the hostid". Then break that into 8-bit chunks, convert those to base 10, and end up with something like 255.255.240.0.

People who dealt with this all day every day would say "Oh, it's obvious! Just convert the IP address into binary, convert the netmask into binary, logically AND those two, then reverse the conversion process, and there's your answer!"

They would get a blank stare in response, and then try to explain by saying "Look, 192.168.254.18 AND 255.255.240.0 is obviously 192.168.240.0, right?" And before you could respond, they would continue "And so, the host part is 'IP AND (NOT NETMASK)' and so 192.168.254.18 AND 0.0.15.255 is obviously 0.0.14.18, so there's your answer."

Needless to say, most people did not find this to be an intuitive system.

Yes, it's how a computer does this, with logical operations on 32-bit registers, but dotted-quad netmasks just confuse most people.

Slash Notation: Just Say What You Mean

I vaguely said "the first so many" when I first explained what the netid and hostid were. If you asked me for an exact answer, I would tell you the number of bits in the netid. Sometimes that's called the "netmask length".

Let's say that I said 20 bits in the netid. OK, that leaves 32 minus 20, or 12 bits in the hostid.

In slash notation, you write the IP address as usual, then a slash character, and then the number of bits in the netid.

For my example, that's 192.168.254.18/20.

20 is not a multiple of 8, so the netid-vs-hostid split doesn't fall on a break between those base 10 numbers. The 192.168 numbers are in the netid and 18 is in the hostid. However, 254 represents a block of 8 bits. The first four of those are in the netid and the rest are in the hostid.

If you insist on my telling you just the netid or hostid part in dotted decimal, you'll need to give me a few moments to figure out the details. But to be honest, that's not something I need to do very often.

The important thing is that we can select whichever netid length (or netmask) provides the best network design. And that leads to...

Subnets

Blocks of IP addresses were originally handed out in three different sizes.

Back in the Day of Classful Addresses

This ended in the early to mid 1990s, but people still think about it, and often assume it still works this way.

There were the Class A blocks, later called /8. The first octet was set, the remaining 24 bits were free for you to assign. There could only be 126 of those blocks, but each one could have over 16.7 million hosts. They were 1.0.0.0/8 through 126.0.0.0/8. (0.0.0.0/8 was reserved, never to be used, and all of 127.0.0.0/8 was set aside for a different reason)

The next size down was Class B or /16 blocks. There could be 32,768 of these, each with over 65,534 hosts. They were 128.0.0.0/16 through 191.255.0.0/16.

Then there were the Class C or /24 blocks. There could be over 2 millions of these, each with 254 hosts. They were 192.0.0.0/24 through 223.255.255.0/24. (254 hosts each and not 256 because there are two prohibited hostid patterns: all zeros is reserved to refer to the network itself in routing tables, and all ones is the broadcast address meaning "all hosts on this network")

Several years ago I did a lot of consulting work for Cummins Engine Company, and I still remember that they have the address block 160.95.0.0/16.

Yes, they really wanted to have up to 65 thousand computers directly accessible from anywhere out on the Internet. This was a long time ago!

A Class B (or /16) address block was much more auspicious than a handful of Class C (or /24) addresses, so they asked for as big a chunk as they could get. The Class A (or /8) blocks were reserved for things like major telecommunications companies. Plus, for reasons I never understood, the pharmaceutical manufacturers Eli Lilly (40.0.0.0/8) and Merck (54.0.0.0/8).

So, Cummins got 160.95.0.0/16. They connected to their ISP and told them they were open for business. Send them all packets bound for the 160.95.0.0/16 address block!

However, there was no way they could use anything beyond a tiny fraction of their address space on one big network. You can't have a Ethernet LAN with tens of thousands of connected devices. Ethernet just doesn't do that. Plus, Ethernet cables can't be longer than 100 meters because of timing standards, but the company has buildings all around the city.

They needed subnets. People cringe when I bring that up, but...

You Already Understand This

You just don't realize that you already understand it.

Well, what you do understand is telephone numbers. But telephone numbers work very much like IP subnetting.

Here's a telephone number: +1-7654092125

Yes, I wrote it in a slightly different format than usual, it's a little harder to read without dashes or spaces, but you could use it. Let's say that it's my phone number. (It isn't, but it's very similar to mine),

If you're very anxious to talk to me, you won't care about cost to you or inconvenience to me. You'll simply call that number.

Now maybe you're kind of anxious, but you want to be careful about cost. Some countries are very expensive to call, because the ruler's brother is the Minister of Telecommunications and they jack up the rates to make more money for the ruling family. But then you notice that this number starts +1, which means the U.S. and Canada. (Plus some U.S. Pacific and Caribbean territories, some of which are pretty expensive to call, plus a few more unexpected Caribbean nations like Trinidad and Tobago).

But, for the most part, and for the sake of my story, +1 means U.S. and Canada. You're OK with the costs of calling there, so you do.

Maybe in addition to your cost, you want to be considerate about time. You want to talk to me, but it doesn't have to be right now. Maybe you'll check and see what time it is where I live. Am I likely to be in bed? The U.S. and Canada span seven time zones, from UTC-10 in the Aleutian Islands and Hawaii through UTC-4 in eastern Canada. In the U.S. and Canada, the next three digits in a phone number are the area code, which narrows it down to a region. You look at the number like this:
+1-765-4092125

Indiana area code map, from https://commons.wikimedia.org/wiki/File:Area_codes_IN.png

In the old days you would have looked at the map in the front of your phone book. Now you ask Wikipedia or Google. Ah, +1-765-xxxxxxx means, within North America, a wide stripe across Indiana slightly north of center, minus the city of Indianapolis. That means the Eastern Time Zone, the same as New York. You check the time, I should be awake, so you make the call.

But maybe you want to go even deeper. The next three digits are the exchange, because that leaves four digits for the actual number, and phone companies have generally used 10,000-line switches for landline systems. So you look at the number like this:
+1-765-409-2125

I start to enthusiastically tell you that +1-765-409 means T-Mobile wireless customers in the West Lafayette area, while +1-765-743 means landlines in the older area of West Lafayette, and +1-765-497 means landlines in newer areas of town, and +1-765-494 means the Purdue University academic campus, and +1-765-495 means Purdue dorms and graduate housing, and ...

Then you tell me to be quiet, as that's far too much information.

Well, for you, sure, but T-Mobile and other providers certainly need to know that level of detail. And, it can be useful for someone who lives in West Lafayette — is that a business or home, or a campus number, or a student's dorm room?

Notice that splitting the phone number at different points takes you to further subdivisions of the worldwide telephone network — North America, which contains north-central Indiana, which contains West Lafayette, which is where Bob got his phone.

When asking "Where is this number?", the answer "Eastern North America" is probably enough detail for you. But I might want to know which part of West Lafayette. We're neither one wrong, we have our own reasons for wanting some level of detail.

Subnetting is Just Like This

The reality is that "the network" is really a network of interconnected networks, each of which quite likely is itself broken up into smaller networks, with even finer subdivisions of those. However, we only care about the details we have to care about.

In my phone number example, you might have seen the country and said "I know enough." Maybe you went as far as the state or province. You probably would not have cared about what city I live in, and I can't imagine you caring about my wireless provider.

The person placing the call, just like the host sending the packet, only wants just enough information to get that done. Sure, routers closer to the destination need to know more and more details, but that's their problem.

Back To My Example

I was talking about Cummins, who had the 160.95.0.0/16 IP address block. For anyone outside Cummins, that's all they needed to know. If the IP address looks like 160.95.*.*, send the packet to that big diesel engine company in Indiana. Let them figure out what to do with it.

Someone there thought about their organization. They had several locations around their city. None of them had over a thousand computers within that one site. Most of the sites had no more than 200 computers.

So they said, "We can't have one enormous network with 65,000 possible addresses, because we couldn't use more than a few hundred to maybe a thousand of those, and it could only cover one building. What if, instead, we had about 250 networks, and each of those had about 250 addresses? Yes, a small number of sites have more than 250 computers, so we'll put multiple networks in each of those larger buildings." They made a table like this:

Site Number of computers Networks
State Street 850 1, 2, 3, 4
Central Avenue 200 5
Jackson Street 100 6
West Side 600 7, 8, 9
...and so on...

They're breaking their too-large network into several smaller networks, called "sub-networks", or "subnets" for short.

An Easy Solution

There's a very easy solution if the above plan for about 250 subnets of about 250 hosts each is acceptable.

The ISP is routing the 160.95.0.0/16 block of addresses to Cummins, so the first 16 bits are the netid as far as the outside world is concerned. The remaining 16 bits are handled once it gets within the organization.

160.95.*.* means Cummins, get the packet to the edge of that company and let them figure it out.

The rather trivial subnetting solution is a /24 netmask. So, out of the 16 bits we're free to set, the first 8 of those are part of the netid and the last 8 are the hostid, as long as you have the inside information about the subnetting scheme used within that company. That is, that Cummins uses a /24 netmask with 160.95.*.* addresses, not the /16 used by the outside world.

What makes this extra easy, and thus attractive, is that the first two octets, or numbers, are the overall network, the third is the subnet number, and the fourth is the host number. So, 160.95.12.20 is at Cummins, on subnet #12, host #20.

 All of Cummins, as far as outsiders care
   |   Some host at Cummins
   |     |
/--+-\ /-+-\
160.95.12.20
\---+---/ |
    |     |
netid and hostid *IF* if you know what they do internally 

To the outside world:

Within Cummins:

Then you will need some networks for the MAN or Metropolitan Area Network, the loop around the city. Plus the point-to-point links between sites, and some other bits and pieces. But our scheme has over 250 networks, so we will have plenty for the various connections.

A Better and Nontrivial Solution

The above is a very trivial solution. You often see it used, as it's so easy.

However, someone might object to that plan. "Look, you are splitting some sites into multiple networks. That means that two hosts in one of those buildings are likely to connected through a router. That adds latency, a fancy way of saying it takes more time for the packet to get there. We need high-performance networking. All hosts within one site should be directly connected through Ethernet switches. Router forwarding should be limited to links between sites. With just one network per site, the table should look like this:"

Site Number of computers Subnet
State Street 850 1
Central Avenue 200 2
Jackson Street 100 3
West Side 600 4
...and so on...

That inventory shows that one site has 850 computers. 8 or even 9 bits of hostid aren't enough. They only provide 256 or 512 possible hostids, respectively. We need 10 bits of hostid, giving us 210 = 1024 possible answers to "Which host on this network?" (two of which are reserved)

The first 16 bits of the IP address are fixed, they have to be in the 160.95.0.0/16 block. Since we have only 16 bits to play with, and we want 10 bits for the hostid, that leaves 6 bits for the netid. Our internal netmask is 16 + 6 or /22.

We will have to use binary to assign address. Let's leave the fixed first 16 bits or two octets in base 10, and then use yellow xxx for additional netid bits, and blue yyy for hostid bits. An address will be like this:

160 . 95 . xxxxxx yy.yyyyyyyy
\-------+-------/ \----+----/
        |              |
      netid         hostid 

Let's say we're setting up host #300 on network #2. 300 in binary is 100101100. The hostid has 10 bits, so it will be 0100101100. 2 in binary is 10, so those added 6 bits of netid will be 000010.

Assembling the pieces, the address will look like this:

160 . 95 . 00001001.00101100 

Now look at where the 8-bit chunks break. I left the dot there. The third octet is 00001001. That's the six added netid bits (that is, the subnet) plus the first two bits of the hostid. Converted from binary to base 10, 00001001 becomes 9.

The fourth octet is made up of the last 8 bits of the 10-bit hostid, 00101100. Converted to base 10, that's 44.

So, host #300 on network #2 gets 160.95.9.44/22

No, this is not intuitive to us humans! That's because we split the address into 8-bit chunks and converted each of those into base 10, distorting what's really going on. But computers and routers have no problem with this, as they use binary. Give them a 32-bit address and tell them how many bits are the initial netid. Routers outside the company assume it's the official /16, routers inside get to know it really splits as /22. Let's convert the 160.95 part into binary and see what's going on:

OUTSIDE
 VIEW
       netid
         |
/--------+--------\
   160   .    95    .     9   .   44
10100000 . 01011111 . 00001001.00101100
\------------+-------------/\----+----/
             |                   |
INSIDE     netid              hostid
 VIEW

The first 16 bits are fixed. All packets with those first 16 bits, and only those packets, will be delivered to the edge of the company.

We have 6 subnet bits, 6 additional bits interpreted as part of the netid within the organization. 26 = 64, so we can assign that many subnets. However, what used to be restrictions, then strong recommendations, and what survives as tradition, discourages the all-zeros and all-ones patterns. So, just 62 subnets to be safe. See this Cisco document for far more detail.

We have 10 hostid bits, and 210 = 1024. Minus the two special patterns, that allows up to 1022 hosts on each of those 62 networks.

Going (Just a Little) Deeper

You can shorten network addresses by leaving off the base 10 numbers that aren't used. Instead of saying that a company uses 160.95.0.0/16, you might just say 160.95/16. I'm not saying that you should do this, but you will see other people doing and so you need to be aware.

My explanation of subnets assumed that every system within an organization uses the same netmask. However, you can have what's called Variable Length Subnet Masks or VLSM. A network with 800 hosts would use /22 so it has 1,022 possible addresses.

A point-to-point link between routers, joining two sites, needs its own address block. It would be wasteful to use a 1,022-host network address block for that link that only has two devices, one at each end! With VLSM, that subnet would use /30, leaving 2 bits for hostid and just two valid patterns, 01 and 10.

If you say that a company was assigned 160.95.0.0/16, all you can assume is that they are somehow using subnets. But if you asked me what their internal subnet mask was, I would have to answer "It depends on how they designed it." And, unless we're going to do some work there, we don't care. We don't need to know about their internet subnet design. We just send a 160.95.0.0/16 packet to the edge of that organization. They figure out the details.

Given the possibility of VLSM, even within the organization the answer is "It depends". If I'm sitting in front of a host on one of their networks, its configuration doesn't give me any clue about the netmask in another network within that organization.

CIDR & VLSM

Maybe you just want to move on, but if you want to learn how to design a VLSM internetwork, see my page on CIDR and VLSM.

Practical Examples

Let's look at that command output again. I have added the -4 option so we see just IPv4, the IPv6 details are left out. First, the IP addresses assigned to the interfaces.

Linux$ ip -4 addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: p3p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:13:3b:12:6f:a9 brd ff:ff:ff:ff:ff:ff
    inet 10.1.1.100/24 brd 10.1.1.255 scope global p3p1
       valid_lft forever preferred_lft forever
3: p7p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:13:3b:12:6f:aa brd ff:ff:ff:ff:ff:ff
    inet 73.103.82.147/21 brd 255.255.255.255 scope global p7p1
       valid_lft forever preferred_lft forever
4: wlp10s0u2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether c8:3a:35:cf:3b:b9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.101/24 brd 192.168.1.255 scope global wlp10s0u2
       valid_lft forever preferred_lft forever

Interface lo is assigned 127.0.0.1/8. The entire 127.0.0.0/8 block, all 16.7 million addresses, is dedicated to "software loopback." It provides a way for applications to do networking without being physically attached to anything. A web browser could connect to a web server running on the same system, by going to http://127.0.0.1/.

It's usually just 127.0.0.1, but it could be any 127.*.*.*. Why? That lets you set up test scenarios using more unique software-loopback-only addresses than anyone could possibly want.

Network
commands for
Linux, Windows,
macOS, Android
Networking
changes in
RHEL/CentOS
5-6-7

Interfaces p3p1 and p7p1 are wired Ethernet connections. Yes, Ethernet interfaces used to be simply eth0, eth1, and so on. However, device order discovery is not predictable, so Ethernet interfaces have names reflected their unchanging physical addresses. If you want the details, see my page on network commands or my page on Linux evolution over the past several years.

Interface p3p1 is assigned 10.1.1.100/24 and p7p1 is assigned 73.103.82.147/21.

Interface wlp10s0u2 is a wireless interface. Again, these used to be wlan0, wlan1, and so on. This one happens to be a wireless interface on a USB stick, so its name specifies the USB bus and device. Again, see one of my other pages for details on modern interface naming.

Interface wlp10s0u2 is assigned 192.168.1.101/24.

Special Network Address Blocks

I already explained that all of 127.0.0.0/8 is reserved for software loopback. There are four other special address blocks.

The 169.254.0.0/16 address block is used for Autoconf, what Apple has called Rendezvous and Bonjour at various times. It's intended to make non-Apple equipment automatically configure themselves the way Apple systems do. That lets them discover and use print and file services within a local-area network.

Routers don't forward 169.254.0.0/16 addresses. Autoconf finds local printers only, those plugged into the same switched LAN. That's what it was designed for.

Network
Address
Translation

The address blocks 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0 are reserved for use within one organization only. Your internal routers may forward their traffic between your networks, but your border routers must not simply forward them. A host using one of these reserved addresses may be able to connect to external servers, if your border router is running NAT or Network Address Translation. These three blocks are sometimes referred to as RFC 1918 addresses, from the document defining them.

Notice that most of these reserved address blocks are "easy", their netmask is a multiple of 8 so it falls on an octet boundary. Autoconf is 169.254.*.*, and the first and last of the of the RFC 1918 blocks are 10.*.*.* and 192.168.*.*. Where, of course, "*" means all numbers 0 through 255.

The middle RFC 1918 block has a netmask that splits an octet. Can you figure out what 172.16.0.0/12 corresponds to in dotted decimal?

Start by noticing that 12 is between 8 and 16, so it's within the second octet. That second octet for this block is represented as "16" in base 10. Next, convert 16 to 8-bit binary, 00010000. 12 bits of netmask, 8 of them in the first octet, so it extends 4 more bits into the second octet.

  172    .    16    .     0    .     0
10101100 . 00010000 . 00000000 . 00000000 / 12

So, the possible addresses use all possible combinations of blue hostid bits in the above.

The second octet can take all values from 00010000 through 00011111, or 16 through 31 in base 10.

The third and fourth octets can be 00000000 through 11111111, or 0 through 255.

So, the answer is:

The block 172.16.0.0/12 corresponds to 172.16.*.* through 172.31.*.*. Or, written another way, 172.16.0.0 through 172.31.255.255.

Bonus question: How many possible hosts belong to these special blocks?

The easy way to answer this is to look at the netmask length, and remember that there are 32 bits in the address. Subtract the netmask from 32 to get the number of hostid bits. N hostid bits provides 2N possible hostid patterns. Then take away the 2 special patterns of all zeros (the whole network itself) and all ones (broadcast, all the hosts on that network).

169.254.0.0/16 :  32 - 16 = 16, 216 - 2 =     65,536 - 2 =     65,534
10.0.0.0/8     :  32 -  8 = 24, 224 - 2 = 16,777,216 - 2 = 16,777,214
172.16.0.0/12  :  32 - 12 = 20, 220 - 2 =  1,048,576 - 2 =  1,048,574
192.168.0.0/16 :  32 - 16 = 16, 216 - 2 =     65,536 - 2 =     65,534

Let's take one last look at the IP address assignments.

Linux$ ip -4 addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: p3p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:13:3b:12:6f:a9 brd ff:ff:ff:ff:ff:ff
    inet 10.1.1.100/24 brd 10.1.1.255 scope global p3p1
       valid_lft forever preferred_lft forever
3: p7p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:13:3b:12:6f:aa brd ff:ff:ff:ff:ff:ff
    inet 73.103.82.147/21 brd 255.255.255.255 scope global p7p1
       valid_lft forever preferred_lft forever
4: wlp10s0u2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether c8:3a:35:cf:3b:b9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.101/24 brd 192.168.1.255 scope global wlp10s0u2
       valid_lft forever preferred_lft forever

Now we can easily recognize that interface lo is software loopback only, and interfaces p3p1 (wired) and wlp0s3f1u4 (wireless) are connected to internal networks.

Interface p7p1 is not on one of these special address blocks. It has a globally reachable IP address. This computer is connected to a cable modem, which does not include a NAT router. It functions like an Ethernet bridge, connecting the computer directly to the live internet.

The whois command shows that my ISP is Comcast. They have the 73.102.0.0/15 address block, among many others.

Linux$ whois 73.103.82.147

NetRange:       73.102.0.0 - 73.103.255.255
CIDR:           73.102.0.0/15
NetName:        INDIANA-CPE-3
NetHandle:      NET-73-102-0-0-1
Parent:         CABLE-1 (NET-73-0-0-0-1)
NetType:        Reassigned
OriginAS:
Customer:       Comcast IP Services, L.L.C. (C06055821)
RegDate:        2016-03-02
Updated:        2016-03-02
Ref:            https://whois.arin.net/rest/net/NET-73-102-0-0-1

CustName:       Comcast IP Services, L.L.C.
Address:        1800 Bishops Gate Blvd
City:           Mount Laurel
StateProv:      NJ
PostalCode:     08054
Country:        US
RegDate:        2016-03-01
Updated:        2016-08-31
Ref:            https://whois.arin.net/rest/customer/C06055821

[... more output omitted ...] 

Routing Tables

I showed you the routing table at the very beginning, but it should make sense now. Here it is again:

$ ip route
default via 73.103.80.1 dev p7p1 metric 5
10.1.1.0/24 dev p3p1 proto kernel scope link src 10.1.1.100
73.103.80.0/21 dev p7p1 proto kernel scope link src 73.103.82.147 metric 5
169.254.0.0/16 dev p7p1 scope link metric 5
169.254.0.0/16 dev wlp10s0u2 scope link metric 35
169.254.0.0/16 dev p3p1 scope link metric 1002
192.168.1.0/24 dev wlp10s0u2 proto kernel scope link src 192.168.1.101 metric 35
IP routing

Let's skip the "default" line and come back to it at the end.

Interface p3p1 is assigned 10.1.1.100/24. That puts it on the 10.1.1.0/24 network. And look at that second line of output: anything bound for the 10.1.1.0/24 network goes out via device p3p1.

[... other output omitted ...]
10.1.1.0/24 dev p3p1  proto kernel  scope link  src 10.1.1.100
[... other output omitted ...] 

Interface p7p1 is assigned 73.103.82.147/21. The /21 netid extends 5 bits into the third octet. 82 in binary is 01010010, so we make the last three bits all zeros (two of them already were), 01010000, and convert that back to base 10, resulting in 80. The /21 netid is 73.103.80.0. There's the third line of output: anything bound for the 73.103.80.0/21 network goes out via device p3p1.

[... other output omitted ...]
73.103.80.0/21 dev p7p1 proto kernel scope link src 73.103.82.147 metric 5
[... other output omitted ...] 

Jumping to the last line of the routing table, interface wlp10s0u2 is assigned 192.168.1.101/24. The last line of output shows that anything bound for the 192.168.1.0/24 network goes out via device wlp0s3f1u4.

[... other output omitted ...]
192.168.1.0/24 dev wlp10s0u2  proto kernel  scope link  src 192.168.1.101  metric 35 

We skipped three lines showing routes to the 169.254.0.0/16 network. Remember that's the Autoconf (or Rendezvous, or Bonjour) block of addresses. No interfaces were assigned specific addresses there, that's the point of Autoconf. If needed, a host derives an Autoconf address by basing the hostid part on its Ethernet MAC or hardware address. It's possible that an Autoconf client might notice that this machine offers print service, and it might send traffic over the Autoconf addresses. These routes allow this host to respond.

[... other output omitted ...]
169.254.0.0/16 dev p7p1  scope link  metric 5
169.254.0.0/16 dev wlp10s0u2  scope link  metric 35
169.254.0.0/16 dev p3p1  scope link  metric 1002
[... other output omitted ...] 

Of course I don't want to accept connections from out on the Internet! That route for 169.254.0.0/16 via p7p1 is dangerous. Don't worry, I use netfilter rules to block Autoconf traffic via p3p1.

Finally, let's go back to the first entry shown for our routing table. That's the default route. That's where this host sends a packet when it doesn't know exactly where it goes. The destination isn't directly connected, it isn't explicitly listed in our routing table, so the default route applies.

default via 73.103.80.1 dev p7p1 metric 5
[... other output omitted ...] 

Our default router (or default gateway) is 73.103.80.1. That's on the 73.103.80.0/21 network, so it goes via interface p7p1.

That's It For IPv4

Congratulations! If you got all the way to this point, and things mostly made sense, you now know much more about IP networking.

The robtex.com service can tell you a lot about an IP address. Here is what it has for yours:

What About IPv6?

Given the material you just went through, you now also understand most of how IP version 6 or IPv6 works. The logic is exactly the same. The only difference is that the addresses are longer and we write them in a different format.

IPv6, Cable Modems,
and your ISP

Major Internet service providers have supported IPv6 for some time. However, you may need to do a little extra work to enable it, especially if you have a cable modem. I had to take extra steps to use IPv6 on Comcast.

IPv6 Addresses

IPv6 addresses are 128 bits long. That provides an enormous number of possible addresses.

Given how long the IPv6 addresses are, plus the confusion caused with IPv4 in dotted decimal when the netmask isn't a multiple of 8, we writes IPv6 addresses differently.

We write IPv6 addresses in base 16 or hexadecimal. The characters 0 through 9 plus a through f can represent all possible 4-bit patterns.

Base 2    Base 16    Base 10
 0000        0          0
 0001        1          1
 0010        2          2
 0011        3          3
 0100        4          4
 0101        5          5
 0110        6          6
 0111        7          7
 1000        8          8
 1001        9          9
 1010        a         10
 1011        b         11
 1100        c         12
 1101        d         13
 1110        e         14
 1111        f         15 

Base 10 is a mess by comparison, as it takes just 1 character some of the time, 2 characters at other times, but it only uses a few of the 2-character combinations.

Each 4-bit piece of an IPv6 address is represented by one base 16 character. A 32-character hexadecimal string would be very difficult to type or read, you would quickly lose your place. So, IPv6 addresses are broken into 4-character groups, each of which represents a 16-bit chunk of the address. Colons separate the groups.

Here is an actual 128-bit IPv6 address shown first in binary, then binary broken into 16-bit chunks, and then in base 16 with colons.

binary:
00100000000000010000010101011000011000000000110100000000000101100110010101010100111010110010000001000100100111011110111011101011

binary in 16-bit chunks:
0010000000000001 0000010101011000 0110000000001101 0000000000010110 0110010101010100 1110101100100000 0100010010011101 1110111011101011

base 16 in 16-bit chunks:
2001:0558:600d:0016:6554:eb20:449d:eeeb

You may not think that the base 16 representation is all that friendly, but it certainly is an improvement over binary!

Shortening IPv6 Addresses

You can write an IPv6 address in a shorter form. You don't have to do this, but applications will. So, you need to be aware of this.

There are two rules for shortening. First, you can omit leading zeros from each 4-character (or 16-bit) group. Here's an example address in both fully spelled out form and shortened by the application of this first rule.

Original: 2001:0550:0018:eb20:0000:0000:049d:eeeb
Rule 1:   2001:550:18:eb20:0:0:49d:eeeb 

Knowing that there should be eight 16-bit or 4-character groups, you can easily tell where to insert leading zeros to pad shorter version back to the original format.

For the second shortening rule, you can collapse any one run of all zeros to "::". Here's the result of that:

Original: 2001:0550:0018:eb20:0000:0000:049d:eeeb
Rule 1:   2001:550:18:eb20:0:0:49d:eeeb
Rule 2:   2001:550:18:eb20::49d:eeeb 

You can still restore the third version to its original form. You know that there should be eight 16-bit groups. You see "::", so you know that at least one group has been dropped. Then you count, and find that just six groups are shown. So, you need to insert two all-zero 16-bit groups. Replace "::" with ":0000:0000:".

Then, in the resulting eight groups, insert leading zeros in those that have just one, two, or three characters, so you end up with eight groups of four characters each.

You see an extreme case of this with the single IPv6 address used for localhost or software loopback. It's 127 bits of 0 then a single 1 bit. Fully written out, that would be 0000:0000:0000:0000:0000:0000:0000:00001. Compressed, it's just ::1.

Practical IPv6 Examples

Here's one last look at the example output. I'm leaving off the -4 option, which means IPv4 only, so we get both IPv4 and IPv6.

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: p3p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:13:3b:12:6f:a9 brd ff:ff:ff:ff:ff:ff
    inet 10.1.1.100/24 brd 10.1.1.255 scope global p3p1
       valid_lft forever preferred_lft forever
    inet6 fc00::213:3bff:fe12:6fa9/64 scope global dynamic mngtmpaddr
       valid_lft 86131sec preferred_lft 14131sec
    inet6 fc00::1:0:0:1/64 scope global dynamic mngtmpaddr
       valid_lft 86131sec preferred_lft 14131sec
    inet6 fe80::213:3bff:fe12:6fa9/64 scope link
       valid_lft forever preferred_lft forever
3: p7p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:13:3b:12:6f:aa brd ff:ff:ff:ff:ff:ff
    inet 73.103.82.147/21 brd 255.255.255.255 scope global p7p1
       valid_lft forever preferred_lft forever
    inet6 2001:558:600d:39:300a:e052:e108:949/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::213:3bff:fe12:6faa/64 scope link
       valid_lft forever preferred_lft forever
4: wlp10s0u2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether c8:3a:35:cf:3b:b9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.101/24 brd 192.168.1.255 scope global wlp10s0u2
       valid_lft forever preferred_lft forever
    inet6 fe80::ca3a:35ff:fecf:3bb9/64 scope link
       valid_lft forever preferred_lft forever

Software loopback interface lo is assigned ::1/128.

Ethernet interface p3p1 is assigned three IPv6 addresses:
fc00::213:3bff:fe12:6fa9/64,
fc00::1:0:0:1/64, and
fe80::213:3bff:fe12:6fa9/64.
It's quite common to have multiple IPv6 addresses assigned to an interface, I'll explain why shortly.

Ethernet interface p7p1 is assigned two IPv6 addresses:
2001:558:600d:39:300a:e052:e108:949/64 and
fe80::213:3bff:fe12:6faa/64.

Wireless interface wlp10s0u2 is using just one IPv6 address:
fe80::ca3a:35ff:fecf:3bb9/64.

Special IPv6 Network Address Blocks

I already explained that ::1/128 is reserved for software loopback. There are several other special IPv6 address blocks. We see some examples in the above.

Now you know... They're like...
127.0.0.0/8 ::1/128
169.254.0.0/16 fe80::/10
10.0.0.0/8 and
172.16.0.0/12 and
192.168.0.0/16
fc00::/7

The address block fe80::/10 is an automatically configured link-local address. It is analogous to 169.254.0.0/16. If you enable IPv6 on an interface, it will have an fe80::/10 address.

An IPv6 router will not forward fe80::/10 addresses. They stay within their network, they are local to that network link.

The least significant 64 bits, the second half of the fe80::/10 address, are based on the Ethernet or wireless hardware address. Not exactly the hardware address, but based on it. We see the hardware or link-layer addresses in the above command output. Let's look at the wireless interface.

$ ip addr show wlp10s0u2
4: wlp10s0u2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether c8:3a:35:cf:3b:b9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.101/24 brd 192.168.1.255 scope global wlp10s0u2
       valid_lft forever preferred_lft forever
    inet6 fe80::ca3a:35ff:fecf:3bb9/64 scope link
       valid_lft forever preferred_lft forever

Start with its hardware address:
c8:3a:35:cf:3b:b9
Invert bit #7, the Universal/Local bit within a hardware address. 0xc8 is 11001000 in binary, flip bit #7 to get 11001010 or 0xca in base 16. So:
ca:3a:35:cf:3b:b9
Insert ff:fe in the middle:
ca:3a:35:ff:fe:cf:3b:b9
Use that as the last 64 bits (the hostid), with fe80/64 as the first 64 bits (the netid), and regroup into 16-bit blocks:
fe80:0000:0000:0000:ca3a:35ff:fecf:3bb9/64
Finally, do the zero compression:
fe80::ca3a:35ff:fecf:3bb9/64

The address block fc00/7 is for unique local addresses. These are analogous to the IPv4 RFC 1918 blocks of 10.0.0/8, 172.16.0.0/12, and 192.168.0.0/16.

Interface p3p1 is using two of these, fc00::213:3bff:fe12:6fa9/64 and fc00::1:0:0:1/64. The first is automatically configured based on its hardware address, after an IPv6 router advertised that the fc00/7 address block is in use internally. The second of those has been specifically configured, probably intended as host #1 on subnet #1. It could have picked this up from a configuration file, or been assigned by a DHCPv6 server.

Network
Address
Translation

An edge router can do IPv6 NAT/PAT or Network Address Translation (and Port Address Translation, which has to be done, but NAT is the main point here). Within the organization, the fc00 addresses are used, with the enormous fc00/7 block divided into subnets just as you would subdivide 10.0.0.0/8 in IPv4. When an outbound packet reaches the edge IPv6 NAT router, its source address is changed (as is, probably, the source port) so it traverses the Internet from that edge router. Replies will be returned there for conversion and relay back into the organization.

Internal clients using fc00::/7 addresses can have their connections masqueraded and forwarded to Internet servers. Clients using fe80::/10 addresses cannot.

There are many more special IPv6 address blocks, for mapping and translating between IPv4 and IPv6 during transitions, tunneling one through the other, plus other other special applications and research and development projects. However, fe80 and fc00 will cover what most people will see most of the time.

Public IPv6 Network Address Blocks

IANA

IANA, the Internet Assigned Numbers Authority, is allocating 2000::/3 for use on the Internet. That's just one-eighth the IPv6 address space. IANA is assigning it to regional Internet registries in large blocks. The address allocation design is intended to allow efficient route aggregation, to keep backbone routing tables from growing too large.

IPv6 Global Unicast Address Assignments

In my example, interface p7p1 is using fe80::213:3bff:fe12:6faa/64 as a link-local address, and it was assigned 2001:558:600d:39:300a:e052:e108:949/64 by the provider. That's one of a very large block of addresses allocated to Comcast. It's a /31 block, so the number of possible addresses is 2(128-31) or 297, a 30-digit number in base 10.

$ whois 2001:558:600d:39:300a:e052:e108:949

NetRange:       2001:558:: - 2001:559:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
CIDR:           2001:558::/31
NetName:        COMCAST6NET
NetHandle:      NET6-2001-558-1
Parent:         ARIN-001 (NET6-2001-400-0)
NetType:        Direct Allocation
OriginAS:       AS7922
Organization:   Comcast Cable Communications, LLC (CCCS)
RegDate:        2003-01-06
Updated:        2016-08-31
Ref:            https://whois.arin.net/rest/net/NET6-2001-558-1

OrgName:        Comcast Cable Communications, LLC
OrgId:          CCCS
Address:        1800 Bishops Gate Blvd
City:           Mt Laurel
StateProv:      NJ
PostalCode:     08054
Country:        US
RegDate:        2001-09-17
Updated:        2017-01-28
Ref:            https://whois.arin.net/rest/org/CCCS

[... more output omitted ...] 

IPv6 Routing

IPv6 routers send frequent Routing Advertisement packets, so IPv6 hosts pick up their default routes automatically. Let's see the IPv6 routing table on my example host.

$ ip -6 route
unreachable ::/96 dev lo metric 1024 error -113 pref medium
unreachable ::ffff:0.0.0.0/96 dev lo metric 1024 error -113 pref medium
2001:558:600d:39::/64 dev p7p1 proto kernel metric 256 pref medium
unreachable 2002:a00::/24 dev lo metric 1024 error -113 pref medium
unreachable 2002:7f00::/24 dev lo metric 1024 error -113 pref medium
unreachable 2002:a9fe::/32 dev lo metric 1024 error -113 pref medium
unreachable 2002:ac10::/28 dev lo metric 1024 error -113 pref medium
unreachable 2002:c0a8::/32 dev lo metric 1024 error -113 pref medium
unreachable 2002:e000::/19 dev lo metric 1024 error -113 pref medium
unreachable 3ffe:ffff::/32 dev lo metric 1024 error -113 pref medium
fc00::/64 dev p3p1 proto kernel metric 256 expires 86116sec pref medium
fe80::/64 dev p3p1 proto kernel metric 256 pref medium
fe80::/64 dev wlp10s0u2 proto kernel metric 256 pref medium
fe80::/64 dev p7p1 proto kernel metric 256 pref medium
default via fe80::201:5cff:fea4:c46 dev p7p1 metric 1024 pref medium

All those "unreachable" lines look ominous, but don't worry! Those correspond to various development projects from years ago. The corresponding special activities no longer go one. These unreachable route entries allow this host to immediately discard a pointless packet, instead of sending it off to the default router and letting it bounce around until something finally discards it.

The ::ffff:0.0.0.0/96 was for mapping IPv4 addresses onto the IPv6 address space, the 2002::/16 address blocks were for the deprecated 6to4 addressing scheme, and 3ffe://16 was for the discontinued 6bone project. If you're curious, see more on obsolete addresses here.

What does work are the routes to directly attached networks 2001:558:600d:39::/64 via p7p1, fc00:64 via p3p1, and fe80::/64 via all interfaces, plus the default route for forwarding to all other destinations.

The default router belongs to the ISP, it has an IPv6 address in the 2001:558:600d:39::/64 block. However, this host prefers to send packets to the default router via its fe80::/64 address. Yes, using link-local addresses across the ISP's network. This is because of address preference tables. The operating system prefers IPv6 over IPv4, and for IPv6, it prefers a destination address with the smallest scope.

Now You Understand IP Addresses and Subnets

IPv6 is already in wide use. If you live in parts of East Asia or South Asia, you may see mostly IPv6 addresses. But anywhere there are mobile phones, there is IPv6. Here is a screenshot from my Android phone.

IPv4 and IPv6 addresses used by an Android phone.

The IPv4 address 192.0.0.4 is part of a reserved block. The phone is using an IPv6 address, which belongs to my mobile phone provider.

Linux$ whois 2607:fb90:ba34:482e:0:24:b92e:8001

NetRange:       2607:FB90:: - 2607:FB90:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
CIDR:           2607:FB90::/32
NetName:        TMOV6-1
NetHandle:      NET6-2607-FB90-1
Parent:         NET6-2600 (NET6-2600-1)
NetType:        Direct Allocation
OriginAS:       AS21928
Organization:   T-Mobile USA, Inc. (TMOBI)
RegDate:        2009-07-14
Updated:        2012-02-24
Ref:            https://whois.arin.net/rest/net/NET6-2607-FB90-1

OrgName:        T-Mobile USA, Inc.
OrgId:          TMOBI
Address:        12920 SE 38th Street
City:           Bellevue
StateProv:      WA
PostalCode:     98006
Country:        US
RegDate:        2003-01-02
Updated:        2017-01-28
Ref:            https://whois.arin.net/rest/org/TMOBI

[... more output omitted ...] 

sipcalc

The sipcalc tool provides command-line IP subnet calculations. It's available as Linux and BSD packages.

$ sipcalc 73.103.82.147/21
-[ipv4 : 73.103.82.147/21] - 0

[CIDR]
Host address            - 73.103.82.147
Host address (decimal)  - 1231508115
Host address (hex)      - 49675293
Network address         - 73.103.80.0
Network mask            - 255.255.248.0
Network mask (bits)     - 21
Network mask (hex)      - FFFFF800
Broadcast address       - 73.103.87.255
Cisco wildcard          - 0.0.7.255
Addresses in network    - 2048
Network range           - 73.103.80.0 - 73.103.87.255
Usable range            - 73.103.80.1 - 73.103.87.254

-
$ sipcalc 2001:558:600d:16:9937:9580:ac52:27f5/64
-[ipv6 : 2001:558:600d:16:9937:9580:ac52:27f5/64] - 0

[IPV6 INFO]
Expanded Address        - 2001:0558:600d:0016:9937:9580:ac52:27f5
Compressed address      - 2001:558:600d:16:9937:9580:ac52:27f5
Subnet prefix (masked)  - 2001:558:600d:16:0:0:0:0/64
Address ID (masked)     - 0:0:0:0:9937:9580:ac52:27f5/64
Prefix address          - ffff:ffff:ffff:ffff:0:0:0:0
Prefix length           - 64
Address type            - Aggregatable Global Unicast Addresses
Network range           - 2001:0558:600d:0016:0000:0000:0000:0000 -
                          2001:0558:600d:0016:ffff:ffff:ffff:ffff

-