Skip to content

Instantly share code, notes, and snippets.

@samueltardieu
Forked from bortzmeyer/gist:1086392
Created July 26, 2011 09:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samueltardieu/1106406 to your computer and use it in GitHub Desktop.
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)
// 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