Skip to content

Instantly share code, notes, and snippets.

@valenting
Last active February 3, 2025 16:40
Show Gist options
  • Select an option

  • Save valenting/dd1125978313320ee0ab7e52768ea48f to your computer and use it in GitHub Desktop.

Select an option

Save valenting/dd1125978313320ee0ab7e52768ea48f to your computer and use it in GitHub Desktop.
DNSServiceQueryRecord MacOS

TODO: Add compilation command

#include <iostream>
#include <thread>
#include <vector>
#include <dns_sd.h>
#include <unistd.h>
#include <cstring>
using std::string;
void queryRecordCallback(
DNSServiceRef sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
const char *fullname,
uint16_t rrtype,
uint16_t rrclass,
uint16_t rdlen,
const void *rdata,
uint32_t ttl,
void *context
) {
if (errorCode == kDNSServiceErr_NoError) {
printf("Received record for: %s\n", fullname);
} else {
printf("Error querying record: %d\n", errorCode);
}
}
void performDNSQuery(const std::string& hostname) {
std::string host = hostname;
printf("starting query :%s\n", host.c_str());
DNSServiceRef sdRef;
DNSServiceErrorType error = DNSServiceQueryRecord(
&sdRef,
0,
0,
host.c_str(),
1,
kDNSServiceClass_IN,
queryRecordCallback,
nullptr
);
if (error != kDNSServiceErr_NoError) {
printf("Error starting query: %d\n", error);
return;
}
int fd = DNSServiceRefSockFD(sdRef);
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
struct timeval timeout;
timeout.tv_sec = 5; // 5-second timeout
timeout.tv_usec = 0;
printf("selecting\n");
struct timeval* select_timeout = NULL;
// select_timeout = &timeout;
// If the target domain doesn't have an HTTPS record
// the callback never gets called and select hangs forever.
// If this isn't a bug in the implementation this is the worst
// API design ever!
int result = select(fd + 1, &readfds, NULL, NULL, select_timeout);
if (result > 0 && FD_ISSET(fd, &readfds)) {
// Process the result
DNSServiceProcessResult(sdRef);
} else if (result == 0) {
printf("select() timed out\n");
} else if (result < 0) {
printf("select() failed\n");
}
DNSServiceRefDeallocate(sdRef);
printf("done query :%s\n", host.c_str());
}
int main(int argc, char* argv[]) {
// If an argument is passed, resolve only that domain
std::string hostname = argv[1];
printf("Resolving single domain: %s\n", hostname.c_str());
performDNSQuery(hostname);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment