UDPFileTransferClient-Server / gethostbyname.c
gethostbyname.c
Raw
/* Code written by Hugh Smith	April 2017	*/

/* replacement code for gethostbyname - works for IPv4 and IPV6  */
/* Warning - this is NOT thread safe. */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
  
#include "gethostbyname.h"

static char * getIPAddressString46(unsigned char * ipAddress, int addressFamily);
static unsigned char * getIPAddress46(const char * hostName, struct sockaddr_storage * aSockaddr, int addressFamily);
 
 void printIPInfo(struct sockaddr_in6 * ipAddressStruct)
{
	// Prints out IP address and Port number
	
	char * ipString = ipAddressToString(ipAddressStruct);
	
	printf("IP: %s Port: %d\n", ipString, ntohs(ipAddressStruct->sin6_port));
	
}

char * ipAddressToString(struct sockaddr_in6 * ipAddressStruct)
{
	// puts IP address into a printable format
	
	static char ipString[INET6_ADDRSTRLEN];

	inet_ntop(AF_INET6, &ipAddressStruct->sin6_addr, ipString, sizeof(ipString));
	
	return ipString;
}
 
 
unsigned char * gethostbyname4(const char * hostName, struct sockaddr_in * aSockaddr)
{
	// returns ipv4 address and fills in the aSockaddr with address (unless its NULL)
	struct sockaddr_in * aSockaddrPtr = aSockaddr;
	struct sockaddr_in aSockaddrTemp;
	
	// if user does not care about the struct make a temp one
	if (aSockaddr == NULL)
	{
		aSockaddrPtr = &aSockaddrTemp;
	}
		
	return(getIPAddress46(hostName, (struct sockaddr_storage *) aSockaddrPtr, AF_INET));
}
 
unsigned char * gethostbyname6(const char * hostName, struct sockaddr_in6 * aSockaddr6)
{
	// returns ipv6 address and fills in the aSockaddr6 with address (unless its NULL)
	struct sockaddr_in6 * aSockaddr6Ptr = aSockaddr6;
	struct sockaddr_in6 aSockaddr6Temp;
	
	// if user does not care about the struct make a temp one
	if (aSockaddr6 == NULL)
	{
		aSockaddr6Ptr = &aSockaddr6Temp;
	}
		
	return(getIPAddress46(hostName, (struct sockaddr_storage *) aSockaddr6Ptr, AF_INET6));
}


char * getIPAddressString4(unsigned char * ipAddress)
{
	return getIPAddressString46(ipAddress, AF_INET);
}

char * getIPAddressString6(unsigned char * ipAddress)
{
	return getIPAddressString46(ipAddress, AF_INET6);
}


static char * getIPAddressString46(unsigned char * ipAddress, int addressFamily)
{
	// makes it easy to print the IP address (v4 or v6)
	static char ipString[INET6_ADDRSTRLEN];

	if (ipAddress != NULL)
	{
		inet_ntop(addressFamily, ipAddress, ipString, sizeof(ipString));			
	}
	else
	{
		strcpy(ipString, "(IP not found)");
	}
	
	return ipString;
}

static unsigned char * getIPAddress46(const char * hostName, struct sockaddr_storage * aSockaddr, int addressFamily) 
{
	// Puts host IPv6 (or mapped IPV4) into the aSockaddr6 struct and return pointer to 16 byte address (NULL on error)
	// Only pulls the first IP address from the list of possible addresses
	
	static unsigned char ipAddress[INET6_ADDRSTRLEN];
	
	uint8_t * returnValue = NULL;
	int addrError = 0;
	struct addrinfo hints;	
	struct addrinfo *hostInfo = NULL;

	memset(&hints,0,sizeof(hints));
	if (addressFamily == AF_INET)
	{
		hints.ai_family = AF_INET;
	}
	else
	{
		hints.ai_flags = AI_V4MAPPED | AI_ALL;
		hints.ai_family = AF_INET6;
	}
	
	if ((addrError = getaddrinfo(hostName, NULL, &hints, &hostInfo)) != 0)
	{
		fprintf(stderr, "Error getaddrinfo (host: %s): %s\n", hostName, gai_strerror(addrError));
		returnValue = NULL;
	}
	else 
	{
		if (addressFamily == AF_INET)
		{
			memcpy(&((struct sockaddr_in *)aSockaddr)->sin_addr.s_addr, &((struct sockaddr_in*)hostInfo->ai_addr)->sin_addr.s_addr, 4);
			memcpy(ipAddress, &((struct sockaddr_in *)aSockaddr)->sin_addr.s_addr, 4); 
		}
		else
		{
			memcpy(((struct sockaddr_in6 *)aSockaddr)->sin6_addr.s6_addr, &(((struct sockaddr_in6 *)hostInfo->ai_addr)->sin6_addr.s6_addr), 16);
			memcpy(ipAddress, &((struct sockaddr_in6 *)aSockaddr)->sin6_addr.s6_addr, 16); 
		}
		
		returnValue = ipAddress;
		freeaddrinfo(hostInfo);
	}

  return returnValue;    // Either Null or IP address
}


void gethostbyname_test()
{
	gethostbyname_test_lookup("www.google.com");
	gethostbyname_test_lookup("ipv6.google.com");
	gethostbyname_test_lookup("my.calpoly.edu");
	gethostbyname_test_lookup("does not exist");
}

void gethostbyname_test_lookup(char * hostname)
{
	unsigned char * ipAddress = NULL;
		
	ipAddress = gethostbyname6(hostname, NULL);
	if (ipAddress != NULL)
	{
		printf("IPV6 Host: %s IP: %s \n", hostname, getIPAddressString6(ipAddress));
	} 
  
	//struct sockaddr_in aSockaddr4;
	ipAddress = gethostbyname4(hostname, NULL);
	if (ipAddress != NULL)
	{
		printf("IPv4 Host: %s IP: %s \n", hostname, getIPAddressString4(ipAddress));
	}
	printf("\n");
}