JMU
Using the Domaing Name System
with Examples in C


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Review
Review (cont.)
DNS Forward Resolution: getaddrinfo() getaddrinfo
int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **first)
Purpose:
Get the IP addresses for a given host (and service) name
Details:
host The host name
service The service name (or port number)
hints Further criteria to use
first The first IP address (in a linked structure)
Return 0 on success; non-zero on error
#define _POSIX_C_SOURCE >= 201112L
#include <netdb.h> netdb.h
#include <sys/socket.h> sys/socket.h
#include <sys/types.h> sys/types.h
DNS Forward Resolution (cont.)
struct addrinfo {
  int              ai_flags;
  int              ai_family;     // AF_INET, AF_INET6
  int              ai_socktype;   // SOCK_STREAM, SOCK_DGRAM
  int              ai_protocol;   // Protocol (name or number)
  socklen_t        ai_addrlen;    // sizeof(si_addr)
  struct sockaddr *ai_addr;       // Socket address
  char            *ai_canonname;  // Canonical name of host (or NULL)
  struct addrinfo *ai_next;       // Pointer to next struct in linked structure
};
  

Note: ai_canonname will be NULL for all elements in the linked structure after the first.

DNS Forward Resolution (cont.): freeaddrinfo() freeaddrinfo
void freeaddrinfo(struct addrinfo *first)
Purpose:
Free the memory allocated by a call to getaddrinfo()
Details:
first The first element in the linked structure
#include <netdb.h> netdb.h
#include <sys/socket.h> sys/socket.h
DNS Forward Resolution (cont.)
unixexamples/dns/get_address.c
        #define _POSIX_C_SOURCE 201112L
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

int
main(int argc, char* argv[])
{
  char dotted_quad[16];
  struct addrinfo  hints;
  struct addrinfo *current, *first;
  struct sockaddr_in *address;

  // Initialize unused fields to 0 or NULL as appropriate
  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_canonname = NULL;
  hints.ai_addr      = NULL;
  hints.ai_next      = NULL;
  // Initialize used fields
  hints.ai_flags    = AI_CANONNAME | AI_NUMERICSERV;
  hints.ai_family   = AF_INET;
  hints.ai_socktype = 0; // Any socket type (could be SOCK_DGRAM or SOCK_STREAM)
  hints.ai_protocol = 0;

  // Get the linked structure of addresses
  getaddrinfo(argv[1], "0", &hints, &first);

  if (first) printf("IP Addresses for %s:\n", first->ai_canonname);
  else       printf("No addresses found for %s\n",  first->ai_canonname);

  // Iterate through the linked structure
  current = first;
  while (current)
    {
      // Get the address
      address = (struct sockaddr_in *)current->ai_addr;

      // Convert to a human-readable string
      memset(&dotted_quad, 0, 16);
      inet_ntop(AF_INET, &address->sin_addr, dotted_quad, 16);

      printf("%s\n", dotted_quad);
      current = current->ai_next;
    }

  // Free the memory used by the linked structure
  freeaddrinfo(first);
  exit(0);
}
        
DNS Reverse Resolution: getnameinfo() getnameinfo
int getnameinfo(const struct sockaddr *address, socklen_t addrlen, char *host, socklen_t hostlen, char* service, socklen servlen, int flags)
Purpose:
Get the host name (and service) for a given IP address
Details:
address The IP address of interest
addrlen The length of the IP address
host The corresponding host nam
hostlen The maximum length of a host name
service The corresponding service
servlen The maximum length of a service name
flags A bit mask of flags
Return 0 on success; non-zero on error
#define _GNU_SOURCE
#define _POSIX_C_SOURCE >= 201112L
#include <netdb.h> netdb.h
#include <sys/socket.h> sys/socket.h
DNS Forward Resolution (cont.)
unixexamples/dns/get_name.c
        #define _GNU_SOURCE
#define _POSIX_C_SOURCE 201112L
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

int
main(int argc, char* argv[])
{
  char   name[NI_MAXHOST], service[NI_MAXSERV];
  struct sockaddr_in address;
  uint16_t port = 0;
  
  // Initialize the arrays that will hold the result
  memset(&name,    0, sizeof(name)); 
  memset(&service, 0, sizeof(service)); 

  if (argc > 2) port = atoi(argv[2]);
  
  // Set the attributes of the address
  address.sin_family = AF_INET;     // IPv4
  address.sin_port   = htons(port); // Use network byte order

  // Convert the command-line argument from human-readable format
  inet_pton(AF_INET, argv[1], &(address.sin_addr));

  // Get the name
  getnameinfo((struct sockaddr *)&address, sizeof(struct sockaddr),
              name, NI_MAXHOST, service, NI_MAXSERV, 0);

  printf("Host Name: %s\n", name);
  printf("Service:   %s\n", service);
  exit(0);
}