1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
32*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
33*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
34*7c478bd9Sstevel@tonic-gate  *
35*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
36*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
37*7c478bd9Sstevel@tonic-gate  * contributors.
38*7c478bd9Sstevel@tonic-gate  */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include "synonyms.h"
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #include <stdio.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
48*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
49*7c478bd9Sstevel@tonic-gate #include <arpa/nameser.h>
50*7c478bd9Sstevel@tonic-gate #include <resolv.h>
51*7c478bd9Sstevel@tonic-gate #include <errno.h>
52*7c478bd9Sstevel@tonic-gate #include <netdb.h>
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate  * Kludge to time out quickly if there is no /etc/resolv.conf
56*7c478bd9Sstevel@tonic-gate  * and a TCP connection to the local DNS server fails.
57*7c478bd9Sstevel@tonic-gate  *
58*7c478bd9Sstevel@tonic-gate  * Moved function from res_send.c to res_mkquery.c.  This
59*7c478bd9Sstevel@tonic-gate  * solves a long timeout problem with nslookup.
60*7c478bd9Sstevel@tonic-gate  *
61*7c478bd9Sstevel@tonic-gate  * __areweinnamed is needed because there is a possibility that the
62*7c478bd9Sstevel@tonic-gate  * user might do bad things to resolv.conf and cause in.named to call
63*7c478bd9Sstevel@tonic-gate  * _confcheck and deadlock the server.
64*7c478bd9Sstevel@tonic-gate  */
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate int __areweinnamed()
67*7c478bd9Sstevel@tonic-gate {
68*7c478bd9Sstevel@tonic-gate 	return (0);
69*7c478bd9Sstevel@tonic-gate }
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate static int _confcheck()
72*7c478bd9Sstevel@tonic-gate {
73*7c478bd9Sstevel@tonic-gate 	int ns;
74*7c478bd9Sstevel@tonic-gate 	struct stat rc_stat;
75*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in ns_sin;
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate 	/* First, we check to see if /etc/resolv.conf exists.
79*7c478bd9Sstevel@tonic-gate 	 * If it doesn't, then localhost is mostlikely to be
80*7c478bd9Sstevel@tonic-gate 	 * the nameserver.
81*7c478bd9Sstevel@tonic-gate 	 */
82*7c478bd9Sstevel@tonic-gate 	if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) {
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate 		/* Next, we check to see if _res.nsaddr is set to loopback.
85*7c478bd9Sstevel@tonic-gate 		 * If it isn't, it has been altered by the application
86*7c478bd9Sstevel@tonic-gate 		 * explicitly and we then want to bail with success.
87*7c478bd9Sstevel@tonic-gate 		 */
88*7c478bd9Sstevel@tonic-gate 		if (__areweinnamed())
89*7c478bd9Sstevel@tonic-gate 			return (0);
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate 		if (_res.nsaddr.sin_addr.S_un.S_addr == htonl(INADDR_LOOPBACK)) {
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 			/* Lastly, we try to connect to the TCP port of the
94*7c478bd9Sstevel@tonic-gate 			 * nameserver.  If this fails, then we know that
95*7c478bd9Sstevel@tonic-gate 			 * DNS is misconfigured and we can quickly exit.
96*7c478bd9Sstevel@tonic-gate 			 */
97*7c478bd9Sstevel@tonic-gate 			ns = socket(AF_INET, SOCK_STREAM, 0);
98*7c478bd9Sstevel@tonic-gate 			IN_SET_LOOPBACK_ADDR(&ns_sin);
99*7c478bd9Sstevel@tonic-gate 			ns_sin.sin_port = htons(NAMESERVER_PORT);
100*7c478bd9Sstevel@tonic-gate 			if (connect(ns, (struct sockaddr *) &ns_sin,
101*7c478bd9Sstevel@tonic-gate 				    sizeof ns_sin) == -1) {
102*7c478bd9Sstevel@tonic-gate 				close(ns);
103*7c478bd9Sstevel@tonic-gate 				return(-1);
104*7c478bd9Sstevel@tonic-gate 			}
105*7c478bd9Sstevel@tonic-gate 			else {
106*7c478bd9Sstevel@tonic-gate 				close(ns);
107*7c478bd9Sstevel@tonic-gate 				return(0);
108*7c478bd9Sstevel@tonic-gate 			}
109*7c478bd9Sstevel@tonic-gate 		}
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 		return(0);
112*7c478bd9Sstevel@tonic-gate 	}
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	return (0);
115*7c478bd9Sstevel@tonic-gate }
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate /*
118*7c478bd9Sstevel@tonic-gate  * Form all types of queries.
119*7c478bd9Sstevel@tonic-gate  * Returns the size of the result or -1.
120*7c478bd9Sstevel@tonic-gate  */
121*7c478bd9Sstevel@tonic-gate res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
122*7c478bd9Sstevel@tonic-gate 	int op;			/* opcode of query */
123*7c478bd9Sstevel@tonic-gate 	char *dname;		/* domain name */
124*7c478bd9Sstevel@tonic-gate 	int class, type;	/* class and type of query */
125*7c478bd9Sstevel@tonic-gate 	char *data;		/* resource record data */
126*7c478bd9Sstevel@tonic-gate 	int datalen;		/* length of data */
127*7c478bd9Sstevel@tonic-gate 	struct rrec *newrr;	/* new rr for modify or append */
128*7c478bd9Sstevel@tonic-gate 	char *buf;		/* buffer to put query */
129*7c478bd9Sstevel@tonic-gate 	int buflen;		/* size of buffer */
130*7c478bd9Sstevel@tonic-gate {
131*7c478bd9Sstevel@tonic-gate 	register HEADER *hp;
132*7c478bd9Sstevel@tonic-gate 	register char *cp;
133*7c478bd9Sstevel@tonic-gate 	register int n;
134*7c478bd9Sstevel@tonic-gate 	char *dnptrs[10], **dpp, **lastdnptr;
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
137*7c478bd9Sstevel@tonic-gate 	if (_res.options & RES_DEBUG)
138*7c478bd9Sstevel@tonic-gate 		printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
139*7c478bd9Sstevel@tonic-gate #endif DEBUG
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	/*
142*7c478bd9Sstevel@tonic-gate 	 * Check to see if we can bailout quickly.
143*7c478bd9Sstevel@tonic-gate 	 * Also rerun res_init if we failed in the past.
144*7c478bd9Sstevel@tonic-gate 	 */
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
147*7c478bd9Sstevel@tonic-gate 		h_errno = NO_RECOVERY;
148*7c478bd9Sstevel@tonic-gate 		return(-1);
149*7c478bd9Sstevel@tonic-gate 	}
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	if (_confcheck() == -1) {
152*7c478bd9Sstevel@tonic-gate 		_res.options &= ~RES_INIT;
153*7c478bd9Sstevel@tonic-gate 		h_errno = NO_RECOVERY;
154*7c478bd9Sstevel@tonic-gate 		return(-1);
155*7c478bd9Sstevel@tonic-gate 	}
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	/*
158*7c478bd9Sstevel@tonic-gate 	 * Initialize header fields.
159*7c478bd9Sstevel@tonic-gate 	 */
160*7c478bd9Sstevel@tonic-gate 	if ((buf == NULL) || (buflen < sizeof (HEADER)))
161*7c478bd9Sstevel@tonic-gate 		return (-1);
162*7c478bd9Sstevel@tonic-gate #ifdef SYSV
163*7c478bd9Sstevel@tonic-gate 	memset(buf, 0, sizeof (HEADER));
164*7c478bd9Sstevel@tonic-gate #else
165*7c478bd9Sstevel@tonic-gate 	bzero(buf, sizeof (HEADER));
166*7c478bd9Sstevel@tonic-gate #endif
167*7c478bd9Sstevel@tonic-gate 	hp = (HEADER *) buf;
168*7c478bd9Sstevel@tonic-gate 	hp->id = htons(++_res.id);
169*7c478bd9Sstevel@tonic-gate 	hp->opcode = op;
170*7c478bd9Sstevel@tonic-gate 	hp->pr = (_res.options & RES_PRIMARY) != 0;
171*7c478bd9Sstevel@tonic-gate 	hp->rd = (_res.options & RES_RECURSE) != 0;
172*7c478bd9Sstevel@tonic-gate 	hp->rcode = NOERROR;
173*7c478bd9Sstevel@tonic-gate 	cp = buf + sizeof (HEADER);
174*7c478bd9Sstevel@tonic-gate 	buflen -= sizeof (HEADER);
175*7c478bd9Sstevel@tonic-gate 	dpp = dnptrs;
176*7c478bd9Sstevel@tonic-gate 	*dpp++ = buf;
177*7c478bd9Sstevel@tonic-gate 	*dpp++ = NULL;
178*7c478bd9Sstevel@tonic-gate 	lastdnptr = dnptrs + sizeof (dnptrs) / sizeof (dnptrs[0]);
179*7c478bd9Sstevel@tonic-gate 	/*
180*7c478bd9Sstevel@tonic-gate 	 * perform opcode specific processing
181*7c478bd9Sstevel@tonic-gate 	 */
182*7c478bd9Sstevel@tonic-gate 	switch (op) {
183*7c478bd9Sstevel@tonic-gate 	case QUERY:
184*7c478bd9Sstevel@tonic-gate 		if ((buflen -= QFIXEDSZ) < 0)
185*7c478bd9Sstevel@tonic-gate 			return (-1);
186*7c478bd9Sstevel@tonic-gate 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
187*7c478bd9Sstevel@tonic-gate 			return (-1);
188*7c478bd9Sstevel@tonic-gate 		cp += n;
189*7c478bd9Sstevel@tonic-gate 		buflen -= n;
190*7c478bd9Sstevel@tonic-gate 		putshort(type, cp);
191*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
192*7c478bd9Sstevel@tonic-gate 		putshort(class, cp);
193*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
194*7c478bd9Sstevel@tonic-gate 		hp->qdcount = htons(1);
195*7c478bd9Sstevel@tonic-gate 		if (op == QUERY || data == NULL)
196*7c478bd9Sstevel@tonic-gate 			break;
197*7c478bd9Sstevel@tonic-gate 		/*
198*7c478bd9Sstevel@tonic-gate 		 * Make an additional record for completion domain.
199*7c478bd9Sstevel@tonic-gate 		 */
200*7c478bd9Sstevel@tonic-gate 		buflen -= RRFIXEDSZ;
201*7c478bd9Sstevel@tonic-gate 		if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
202*7c478bd9Sstevel@tonic-gate 			return (-1);
203*7c478bd9Sstevel@tonic-gate 		cp += n;
204*7c478bd9Sstevel@tonic-gate 		buflen -= n;
205*7c478bd9Sstevel@tonic-gate 		putshort(T_NULL, cp);
206*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
207*7c478bd9Sstevel@tonic-gate 		putshort(class, cp);
208*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
209*7c478bd9Sstevel@tonic-gate 		putlong(0, cp);
210*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_long);
211*7c478bd9Sstevel@tonic-gate 		putshort(0, cp);
212*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
213*7c478bd9Sstevel@tonic-gate 		hp->arcount = htons(1);
214*7c478bd9Sstevel@tonic-gate 		break;
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	case IQUERY:
217*7c478bd9Sstevel@tonic-gate 		/*
218*7c478bd9Sstevel@tonic-gate 		 * Initialize answer section
219*7c478bd9Sstevel@tonic-gate 		 */
220*7c478bd9Sstevel@tonic-gate 		if (buflen < 1 + RRFIXEDSZ + datalen)
221*7c478bd9Sstevel@tonic-gate 			return (-1);
222*7c478bd9Sstevel@tonic-gate 		*cp++ = '\0';	/* no domain name */
223*7c478bd9Sstevel@tonic-gate 		putshort(type, cp);
224*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
225*7c478bd9Sstevel@tonic-gate 		putshort(class, cp);
226*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
227*7c478bd9Sstevel@tonic-gate 		putlong(0, cp);
228*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_long);
229*7c478bd9Sstevel@tonic-gate 		putshort(datalen, cp);
230*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
231*7c478bd9Sstevel@tonic-gate 		if (datalen) {
232*7c478bd9Sstevel@tonic-gate #ifdef SYSV
233*7c478bd9Sstevel@tonic-gate 			memcpy((void *)cp, (void *)data, datalen);
234*7c478bd9Sstevel@tonic-gate #else
235*7c478bd9Sstevel@tonic-gate 			bcopy(data, cp, datalen);
236*7c478bd9Sstevel@tonic-gate #endif
237*7c478bd9Sstevel@tonic-gate 			cp += datalen;
238*7c478bd9Sstevel@tonic-gate 		}
239*7c478bd9Sstevel@tonic-gate 		hp->ancount = htons(1);
240*7c478bd9Sstevel@tonic-gate 		break;
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate #ifdef ALLOW_UPDATES
243*7c478bd9Sstevel@tonic-gate 	/*
244*7c478bd9Sstevel@tonic-gate 	 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
245*7c478bd9Sstevel@tonic-gate 	 * (Record to be modified is followed by its replacement in msg.)
246*7c478bd9Sstevel@tonic-gate 	 */
247*7c478bd9Sstevel@tonic-gate 	case UPDATEM:
248*7c478bd9Sstevel@tonic-gate 	case UPDATEMA:
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	case UPDATED:
251*7c478bd9Sstevel@tonic-gate 		/*
252*7c478bd9Sstevel@tonic-gate 		 * The res code for UPDATED and UPDATEDA is the same; user
253*7c478bd9Sstevel@tonic-gate 		 * calls them differently: specifies data for UPDATED; server
254*7c478bd9Sstevel@tonic-gate 		 * ignores data if specified for UPDATEDA.
255*7c478bd9Sstevel@tonic-gate 		 */
256*7c478bd9Sstevel@tonic-gate 	case UPDATEDA:
257*7c478bd9Sstevel@tonic-gate 		buflen -= RRFIXEDSZ + datalen;
258*7c478bd9Sstevel@tonic-gate 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
259*7c478bd9Sstevel@tonic-gate 			return (-1);
260*7c478bd9Sstevel@tonic-gate 		cp += n;
261*7c478bd9Sstevel@tonic-gate 		putshort(type, cp);
262*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
263*7c478bd9Sstevel@tonic-gate 		putshort(class, cp);
264*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
265*7c478bd9Sstevel@tonic-gate 		putlong(0, cp);
266*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_long);
267*7c478bd9Sstevel@tonic-gate 		putshort(datalen, cp);
268*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
269*7c478bd9Sstevel@tonic-gate 		if (datalen) {
270*7c478bd9Sstevel@tonic-gate #ifdef SYSV
271*7c478bd9Sstevel@tonic-gate 			memcpy((void *)cp, (void *)data, datalen);
272*7c478bd9Sstevel@tonic-gate #else
273*7c478bd9Sstevel@tonic-gate 			bcopy(data, cp, datalen);
274*7c478bd9Sstevel@tonic-gate #endif
275*7c478bd9Sstevel@tonic-gate 			cp += datalen;
276*7c478bd9Sstevel@tonic-gate 		}
277*7c478bd9Sstevel@tonic-gate 		if ((op == UPDATED) || (op == UPDATEDA)) {
278*7c478bd9Sstevel@tonic-gate 			hp->ancount = htons(0);
279*7c478bd9Sstevel@tonic-gate 			break;
280*7c478bd9Sstevel@tonic-gate 		}
281*7c478bd9Sstevel@tonic-gate 		/* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 	case UPDATEA:	/* Add new resource record */
284*7c478bd9Sstevel@tonic-gate 		buflen -= RRFIXEDSZ + datalen;
285*7c478bd9Sstevel@tonic-gate 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
286*7c478bd9Sstevel@tonic-gate 			return (-1);
287*7c478bd9Sstevel@tonic-gate 		cp += n;
288*7c478bd9Sstevel@tonic-gate 		putshort(newrr->r_type, cp);
289*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
290*7c478bd9Sstevel@tonic-gate 		putshort(newrr->r_class, cp);
291*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
292*7c478bd9Sstevel@tonic-gate 		putlong(0, cp);
293*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_long);
294*7c478bd9Sstevel@tonic-gate 		putshort(newrr->r_size, cp);
295*7c478bd9Sstevel@tonic-gate 		cp += sizeof (u_short);
296*7c478bd9Sstevel@tonic-gate 		if (newrr->r_size) {
297*7c478bd9Sstevel@tonic-gate #ifdef SYSV
298*7c478bd9Sstevel@tonic-gate 			memcpy((void *)cp, newrr->r_data, newrr->r_size);
299*7c478bd9Sstevel@tonic-gate #else
300*7c478bd9Sstevel@tonic-gate 			bcopy(newrr->r_data, cp, newrr->r_size);
301*7c478bd9Sstevel@tonic-gate #endif
302*7c478bd9Sstevel@tonic-gate 			cp += newrr->r_size;
303*7c478bd9Sstevel@tonic-gate 		}
304*7c478bd9Sstevel@tonic-gate 		hp->ancount = htons(0);
305*7c478bd9Sstevel@tonic-gate 		break;
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate #endif ALLOW_UPDATES
308*7c478bd9Sstevel@tonic-gate 	}
309*7c478bd9Sstevel@tonic-gate 	return (cp - buf);
310*7c478bd9Sstevel@tonic-gate }
311