Created
March 13, 2015 17:08
-
-
Save weissi/bf4cc09931ba91fdaa5e to your computer and use it in GitHub Desktop.
getaddrinfo-test
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
#ifdef _WIN32 | |
#include <ws2tcpip.h> | |
#include <in6addr.h> | |
#else | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netdb.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#endif | |
#include <inttypes.h> | |
#include <ctype.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#ifdef _WIN32 | |
#include <malloc.h> | |
#endif | |
struct net_addr { | |
uint16_t family; | |
union { | |
struct in_addr ipv4; | |
struct in6_addr ipv6; | |
}; | |
int64_t ts_hyb; | |
}; | |
struct dns_response { | |
const char *cname; | |
char *canon_name; | |
struct net_addr *a; | |
int err; | |
int denied; | |
int64_t cost_ms; | |
}; | |
int main(int argc, char **argv) | |
{ | |
int r = 111; | |
const char *dname; | |
struct addrinfo *i, *info = NULL, hints; | |
struct dns_response ret; | |
size_t max_n, k = 0; | |
#ifdef _WIN32 | |
WSADATA Data; | |
#endif | |
memset(&ret, 0, sizeof(ret)); | |
#ifdef _WIN32 | |
WSAStartup(MAKEWORD(2, 0), &Data); | |
#endif | |
if (argc < 2) { | |
fprintf(stderr, "usage: %s <domain_name>\n", argv ? argv[0] : ""); | |
r = 1; | |
goto out; | |
} | |
dname = argv[1]; | |
memset(&hints, 0, sizeof(hints)); | |
hints.ai_family = AF_UNSPEC; | |
hints.ai_flags = AI_CANONNAME; | |
ret.cname = dname; | |
ret.err = getaddrinfo(dname, NULL, &hints, &info); | |
fprintf(stdout, "%s:\n", dname); | |
if (ret.err) { | |
fprintf(stdout, "getaddrinfo FAILED err %d\n", ret.err); | |
r = 0; | |
goto out; | |
} | |
max_n = 0; | |
for (i = info; i; i = i->ai_next) | |
max_n++; | |
if (!max_n) | |
goto out; | |
max_n += 1; /* for the NULL one */ | |
ret.a = calloc(1, max_n * sizeof(*ret.a)); | |
if (!ret.a) { | |
ret.err = EAI_MEMORY; | |
fprintf(stderr, "%s: memory error\n", __FUNCTION__); | |
r = 2; | |
goto out; | |
} | |
if (info && info->ai_canonname && !ret.canon_name) { | |
fprintf(stdout, "ptr: %p, %s\n", info->ai_canonname, info->ai_canonname); | |
ret.canon_name = strdup(info->ai_canonname); | |
} | |
for (i = info; i; i = i->ai_next) { | |
int j; | |
if (!i->ai_addr || (i->ai_family != AF_INET && i->ai_family != AF_INET6)) | |
continue; | |
if (i->ai_family == AF_INET) { | |
struct in_addr addr; | |
if (i->ai_addrlen < sizeof(struct sockaddr_in)) | |
continue; | |
addr = ((struct sockaddr_in *) i->ai_addr)->sin_addr; | |
for (j = 0; j < k; j++) { | |
if (ret.a[j].family != AF_INET) | |
continue; | |
if (addr.s_addr == ret.a[j].ipv4.s_addr) | |
break; | |
} | |
if (j != k) | |
continue; | |
ret.a[k].family = AF_INET; | |
ret.a[k].ipv4 = addr; | |
} else { /* IPv6 */ | |
struct in6_addr addr; | |
if (i->ai_addrlen < sizeof(struct sockaddr_in6)) | |
continue; | |
addr = ((struct sockaddr_in6 *)i->ai_addr)->sin6_addr; | |
for (j = 0; j < k; j++) { | |
if (ret.a[j].family != AF_INET6) | |
continue; | |
if (memcmp(&addr, &ret.a[j].ipv6, sizeof(addr)) == 0) | |
break; | |
} | |
if (j != k) | |
continue; | |
ret.a[k].family = AF_INET6; | |
ret.a[k].ipv6 = ((struct sockaddr_in6 *)i->ai_addr)->sin6_addr; | |
} | |
k++; | |
fprintf(stdout, "flags: 0x%08x\n", i->ai_flags); | |
} | |
if (ret.canon_name && strcasecmp(ret.canon_name, dname)) | |
fprintf(stdout, "CANON NAME len %u '%s'\n", (unsigned) strlen(ret.canon_name), ret.canon_name); | |
if ((unsigned) strlen(ret.canon_name) > 100) { | |
fprintf(stdout, "BROKEN!!!\n"); | |
fprintf(stdout, "GREP-MARKER-XXX: "); | |
for (unsigned i=0; i<(unsigned)strlen(ret.canon_name); i++) { | |
fprintf(stdout, "%.2x", *(unsigned char *)((info->ai_canonname)+i)); | |
} | |
fprintf(stdout, "\n"); | |
} | |
k = 0; | |
while (ret.a && ret.a[k].family) { | |
if (ret.a[k].family == AF_INET) { | |
char *ss_addr; | |
ss_addr = inet_ntoa(ret.a[k].ipv4); | |
fprintf(stdout, "A %s\n", ss_addr ? ss_addr : "(invalid)"); | |
} | |
k++; | |
} | |
r = 0; | |
out: | |
fprintf(stdout, "\n"); | |
if (info) | |
freeaddrinfo(info); | |
free(ret.a); | |
#ifdef _WIN32 | |
WSACleanup(); | |
#endif | |
return r; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment