How to use NSHost to get the name behind a bunch of LAN ip addresses?

1.3k views Asked by At

I know how to get the name behind an ip address using the terminal and dig. I.e:

dig @224.0.0.251 -p5353 -x 192.168.0.195 +short

However, I don't want to use NSTask in my application. How can I use NSHost to get the name behind an ip address within a LAN? I tried this, but it always returns nil:

NSHost *myHost = [NSHost hostWithAddress:@"192.168.0.195"]; 
NSLog(@"name: %@", [myHost name]);

Thanks a lot!

Edit: These methods/functions... +[NSHost hostWithAddress:] gethostbyaddr(3) - A BSD function ...seem to be the same as:

dig -x 192.168.0.195

If I use that dig command in the terminal it says that no servers could be reached. (Yes I don't have a DNS server in my LAN), so no wonder I get back nil.

It would be great if I could implement dig @224.0.0.251 -p5353 -x 192.168.0.195 +short (bonjour multicast lookup) in my app without having to use NSTask. :)

1

There are 1 answers

1
xnyhps On BEST ANSWER

It does not use NSHost, but uses the Bonjour-API and it seems to work as you want:

#import <Cocoa/Cocoa.h>
#import <dns_sd.h>
#import <resolv.h>

static void callback(DNSServiceRef serviceRef, 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) {

    char result[1024] = {0};
    dn_expand(rdata, rdata + rdlen, rdata, result, 1024);
    NSLog(@"Found: %s", result);
}

int main(int argc, char const *argv[]) {
    DNSServiceRef reverseLookupService = NULL;

    DNSServiceErrorType error = kDNSServiceErr_NoError;
    error = DNSServiceQueryRecord(&reverseLookupService, kDNSServiceFlagsForceMulticast,
        kDNSServiceInterfaceIndexAny, "5.1.168.192.in-addr.arpa.",
        kDNSServiceType_PTR, kDNSServiceClass_IN,
        callback, NULL);

    if (error != kDNSServiceErr_NoError) {
        NSLog(@"Error: %d", error);
        exit(1);
    }

    error = DNSServiceProcessResult(reverseLookupService);

    DNSServiceRefDeallocate(reverseLookupService);

    return 0;
}

The important part is using DNSServiceQueryRecord with kDNSServiceFlagsForceMulticast. Look at https://developer.apple.com/library/mac/#documentation/Networking/Reference/DNSServiceDiscovery_CRef/dns_sd_h/index.html#//apple_ref/c/func/DNSServiceQueryRecord for more info about this function.

You'll have to convert the IP address to in-addr.arpa.-format yourself, but that is not hard (the octets are backwards with "in-addr.arpa." at the end. IPv6 is probably similar, but I have not tested it).

It imports resolv.h (and you need to link it to libresolv), but only for dn_expand. The data passed to the callback is compressed, and dn_expand creates a human-readable representation.