Module Name: src
Committed By: tsarna
Date: Mon Oct 5 03:54:17 UTC 2009
Modified Files:
src/distrib/sets/lists/base: shl.mi
src/external/apache2/mDNSResponder: Makefile
Added Files:
src/external/apache2/mDNSResponder/nss: Makefile nss_mdns.c
Log Message:
Add nss_mdns, a nsswitch plugin for host lookups vis mDNS ("Bonjour"),
eg "hostname.local". This is a work in progress, but basically
functional. (note: this requires mdnsd to be running.)
To generate a diff of this commit:
cvs rdiff -u -r1.495 -r1.496 src/distrib/sets/lists/base/shl.mi
cvs rdiff -u -r1.1 -r1.2 src/external/apache2/mDNSResponder/Makefile
cvs rdiff -u -r0 -r1.1 src/external/apache2/mDNSResponder/nss/Makefile \
src/external/apache2/mDNSResponder/nss/nss_mdns.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/distrib/sets/lists/base/shl.mi
diff -u src/distrib/sets/lists/base/shl.mi:1.495 src/distrib/sets/lists/base/shl.mi:1.496
--- src/distrib/sets/lists/base/shl.mi:1.495 Sun Oct 4 22:06:34 2009
+++ src/distrib/sets/lists/base/shl.mi Mon Oct 5 03:54:17 2009
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.495 2009/10/04 22:06:34 christos Exp $
+# $NetBSD: shl.mi,v 1.496 2009/10/05 03:54:17 tsarna Exp $
#
# Note: Don't delete entries from here - mark them as "obsolete" instead,
# unless otherwise stated below.
@@ -166,6 +166,7 @@
./usr/lib/libutil.so.7.17 base-sys-shlib
./usr/lib/libwrap.so.1.0 base-net-shlib
./usr/lib/libz.so.1.0 base-sys-shlib
+./usr/lib/nss_mdns.so.0 base-mdns-shlib mdns
./usr/lib/security/pam_afslog.so.3 base-sys-shlib kerberos,pam
./usr/lib/security/pam_chroot.so.3 base-sys-shlib pam
./usr/lib/security/pam_deny.so.3 base-sys-shlib pam
Index: src/external/apache2/mDNSResponder/Makefile
diff -u src/external/apache2/mDNSResponder/Makefile:1.1 src/external/apache2/mDNSResponder/Makefile:1.2
--- src/external/apache2/mDNSResponder/Makefile:1.1 Tue Sep 29 23:56:27 2009
+++ src/external/apache2/mDNSResponder/Makefile Mon Oct 5 03:54:17 2009
@@ -1,5 +1,5 @@
-# $NetBSD: Makefile,v 1.1 2009/09/29 23:56:27 tsarna Exp $
+# $NetBSD: Makefile,v 1.2 2009/10/05 03:54:17 tsarna Exp $
-SUBDIR= usr.bin usr.sbin
+SUBDIR= usr.bin usr.sbin nss
.include <bsd.subdir.mk>
Added files:
Index: src/external/apache2/mDNSResponder/nss/Makefile
diff -u /dev/null src/external/apache2/mDNSResponder/nss/Makefile:1.1
--- /dev/null Mon Oct 5 03:54:17 2009
+++ src/external/apache2/mDNSResponder/nss/Makefile Mon Oct 5 03:54:17 2009
@@ -0,0 +1,36 @@
+# $NetBSD: Makefile,v 1.1 2009/10/05 03:54:17 tsarna Exp $
+
+LIB= nss_mdns
+SHLIB_MAJOR= 0
+
+NOLINT= # don't build a lint library
+NOPROFILE= # don't build a profile library
+NOPICINSTALL= # don't install _pic.a library
+
+.include <bsd.own.mk>
+
+.include "${.CURDIR}/../Makefile.inc"
+
+SRCS= nss_mdns.c
+LDADD+= -ldns_sd
+DPADD+= ${LIBDNS_SD}
+
+.if ${MKPIC} != "no"
+.PRECIOUS: ${DESTDIR}${LIBDIR}/${LIB}.so.${SHLIB_MAJOR}
+libinstall:: ${DESTDIR}${LIBDIR}/${LIB}.so.${SHLIB_MAJOR}
+.else
+libinstall::
+.endif
+
+.include <bsd.lib.mk>
+
+${DESTDIR}${LIBDIR}/${LIB}.so.${SHLIB_MAJOR}: lib${LIB}.so.${SHLIB_FULLVERSION}
+ ${_MKTARGET_INSTALL}
+ ${INSTALL_FILE} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
+ ${.ALLSRC} ${.TARGET}
+
+#.if defined(LD32DIR)
+#LIBDIR=/usr/lib/${LD32DIR}
+#.else
+#LIBDIR=/usr/lib
+#.endif
Index: src/external/apache2/mDNSResponder/nss/nss_mdns.c
diff -u /dev/null src/external/apache2/mDNSResponder/nss/nss_mdns.c:1.1
--- /dev/null Mon Oct 5 03:54:17 2009
+++ src/external/apache2/mDNSResponder/nss/nss_mdns.c Mon Oct 5 03:54:17 2009
@@ -0,0 +1,673 @@
+/* $NetBSD: nss_mdns.c,v 1.1 2009/10/05 03:54:17 tsarna Exp $ */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Tyler C. Sarna
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Multicast DNS ("Bonjour") hosts name service switch
+ *
+ * Documentation links:
+ *
+ * http://developer.apple.com/bonjour/
+ * http://www.multicastdns.org/
+ * http://www.dns-sd.org/
+ */
+
+#include <nsswitch.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <dns_sd.h>
+#include <poll.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef lint
+#define UNUSED(a) (void)&a
+#else
+#define UNUSED(a) a = a
+#endif
+
+#if defined(__NetBSD__) && (__NetBSD_Version__ < 599002000)
+static struct addrinfo *
+allocaddrinfo(socklen_t addrlen)
+{
+ struct addrinfo *ai;
+
+ ai = calloc(sizeof(struct addrinfo) + addrlen, 1);
+ if (ai) {
+ ai->ai_addrlen = addrlen;
+ ai->ai_addr = (void *)(ai+1);
+ }
+
+ return ai;
+}
+#endif
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+typedef struct callback_ctx {
+ int done;
+} callback_ctx;
+
+typedef struct hostent_ctx {
+ callback_ctx cb_ctx; /* must come first */
+ struct hostent host;
+ char *h_addr_ptrs[MAXADDRS + 1];
+ char *host_aliases[MAXALIASES];
+ char addrs[MAXADDRS * 16];
+ char buf[8192], *next;
+ int done, naliases, naddrs;
+} hostent_ctx;
+
+typedef struct addrinfo_ctx {
+ callback_ctx cb_ctx; /* must come first */
+ struct addrinfo start, *last;
+} addrinfo_ctx;
+
+#define HCTX_BUFLEFT(c) (sizeof((c)->buf) - ((c)->next - (c)->buf))
+
+static hostent_ctx h_ctx;
+
+
+static int _mdns_getaddrinfo(void *cbrv, void *cbdata, va_list ap);
+static int _mdns_gethtbyaddr(void *cbrv, void *cbdata, va_list ap);
+static int _mdns_gethtbyname(void *cbrv, void *cbdata, va_list ap);
+
+static void _mdns_addrinfo_init(addrinfo_ctx *ctx, const struct addrinfo *ai);
+static void _mdns_addrinfo_add_ai(addrinfo_ctx *ctx, struct addrinfo *ai);
+static struct addrinfo *_mdns_addrinfo_done(addrinfo_ctx *ctx);
+
+static void _mdns_hostent_init(hostent_ctx *ctx, int af, int addrlen);
+static void _mdns_hostent_add_host(hostent_ctx *ctx, const char *name);
+static void _mdns_hostent_add_addr(hostent_ctx *ctx, const void *addr, uint16_t len);
+static struct hostent *_mdns_hostent_done(hostent_ctx *ctx);
+
+static void _mdns_addrinfo_cb(DNSServiceRef sdRef, DNSServiceFlags flags,
+ uint32_t interfaceIndex, DNSServiceErrorType errorCode,
+ const char *hostname, const struct sockaddr *address, uint32_t ttl,
+ void *context);
+static void _mdns_hostent_cb(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);
+static void _mdns_eventloop(DNSServiceRef sdRef, callback_ctx *ctx);
+
+static char *_mdns_rdata2name(const unsigned char *rdata, uint16_t rdlen,
+ char *buf, size_t buflen);
+
+
+static ns_mtab mtab[] = {
+ { NSDB_HOSTS, "getaddrinfo", _mdns_getaddrinfo, NULL },
+ { NSDB_HOSTS, "gethostbyaddr", _mdns_gethtbyaddr, NULL },
+ { NSDB_HOSTS, "gethostbyname", _mdns_gethtbyname, NULL },
+};
+
+
+
+ns_mtab *
+nss_module_register(const char *source, u_int *nelems,
+ nss_module_unregister_fn *unreg)
+{
+ UNUSED(source);
+ UNUSED(unreg);
+
+ *nelems = sizeof(mtab) / sizeof(mtab[0]);
+ *unreg = NULL;
+
+ return mtab;
+}
+
+
+
+static int
+_mdns_getaddrinfo(void *cbrv, void *cbdata, va_list ap)
+{
+ const struct addrinfo *pai;
+ const char *name;
+ addrinfo_ctx ctx;
+ DNSServiceProtocol proto;
+ DNSServiceErrorType err;
+ DNSServiceRef sdRef;
+
+ UNUSED(cbdata);
+
+ name = va_arg(ap, char *);
+ pai = va_arg(ap, struct addrinfo *);
+
+ //XXX check valid name space
+
+ switch (pai->ai_family) {
+ case AF_UNSPEC:
+ proto = kDNSServiceProtocol_IPv6 | kDNSServiceProtocol_IPv4;
+ break;
+
+ case AF_INET6:
+ proto = kDNSServiceProtocol_IPv6;
+ break;
+
+ case AF_INET:
+ proto = kDNSServiceProtocol_IPv4;
+ break;
+
+ default:
+ return NS_UNAVAIL;
+ }
+
+ _mdns_addrinfo_init(&ctx, pai);
+
+ err = DNSServiceGetAddrInfo(
+ &sdRef,
+ kDNSServiceFlagsForceMulticast,
+ kDNSServiceInterfaceIndexAny,
+ proto,
+ name,
+ _mdns_addrinfo_cb,
+ &ctx
+ );
+
+ if (err) {
+ h_errno = NETDB_INTERNAL;
+ return NS_UNAVAIL;
+ }
+
+ _mdns_eventloop(sdRef, (void *)&h_ctx);
+
+ DNSServiceRefDeallocate(sdRef);
+
+ if (ctx.start.ai_next) {
+ *(struct addrinfo **)cbrv = _mdns_addrinfo_done(&ctx);
+
+ return NS_SUCCESS;
+ } else {
+ return NS_NOTFOUND;
+ }
+}
+
+
+
+static int
+_mdns_gethtbyaddr(void *cbrv, void *cbdata, va_list ap)
+{
+ const unsigned char *addr;
+ int addrlen, af;
+ char qbuf[NS_MAXDNAME + 1], *qp, *ep;
+ int advance, n;
+ DNSServiceErrorType err;
+ DNSServiceRef sdRef;
+
+ UNUSED(cbdata);
+
+ addr = va_arg(ap, unsigned char *);
+ addrlen = va_arg(ap, int);
+ af = va_arg(ap, int);
+
+ //XXX Check if in valid address space
+
+ switch (af) {
+ case AF_INET:
+ (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
+ (addr[3] & 0xff), (addr[2] & 0xff),
+ (addr[1] & 0xff), (addr[0] & 0xff));
+ break;
+
+ case AF_INET6:
+ qp = qbuf;
+ ep = qbuf + sizeof(qbuf) - 1;
+ for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+ advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
+ addr[n] & 0xf,
+ ((unsigned int)addr[n] >> 4) & 0xf);
+ if (advance > 0 && qp + advance < ep)
+ qp += advance;
+ else {
+ h_errno = NETDB_INTERNAL;
+ return NS_NOTFOUND;
+ }
+ }
+ if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
+ h_errno = NETDB_INTERNAL;
+ return NS_NOTFOUND;
+ }
+ break;
+
+ default:
+ h_errno = NETDB_INTERNAL;
+ return NS_NOTFOUND;
+ }
+
+ _mdns_hostent_init(&h_ctx, af, addrlen);
+ _mdns_hostent_add_addr(&h_ctx, addr, addrlen);
+
+ err = DNSServiceQueryRecord(
+ &sdRef,
+ kDNSServiceFlagsForceMulticast,
+ kDNSServiceInterfaceIndexAny,
+ qbuf,
+ kDNSServiceType_PTR,
+ kDNSServiceClass_IN,
+ _mdns_hostent_cb,
+ &h_ctx
+ );
+
+ if (err) {
+ h_errno = NETDB_INTERNAL;
+ return NS_UNAVAIL;
+ }
+
+ _mdns_eventloop(sdRef, (void *)&h_ctx);
+
+ DNSServiceRefDeallocate(sdRef);
+
+ if (h_ctx.naliases) {
+ *(struct hostent **)cbrv = _mdns_hostent_done(&h_ctx);
+
+ return NS_SUCCESS;
+ } else {
+ return NS_NOTFOUND;
+ }
+}
+
+
+
+static int
+_mdns_gethtbyname(void *cbrv, void *cbdata, va_list ap)
+{
+ const char *name;
+ int namelen, af, addrlen, rrtype;
+ DNSServiceErrorType err;
+ DNSServiceRef sdRef;
+
+ UNUSED(cbdata);
+
+ name = va_arg(ap, char *);
+ namelen = va_arg(ap, int);
+ af = va_arg(ap, int);
+
+ UNUSED(namelen);
+
+ //XXX Check if in valid name space
+
+ switch (af) {
+ case AF_INET:
+ rrtype = kDNSServiceType_A;
+ addrlen = 4;
+ break;
+
+ case AF_INET6:
+ rrtype = kDNSServiceType_AAAA;
+ addrlen = 16;
+ break;
+
+ default:
+ h_errno = NETDB_INTERNAL;
+ return NS_NOTFOUND;
+ }
+
+ _mdns_hostent_init(&h_ctx, af, addrlen);
+ _mdns_hostent_add_host(&h_ctx, name);
+
+ err = DNSServiceQueryRecord(
+ &sdRef,
+ kDNSServiceFlagsForceMulticast,
+ kDNSServiceInterfaceIndexAny,
+ name,
+ rrtype,
+ kDNSServiceClass_IN,
+ _mdns_hostent_cb,
+ &h_ctx
+ );
+
+ if (err) {
+ h_errno = NETDB_INTERNAL;
+ return NS_UNAVAIL;
+ }
+
+ _mdns_eventloop(sdRef, (void *)&h_ctx);
+
+ DNSServiceRefDeallocate(sdRef);
+
+ if (h_ctx.naddrs) {
+ *(struct hostent **)cbrv = _mdns_hostent_done(&h_ctx);
+
+ return NS_SUCCESS;
+ } else {
+ return NS_NOTFOUND;
+ }
+}
+
+
+
+static void
+_mdns_addrinfo_init(addrinfo_ctx *ctx, const struct addrinfo *ai)
+{
+ ctx->cb_ctx.done = 0;
+ ctx->start = *ai;
+ ctx->start.ai_next = NULL;
+ ctx->start.ai_canonname = NULL;
+ ctx->last = &(ctx->start);
+}
+
+
+
+static void
+_mdns_addrinfo_add_ai(addrinfo_ctx *ctx, struct addrinfo *ai)
+{
+ ctx->last->ai_next = ai;
+ while (ctx->last->ai_next)
+ ctx->last = ctx->last->ai_next;
+}
+
+
+
+static struct addrinfo *
+_mdns_addrinfo_done(addrinfo_ctx *ctx)
+{
+ struct addrinfo head, *t, *p;
+
+ /* sort v6 up */
+
+ t = &head;
+ p = &(ctx->start);
+
+ while (p->ai_next) {
+ if (p->ai_next->ai_family == AF_INET6) {
+ t->ai_next = p->ai_next;
+ t = t->ai_next;
+ p->ai_next = p->ai_next->ai_next;
+ } else {
+ p = p->ai_next;
+ }
+ }
+
+ /* add rest of list and reset start to the new list*/
+ t->ai_next = ctx->start.ai_next;
+ ctx->start.ai_next = head.ai_next;
+
+ return ctx->start.ai_next;
+}
+
+
+
+static void
+_mdns_hostent_init(hostent_ctx *ctx, int af, int addrlen)
+{
+ int i;
+
+ ctx->cb_ctx.done = ctx->naliases = ctx->naddrs = 0;
+ ctx->next = ctx->buf;
+
+ ctx->host.h_aliases = ctx->host_aliases;
+ ctx->host.h_addr_list = ctx->h_addr_ptrs;
+ ctx->host.h_name = ctx->host.h_aliases[0] = NULL;
+ ctx->host.h_addrtype = af;
+ ctx->host.h_length = addrlen;
+
+ for (i = 0; i < MAXADDRS; i++) {
+ ctx->host.h_addr_list[i] = &(ctx->addrs[i * 16]);
+ }
+}
+
+
+
+static void
+_mdns_hostent_add_host(hostent_ctx *ctx, const char *name)
+{
+ size_t len = strlen(name);
+
+ if (name && (HCTX_BUFLEFT(ctx) > len) && (ctx->naliases < MAXALIASES)) {
+ /* skip dupe names */
+ if ((ctx->host.h_name) && !strcmp(ctx->host.h_name, name)) {
+ return;
+ }
+
+ strcpy(ctx->next, name);
+ if (ctx->naliases == 0) {
+ ctx->host.h_name = ctx->next;
+ } else {
+ ctx->host.h_aliases[ctx->naliases - 1] = ctx->next;
+ }
+
+ ctx->next += (len + 1);
+ ctx->naliases++;
+ } /* else silently ignore */
+}
+
+
+
+static void
+_mdns_hostent_add_addr(hostent_ctx *ctx, const void *addr, uint16_t len)
+{
+ if ((len == ctx->host.h_length) && (ctx->naddrs < MAXADDRS)) {
+ memcpy(ctx->host.h_addr_list[ctx->naddrs++], addr, (size_t)len);
+ } /* else wrong address type or out of room... silently skip */
+}
+
+
+
+static struct hostent *
+_mdns_hostent_done(hostent_ctx *ctx)
+{
+ if (ctx->naliases) {
+ /* terminate array */
+ ctx->host.h_aliases[ctx->naliases - 1] = NULL;
+ ctx->host.h_addr_list[ctx->naddrs] = NULL;
+ }
+
+ return &(ctx->host);
+}
+
+
+
+static void
+_mdns_addrinfo_cb(
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *hostname,
+ const struct sockaddr *address,
+ uint32_t ttl,
+ void *context
+) {
+ addrinfo_ctx *ctx = context;
+ struct addrinfo *ai;
+
+ UNUSED(sdRef);
+ UNUSED(interfaceIndex);
+ UNUSED(hostname);
+ UNUSED(ttl);
+
+ if (errorCode == kDNSServiceErr_NoError) {
+ if (! (flags & kDNSServiceFlagsMoreComing)) {
+ ctx->cb_ctx.done = 1;
+ }
+
+ ai = allocaddrinfo((socklen_t)(address->sa_len));
+ if (ai) {
+ ai->ai_flags = ctx->start.ai_flags;
+ ai->ai_family = address->sa_family;
+ ai->ai_socktype = ctx->start.ai_socktype;
+ ai->ai_protocol = ctx->start.ai_protocol;
+ memcpy(ai->ai_addr, address, (size_t)(address->sa_len));
+
+ //XXX canonname?
+ _mdns_addrinfo_add_ai(ctx, ai);
+ }
+ }
+}
+
+
+
+static void
+_mdns_hostent_cb(
+ 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
+) {
+ hostent_ctx *ctx = (hostent_ctx *)context;
+ char buf[NS_MAXDNAME+1];
+
+ UNUSED(sdRef);
+ UNUSED(interfaceIndex);
+ UNUSED(rrclass);
+ UNUSED(ttl);
+
+ if (! (flags & kDNSServiceFlagsMoreComing)) {
+ ctx->cb_ctx.done = 1;
+ }
+
+ if (errorCode == kDNSServiceErr_NoError) {
+ switch (rrtype) {
+ case kDNSServiceType_PTR:
+ if (!_mdns_rdata2name(rdata, rdlen, buf, sizeof(buf))) {
+ /* corrupt response -- skip */
+ return;
+ }
+
+ _mdns_hostent_add_host(ctx, buf);
+ break;
+
+ case kDNSServiceType_A:
+ if (ctx->host.h_addrtype == AF_INET) {
+ _mdns_hostent_add_host(ctx, fullname);
+ _mdns_hostent_add_addr(ctx, rdata, rdlen);
+ }
+ break;
+
+ case kDNSServiceType_AAAA:
+ if (ctx->host.h_addrtype == AF_INET6) {
+ _mdns_hostent_add_host(ctx, fullname);
+ _mdns_hostent_add_addr(ctx, rdata, rdlen);
+ }
+ break;
+ }
+ }
+}
+
+
+
+static void
+_mdns_eventloop(DNSServiceRef sdRef, callback_ctx *ctx)
+{
+ struct pollfd fds;
+ int fd, ret;
+
+ fd = DNSServiceRefSockFD(sdRef);
+ fds.fd = fd;
+ fds.events = POLLRDNORM;
+
+ while (!ctx->done) {
+ ret = poll(&fds, 1, 500);
+ if (ret > 0) {
+ DNSServiceProcessResult(sdRef);
+ } else {
+ break;
+ }
+ }
+}
+
+
+
+static char *
+_mdns_rdata2name(const unsigned char *rdata, uint16_t rdlen, char *buf, size_t buflen)
+{
+ unsigned char l;
+ char *r = buf;
+
+ /* illegal 0-size answer or not enough room for even "." */
+ if ((!rdlen) || (rdlen < 2)) {
+ return NULL;
+ }
+
+ buflen--; /* reserve space for terminating NUL now */
+
+ /* special case empty as "." */
+ if ((rdlen == 1) && (!*rdata)) {
+ strcpy(buf, ".");
+
+ return r;
+ }
+
+ while (rdlen && *rdata) {
+ /* label length byte */
+ l = *rdata++; rdlen--;
+
+ if (l > 63) {
+ /* compression or bitstrings -- shouldn't happen */
+ return NULL;
+ } else if (l > buflen) {
+ /* not enough space */
+ return NULL;
+ } else if (l > rdlen) {
+ /* label shouldn't be longer than remaining rdata */
+ return NULL;
+ } else if (!l) {
+ /* empty label -- should be done */
+ if (rdlen) {
+ /* but more left!? */
+ return NULL;
+ } else {
+ break;
+ }
+ }
+
+ memcpy(buf, rdata, (size_t)l);
+ rdata += l; buf += l;
+ rdlen -= l; buflen -= l;
+
+ /* Another label to come? add a separator */
+ if (rdlen && *rdata) {
+ if (!buflen) {
+ return NULL;
+ }
+
+ *buf++ = '.'; buflen--;
+ }
+ }
+
+ /* we reserved space above, so we know we have space
+ to add this termination */
+
+ *buf = '\0';
+
+ return r;
+}