IP lookup example program

To demonstrate the getaddrinfo() and getnameinfo() functions, we will implement a short program. This program takes a name or IP address for its only argument. It then uses getaddrinfo() to resolve that name or that IP address into an address structure, and the program prints that IP address using getnameinfo() for the text conversion. If multiple addresses are associated with a name, it prints each of them. It also indicates any errors.

To begin with, we need to include our required header for this chapter. We also define AI_ALL for systems that are missing it. The code for this is as follows:

/*lookup.c*/

#include "chap05.h"

#ifndef AI_ALL
#define AI_ALL 0x0100
#endi

We can then begin the main() function and check that the user passed in a hostname to lookup. If the user doesn't pass in a hostname, we print a helpful reminder. The code for this is as follows:

/*lookup.c continued*/

int main(int argc, char *argv[]) {

if (argc < 2) {
printf("Usage: lookup hostname ");
printf("Example: lookup example.com ");
exit(0);
}

We need the following code to initialize Winsock on Windows platforms:

/*lookup.c continued*/

#if defined(_WIN32)
WSADATA d;
if (WSAStartup(MAKEWORD(2, 2), &d)) {
fprintf(stderr, "Failed to initialize. ");
return 1;
}
#endif

We can then call getaddrinfo() to convert the hostname or address into a struct addrinfo. The code for that is as follows:

/*lookup.c continued*/

printf("Resolving hostname '%s' ", argv[1]);
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_ALL;
struct addrinfo *peer_address;
if (getaddrinfo(argv[1], 0, &hints, &peer_address)) {
fprintf(stderr, "getaddrinfo() failed. (%d) ", GETSOCKETERRNO());
return 1;
}

The previous code first prints the hostname or address that is passed in as the first command-line argument. This argument is stored in argv[1]. We then set hints.ai_flags = AI_ALL to specify that we want all available addresses of any type, including both IPv4 and IPv6 addresses.

getaddrinfo() is then called with argv[1]. We pass 0 in for the service argument because we don't care about the port number. We are only trying to resolve an address. If argv[1] contains a name, such as example.com, then our operating system performs a DNS query (assuming the hostname isn't already in the local cache). If argv[1] contains an address such as 192.168.1.1, then getaddrinfo() simply fills in the resulting struct addrinfo as needed.

If the user passed in an invalid address or a hostname for which no record could be found, then getaddrinfo() returns a non-zero value. In that case, our previous code prints out the error.

Now that peer_address holds the desired address(es), we can use getnameinfo() to convert them to text. The following code does that:

/*lookup.c continued*/

printf("Remote address is: ");
struct addrinfo *address = peer_address;
do {
char address_buffer[100];
getnameinfo(address->ai_addr, address->ai_addrlen,
address_buffer, sizeof(address_buffer),
0, 0,
NI_NUMERICHOST);
printf(" %s ", address_buffer);
} while ((address = address->ai_next));

This code works by first storing peer_address in a new variable, address. We then enter a loop. address_buffer[] is declared to store the text address, and we call getnameinfo() to fill in that address. The last parameter to getnameinfo(), NI_NUMERICHOST, indicates that we want it to put the IP address into address_buffer and not a hostname. The address buffer can then simply be printed out with printf().

If getaddrinfo() returned multiple addresses, then the next address is pointed to by address->ai_next. We assign address->ai_next to address and loop if it is non-zero. This is a simple example of walking through a linked list.

After we've printed our address, we should use freeaddrinfo() to free the memory allocated by getaddrinfo(). We should also call the Winsock cleanup function on Windows. We can do both with the following code:

/*lookup.c continued*/

freeaddrinfo(peer_address);

#if defined(_WIN32)
WSACleanup();
#endif

return 0;
}

That concludes our lookup program.

You can compile and run lookup.c on Linux and macOS by using the following command:

gcc lookup.c -o lookup
./lookup example.com

Compiling and running on Windows with MinGW is done in the following way:

gcc lookup.c -o lookup.exe -lws2_32
lookup.exe example.com

The following screenshot is an example of using lookup to print the IP addresses for example.com:

Although getaddrinfo() makes performing DNS lookups easy, it is useful to know what happens behind the scenes. We will now look at the DNS protocol in more detail.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.195.128