Home > Articles

Manipulating IP Numbers

To ease the programming burden of turning IP numbers in string form into usable socket addresses, a number of conversion functions have been provided. These and other useful functions will be presented in the following sections.

Using the inet_addr(3) Function

The first function that you will learn about is an older function, which should probably no longer be used in new code. However, you will find it in a lot of existing network code, and so you should become familiar with it and know its limitations.

The synopsis for inet_addr(3) is as follows:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

unsigned long inet_addr(const char *string);

This function accepts an input C string argument string and parses the dotted-quad notation into a 32-bit Internet address value. The 32-bit value returned is in network byte order.

If the input argument string does not represent a valid dotted-quad address, the value INADDR_NONE is returned. Any other returned value represents the converted value.

Note

The 32-bit value returned by inet_addr(3) is in network byte order. Do not use htonl(3) on the returned value, because it is already in network byte order.

Caution

The inet_addr(3) does not establish a reason code in errno when INADDR_NONE is returned. So, do not test errno or report it when an error indication is returned by this function.

The program shown in Listing 3.3 is an example of how you would use this function. To compile and run the program, perform the following:

$ make inetaddr
gcc -c  -D_GNU_SOURCE -Wall inetaddr.c
gcc inetaddr.o -o inetaddr
$ ./inetaddr

The program in Listing 3.3, when it is run, converts a C string constant containing an IP number into a network sequenced 32-bit IP address. This value is then placed into an AF_INET socket address and bound to the socket.

Listing 3.3: inetaddr.c--Example Program Using inet_addr(3)

1:   /* inetaddr.c:
2:    * 
3:    * Example using inet_addr(3):
4:    */
5:   #include <stdio.h>
6:   #include <unistd.h>
7:   #include <stdlib.h>
8:   #include <errno.h>
9:   #include <string.h>
10:  #include <sys/types.h>
11:  #include <sys/socket.h>
12:  #include <netinet/in.h>
13:  #include <arpa/inet.h>
14:  
15:  /*
16:   * This function reports the error and
17:   * exits back to the shell:
18:   */
19:  static void
20:  bail(const char *on_what) {
21:      fputs(on_what,stderr);
22:      fputc('\n',stderr);
23:      exit(1);
24:  }
25:  
26:  int
27:  main(int argc,char **argv) {
28:      int z;
29:      struct sockaddr_in adr_inet;/* AF_INET */
30:      int len_inet;               /* length  */
31:      int sck_inet;                /* Socket */
32:  
33:      /* Create a Socket */
34:      sck_inet = socket(AF_INET,SOCK_STREAM,0);
35:  
36:      if ( sck_inet == -1 )
37:          bail("socket()");
38:  
39:      /* Establish address */
40:      memset(&adr_inet,0,sizeof adr_inet);
41:  
42:      adr_inet.sin_family = AF_INET;
43:      adr_inet.sin_port = htons(9000);
44:  
45:      adr_inet.sin_addr.s_addr =
46:          inet_addr("127.0.0.95");
47:  
48:      if ( adr_inet.sin_addr.s_addr == INADDR_NONE )
49:          bail("bad address.");
50:  
51:      len_inet = sizeof adr_inet;
52:  
53:      /* Bind it to the socket */
54:      z = bind(sck_inet,
55:          (struct sockaddr *)&adr_inet,
56:          len_inet);
57:  
58:      if ( z == -1 )
59:          bail("bind()");
60:  
61:      /* Display our socket address */
62:      system("netstat -pa --tcp 2>/dev/null"
63:          "| grep inetaddr");
64:  
65:      return 0;
66:  }

Note

If netstat(1) command on your system does not support the options used in lines 62 and 63 of Listing 3.3, substitute the following call if you have lsof installed:

system("lsof -i tcp | grep inetaddr");

The general program structure is very similar to the ones used in the previous chapter. However, the steps used to set up the socket address are a bit different. They are

  1. The socket address structure is zeroed out in line 40. This is an optional step, but many find that this helps debugging should it become necessary.

  2. The address family is established as AF_INET in line 42.

  3. The port number has been established as port 9000 in this example (line 43).

  4. The function inet_addr(3) is called in line 46 to convert the string constant "127.0.0.95" into a network 32-bit address. This value is stored into the socket address member adr_inet.sin_addr.s_addr.

  5. The value returned from the conversion in step 4 is tested to see whether it matches the value INADDR_NONE in line 48. If it does, this indicates that the value provided in the C string was not a good Internet IP number (the program bails out in line 49 if this happens).

  6. Finally, the length of the socket address is established in line 51 as before.

The above procedure has established the socket address in the variable adr_inet. This is later passed to bind(2) in line 54, which has not been covered yet. The bind(3) call just applies the address to the socket (the full discussion will otherwise be deferred for now).

The important thing that you accomplish with the use of the inet_addr(3) function is that you are spared from performing all parsing and testing of the input IP number.

Tip

Avoid using inet_addr(3) in new programs. Use the function inet_aton(3) instead.

The inet_addr(3) function has the limitation that it returns the value INADDR_NONE if the input argument is an invalid IP number. The limitation is that it also returns the value INADDR_NONE if you pass it the valid IP address of 255.255.255.255.

Tip

This creates a problem for programs like the ping(8) command where this is a valid broadcast address to use.

Running the program yields the following output:

$ ./inetaddr
tcp 0 0 127.0.0.95:9000  *:*  CLOSE  992/inetaddr
$ 

The program invokes netstat(1) using grep to look for the program name inetaddr. Consequently, you see one output line showing the address established for the socket as 127.0.0.95:9000. You'll remember that the program arbitrarily chose the port number 9000 for this experiment.

The inet_aton(3) Function

The inet_aton(3) is an improved way to convert a string IP number into a 32-bit networked sequenced IP number. The synopsis of the function is given as follows:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int inet_aton(const char *string, struct in_addr *addr);

The inet_aton(3) function accepts two arguments. They are

  1. The input argument string, which contains the ASCII representation of the dotted-quad IP number.

  2. The output argument addr is the structure that will be updated with the new IP address.

The return value of the function is nonzero (true) if the conversion succeeds. The value zero (false) is returned if the input address is incorrect. There is no error code established in errno, so its value should be ignored.

What is a little bit confusing about this function is the pointer required for argument two of this function call. If you define an AF_INET socket address as

struct sockaddr_in adr_inet; /* AF_INET */

the pointer that should be supplied as argument two of the inet_aton(3) function is the following:

&adr_inet.sin_addr

Review Listing 2.7 in Chapter 2, "Domains and Address Families," page 48, if this does

not seem clear to you. It will make more sense when you review the definition of the

sockaddr_in structure.

Listing 3.4 shows a program that calls upon inet_aton(3) instead of the older inet_addr(3) function that you learned about in the previous section. This program operates the same way, except that it is compiled and executed as follows:

$ make inetaton
gcc -c  -D_GNU_SOURCE -Wall inetaton.c
gcc inetaton.o -o inetaton
$ ./inetaton

Now, spend a few moments examining Listing 3.4. You'll find that the new function is invoked in lines 45 to 47.

Listing 3.4: inetaton.c--Using inet_aton(3)

1:   /* inetaton.c:
2:    * 
3:    * Example using inet_aton(3) :
4:    */
5:   #include <stdio.h>
6:   #include <unistd.h>
7:   #include <stdlib.h>
8:   #include <errno.h>
9:   #include <string.h>
10:  #include <sys/types.h>
11:  #include <sys/socket.h>
12:  #include <netinet/in.h>
13:  #include <arpa/inet.h>
14:  
15:  /*
16:   * This function reports the error and
17:   * exits back to the shell:
18:   */
19:  static void
20:  bail(const char *on_what) {
21:      fputs(on_what,stderr);
22:      fputc('\n',stderr);
23:      exit(1);
24:  }
25:  
26:  int
27:  main(int argc,char **argv) {
28:      int z;
29:      struct sockaddr_in adr_inet;/* AF_INET */
30:      int len_inet;               /* length  */
31:      int sck_inet;                /* Socket */
32:  
33:      /* Create a Socket */
34:      sck_inet = socket(AF_INET,SOCK_STREAM,0);
35:  
36:      if ( sck_inet == -1 )
37:          bail("socket()");
38:  
39:      /* Establish address */
40:      memset(&adr_inet,0,sizeof adr_inet);
41:  
42:      adr_inet.sin_family = AF_INET;
43:      adr_inet.sin_port = htons(9000);
44:  
45:      if ( !inet_aton("127.0.0.23",
46:                &adr_inet.sin_addr) )
47:          bail("bad address.");
48:  
49:      len_inet = sizeof adr_inet;
50:  
51:      /* Bind it to the socket */
52:      z = bind(sck_inet,
53:          (struct sockaddr *)&adr_inet,
54:          len_inet);
55:  
56:      if ( z == -1 )
57:          bail("bind()");
58:  
59:      /* Display our socket address */
60:      system("netstat -pa --tcp 2>/dev/null"
61:          "| grep inetaton");
62:  
63:      return 0;
64:  }

Running this program yields the following results:

$ ./inetaton
tcp 0 0 127.0.0.23:9000  *:*  CLOSE  1007/inetaton       
>$ 

Note

If netstat(1) command on your system does not support the options used in lines 60 and 61 of Listing 3.4, substitute the following call if you have lsof installed:

system("lsof -i tcp | grep inetaton");

While the bulk of the program was the same as the previous one in Listing 3.3, the following steps are of particular importance:

  1. The new function inet_aton(3) is invoked from within the if statement in line 45.

  2. Note the second argument in line 46, given as the value &adr_inet.sin_addr. This is the required pointer for argument two.

  3. If the return value of the function in line 45 is zero, this indicates the conversion failed, and line 47 is executed.

The program in Listing 3.4 shows you how easily the newer function inet_aton(3) can be put to work in place of the older function inet_addr(3). There are perhaps three things that you need to remember about this function:

  • The pointer in argument two always refers to the sockaddr_in member sin_addr (&adr_inet.sin_addr in the example program).

  • The return value indicates a Boolean success value. A return value of true (nonzero) means that the call succeeded, whereas false (zero) means that it failed.

  • Do not consult the value in errno. No meaningful code is established by inet_aton(3) for errno.

In the next section, you'll see how you can take a socket IP address and convert it back to a string for reporting purposes.

Using the inet_ntoa(3) Function

There are times when a socket address represents the address of a user that has connected to your server, or represents the sender of a UDP packet. The job of converting a network sequenced 32-bit value into dotted-quad notation is inconvenient. Hence, the inet_ntoa(3) function has been provided. The synopsis of the function is as follows:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

char *inet_ntoa(struct in_addr addr);

The function requires only one input argument addr. Note that the struct in_addr is an internal part of the Internet socket address. The address is converted into a static buffer, which is internal to the function. This character array pointer is returned as the return value. The results will be valid only until the next call to this function.

4 Review the sockaddr_in structure in Figure 2.3 of Chapter 2, "Domains and

Address Families," page 48. This will help you visualize the physical address structure that

you are working with.

If a socket address addr exists in your program as a sockaddr_in structure, then the following code shows how to use inet_ntoa(3) to perform the conversion. The IP number is converted to a string and reported, using the printf(3) function:

struct sockaddr_in addr;   /* Socket Address */

printf("IP ADDR: %s\n",
    inet_ntoa(addr.sin_addr));

A complete example program is provided in Listing 3.5. To compile and run this program, the following steps are required:

$ make inetntoa
gcc -c  -D_GNU_SOURCE -Wall inetntoa.c
gcc inetntoa.o -o inetntoa
$ ./inetntoa

The program in Listing 3.5 uses the same steps to set up the address as did the previous example program. The function inet_ntoa(3) is called upon to allow the IP number to be displayed.

Listing 3.5: inetntoa.c--Demonstration of inet_ntoa(3) Function

1:   /* inetntoa.c:
2:    * 
3:    * Example using inet_ntoa(3):
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:  #include <arpa/inet.h>
12:  
13:  int
14:  main(int argc,char **argv) {
15:      struct sockaddr_in adr_inet;/* AF_INET */
16:      int len_inet;               /* length  */
17:  
18:      /*
19:       * Establish address (pretend we got
20:       * this address from a connecting
21:       * client):
22:       */
23:      memset(&adr_inet,0,sizeof adr_inet);
24:  
25:      adr_inet.sin_family = AF_INET;
26:      adr_inet.sin_port = htons(9000);
27:  
28:      if ( !inet_aton("127.0.0.23",
29:                &adr_inet.sin_addr) )
30:          puts("bad address.");
31:  
32:      len_inet = sizeof adr_inet;
33:  
34:      /*
35:       * Demonstrate use of inet_ntoa(3):
36:       */
37:      printf("The IP Address is %s\n",
38:          inet_ntoa(adr_inet.sin_addr));
39:  
40:      return 0;
41:  }

Now, review the steps that were taken in the program:

  1. The structure adr_inet is declared as a sockaddr_in type in line 15. This is the form of the address that you'll work with most of the time.

  2. Lines 23 to 32 set up the address, just as before. In this example, the socket(2) and bind(2) calls were omitted because they don't help in this illustration.

  3. Line 37 shows a call to printf(3). Here, the statement calls upon inet_ntoa(3) in line 38 to convert the IP address in adr_inet to string form so that it can be printed.

The results returned from inet_ntoa(3) are valid only until the next call to this function.

Caution

Due to the limitation given in the previous note, if you use this function in threaded code, you must make certain that only one thread at a time calls this function. Failure to heed this advice will result in returned results being overwritten by other threads.

The program's output is shown as follows:

$ ./inetntoa
The IP Address is 127.0.0.23
$ 

You know, because of the initialization in line 28, that this is the correct result. Line 38 converts this value back into a string.

Using inet_network(3)

There might be occasions in which it is more convenient to have the dotted-quad IP number converted into a 32-bit host-ordered value. This is more convenient when you are applying mask values to extract host or network bits from the addresses.

The function synopsis for inet_network(3) is as follows:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

unsigned long inet_network(const char *addr);

This function takes one input string containing a dotted quad address in argument addr. The return value is the 32-bit value of the IP address, but in host-order format. However, if the input value is malformed, the returned result will be 0xFFFFFFFF (all 1 bits).

Having the returned value in host-endian order means that you can safely assume constants for mask values and bit positions. If the returned value were in network-endian order, the constants and code would then be different for different CPU platforms.

An example of how inet_network(3) might be used is shown next. The following shows how to extract the network address from a class C address:

unsigned long net_addr;

net_addr = 
    inet_network("192.168.9.1") & 0xFFFFFF00;

The value assigned to net_addr would be the value 0xC0A80900 (or 192.168.9.0 in dotted-quad notation). The logical and operation masked out the low-order eight bits to arrive at the network ID without the host ID.

The example shown in Listing 3.6 illustrates how the inet_network(3) function can be used. The program also calls upon the htonl(3) function to display how the value looks in network-endian order.

Listing 3.6: network.c--Demonstration of the inet_network(3) Function

1:   /* network.c:
2:    * 
3:    * Example using inet_network(3):
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:  #include <arpa/inet.h>
12:  
13:  int
14:  main(int argc,char **argv) {
15:      int x;
16:      const char *addr[] = {
17:          "44.135.86.12",
18:          "127.0.0.1",
19:          "172.16.23.95",
20:          "192.168.9.1"
21:      };
22:      unsigned long net_addr;
23:  
24:      for ( x=0; x<4; ++x ) {
25:          net_addr = inet_network(addr[x]);
26:          printf("%14s = 0x%08lX net 0x%08lX\n",
27:              addr[x],net_addr,
28:              (unsigned long)htonl(net_addr));
29:      }
30:  
31:      return 0;
32:  }

This program is compiled and run as follows:

$ make network
gcc -c  -D_GNU_SOURCE -Wall network.c
gcc network.o -o network
$ 

The steps used in the program shown in Listing 3.6 are as follows:

  1. Four arbitrarily picked IP numbers are declared in lines 17 to 20 to initialize the array addr[].

  2. Lines 24 to 29 loop through each of the four strings in the addr[] array, starting with the first.

  3. The inet_network(3) function is called in line 25 to convert the string into a host-endian ordered 32-bit value representing the IP number given.

  1. The printf(3) function is called in line 26 to illustrate the output values. The first is the original string that was given to inet_network(3) in line 25. The second value printed is the value returned by inet_network(3), which is in host-endian form. The last value displayed on the line is the network-endian ordered value. For Intel CPU platforms, the last two columns will display differently.

The program is run as follows:

$ ./network
  44.135.86.12 = 0x2C87560C net 0x0C56872C
     127.0.0.1 = 0x7F000001 net 0x0100007F
  172.16.23.95 = 0xAC10175F net 0x5F1710AC
   192.168.9.1 = 0xC0A80901 net 0x0109A8C0
$ 

This program was run on an Intel CPU running Linux. Consequently, because an Intel CPU is little-endian by design, its host-ordered value (second column) and the networked-ordered value (last column) appear different. If you run this same program on a big-endian machine, the last two columns will be identical.

Using the inet_lnaof(3) Function

The inet_lnaof(3) function converts the IP number contained in a socket address, which is in network byte order, to a host ID number with the network ID removed. The return value is in host-endian order.

This function saves you from having to determine the class of the IP number and then extracting the host ID portion. The function synopsis for inet_lnaof(3) is given as follows:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

unsigned long inet_lnaof(struct in_addr addr);

The input argument addr must be the struct in_addr member of the socket address that you will normally be working with. This value will be in network byte sequence, which is what the function expects. An example of how to invoke the function using a sockaddr_in address is given as follows:

struct sockaddr_in addr;   /* Socket Address */
unsigned long host_id;     /* Host ID number */

host_id = inet_lnaof(addr.sin_addr);

Table 3.5 shows some example values that can be supplied to the input of inet_lnaof(3) and the values that result. To make the reasons for the results clearer, the class of each example address is included in the table.

Table 3.5: Example Values Returned from inet_lnaof(3) (the Hexadecimal Values Are Host-Endian Ordered)

IP Number

Class

Hexadecimal

Dotted-Quad

44.135.86.12

A

0087560C

0.135.86.12

127.0.0.1

A

00000001

0.0.0.1

172.16.23.95

B

0000175F

0.0.23.95

192.168.9.1

C

00000001

0.0.0.1


You should notice in the table's class A examples only the first byte is zeroed in the returned result (review Figure 3.1 to visualize the class boundaries again if you need to). In the class B example, the upper 16 bits are zeroed in the returned result. Finally, the class C example in Table 3.5 zeroes out the upper 3 bytes of the address, leaving the host ID behind in the last byte.

Note

The input is in network-endian sequence. The returned value is in host-endian sequence.

Using the inet_netof(3) Function

The inet_netof(3) function is the companion to the inet_lnaof(3) function. The inet_netof(3) function returns the network ID instead of the host ID value. In all other respects, these functions are the same. The following lists the function synopsis:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

unsigned long inet_netof(struct in_addr addr);

Again, the input is the struct in_addr member of the socket address sockaddr_in structure that you'll normally be working with. An example of its use is given as follows:

struct sockaddr_in addr;   /* Socket Address */
unsigned long net_id;      /* Network ID number */

net_id = inet_netof(addr.sin_addr);

Table 3.6 shows the same example IP numbers used in Table 3.5. Table 3.6 shows the values returned for the function inet_netof(3) function, however.

Table 3.6: Example Values Returned from inet_netof(3) (the Hexadecimal Values Are Host-Endian Ordered)

IP Number

Class

Hexadecimal

Dotted-Quad

44.135.86.12

A

0000002C

0.0.0.44

127.0.0.1

A

0000007F

0.0.0.127

172.16.23.95

B

0000AC10

0.0.172.16

192.168.9.1

C

00C0A809

0.192.168.9


You might find the values in Table 3.6 to be a bit of a surprise. These return values are the network bits shifted right, in order to eliminate the host ID bits. What you are left with is the right-justified network ID number.

Note

The return values from inet_netof(3) are right-justified. The host ID bits are shifted out.

Using the inet_makeaddr(3) Function

With the functions inet_lnaof(3) and inet_netof(3), you have the ability to extract host and network ID values. To re-create a consolidated IP address with the network and host ID values combined, you need to use the inet_makeaddr(3) function. Its function synopsis is as follows:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

struct in_addr inet_makeaddr(int net,int host);

The arguments to the inet_makeaddr(3) function are described as follows:

  1. The net argument is the network ID, right-justified and in host-endian order. This same value is returned from the function inet_netof(3).

  1. The host argument is the host ID, which is in host-endian order. This same value is returned from the function inet_lnaof(3).

The value returned in the struct in_addr member of the sockaddr_in socket address. This value is in network-endian sequence, which is correct for the socket address.

A program has been provided in Listing 3.7 that uses the three functions inet_lnaof(3), inet_netof(3), and inet_makeaddr(3). The IP address is split apart from a sockaddr_in structure into its network and host ID parts. Then, the socket address is zeroed out and reconstructed from just the network and host ID parts.

Listing 3.7: makeaddr.c--Demonstration of inet_netof(3), inet_lnaof(3), and inet_makeaddr(3)

1:   /* makeaddr.c:
2:    * 
3:    * Demonstrate inet_lnaof, inet_netof
4:    * and inet_makeaddr(3) functions;
5:    */
6:   #include <stdio.h>
7:   #include <unistd.h>
8:   #include <stdlib.h>
9:   #include <sys/types.h>
10:  #include <sys/socket.h>
11:  #include <netinet/in.h>
12:  #include <arpa/inet.h>
13:  
14:  int
15:  main(int argc,char **argv) {
16:      int x;
17:      struct sockaddr_in adr_inet;/* AF_INET */
18:      const char *addr[] = {
19:          "44.135.86.12",
20:          "127.0.0.1",
21:          "172.16.23.95",
22:          "192.168.9.1"
23:      };
24:      unsigned long net, hst;
25:  
26:      for ( x=0; x<4; ++x ) {
27:          /*
28:           * Create a socket address:
29:           */
30:          memset(&adr_inet,0,sizeof adr_inet);
31:          adr_inet.sin_family = AF_INET;
32:          adr_inet.sin_port = htons(9000);
33:          if ( !inet_aton(addr[x],
34:                    &adr_inet.sin_addr) )
35:              puts("bad address.");
36:  
37:          /*
38:           * Split address into Host & Net ID
39:           */
40:          hst = inet_lnaof(adr_inet.sin_addr);
41:          net = inet_netof(adr_inet.sin_addr);
42:  
43:          printf("%14s : net=0x%08lX host=0x%08lX\n",
44:              inet_ntoa(adr_inet.sin_addr),net,hst);
45:  
46:          /*
47:           * Zero the address to prove later that
48:           * we can reconstruct this value:
49:           */
50:          memset(&adr_inet,0,sizeof adr_inet);
51:          adr_inet.sin_family = AF_INET;
52:          adr_inet.sin_port = htons(9000);
53:  
54:          adr_inet.sin_addr =
55:              inet_makeaddr(net,hst);
56:  
57:          /*
58:           * Now display the reconstructed
59:           * address:
60:           */
61:          printf("%14s : %s\n\n",
62:              "inet_makeaddr",
63:              inet_ntoa(adr_inet.sin_addr));
64:      }
65:  
66:      return 0;
67:  }

To compile the program in Listing 3.7, perform the following:

$ make makeaddr
gcc -c  -D_GNU_SOURCE -Wall makeaddr.c
gcc makeaddr.o -o makeaddr
$ 

The procedure used in Listing 3.7 is as follows:

  1. The socket address is declared in line 17 as a sockaddr_in structure. This is the form of the socket address that you'll normally work with.

  2. Four example addresses are declared in lines 18 to 23.

  3. The loop starts in line 26, and iterates through each of the four example IP numbers declared in step 2.

  4. Lines 30 to 35 set up a sockaddr_in socket address. Port 9000 was just an arbitrary port number used as an example.

  5. The host ID is extracted from the socket address adr_inet in line 40.

  6. The network ID is extracted from the socket address adr_inet in line 41.

  7. The example IP number, network ID, and host ID numbers are reported in lines 43 and 44.

  8. The entire socket address adr_inet is zeroed out in line 50. This was done to eliminate any doubt that the socket address is re-created later.

  9. The address family and example port number are re-established in lines 51 and 52.

  10. The IP number is reconstructed by calling inet_makeaddr(3) in lines 54 and 55. The input values are the extracted values net and hst from steps 5 and 6.

  11. The reconstructed address is reported in lines 61 to 63.

Running the program yields the following results:

$ ./makeaddr
  44.135.86.12 : net=0x0000002C host=0x0087560C
 inet_makeaddr : 44.135.86.12

     127.0.0.1 : net=0x0000007F host=0x00000001
 inet_makeaddr : 127.0.0.1

  172.16.23.95 : net=0x0000AC10 host=0x0000175F
 inet_makeaddr : 172.16.23.95

   192.168.9.1 : net=0x00C0A809 host=0x00000001
 inet_makeaddr : 192.168.9.1

$ 

In each case, you can see for yourself that the program did indeed re-create the final IP numbers from the extracted host and network ID numbers.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020