Address Conversion Functions
- Address Conversion Functions
- Allocating IP Addresses
- Manipulating IP Numbers
- What's Next
Address Conversion Functions
In the last chapter, you learned how various types of socket addresses could be allocated and initialized. These were all simple cases of initializing from a constant. Setting up an address from a C string with varying addresses requires more programming effort. In this chapter, you will focus on the additional issues pertaining to establishing Internet addresses, and learning about the functions that can assist you in this area.
In this chapter, you will learn about
Classes of internet addresses
IP netmasks
Private and reserved IP numbers
Functions that convert IP numbers
Before you get started however, it's a good time to review the design of an IP address. Then, you'll have a greater insight into the job that is ahead of you.
Internet IP Numbers
The IP number consists of four decimal values separated by decimal points, often referred to as "dots." This convention is frequently called dotted-quad notation, or sometimes dotted-decimal notation. Each decimal value represents the unsigned value of one byte, in network byte sequence. Remember that network order requires that the most significant bytes appear first.
Each byte is considered as an unsigned 8-bit value. This restricts each byte to a decimal value range of zero to 255. Because the value is unsigned, the value cannot be negative, and a plus sign is not permitted. Consider the address 192.168.0.1, for example; you know that the first byte in network order must have the value of 192 decimal.
When you see a movie showing an IP number on the screen with a value such as 192.168.300.5, you know that the producer knew very little about TCP/IP networking! Although this IP number is syntactically correct, the decimal value 300 obviously exceeds the maximum unsigned value of 255.
Later, starting with the section "Manipulating IP Numbers," you will look at functions that can parse a C string into network address bytes, and range check the decimal values for you.
Internet Address Classes
Internet addresses are made up of two components:
Network number (most significant bits)
Host number (least significant bits)
The network number identifies the network where the host can be contacted. The host number identifies one host (your PC, for example) out of several on that particular network.
As you already know, the IP number is a 32-bit value (or four 8-bit bytes). However, the division between the network number and host number components is not at a fixed location. The dividing line depends upon the classification of the address, which is determined by examining the most significant byte of the address. Table 3.1 summarizes how IP numbers are classified.
Table 3.1: Internet Address Classes
Class |
Lowest |
Highest |
Network Bits |
Host Bits |
A |
0.0.0.0 |
127.255.255.255 |
7 |
24 |
B |
128.0.0.0 |
191.255.255.255 |
14 |
16 |
C |
192.0.0.0 |
223.255.255.255 |
21 |
8 |
D |
224.0.0.0 |
239.255.255.255 |
28 |
N/A |
E |
240.0.0.0 |
247.255.255.255 |
27 |
N/A |
Class A, B, and C define specific IP addresses of hosts. For class D and E addresses, there are zero host bits available in the address. Class D addresses are used for multicasting where the 28 bits are used to describe a multicast group. The 27 bits of the class E address are reserved.
Figure 3.1 helps you visualize the breakdown of the 32-bit IP address. The frequently used classes A, B, and C are shown.
Figure 3.1 This figure illustrates the Internet address classes A, B, and C.
Understanding Netmask Values
There are situations in which you must determine the netmask value of an address. This is particularly true if you are setting up your own network. So, just what is a netmask value anyway?
If you take the Internet IP Address as a 32-bit number, then you know that the network ID is specified in the most significant bits of the address. Additionally, the host ID is specified by the least significant bits of the same address (review Figure 3.1 if necessary). The netmask is simply the value that you would "bit-wise and" with the address to leave only the network ID. Figure 3.2 illustrates how the IP address 192.168.9.1 is masked to extract only the network ID bits.
Tip
You will often hear people use the terms net and subnet interchangeably. Technically speaking, these terms represent two distinctly different network ID values. The network ID identifies the network ID number proper.
However, within an IPv4 number, it is possible to further subdivide the host ID leaving a subnetwork ID in the most significant bits of the host ID and the final host ID in the least significant bits. When subnetting is used, the netmask value will take into account these additional subnetwork ID bits.
Tip
Consequently, when subnetting is in use, the network mask will differ from the ones presented in this chapter.
Figure 3.2 Applying a netmask to 192.168.9.1 yields a network address.
The resulting most significant bits represent the network portion of the IP address without the host ID. Figure 3.3 illustrates how the network mask is converted from hexadecimal back into dotted-quad notation.
Figure 3.3 Here is the netmask expressed in dotted-quad notation.
If you must set up your own IP network, then you will need to determine what the netmask values should be. Table 3.2 lists the netmask values for class A, B, and C addresses.
Table 3.2: Netmask Values by IP Class
Class |
Lowest |
Highest |
Netmask |
A |
0.0.0.0 |
127.255.255.255 |
255.0.0.0 |
B |
128.0.0.0 |
191.255.255.255 |
255.255.0.0 |
C |
192.0.0.0 |
223.255.255.255 |
255.255.255.0 |
Sometimes, in networking software, your software must be able to classify a network address. Sometimes this is simply done in order to determine a default netmask value.
Listing 3.1 provides a short program that illustrates how to classify an IP address, starting from a socket address. To compile and run the provided source code, perform the following:
$ make netmask gcc -c -D_GNU_SOURCE -Wall netmask.c gcc netmask.o -o netmask $ ./netmask
The program in Listing 3.1 sets up four different IP addresses in an Internet socket address structure. Then, the address is examined and classified. This is done to demonstrate how you would classify an IP address of a remote client that has connected to your server.
Listing 3.1: netmask.c--Classifying and Determining a Netmask
1: /* netmask.c: 2: * 3: * Classify an IP address: 4: */ 5: #include <stdio.h> 6: #include <unistd.h> 7: #include <stdlib.h> 8: #include <sys/types.h> 9: #include <sys/socket.h> 10: #include <netinet/in.h> 11: 12: int 13: main(int argc,char **argv) { 14: int x; /* Index variable */ 15: struct sockaddr_in adr_inet;/* AF_INET */ 16: int len_inet; /* length */ 17: unsigned msb; /* Most significant byte */ 18: char class; 19: char *netmask; 20: static struct { 21: unsigned char ip[4]; 22: } addresses[] = { 23: { { 44,135,86,12 } }, 24: { { 127,0,0,1 } }, 25: { { 172,16,23,95 } }, 26: { { 192,168,9,1 } } 27: }; 28: 29: for ( x=0; x<4; ++x ) { 30: /* 31: * Set up the socket address, to 32: * demonstrate how to classify it: 33: */ 34: memset(&adr_inet,0,sizeof adr_inet); 35: adr_inet.sin_family = AF_INET; 36: adr_inet.sin_port = htons(9000); 37: memcpy(&adr_inet.sin_addr.s_addr, 38: addresses[x].ip,4); 39: len_inet = sizeof adr_inet; 40: 41: /* 42: * Classify this address: 43: * 44: * 1. Get the Most Significant Byte 45: * 2. Classify by that byte 46: */ 47: msb = *(unsigned char *) 48: &adr_inet.sin_addr.s_addr; 49: 50: if ( (msb & 0x80) == 0x00 ) { 51: class = 'A'; 52: netmask = "255.0.0.0"; 53: } else if ( (msb & 0xC0) == 0x80 ) { 54: class = 'B'; 55: netmask = "255.255.0.0"; 56: } else if ( (msb & 0xE0) == 0xC0 ) { 57: class = 'C'; 58: netmask = "255.255.255.0"; 59: } else if ( (msb & 0xF0) == 0xE0 ) { 60: class = 'D'; 61: netmask = "255.255.255.255"; 62: } else { 63: class = 'E'; 64: netmask = "255.255.255.255"; 65: } 66: 67: printf("Address %u.%u.%u.%u is class %c " 68: "netmask %s\n", 69: addresses[x].ip[0], 70: addresses[x].ip[1], 71: addresses[x].ip[2], 72: addresses[x].ip[3], 73: class, 74: netmask); 75: } 76: 77: return 0; 78: }
The operation of this demonstration program can be summarized in the following steps:
-
The socket address structure adr_inet is defined in line 15. This will be the address that will be examined for classification.
-
The addresses to be tested are defined in a static array of structures, defined in lines 20 to 27. You might want to experiment by trying other address numbers in lines 23 to 26.
-
Line 29 starts a loop that will iterate through four entries in the addresses[] array. The subscript value will be the variable x.
-
A socket address is initialized in lines 34 to 39, from addresses[x]. This is done in the same manner it was presented in the last chapter, and should look familiar to you now.
-
The most significant byte is extracted out of the socket address adr_inet in line 47. You will remember that the most significant byte is the first byte of the address, in network byte order (big-endian). With this byte lifted from the socket address, it will be possible to classify the address based upon the high-order bits in this byte.
-
The if statement in line 50 tests to see whether the high-order bit is zero (review Figure 3.1, looking at the class A address). If the high-order bit is zero, you know you have a class A address (lines 51 and 52 execute).
-
The if statement in line 53 tests to see whether the high-order bit is 1, and the 2nd highest bit is a 0 (review the class B address in Figure 3.1). If this is true, then the statements in lines 54 and 55 classify this address as class B.
-
The if statement in line 56 tests to see whether the highest two bits are 11 (binary), followed by a 0 bit. If this is true, then lines 57 and 58 classify the address as a class C address (review Figure 3.1 for class C addresses).
-
The if statement in line 59 tests for the high-order bit pattern of 1110. This causes the address to be classified as a class D address. Note for class D and class E, the netmask is set to 255.255.255.255 because the entire address is a network address.
-
The else statement in line 62 evaluates everything remaining as a class E address, and sets the netmask also to 255.255.255.255 (see step 9).
-
The results of the classification are reported in lines 67 to 74.
Listing 3.2 shows the output that results from running this demonstration program.
Listing 3.2: The Output of the netmask.c Demonstration Program
$ ./netmask Address 44.135.86.12 is class A netmask 255.0.0.0 Address 127.0.0.1 is class A netmask 255.0.0.0 Address 172.16.23.95 is class B netmask 255.255.0.0 Address 192.168.9.1 is class C netmask 255.255.255.0 $
With the example code demonstrated in Listing 3.1, you will be ready to classify any IP number that you must process.
While your attention is still focused upon IP numbers, now is a good time to cover private IP number allocations. These are addresses that you will use if you decide to establish your own private network.