Last active
December 15, 2015 13:28
-
-
Save achernya/5267015 to your computer and use it in GitHub Desktop.
Demonstration that OS X has working resolver(3) functions in its standard library.
This file contains 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 <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
// Uncomment this and link with -lresolv | |
//#include <resolv.h> | |
#include <arpa/nameser_compat.h> | |
#include <arpa/inet.h> | |
// We want minimum headers for now, so define NS_QFIXEDSZ if needed | |
#ifndef NS_QFIXEDSZ | |
#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ | |
#endif | |
#define A_RECORD 1 | |
int | |
main(int argc, char* argv[]) { | |
if (argc != 2) { | |
fprintf(stderr, "Specify a domain to resolve.\n"); | |
return EXIT_FAILURE; | |
} | |
if (res_init() != 0) { | |
fprintf(stderr, "Unable to initialize the resolver.\n"); | |
return EXIT_FAILURE; | |
} | |
char answer[1024] = ""; | |
int answer_length = 0; | |
answer_length = res_search(argv[1], 1, A_RECORD, answer, sizeof(answer)); | |
if (answer_length < 0) { | |
fprintf(stderr, "Unable to resolve %s\n", argv[1]); | |
return EXIT_FAILURE; | |
} | |
// Get a DNS Header and figure out how many answer we have | |
HEADER* hdr = (HEADER*) answer; | |
hdr->ancount = ntohs(hdr->ancount); | |
hdr->qdcount = ntohs(hdr->qdcount); | |
char* record = answer + sizeof(HEADER); | |
char* end = answer + answer_length; | |
int i = 0, skip = 0; | |
char name[1024] = ""; | |
// First, iterate over the question records and skip them | |
for (i = 0; (i < hdr->qdcount); i++) { | |
skip = dn_expand(answer, end, record, name, sizeof(name)); | |
char* proposed_record = record + skip + QFIXEDSZ; | |
if (proposed_record >= end) { | |
fprintf(stderr, "Something went wrong while parsing the DNS response.\n"); | |
return EXIT_FAILURE; | |
} | |
record = proposed_record; | |
} | |
for (i = 0; (i < hdr->ancount); i++) { | |
skip = dn_expand(answer, end, record, name, sizeof(name)); | |
char* proposed_ip = record + skip + 10; | |
if (proposed_ip >= end) { | |
fprintf(stderr, "Something went wrong while finding the IP in the DNS response.\n"); | |
return EXIT_FAILURE; | |
} | |
char* values = record + skip; | |
// Array indices as per RFC 1035 | |
int type = ntohs(*(short*)(values + 0)); | |
int class = ntohs(*(short*)(values + 2)); | |
int len = ntohs(*(short*)(values + 8)); | |
record = proposed_ip + len; | |
if (type != A_RECORD) { | |
continue; | |
} | |
int ip = ntohl(*(int*) proposed_ip); | |
printf("Response: %d.%d.%d.%d\n", | |
(ip >> 24) & 0xFF, | |
(ip >> 16) & 0xFF, | |
(ip >> 8) & 0xFF, | |
(ip >> 0) & 0xFF); | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment