2

I've been searching for a while without any success, how am I supposed to get a DNS TXT record for a domain in Objective-C?

My goal is to get the same output as: dig -t txt google.com +short

PS: No NSTask/pipping please! (I'm currently doing that but it's bad). The code can be written in C, I'll just write a wrapper later. I don't care about AppStore rules.

Thank you!

TCB13
  • 2,826
  • 2
  • 34
  • 62
  • Can you please explain the bad about NSTask/pipping. I am currently using NSTask for DNS txt queries. – sanjeev sharma Feb 17 '15 at 10:51
  • 1
    @sanjeevsharma please check the accepted answer is solves your problem. `NSTask` and pipping are bad because they bring you security issues and won't be accepted on the AppStore, probably. It's easier for an hacker to change `dig` to another binary and craft a custom DNS response or inject other data in your app without you knowing it. – TCB13 Feb 17 '15 at 11:22

2 Answers2

4

Use DNSServiceQueryRecord in dns_sd.h:

#import <dns_sd.h>

// ...

DNSServiceRef serviceRef;

DNSServiceQueryRecord(&serviceRef, 0, 0, "hmspl.de", kDNSServiceType_TXT,
                      kDNSServiceClass_IN, queryCallback, NULL);

DNSServiceProcessResult(serviceRef);
DNSServiceRefDeallocate(serviceRef);

// ...

static void queryCallback(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 && rdlen > 1) {
        NSMutableData *txtData = [NSMutableData dataWithCapacity:rdlen];

        for (uint16_t i = 1; i < rdlen; i += 256) {
            [txtData appendBytes:rdata + i length:MIN(rdlen - i, 255)];
        }

        NSString *theTXT = [[NSString alloc] initWithBytes:txtData.bytes length:txtData.length encoding:NSASCIIStringEncoding];
        NSLog(@"%@", theTXT);
    }
}

See https://developer.apple.com/library/mac/#documentation/Networking/Reference/DNSServiceDiscovery_CRef/Reference/reference.html#//apple_ref/doc/c_ref/DNSServiceQueryRecord

Danilo
  • 3,137
  • 2
  • 16
  • 23
  • Any tips on why do I always get a garbage char at the beginning of the string? Thank you. – TCB13 Jun 26 '13 at 23:47
  • 1
    This is a single length byte indicating the length of the TXT being between 0 and 255. I will update my answer to start rdata at 1. – Danilo Jun 27 '13 at 00:02
  • I just realized that if the TXT is larger than 255 bytes the single length byte repeats itself in `theTXT`. I will update my answer to take that into account. – Danilo Jun 27 '13 at 00:31
  • Why would you want it to be synchronous? – Danilo Jun 27 '13 at 00:35
  • it's a command line application, no reason to be asynchronous. Also it adds more complexity. – TCB13 Jun 27 '13 at 00:43
  • You could use a semaphore. See http://stackoverflow.com/questions/4326350/how-do-i-wait-for-an-asynchronously-dispatched-block-to-finish – Danilo Jun 27 '13 at 00:56
  • TCB, did this answer your question? If so please mark it as such. – Danilo Jun 28 '13 at 00:04
  • @Danilo, this great, thank you! One question: when i run your example code, the results has some *weird* chars, there were i would expect a *period* (.) i see a different chars (like \x02, \x03). I tried it with *kDNSServiceType_NS*, any idea where thats coming from? Looking direct at the memory (*rdata) it looks fine. – Roger Dec 18 '13 at 00:11
  • I think you'll want to use dns_parse_resource_record to parse the rdata. That would remove the so-called garbage. This link shows how to do that parsing for SRV records. TXT records would use a similar mechanism but with kDNSServiceType_TXT as the service type and using the txt portion of the union to get back the parsed data. https://developer.apple.com/library/mac/samplecode/SRVResolver/Listings/SRVResolver_m.html#//apple_ref/doc/uid/DTS40009625-SRVResolver_m-DontLinkElementID_5 – Rich Waters Feb 13 '15 at 21:27
0

can use like this code remove \x02 \x03, I removed \0x12 \0x17 use $man ascii check char result[256]={0}; dn_expand(rdata, rdata + rdlen, rdata, result, 256);

        NSMutableData *txtData = [NSMutableData dataWithCapacity:rdlen];

        char *p=(char*)rdata;

        for (uint16_t i = 0; i < rdlen; i++) {

            DLog(@"%c\n",*p);
            if (*p > 0x20) {
                [txtData appendBytes:p length:1];


            }
            p++;
        }
yarshure
  • 61
  • 7