Skip to content

Instantly share code, notes, and snippets.

@weissi
Created March 13, 2015 17:08
Show Gist options
  • Save weissi/bf4cc09931ba91fdaa5e to your computer and use it in GitHub Desktop.
Save weissi/bf4cc09931ba91fdaa5e to your computer and use it in GitHub Desktop.
getaddrinfo-test
#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