-
-
Save samueltardieu/1106406 to your computer and use it in GitHub Desktop.
Resolve names, using the standard library (so, going through NSS and things like that, unlike dig)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compile with -std=gnu99 to get the proper definitions of struct addrinfo | |
#include <stdbool.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <netdb.h> | |
#include <arpa/inet.h> | |
#include <errno.h> | |
#include <netinet/in.h> | |
#include <netinet/ip.h> | |
#include <netinet/ip6.h> | |
#define MAXHOSTNAMELEN 256 | |
static void | |
usage(const char *progname, int exit_code) | |
{ | |
fprintf(stderr, "Usage: %s [--help | hostname]\n", progname); | |
exit(exit_code); | |
} | |
// Warning: every successful call to text_of will leak memory | |
static const char * | |
text_of(struct sockaddr *address) | |
{ | |
char *text = malloc(INET6_ADDRSTRLEN); | |
const char *result; | |
if (address->sa_family == AF_INET6) { | |
struct sockaddr_in6 *address_v6 = (struct sockaddr_in6 *) address; | |
result = inet_ntop(AF_INET6, &address_v6->sin6_addr, text, INET6_ADDRSTRLEN); | |
} else if (address->sa_family == AF_INET) { | |
struct sockaddr_in *address_v4 = (struct sockaddr_in *) address; | |
result = inet_ntop(AF_INET, &address_v4->sin_addr, text, INET_ADDRSTRLEN); | |
} else { | |
free(text); | |
return "[Unknown family address]"; | |
} | |
if (result == NULL) { | |
free(text); | |
return "[Internal error in address formatting]"; | |
} | |
return text; | |
} | |
int | |
main(int argc, const char *argv[]) | |
{ | |
char hostname[MAXHOSTNAMELEN + 1]; | |
struct addrinfo hints_numeric; | |
struct addrinfo *result; | |
if (argc != 2) | |
usage(argv[0], EXIT_FAILURE); | |
else if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) | |
usage(argv[0], EXIT_SUCCESS); | |
strncpy(hostname, argv[1], MAXHOSTNAMELEN); | |
hostname[MAXHOSTNAMELEN] = '\0'; | |
/* RFC 1123 says we must try IP addresses first */ | |
memset(&hints_numeric, 0, sizeof(hints_numeric)); | |
hints_numeric.ai_flags = AI_NUMERICHOST; | |
hints_numeric.ai_socktype = SOCK_STREAM; | |
result = alloca(sizeof(struct addrinfo)); | |
memset(&result, 0, sizeof(&result)); | |
int status = getaddrinfo(hostname, NULL, &hints_numeric, &result); | |
switch(status) { | |
case 0: | |
fprintf(stdout, "%s is an IP address\n", hostname); | |
break; | |
case EAI_NONAME: { | |
/* Not an IP address */ | |
struct addrinfo hints; | |
memset(&hints, 0, sizeof(hints)); | |
hints.ai_family = AF_UNSPEC; | |
hints.ai_socktype = SOCK_STREAM; | |
result = malloc(sizeof(struct addrinfo)); | |
status = getaddrinfo(hostname, NULL, &hints, &result); | |
if (status) { | |
fprintf(stderr, "Nothing found about host name %s\n", hostname); | |
exit(EXIT_FAILURE); | |
} | |
bool plural = result && result->ai_next; | |
fprintf(stdout, "Address%s of %s %s", plural ? "es" : "", hostname, plural ? "are" : "is"); | |
fprintf(stdout, " %s", text_of(result->ai_addr)); | |
for (struct addrinfo *hostref = result->ai_next; hostref != NULL; hostref = hostref->ai_next) | |
fprintf(stdout, ", %s ", text_of(hostref->ai_addr)); | |
fprintf(stdout, "\n"); | |
break; | |
} | |
default: | |
fprintf(stderr, "Internal error, cannot resolve %s (error %i)\n", | |
hostname, status); | |
exit(EXIT_FAILURE); | |
} | |
exit(EXIT_SUCCESS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment