Skip to content

Instantly share code, notes, and snippets.

@bortzmeyer
Created July 16, 2011 14:16
Show Gist options
  • Save bortzmeyer/1086392 to your computer and use it in GitHub Desktop.
Save bortzmeyer/1086392 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)
#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)
{
fprintf(stderr, "Usage: %s hostname\n", progname);
}
static char *
text_of(const struct sockaddr *address)
{
char *text = malloc(INET6_ADDRSTRLEN);
const char *result;
struct sockaddr_in6 *address_v6;
struct sockaddr_in *address_v4;
if (address->sa_family == AF_INET6) {
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) {
address_v4 = (struct sockaddr_in *) address;
result = inet_ntop(AF_INET, &address_v4->sin_addr, text, INET_ADDRSTRLEN);
} else {
return ("[Unknown family address]");
}
if (result == NULL) {
return ("[Internal error in address formating]");
}
return text;
}
int
main(int argc, char **argv)
{
char hostname[MAXHOSTNAMELEN + 1];
struct addrinfo hints_numeric, hints;
struct addrinfo *result, *hostref;
int status;
if (argc != 2) {
usage(argv[0]);
exit(EXIT_FAILURE);
}
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 = malloc(sizeof(struct addrinfo));
memset(&result, 0, sizeof(&result));
status = getaddrinfo(hostname, NULL, &hints_numeric, &result);
if (!status) {
fprintf(stdout, "%s is an IP address\n", hostname);
} else {
if (status == EAI_NONAME) {
/* Not an IP address */
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);
}
} else {
fprintf(stderr, "Internal error, cannot resolve \"%s\" (error %i)\n",
hostname, status);
exit(EXIT_FAILURE);
}
fprintf(stdout, "Address(es) of %s is(are):", hostname);
fprintf(stdout, " %s ", text_of(result->ai_addr));
for (hostref = result->ai_next; hostref != NULL; hostref = hostref->ai_next) {
fprintf(stdout, "%s ", text_of(hostref->ai_addr));
}
fprintf(stdout, "\n");
}
exit(EXIT_SUCCESS);
}
@bortzmeyer
Copy link
Author

I deleted the progname variable. For the other variables, I'm not convinced, I prefer to have all declarations at the beginning of the function, even if it means not having them at the "proper" scope.

@samueltardieu
Copy link

Why? This brings no advantage, and let you see them (and potentially use them) before they have been defined or after they have been freed in case of pointers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment