Skip to content

Instantly share code, notes, and snippets.

@achernya
Last active December 15, 2015 13:28
Show Gist options
  • Save achernya/5267015 to your computer and use it in GitHub Desktop.
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.
#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