Skip to content

Instantly share code, notes, and snippets.

@bortzmeyer
Created July 16, 2011 14:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • 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);
}
@samueltardieu
Copy link

Since usage() is only called from main(), progname is useless and argv[0] should simply be passed as a parameter to usage().

Internal functions should be marked as static to allow for more optimizations.

@bortzmeyer
Copy link
Author

New versions, thanks to your remarks and to splint.

@samueltardieu
Copy link

const struct sockaddr *address

address_v6 and address_v4 should be declared in the proper scope (one level below each)

You didn't fix the useless (and bogus, program name can be longer than MAXHOSTNAMELEN) argv[0] copy

Yes, I'm nitpicking, but you asked for a code review didn't you? :)

@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