Created
July 16, 2011 14:16
-
-
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)
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
#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); | |
} |
New versions, thanks to your remarks and to splint.
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? :)
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.
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
Since
usage()
is only called frommain()
,progname
is useless andargv[0]
should simply be passed as a parameter tousage()
.Internal functions should be marked as
static
to allow for more optimizations.