xref: /titanic_44/usr/src/lib/nsswitch/mdns/common/mdns_common.c (revision 4b22b9337f359bfd063322244f5336cc7c6ffcfa)
1*4b22b933Srs200217 /*
2*4b22b933Srs200217  * CDDL HEADER START
3*4b22b933Srs200217  *
4*4b22b933Srs200217  * The contents of this file are subject to the terms of the
5*4b22b933Srs200217  * Common Development and Distribution License (the "License").
6*4b22b933Srs200217  * You may not use this file except in compliance with the License.
7*4b22b933Srs200217  *
8*4b22b933Srs200217  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4b22b933Srs200217  * or http://www.opensolaris.org/os/licensing.
10*4b22b933Srs200217  * See the License for the specific language governing permissions
11*4b22b933Srs200217  * and limitations under the License.
12*4b22b933Srs200217  *
13*4b22b933Srs200217  * When distributing Covered Code, include this CDDL HEADER in each
14*4b22b933Srs200217  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4b22b933Srs200217  * If applicable, add the following below this CDDL HEADER, with the
16*4b22b933Srs200217  * fields enclosed by brackets "[]" replaced with your own identifying
17*4b22b933Srs200217  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4b22b933Srs200217  *
19*4b22b933Srs200217  * CDDL HEADER END
20*4b22b933Srs200217  */
21*4b22b933Srs200217 
22*4b22b933Srs200217 /*
23*4b22b933Srs200217  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*4b22b933Srs200217  * Use is subject to license terms.
25*4b22b933Srs200217  */
26*4b22b933Srs200217 
27*4b22b933Srs200217 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*4b22b933Srs200217 
29*4b22b933Srs200217 #include "mdns_common.h"
30*4b22b933Srs200217 
31*4b22b933Srs200217 static int _nss_mdns_queryrecord(const char *rrname, int rrclass, int rrtype,
32*4b22b933Srs200217 		DNSServiceQueryRecordReply callback,
33*4b22b933Srs200217 		struct mdns_querydata *data);
34*4b22b933Srs200217 static void _nss_mdns_get_svcstatetimestamp(struct timeval *);
35*4b22b933Srs200217 static void _nss_mdns_loadsmfcfg(mdns_backend_ptr_t);
36*4b22b933Srs200217 static void _nss_mdns_freesmfcfg(mdns_backend_ptr_t);
37*4b22b933Srs200217 static boolean_t cmpdmn(char *, char **, int);
38*4b22b933Srs200217 static char *RDataToName(char *data, char *buffer, int datalen, int buflen);
39*4b22b933Srs200217 static int searchdomain(mdns_backend_ptr_t, char *, int, char **);
40*4b22b933Srs200217 static boolean_t validdomain(mdns_backend_ptr_t, char *, int);
41*4b22b933Srs200217 
42*4b22b933Srs200217 /*
43*4b22b933Srs200217  * This file includes the functions to query for host name
44*4b22b933Srs200217  * information via Multicast DNS (mDNS). The function
45*4b22b933Srs200217  * _nss_mdns_queryrecord queries for the host information via
46*4b22b933Srs200217  * Multicast DNS. _nss_mdns_querybyname and _nss_mdns_querybyaddr
47*4b22b933Srs200217  * query for host IP address and hostname by querying for A/AAAA
48*4b22b933Srs200217  * and PTR DNS resource records respectively. DNSServiceQueryRecord
49*4b22b933Srs200217  * in libdns_sd sends a request to the mDNS daemon (mdnsd) to place
50*4b22b933Srs200217  * the DNS query via multicast and return the results.
51*4b22b933Srs200217  * mdnsd is managed by SMF (FMRI: svc:/network/dns/multicast:default).
52*4b22b933Srs200217  *
53*4b22b933Srs200217  * gethostent.c and gethostent6.c implement the nsswitch 'hosts'
54*4b22b933Srs200217  * backend module getXbyY functions: getbyname and getbyaddr.
55*4b22b933Srs200217  * getby* functions in gethostent.c  supports only IPv4 and
56*4b22b933Srs200217  * getby* functions in gethostent6.c returns both IPv4 and
57*4b22b933Srs200217  * IPv6 results. Functions in gethostent.c and gethostent6.c
58*4b22b933Srs200217  * call the _nss_mdns_queryby* functions in mdns_common.c to
59*4b22b933Srs200217  * query for host information via mDNS.
60*4b22b933Srs200217  *
61*4b22b933Srs200217  * Configuration for mdns is stored in SMF and is accessed using
62*4b22b933Srs200217  * the FMRI: svc:/network/dns/multicast:default. Configuration
63*4b22b933Srs200217  * includes the list of valid DNS domains checked before querying host
64*4b22b933Srs200217  * information via mDNS and the search list to use for host lookup via
65*4b22b933Srs200217  * mDNS. The default valid domain list in the mDNS service supports host
66*4b22b933Srs200217  * lookups for hostnames in the ".local" domain and hostname queries
67*4b22b933Srs200217  * for link-local IPv4 and IPv6 addresses. _nss_mdns_loadsmfcfg
68*4b22b933Srs200217  * loads the nss_mdns configuration from SMF and the function
69*4b22b933Srs200217  * _nss_mdns_updatecfg checks for any updates in nss_mdns configuration.
70*4b22b933Srs200217  */
71*4b22b933Srs200217 
72*4b22b933Srs200217 static int
_nss_mdns_queryrecord(const char * rrname,int rrclass,int rrtype,DNSServiceQueryRecordReply callback,struct mdns_querydata * data)73*4b22b933Srs200217 _nss_mdns_queryrecord(const char *rrname, int rrclass, int rrtype,
74*4b22b933Srs200217 		DNSServiceQueryRecordReply callback,
75*4b22b933Srs200217 		struct mdns_querydata *data)
76*4b22b933Srs200217 {
77*4b22b933Srs200217 	int sockfd;
78*4b22b933Srs200217 	int flags = kDNSServiceFlagsForceMulticast;  /* Multicast only */
79*4b22b933Srs200217 	int opinterface = kDNSServiceInterfaceIndexAny;
80*4b22b933Srs200217 	DNSServiceErrorType err;
81*4b22b933Srs200217 	DNSServiceRef ref = NULL;
82*4b22b933Srs200217 	int ret;
83*4b22b933Srs200217 	struct fd_set readfds;
84*4b22b933Srs200217 	struct timeval tv;
85*4b22b933Srs200217 
86*4b22b933Srs200217 	data->status = NSS_NOTFOUND;
87*4b22b933Srs200217 #ifdef DEBUG
88*4b22b933Srs200217 	syslog(LOG_DEBUG, "nss_mdns: query called rrname:%s rrtype:%d",
89*4b22b933Srs200217 	    rrname, rrtype);
90*4b22b933Srs200217 #endif
91*4b22b933Srs200217 	err = DNSServiceQueryRecord(&ref, flags, opinterface,
92*4b22b933Srs200217 	    rrname, rrtype, rrclass, callback, data);
93*4b22b933Srs200217 	if (err != kDNSServiceErr_NoError || ref == NULL ||
94*4b22b933Srs200217 	    (sockfd = DNSServiceRefSockFD(ref)) == NULL) {
95*4b22b933Srs200217 		DNSServiceRefDeallocate(ref);
96*4b22b933Srs200217 		data->status = NSS_UNAVAIL;
97*4b22b933Srs200217 		return (NSS_UNAVAIL);
98*4b22b933Srs200217 	}
99*4b22b933Srs200217 
100*4b22b933Srs200217 	do {
101*4b22b933Srs200217 		FD_ZERO(&readfds);
102*4b22b933Srs200217 		FD_SET(sockfd, &readfds);
103*4b22b933Srs200217 		tv.tv_sec = NSSMDNS_MAXQRYTMO;
104*4b22b933Srs200217 		tv.tv_usec = 0;
105*4b22b933Srs200217 
106*4b22b933Srs200217 		/* Wait until response received from mDNS daemon */
107*4b22b933Srs200217 		ret = select(sockfd + 1, &readfds, NULL, NULL, &tv);
108*4b22b933Srs200217 		if (!((ret > 0) && FD_ISSET(sockfd, &readfds) &&
109*4b22b933Srs200217 		    (DNSServiceProcessResult(ref) == kDNSServiceErr_NoError))) {
110*4b22b933Srs200217 			data->status = NSS_NOTFOUND;
111*4b22b933Srs200217 			if (errno != EINTR)
112*4b22b933Srs200217 				data->qrydone = B_TRUE;
113*4b22b933Srs200217 		}
114*4b22b933Srs200217 	} while (data->qrydone != B_TRUE);
115*4b22b933Srs200217 
116*4b22b933Srs200217 	if (data->status == NSS_SUCCESS && (data->withttlbuffer == NULL)) {
117*4b22b933Srs200217 		nss_XbyY_args_t *argp = data->argp;
118*4b22b933Srs200217 		if (argp->buf.result != NULL) {
119*4b22b933Srs200217 			int stat;
120*4b22b933Srs200217 
121*4b22b933Srs200217 			if (data->buffer == NULL) {
122*4b22b933Srs200217 				data->status = NSS_NOTFOUND;
123*4b22b933Srs200217 				DNSServiceRefDeallocate(ref);
124*4b22b933Srs200217 				return (data->status);
125*4b22b933Srs200217 			}
126*4b22b933Srs200217 			stat = (*argp->str2ent)(data->buffer,
127*4b22b933Srs200217 			    strlen(data->buffer),
128*4b22b933Srs200217 			    argp->buf.result, argp->buf.buffer,
129*4b22b933Srs200217 			    argp->buf.buflen);
130*4b22b933Srs200217 			if (stat == NSS_STR_PARSE_SUCCESS) {
131*4b22b933Srs200217 				argp->returnval = argp->buf.result;
132*4b22b933Srs200217 				argp->returnlen = 1;
133*4b22b933Srs200217 			} else {
134*4b22b933Srs200217 				data->status = NSS_NOTFOUND;
135*4b22b933Srs200217 				if (stat == NSS_STR_PARSE_ERANGE)
136*4b22b933Srs200217 					argp->erange = 1;
137*4b22b933Srs200217 			}
138*4b22b933Srs200217 			free(data->buffer);
139*4b22b933Srs200217 		} else {
140*4b22b933Srs200217 			argp->returnval = argp->buf.buffer;
141*4b22b933Srs200217 			argp->returnlen = strlen(argp->buf.buffer);
142*4b22b933Srs200217 		}
143*4b22b933Srs200217 		data->buffer = NULL;
144*4b22b933Srs200217 		data->buflen = 0;
145*4b22b933Srs200217 	}
146*4b22b933Srs200217 
147*4b22b933Srs200217 	if (data->status != NSS_SUCCESS)
148*4b22b933Srs200217 		data->argp->h_errno = HOST_NOT_FOUND;
149*4b22b933Srs200217 
150*4b22b933Srs200217 	DNSServiceRefDeallocate(ref);
151*4b22b933Srs200217 	return (data->status);
152*4b22b933Srs200217 }
153*4b22b933Srs200217 
154*4b22b933Srs200217 static void
155*4b22b933Srs200217 /* LINTED E_FUNC_ARG_UNUSED */
_nss_mdns_querynamereply(DNSServiceRef sdRef,const DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullname,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata,uint32_t ttl,void * context)156*4b22b933Srs200217 _nss_mdns_querynamereply(DNSServiceRef sdRef, const DNSServiceFlags flags,
157*4b22b933Srs200217 		/* LINTED E_FUNC_ARG_UNUSED */
158*4b22b933Srs200217 		uint32_t ifIndex, DNSServiceErrorType errorCode,
159*4b22b933Srs200217 		const char *fullname, uint16_t rrtype, uint16_t rrclass,
160*4b22b933Srs200217 		/* LINTED E_FUNC_ARG_UNUSED */
161*4b22b933Srs200217 		uint16_t rdlen, const void *rdata, uint32_t ttl,
162*4b22b933Srs200217 		void *context)
163*4b22b933Srs200217 {
164*4b22b933Srs200217 	struct mdns_querydata *qdata;
165*4b22b933Srs200217 	nss_XbyY_args_t *argp;
166*4b22b933Srs200217 	int firstent = 0;
167*4b22b933Srs200217 	int af;
168*4b22b933Srs200217 	char addrstore[INET6_ADDRSTRLEN];
169*4b22b933Srs200217 	char *buffer;
170*4b22b933Srs200217 	int len;
171*4b22b933Srs200217 	int remlen;
172*4b22b933Srs200217 
173*4b22b933Srs200217 	qdata = (struct mdns_querydata *)context;
174*4b22b933Srs200217 	argp = qdata->argp;
175*4b22b933Srs200217 
176*4b22b933Srs200217 	if (errorCode != kDNSServiceErr_NoError) {
177*4b22b933Srs200217 		qdata->qrydone = B_TRUE;
178*4b22b933Srs200217 		return;
179*4b22b933Srs200217 	}
180*4b22b933Srs200217 	if ((flags & kDNSServiceFlagsMoreComing))
181*4b22b933Srs200217 		qdata->qrydone = B_FALSE;
182*4b22b933Srs200217 	else
183*4b22b933Srs200217 		qdata->qrydone = B_TRUE;
184*4b22b933Srs200217 	if (!(flags & kDNSServiceFlagsAdd))
185*4b22b933Srs200217 		return;
186*4b22b933Srs200217 	if (rrclass != kDNSServiceClass_IN)
187*4b22b933Srs200217 		return;
188*4b22b933Srs200217 
189*4b22b933Srs200217 	if (rrtype == kDNSServiceType_A)
190*4b22b933Srs200217 		af = AF_INET;
191*4b22b933Srs200217 	else if (rrtype == kDNSServiceType_AAAA)
192*4b22b933Srs200217 		af = AF_INET6;
193*4b22b933Srs200217 	else
194*4b22b933Srs200217 		return;
195*4b22b933Srs200217 
196*4b22b933Srs200217 	if (qdata->buffer == NULL) {
197*4b22b933Srs200217 		if (qdata->withttlbsize > 0) {
198*4b22b933Srs200217 			remlen = qdata->buflen =
199*4b22b933Srs200217 			    qdata->withttlbsize;
200*4b22b933Srs200217 			buffer = qdata->buffer =
201*4b22b933Srs200217 			    qdata->withttlbuffer;
202*4b22b933Srs200217 			(void) memset(qdata->buffer, 0, remlen);
203*4b22b933Srs200217 		} else {
204*4b22b933Srs200217 			remlen = qdata->buflen =
205*4b22b933Srs200217 			    argp->buf.buflen;
206*4b22b933Srs200217 			if (argp->buf.result != NULL) {
207*4b22b933Srs200217 				buffer = qdata->buffer =
208*4b22b933Srs200217 				    calloc(1, remlen);
209*4b22b933Srs200217 			} else {
210*4b22b933Srs200217 				/* Return in file format */
211*4b22b933Srs200217 				(void) memset(argp->buf.buffer,
212*4b22b933Srs200217 				    0, remlen);
213*4b22b933Srs200217 				buffer = qdata->buffer = argp->buf.buffer;
214*4b22b933Srs200217 			}
215*4b22b933Srs200217 		}
216*4b22b933Srs200217 		firstent = 1;
217*4b22b933Srs200217 	} else {
218*4b22b933Srs200217 		buffer = qdata->buffer + strlen(qdata->buffer);
219*4b22b933Srs200217 		remlen = qdata->buflen - strlen(qdata->buffer);
220*4b22b933Srs200217 	}
221*4b22b933Srs200217 
222*4b22b933Srs200217 #ifdef DEBUG
223*4b22b933Srs200217 	syslog(LOG_DEBUG, "nss_mdns: querynamereply remlen:%d", remlen);
224*4b22b933Srs200217 #endif
225*4b22b933Srs200217 	if (inet_ntop(af, rdata, addrstore, INET6_ADDRSTRLEN) != NULL) {
226*4b22b933Srs200217 		if (firstent)
227*4b22b933Srs200217 			len = snprintf(buffer, remlen, "%s %s",
228*4b22b933Srs200217 			    addrstore, fullname);
229*4b22b933Srs200217 		else
230*4b22b933Srs200217 			len = snprintf(buffer, remlen, "\n%s %s",
231*4b22b933Srs200217 			    addrstore, fullname);
232*4b22b933Srs200217 		if (len >= remlen || len < 0) {
233*4b22b933Srs200217 			qdata->status = NSS_NOTFOUND;
234*4b22b933Srs200217 			qdata->argp->erange = 1;
235*4b22b933Srs200217 			qdata->argp->h_errno = HOST_NOT_FOUND;
236*4b22b933Srs200217 			return;
237*4b22b933Srs200217 		}
238*4b22b933Srs200217 		qdata->ttl	= ttl;
239*4b22b933Srs200217 		qdata->status	= NSS_SUCCESS;
240*4b22b933Srs200217 #ifdef DEBUG
241*4b22b933Srs200217 		syslog(LOG_DEBUG, "nss_mdns: querynamereply buffer:%s", buffer);
242*4b22b933Srs200217 #endif
243*4b22b933Srs200217 	} else {
244*4b22b933Srs200217 		qdata->status = NSS_NOTFOUND;
245*4b22b933Srs200217 		qdata->argp->h_errno = HOST_NOT_FOUND;
246*4b22b933Srs200217 	}
247*4b22b933Srs200217 }
248*4b22b933Srs200217 
249*4b22b933Srs200217 int
_nss_mdns_querybyname(mdns_backend_ptr_t be,char * qname,int af,struct mdns_querydata * data)250*4b22b933Srs200217 _nss_mdns_querybyname(mdns_backend_ptr_t be, char *qname,
251*4b22b933Srs200217 		int af, struct mdns_querydata *data)
252*4b22b933Srs200217 {
253*4b22b933Srs200217 	int rrtype;
254*4b22b933Srs200217 	int rrclass;
255*4b22b933Srs200217 	int srchidx = 0;
256*4b22b933Srs200217 	int rc;
257*4b22b933Srs200217 	char hname[MAXDNAME];
258*4b22b933Srs200217 	char *name;
259*4b22b933Srs200217 	char *sname;
260*4b22b933Srs200217 
261*4b22b933Srs200217 	rrclass = kDNSServiceClass_IN;
262*4b22b933Srs200217 	if (af == AF_INET6)
263*4b22b933Srs200217 		rrtype = kDNSServiceType_ANY;
264*4b22b933Srs200217 	else if (af == AF_INET)
265*4b22b933Srs200217 		rrtype = kDNSServiceType_A;
266*4b22b933Srs200217 	else
267*4b22b933Srs200217 		return (NSS_NOTFOUND);
268*4b22b933Srs200217 
269*4b22b933Srs200217 	name = strdup(qname);
270*4b22b933Srs200217 	if (name == NULL)
271*4b22b933Srs200217 		return (NSS_UNAVAIL);
272*4b22b933Srs200217 
273*4b22b933Srs200217 	while ((srchidx = searchdomain(be, name, srchidx, &sname)) != -1) {
274*4b22b933Srs200217 		if (sname != NULL)
275*4b22b933Srs200217 			(void) snprintf(hname, sizeof (hname), "%s.%s",
276*4b22b933Srs200217 			    name, sname);
277*4b22b933Srs200217 		else
278*4b22b933Srs200217 			(void) strlcpy(hname, name, sizeof (hname));
279*4b22b933Srs200217 #ifdef DEBUG
280*4b22b933Srs200217 	syslog(LOG_DEBUG, "nss_mdns: querybyname called" \
281*4b22b933Srs200217 	    " srchidx:%d af:%d hname:%s", srchidx, af, qname);
282*4b22b933Srs200217 #endif
283*4b22b933Srs200217 		rc = _nss_mdns_queryrecord(hname, rrclass, rrtype,
284*4b22b933Srs200217 		    _nss_mdns_querynamereply, data);
285*4b22b933Srs200217 		if ((rc == NSS_UNAVAIL) || (rc == NSS_SUCCESS)) {
286*4b22b933Srs200217 			free(name);
287*4b22b933Srs200217 			return (rc);
288*4b22b933Srs200217 		}
289*4b22b933Srs200217 	}
290*4b22b933Srs200217 	free(name);
291*4b22b933Srs200217 	return (NSS_NOTFOUND);
292*4b22b933Srs200217 }
293*4b22b933Srs200217 
294*4b22b933Srs200217 static void
295*4b22b933Srs200217 /* LINTED E_FUNC_ARG_UNUSED */
_nss_mdns_queryaddrreply(DNSServiceRef sdRef,const DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullname,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata,uint32_t ttl,void * context)296*4b22b933Srs200217 _nss_mdns_queryaddrreply(DNSServiceRef sdRef, const DNSServiceFlags flags,
297*4b22b933Srs200217 		/* LINTED E_FUNC_ARG_UNUSED */
298*4b22b933Srs200217 		uint32_t ifIndex, DNSServiceErrorType errorCode,
299*4b22b933Srs200217 		/* LINTED E_FUNC_ARG_UNUSED */
300*4b22b933Srs200217 		const char *fullname, uint16_t rrtype, uint16_t rrclass,
301*4b22b933Srs200217 		uint16_t rdlen, const void *rdata, uint32_t ttl,
302*4b22b933Srs200217 		void *context)
303*4b22b933Srs200217 {
304*4b22b933Srs200217 	struct mdns_querydata *qdata;
305*4b22b933Srs200217 	nss_XbyY_args_t *argp;
306*4b22b933Srs200217 	char hostname[NI_MAXHOST];
307*4b22b933Srs200217 	int firstent = 0;
308*4b22b933Srs200217 	char *buffer;
309*4b22b933Srs200217 	int len;
310*4b22b933Srs200217 	int remlen;
311*4b22b933Srs200217 
312*4b22b933Srs200217 	qdata = (struct mdns_querydata *)context;
313*4b22b933Srs200217 	argp = qdata->argp;
314*4b22b933Srs200217 
315*4b22b933Srs200217 	if (errorCode != kDNSServiceErr_NoError) {
316*4b22b933Srs200217 		qdata->qrydone = B_TRUE;
317*4b22b933Srs200217 		return;
318*4b22b933Srs200217 	}
319*4b22b933Srs200217 	if ((flags & kDNSServiceFlagsMoreComing))
320*4b22b933Srs200217 		qdata->qrydone = B_FALSE;
321*4b22b933Srs200217 	else
322*4b22b933Srs200217 		qdata->qrydone = B_TRUE;
323*4b22b933Srs200217 	if (!(flags & kDNSServiceFlagsAdd))
324*4b22b933Srs200217 		return;
325*4b22b933Srs200217 	if (rrclass != kDNSServiceClass_IN)
326*4b22b933Srs200217 		return;
327*4b22b933Srs200217 	if (rrtype != kDNSServiceType_PTR)
328*4b22b933Srs200217 		return;
329*4b22b933Srs200217 
330*4b22b933Srs200217 	if (qdata->buffer == NULL) {
331*4b22b933Srs200217 		remlen = qdata->buflen = argp->buf.buflen;
332*4b22b933Srs200217 		if (argp->buf.result != NULL) {
333*4b22b933Srs200217 			buffer = qdata->buffer = calloc(1, remlen);
334*4b22b933Srs200217 		} else {
335*4b22b933Srs200217 			/* Return in file format */
336*4b22b933Srs200217 			(void) memset(argp->buf.buffer, 0, remlen);
337*4b22b933Srs200217 			buffer = qdata->buffer = argp->buf.buffer;
338*4b22b933Srs200217 		}
339*4b22b933Srs200217 		firstent = 1;
340*4b22b933Srs200217 	} else {
341*4b22b933Srs200217 		buffer = qdata->buffer + strlen(qdata->buffer);
342*4b22b933Srs200217 		remlen = qdata->buflen - strlen(qdata->buffer);
343*4b22b933Srs200217 	}
344*4b22b933Srs200217 
345*4b22b933Srs200217 	if (RDataToName((char *)rdata, hostname, rdlen, NI_MAXHOST) == NULL) {
346*4b22b933Srs200217 		qdata->status = NSS_NOTFOUND;
347*4b22b933Srs200217 		qdata->argp->h_errno = HOST_NOT_FOUND;
348*4b22b933Srs200217 		return;
349*4b22b933Srs200217 	}
350*4b22b933Srs200217 
351*4b22b933Srs200217 #ifdef DEBUG
352*4b22b933Srs200217 	syslog(LOG_DEBUG, "nss_mdns: querynamereply remlen:%d", remlen);
353*4b22b933Srs200217 #endif
354*4b22b933Srs200217 	if (firstent)
355*4b22b933Srs200217 		len = snprintf(buffer, remlen, "%s %s",
356*4b22b933Srs200217 		    qdata->paddrbuf, hostname);
357*4b22b933Srs200217 	else
358*4b22b933Srs200217 		len = snprintf(buffer, remlen, "\n%s %s",
359*4b22b933Srs200217 		    qdata->paddrbuf, hostname);
360*4b22b933Srs200217 	if (len >= remlen || len < 0) {
361*4b22b933Srs200217 		qdata->status = NSS_NOTFOUND;
362*4b22b933Srs200217 		qdata->argp->erange = 1;
363*4b22b933Srs200217 		qdata->argp->h_errno = HOST_NOT_FOUND;
364*4b22b933Srs200217 		return;
365*4b22b933Srs200217 	}
366*4b22b933Srs200217 	qdata->status	= NSS_SUCCESS;
367*4b22b933Srs200217 	qdata->ttl	= ttl;
368*4b22b933Srs200217 }
369*4b22b933Srs200217 
370*4b22b933Srs200217 int
371*4b22b933Srs200217 /* LINTED E_FUNC_ARG_UNUSED */
_nss_mdns_querybyaddr(mdns_backend_ptr_t be,char * name,int af,struct mdns_querydata * data)372*4b22b933Srs200217 _nss_mdns_querybyaddr(mdns_backend_ptr_t be, char *name, int af,
373*4b22b933Srs200217 		struct mdns_querydata *data)
374*4b22b933Srs200217 {
375*4b22b933Srs200217 	int rrtype;
376*4b22b933Srs200217 	int rrclass;
377*4b22b933Srs200217 
378*4b22b933Srs200217 #ifdef DEBUG
379*4b22b933Srs200217 	syslog(LOG_DEBUG, "nss_mdns: querybyaddr called" \
380*4b22b933Srs200217 	    " af:%d addr:%s", af, name);
381*4b22b933Srs200217 #endif
382*4b22b933Srs200217 	rrclass = kDNSServiceClass_IN;
383*4b22b933Srs200217 	rrtype = kDNSServiceType_PTR;
384*4b22b933Srs200217 
385*4b22b933Srs200217 	if (validdomain(be, name, 0) == B_FALSE) {
386*4b22b933Srs200217 		data->status = NSS_NOTFOUND;
387*4b22b933Srs200217 		return (NSS_NOTFOUND);
388*4b22b933Srs200217 	}
389*4b22b933Srs200217 	return (_nss_mdns_queryrecord(name, rrclass, rrtype,
390*4b22b933Srs200217 	    _nss_mdns_queryaddrreply, data));
391*4b22b933Srs200217 }
392*4b22b933Srs200217 
393*4b22b933Srs200217 /*
394*4b22b933Srs200217  * Converts the encoded name in RData returned
395*4b22b933Srs200217  * by mDNS query to name in file format
396*4b22b933Srs200217  */
397*4b22b933Srs200217 static char *
RDataToName(char * data,char * buffer,int datalen,int buflen)398*4b22b933Srs200217 RDataToName(char *data, char *buffer, int datalen, int buflen)
399*4b22b933Srs200217 {
400*4b22b933Srs200217 	char *src = data;
401*4b22b933Srs200217 	char *srcend = data + datalen;
402*4b22b933Srs200217 	char *ptr = buffer;
403*4b22b933Srs200217 	char *end;
404*4b22b933Srs200217 	char *bend = buffer + buflen - 1; /* terminal '\0' */
405*4b22b933Srs200217 	int domainlen = 0;
406*4b22b933Srs200217 
407*4b22b933Srs200217 	while ((src < srcend) && (*src != 0)) {
408*4b22b933Srs200217 
409*4b22b933Srs200217 		/* first byte is len */
410*4b22b933Srs200217 		domainlen = *src++;
411*4b22b933Srs200217 		end = src + domainlen;
412*4b22b933Srs200217 
413*4b22b933Srs200217 		while ((src < end) && (ptr < bend)) {
414*4b22b933Srs200217 			uint8_t ch = *src++;
415*4b22b933Srs200217 			if (ch == '.' || ch == '\\') {
416*4b22b933Srs200217 				*ptr++ = '\\';
417*4b22b933Srs200217 			}
418*4b22b933Srs200217 			*ptr++ = ch;
419*4b22b933Srs200217 		}
420*4b22b933Srs200217 
421*4b22b933Srs200217 		/*
422*4b22b933Srs200217 		 * Check if we copied entire domain str. and
423*4b22b933Srs200217 		 * if space is still remaining for '.' seperator
424*4b22b933Srs200217 		 */
425*4b22b933Srs200217 		if ((src != end) || (ptr == bend))
426*4b22b933Srs200217 			return (NULL);
427*4b22b933Srs200217 		*ptr++ = '.';
428*4b22b933Srs200217 	}
429*4b22b933Srs200217 	*ptr = '\0';
430*4b22b933Srs200217 	return (ptr);
431*4b22b933Srs200217 }
432*4b22b933Srs200217 
433*4b22b933Srs200217 nss_backend_t *
_nss_mdns_constr(mdns_backend_op_t ops[],int n_ops)434*4b22b933Srs200217 _nss_mdns_constr(mdns_backend_op_t ops[], int n_ops)
435*4b22b933Srs200217 {
436*4b22b933Srs200217 	mdns_backend_ptr_t	be;
437*4b22b933Srs200217 
438*4b22b933Srs200217 	if ((be = (mdns_backend_ptr_t)calloc(1, sizeof (*be))) == NULL)
439*4b22b933Srs200217 		return (NULL);
440*4b22b933Srs200217 	be->ops = ops;
441*4b22b933Srs200217 	be->n_ops = n_ops;
442*4b22b933Srs200217 	_nss_mdns_updatecfg(be);
443*4b22b933Srs200217 	return ((nss_backend_t *)be);
444*4b22b933Srs200217 }
445*4b22b933Srs200217 
446*4b22b933Srs200217 void
_nss_mdns_destr(mdns_backend_ptr_t be)447*4b22b933Srs200217 _nss_mdns_destr(mdns_backend_ptr_t be)
448*4b22b933Srs200217 {
449*4b22b933Srs200217 	if (be != NULL) {
450*4b22b933Srs200217 		_nss_mdns_freesmfcfg(be);
451*4b22b933Srs200217 		free(be);
452*4b22b933Srs200217 	}
453*4b22b933Srs200217 }
454*4b22b933Srs200217 
455*4b22b933Srs200217 static int
searchdomain(mdns_backend_ptr_t be,char * name,int srchidx,char ** sname)456*4b22b933Srs200217 searchdomain(mdns_backend_ptr_t be, char *name, int srchidx, char **sname)
457*4b22b933Srs200217 {
458*4b22b933Srs200217 	int trailing_dot = 0;
459*4b22b933Srs200217 	char *ch;
460*4b22b933Srs200217 	*sname = NULL;
461*4b22b933Srs200217 
462*4b22b933Srs200217 	ch = name + strlen(name) - 1;
463*4b22b933Srs200217 	if ((*ch) == '.')
464*4b22b933Srs200217 		trailing_dot++;
465*4b22b933Srs200217 
466*4b22b933Srs200217 	if (trailing_dot && srchidx > 0)
467*4b22b933Srs200217 		/*
468*4b22b933Srs200217 		 * If there is a trailing dot in the query
469*4b22b933Srs200217 		 * name, do not perform any additional queries
470*4b22b933Srs200217 		 * with search domains.
471*4b22b933Srs200217 		 */
472*4b22b933Srs200217 		return (-1);
473*4b22b933Srs200217 
474*4b22b933Srs200217 	if (srchidx == 0) {
475*4b22b933Srs200217 		/*
476*4b22b933Srs200217 		 * If there is a trailing dot in the query
477*4b22b933Srs200217 		 * or atleast one dot in the query name then
478*4b22b933Srs200217 		 * perform a query as-is once first.
479*4b22b933Srs200217 		 */
480*4b22b933Srs200217 		++srchidx;
481*4b22b933Srs200217 		if ((trailing_dot || (strchr(name, '.') != NULL))) {
482*4b22b933Srs200217 			if (validdomain(be, name, 1) == B_TRUE)
483*4b22b933Srs200217 				return (srchidx);
484*4b22b933Srs200217 			else if (trailing_dot)
485*4b22b933Srs200217 				return (-1);
486*4b22b933Srs200217 		}
487*4b22b933Srs200217 	}
488*4b22b933Srs200217 
489*4b22b933Srs200217 	if ((srchidx > NSSMDNS_MAXSRCHDMNS) ||
490*4b22b933Srs200217 	    (be->dmnsrchlist[srchidx-1] == NULL))
491*4b22b933Srs200217 		return (-1);
492*4b22b933Srs200217 
493*4b22b933Srs200217 	*sname = be->dmnsrchlist[srchidx-1];
494*4b22b933Srs200217 	return (++srchidx);
495*4b22b933Srs200217 }
496*4b22b933Srs200217 
497*4b22b933Srs200217 /*
498*4b22b933Srs200217  * This function determines if the domain name in the query
499*4b22b933Srs200217  * matches any of the valid & search domains in the nss_mdns
500*4b22b933Srs200217  * configuration.
501*4b22b933Srs200217  */
502*4b22b933Srs200217 static boolean_t
validdomain(mdns_backend_ptr_t be,char * name,int chksrchdmns)503*4b22b933Srs200217 validdomain(mdns_backend_ptr_t be, char *name, int chksrchdmns)
504*4b22b933Srs200217 {
505*4b22b933Srs200217 	char *nameptr;
506*4b22b933Srs200217 
507*4b22b933Srs200217 	/* Remove any trailing and leading dots in the name  */
508*4b22b933Srs200217 	nameptr = name + strlen(name) - 1;
509*4b22b933Srs200217 	while (*nameptr && (nameptr != name) && (*nameptr == '.'))
510*4b22b933Srs200217 		nameptr--;
511*4b22b933Srs200217 	*(++nameptr) = '\0';
512*4b22b933Srs200217 	nameptr = name;
513*4b22b933Srs200217 	while (*nameptr && (*nameptr == '.'))
514*4b22b933Srs200217 		nameptr++;
515*4b22b933Srs200217 	if (*nameptr == '\0')
516*4b22b933Srs200217 		return (B_FALSE);
517*4b22b933Srs200217 
518*4b22b933Srs200217 	/* Compare with search domains */
519*4b22b933Srs200217 	if (chksrchdmns && (cmpdmn(nameptr, be->dmnsrchlist,
520*4b22b933Srs200217 	    NSSMDNS_MAXSRCHDMNS) == B_TRUE))
521*4b22b933Srs200217 		return (B_TRUE);
522*4b22b933Srs200217 
523*4b22b933Srs200217 	/* Compare with valid domains */
524*4b22b933Srs200217 	return (cmpdmn(nameptr, be->validdmnlist, NSSMDNS_MAXVALIDDMNS));
525*4b22b933Srs200217 }
526*4b22b933Srs200217 
527*4b22b933Srs200217 static boolean_t
cmpdmn(char * name,char ** dmnlist,int maxdmns)528*4b22b933Srs200217 cmpdmn(char *name, char **dmnlist, int maxdmns)
529*4b22b933Srs200217 {
530*4b22b933Srs200217 	char *vptr;
531*4b22b933Srs200217 	int vdlen;
532*4b22b933Srs200217 	char *cptr;
533*4b22b933Srs200217 	int nlen;
534*4b22b933Srs200217 	int i;
535*4b22b933Srs200217 
536*4b22b933Srs200217 	nlen = strlen(name);
537*4b22b933Srs200217 	for (i = 0; (i < maxdmns) &&
538*4b22b933Srs200217 	    ((vptr = dmnlist[i]) != NULL); i++) {
539*4b22b933Srs200217 		vdlen = strlen(vptr);
540*4b22b933Srs200217 		if (vdlen > nlen)
541*4b22b933Srs200217 			continue;
542*4b22b933Srs200217 		cptr = name + nlen - vdlen;
543*4b22b933Srs200217 		if (strncasecmp(cptr, vptr, vdlen) == 0)
544*4b22b933Srs200217 			return (B_TRUE);
545*4b22b933Srs200217 	}
546*4b22b933Srs200217 	return (B_FALSE);
547*4b22b933Srs200217 }
548*4b22b933Srs200217 
549*4b22b933Srs200217 static void
_nss_mdns_get_svcstatetimestamp(struct timeval * ptv)550*4b22b933Srs200217 _nss_mdns_get_svcstatetimestamp(struct timeval *ptv)
551*4b22b933Srs200217 {
552*4b22b933Srs200217 	scf_handle_t *h;
553*4b22b933Srs200217 	scf_simple_prop_t *sprop;
554*4b22b933Srs200217 	int32_t nsec;
555*4b22b933Srs200217 
556*4b22b933Srs200217 	(void) memset(ptv, 0, sizeof (struct timeval));
557*4b22b933Srs200217 
558*4b22b933Srs200217 	h = scf_handle_create(SCF_VERSION);
559*4b22b933Srs200217 	if (h == NULL)
560*4b22b933Srs200217 		return;
561*4b22b933Srs200217 
562*4b22b933Srs200217 	if (scf_handle_bind(h) == -1) {
563*4b22b933Srs200217 		scf_handle_destroy(h);
564*4b22b933Srs200217 		return;
565*4b22b933Srs200217 	}
566*4b22b933Srs200217 
567*4b22b933Srs200217 	if ((sprop = scf_simple_prop_get(h, SMF_MDNS_FMRI,
568*4b22b933Srs200217 	    SCF_PG_RESTARTER, SCF_PROPERTY_STATE_TIMESTAMP)) != NULL) {
569*4b22b933Srs200217 		ptv->tv_sec = *(time_t *)(scf_simple_prop_next_time(sprop,
570*4b22b933Srs200217 		    &nsec));
571*4b22b933Srs200217 		ptv->tv_usec = nsec / 1000;
572*4b22b933Srs200217 		scf_simple_prop_free(sprop);
573*4b22b933Srs200217 	}
574*4b22b933Srs200217 
575*4b22b933Srs200217 	if (h != NULL)
576*4b22b933Srs200217 		scf_handle_destroy(h);
577*4b22b933Srs200217 }
578*4b22b933Srs200217 
579*4b22b933Srs200217 void
_nss_mdns_updatecfg(mdns_backend_ptr_t be)580*4b22b933Srs200217 _nss_mdns_updatecfg(mdns_backend_ptr_t be)
581*4b22b933Srs200217 {
582*4b22b933Srs200217 	struct timeval statetimestamp;
583*4b22b933Srs200217 
584*4b22b933Srs200217 	/*
585*4b22b933Srs200217 	 * Update configuration if current svc state timestamp
586*4b22b933Srs200217 	 * is different from last known svc state timestamp
587*4b22b933Srs200217 	 */
588*4b22b933Srs200217 	_nss_mdns_get_svcstatetimestamp(&statetimestamp);
589*4b22b933Srs200217 	if ((statetimestamp.tv_sec == 0) && (statetimestamp.tv_usec == 0)) {
590*4b22b933Srs200217 		syslog(LOG_ERR, "nss_mdns: error checking " \
591*4b22b933Srs200217 		    "svc:/network/dns/multicast:default" \
592*4b22b933Srs200217 		    " service timestamp");
593*4b22b933Srs200217 	} else if ((be->conftimestamp.tv_sec == statetimestamp.tv_sec) &&
594*4b22b933Srs200217 	    (be->conftimestamp.tv_usec == statetimestamp.tv_usec)) {
595*4b22b933Srs200217 		return;
596*4b22b933Srs200217 	}
597*4b22b933Srs200217 
598*4b22b933Srs200217 	_nss_mdns_freesmfcfg(be);
599*4b22b933Srs200217 	_nss_mdns_loadsmfcfg(be);
600*4b22b933Srs200217 	be->conftimestamp.tv_sec = statetimestamp.tv_sec;
601*4b22b933Srs200217 	be->conftimestamp.tv_usec = statetimestamp.tv_usec;
602*4b22b933Srs200217 }
603*4b22b933Srs200217 
604*4b22b933Srs200217 static void
load_mdns_domaincfg(scf_handle_t * h,char ** storelist,const char * scfprop,int maxprops)605*4b22b933Srs200217 load_mdns_domaincfg(scf_handle_t *h, char **storelist,
606*4b22b933Srs200217 			const char *scfprop, int maxprops)
607*4b22b933Srs200217 {
608*4b22b933Srs200217 	scf_simple_prop_t *sprop;
609*4b22b933Srs200217 	char *tchr;
610*4b22b933Srs200217 	char *pchr;
611*4b22b933Srs200217 	int tlen;
612*4b22b933Srs200217 	int cnt = 0;
613*4b22b933Srs200217 
614*4b22b933Srs200217 	if ((sprop = scf_simple_prop_get(h, SMF_MDNS_FMRI,
615*4b22b933Srs200217 	    SMF_NSSMDNSCFG_PROPGRP, scfprop)) == NULL)
616*4b22b933Srs200217 			return;
617*4b22b933Srs200217 
618*4b22b933Srs200217 	while ((cnt < maxprops) &&
619*4b22b933Srs200217 	    (tchr = scf_simple_prop_next_astring(sprop)) != NULL) {
620*4b22b933Srs200217 
621*4b22b933Srs200217 		/* Remove beginning & trailing '.' chars */
622*4b22b933Srs200217 		while (*tchr && (*tchr == '.'))
623*4b22b933Srs200217 			tchr++;
624*4b22b933Srs200217 
625*4b22b933Srs200217 		if (*tchr && ((tlen = strlen(tchr)) < MAXDNAME)) {
626*4b22b933Srs200217 			pchr = &tchr[tlen-1];
627*4b22b933Srs200217 			while ((pchr != tchr) && (*pchr == '.'))
628*4b22b933Srs200217 				pchr--;
629*4b22b933Srs200217 			*(++pchr) = '\0';
630*4b22b933Srs200217 			storelist[cnt] = strdup(tchr);
631*4b22b933Srs200217 			cnt++;
632*4b22b933Srs200217 		}
633*4b22b933Srs200217 	}
634*4b22b933Srs200217 	scf_simple_prop_free(sprop);
635*4b22b933Srs200217 }
636*4b22b933Srs200217 
637*4b22b933Srs200217 static void
_nss_mdns_loadsmfcfg(mdns_backend_ptr_t be)638*4b22b933Srs200217 _nss_mdns_loadsmfcfg(mdns_backend_ptr_t be)
639*4b22b933Srs200217 {
640*4b22b933Srs200217 	scf_handle_t *h;
641*4b22b933Srs200217 
642*4b22b933Srs200217 	h = scf_handle_create(SCF_VERSION);
643*4b22b933Srs200217 	if (h == NULL)
644*4b22b933Srs200217 		return;
645*4b22b933Srs200217 
646*4b22b933Srs200217 	if (scf_handle_bind(h) == -1) {
647*4b22b933Srs200217 		scf_handle_destroy(h);
648*4b22b933Srs200217 		return;
649*4b22b933Srs200217 	}
650*4b22b933Srs200217 
651*4b22b933Srs200217 	load_mdns_domaincfg(h, &(be->dmnsrchlist[0]),
652*4b22b933Srs200217 	    SMF_NSSMDNSCFG_SRCHPROP, NSSMDNS_MAXSRCHDMNS);
653*4b22b933Srs200217 
654*4b22b933Srs200217 	load_mdns_domaincfg(h, &(be->validdmnlist[0]),
655*4b22b933Srs200217 	    SMF_NSSMDNSCFG_DMNPROP, NSSMDNS_MAXVALIDDMNS);
656*4b22b933Srs200217 
657*4b22b933Srs200217 	if (h != NULL)
658*4b22b933Srs200217 		scf_handle_destroy(h);
659*4b22b933Srs200217 }
660*4b22b933Srs200217 
661*4b22b933Srs200217 static void
_nss_mdns_freesmfcfg(mdns_backend_ptr_t be)662*4b22b933Srs200217 _nss_mdns_freesmfcfg(mdns_backend_ptr_t be)
663*4b22b933Srs200217 {
664*4b22b933Srs200217 	int idx;
665*4b22b933Srs200217 	if (be == NULL)
666*4b22b933Srs200217 		return;
667*4b22b933Srs200217 	for (idx = 0; idx < NSSMDNS_MAXSRCHDMNS; idx++) {
668*4b22b933Srs200217 		if (be->dmnsrchlist[idx] != NULL) {
669*4b22b933Srs200217 			free(be->dmnsrchlist[idx]);
670*4b22b933Srs200217 			be->dmnsrchlist[idx] = NULL;
671*4b22b933Srs200217 		}
672*4b22b933Srs200217 	}
673*4b22b933Srs200217 	for (idx = 0; idx < NSSMDNS_MAXVALIDDMNS; idx++) {
674*4b22b933Srs200217 		if (be->validdmnlist[idx] != NULL) {
675*4b22b933Srs200217 			free(be->validdmnlist[idx]);
676*4b22b933Srs200217 			be->validdmnlist[idx] = NULL;
677*4b22b933Srs200217 		}
678*4b22b933Srs200217 	}
679*4b22b933Srs200217 }
680*4b22b933Srs200217 
681*4b22b933Srs200217 /*
682*4b22b933Srs200217  * Performs lookup for IP address by hostname via mDNS and returns
683*4b22b933Srs200217  * results along with the TTL value from the mDNS resource records.
684*4b22b933Srs200217  * Called by nscd wth a ptr to packed bufer and packed buffer size.
685*4b22b933Srs200217  */
686*4b22b933Srs200217 nss_status_t
_nss_mdns_gethost_withttl(void * buffer,size_t bufsize,int ipnode)687*4b22b933Srs200217 _nss_mdns_gethost_withttl(void *buffer, size_t bufsize, int ipnode)
688*4b22b933Srs200217 {
689*4b22b933Srs200217 	nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
690*4b22b933Srs200217 	nss_XbyY_args_t arg;
691*4b22b933Srs200217 	int dbop;
692*4b22b933Srs200217 	int af;
693*4b22b933Srs200217 	int len;
694*4b22b933Srs200217 	int blen;
695*4b22b933Srs200217 	char *dbname;
696*4b22b933Srs200217 	nss_status_t sret;
697*4b22b933Srs200217 	char *hname;
698*4b22b933Srs200217 	struct mdns_querydata qdata;
699*4b22b933Srs200217 	nssuint_t *pttl;
700*4b22b933Srs200217 	mdns_backend_ptr_t be = NULL;
701*4b22b933Srs200217 
702*4b22b933Srs200217 	(void) memset(&qdata, 0, sizeof (struct mdns_querydata));
703*4b22b933Srs200217 
704*4b22b933Srs200217 	qdata.argp = &arg;
705*4b22b933Srs200217 
706*4b22b933Srs200217 	/*
707*4b22b933Srs200217 	 * Retrieve withttl buffer and size from the passed packed buffer.
708*4b22b933Srs200217 	 * Results are returned along with ttl in this buffer.
709*4b22b933Srs200217 	 */
710*4b22b933Srs200217 	qdata.withttlbsize = pbuf->data_len - sizeof (nssuint_t);
711*4b22b933Srs200217 	qdata.withttlbuffer = (char *)buffer + pbuf->data_off;
712*4b22b933Srs200217 
713*4b22b933Srs200217 	sret = nss_packed_getkey(buffer, bufsize, &dbname, &dbop, &arg);
714*4b22b933Srs200217 	if (sret != NSS_SUCCESS)
715*4b22b933Srs200217 		return (NSS_ERROR);
716*4b22b933Srs200217 
717*4b22b933Srs200217 	if (ipnode) {
718*4b22b933Srs200217 		if (arg.key.ipnode.flags != 0)
719*4b22b933Srs200217 			return (NSS_ERROR);
720*4b22b933Srs200217 		hname = (char *)arg.key.ipnode.name;
721*4b22b933Srs200217 		af = arg.key.ipnode.af_family;
722*4b22b933Srs200217 	} else {
723*4b22b933Srs200217 		af = AF_INET;
724*4b22b933Srs200217 		hname = (char *)arg.key.name;
725*4b22b933Srs200217 	}
726*4b22b933Srs200217 
727*4b22b933Srs200217 	if ((be = (mdns_backend_ptr_t)calloc(1, sizeof (*be))) == NULL)
728*4b22b933Srs200217 		return (NSS_ERROR);
729*4b22b933Srs200217 	_nss_mdns_updatecfg(be);
730*4b22b933Srs200217 
731*4b22b933Srs200217 	/* Zero out the withttl buffer prior to use */
732*4b22b933Srs200217 	(void) memset(qdata.withttlbuffer, 0, qdata.withttlbsize);
733*4b22b933Srs200217 
734*4b22b933Srs200217 #ifdef DEBUG
735*4b22b933Srs200217 	syslog(LOG_DEBUG, "nss_mdns: querybyname withttl called" \
736*4b22b933Srs200217 	    " af:%d hname:%s", af, hname);
737*4b22b933Srs200217 #endif
738*4b22b933Srs200217 	if (_nss_mdns_querybyname(be, hname, af, &qdata) == NSS_SUCCESS) {
739*4b22b933Srs200217 		blen = strlen(qdata.buffer);
740*4b22b933Srs200217 		len = ROUND_UP(blen, sizeof (nssuint_t));
741*4b22b933Srs200217 
742*4b22b933Srs200217 		if (len + sizeof (nssuint_t) > pbuf->data_len) {
743*4b22b933Srs200217 			_nss_mdns_freesmfcfg(be);
744*4b22b933Srs200217 			free(be);
745*4b22b933Srs200217 			return (NSS_ERROR);
746*4b22b933Srs200217 		}
747*4b22b933Srs200217 
748*4b22b933Srs200217 		pbuf->ext_off = pbuf->data_off + len;
749*4b22b933Srs200217 		pbuf->ext_len = sizeof (nssuint_t);
750*4b22b933Srs200217 		pbuf->data_len = blen;
751*4b22b933Srs200217 
752*4b22b933Srs200217 		/* Return ttl in the packed buffer at ext_off */
753*4b22b933Srs200217 		pttl = (nssuint_t *)((void *)((char *)pbuf + pbuf->ext_off));
754*4b22b933Srs200217 		*pttl = qdata.ttl;
755*4b22b933Srs200217 
756*4b22b933Srs200217 		_nss_mdns_freesmfcfg(be);
757*4b22b933Srs200217 		free(be);
758*4b22b933Srs200217 		return (NSS_SUCCESS);
759*4b22b933Srs200217 	}
760*4b22b933Srs200217 	_nss_mdns_freesmfcfg(be);
761*4b22b933Srs200217 	free(be);
762*4b22b933Srs200217 	return (NSS_ERROR);
763*4b22b933Srs200217 }
764