从IP地址获取链接本地域名​​(即使用多播DNS和DNS-SD进行反向DNS查找)

时间:2013-10-11 02:31:39

标签: bonjour zeroconf mdns reverse-dns dns-sd

我在LAN上的设备上运行的服务器应用程序可通过DNS-SD(即Zeroconf / Bonjour / Avahi)发现。同样在LAN上的客户端设备连接到此服务器。我无法控制用于连接到我的服务器应用程序的应用程序,但我知道他们可能正在使用DNS-SD和mDNS来发现并连接到服务器。如何在C或C ++中仅检索识别这些客户端设备的链接本地域名​​?

根据RFC 6762 Multicast DNS - Section 4. Reverse Address Mapping
“Like”.local。“,IPv4和IPv6反向映射域也被定义为链接本地...由于此域下的名称对应于IPv4链接本地地址,因此本地链接是合乎逻辑的。找到与这些名称有关的信息的最佳位置。“

理论上,应该可以通过IP地址查找链接本地域名​​。有谁知道怎么样?也许我没有找到合适的位置,但我没有在Bonjour文档中看到API调用。

1 个答案:

答案 0 :(得分:1)

我最终通过Apple的Bonjour Dev邮件列表得到了这个问题的答案。

根据 Quinn“The Eskimo!”,以下是您可以这样做的方法:

static void DNSCallback(
    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
)
{
    const uint8_t *     cursor;

    fprintf(stderr, "DNSCallback\n");
    assert(rrtype == kDNSServiceType_PTR);
    assert(rrclass == kDNSServiceClass_IN);
    cursor = (const uint8_t *) rdata;
    while ( *cursor != 0 ) {
        fprintf(stderr, "%.*s.", (int) *cursor, cursor + 1);
        cursor += *cursor + 1;
    }
    fprintf(stderr, "\n");
}

static void SocketCallBack(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
    DNSServiceErrorType err;

    fprintf(stderr, "SocketCallBack\n");

    err = DNSServiceProcessResult(((AppDelegate *) info)->sdRef);
    fprintf(stderr, "err = %d\n", (int) err);
}

- (IBAction)testAction:(id)sender
{
    DNSServiceErrorType err;
    int                 sock;
    CFSocketRef         cfSock;

    fprintf(stderr, "-[AppDelegate testAction:]\n");

    assert(self->sdRef == NULL);

    err = DNSServiceQueryRecord(
        &self->sdRef,
        kDNSServiceFlagsForceMulticast,
        0,
        "9.40.0.10.in-addr.arpa.",
        kDNSServiceType_PTR,
        kDNSServiceClass_IN,
        DNSCallback,
        self
    );
    fprintf(stderr, "err = %d\n", (int) err);

    sock = DNSServiceRefSockFD(self->sdRef);
    fprintf(stderr, "sock = %d\n", sock);

    CFSocketContext context = { 0, self, NULL, NULL, NULL };

    cfSock = CFSocketCreateWithNative(NULL, sock, kCFSocketReadCallBack, SocketCallBack, &context);
    assert(cfSock != NULL);

    CFRunLoopSourceRef rls;
    rls = CFSocketCreateRunLoopSource(NULL, cfSock, 0);
    assert(rls != NULL);

    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
}

此示例将找到IP地址10.0.40.9的链接本地主机名。 IP地址以相反的顺序插入。