1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate /*
27*0Sstevel@tonic-gate  * Copyright 1993-2003 Sun Microsystems, Inc.  All rights reserved.
28*0Sstevel@tonic-gate  * Use is subject to license terms.
29*0Sstevel@tonic-gate  */
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.4.1.2 */
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include "mt.h"
35*0Sstevel@tonic-gate #include <stdlib.h>
36*0Sstevel@tonic-gate #include <rpc/trace.h>
37*0Sstevel@tonic-gate #include <unistd.h>
38*0Sstevel@tonic-gate #include <stropts.h>
39*0Sstevel@tonic-gate #include <sys/stream.h>
40*0Sstevel@tonic-gate #define	_SUN_TPI_VERSION 2
41*0Sstevel@tonic-gate #include <sys/tihdr.h>
42*0Sstevel@tonic-gate #include <sys/timod.h>
43*0Sstevel@tonic-gate #include <xti.h>
44*0Sstevel@tonic-gate #include <stdio.h>
45*0Sstevel@tonic-gate #include <errno.h>
46*0Sstevel@tonic-gate #include <signal.h>
47*0Sstevel@tonic-gate #include "tx.h"
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate /*
50*0Sstevel@tonic-gate  * Function protoypes
51*0Sstevel@tonic-gate  */
52*0Sstevel@tonic-gate static int _alloc_buf(struct netbuf *buf, t_scalar_t n, int fields,
53*0Sstevel@tonic-gate     int api_semantics);
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate char *
56*0Sstevel@tonic-gate _tx_alloc(int fd, int struct_type, int fields, int api_semantics)
57*0Sstevel@tonic-gate {
58*0Sstevel@tonic-gate 	struct strioctl strioc;
59*0Sstevel@tonic-gate 	struct T_info_ack info;
60*0Sstevel@tonic-gate 	union structptrs {
61*0Sstevel@tonic-gate 		char	*caddr;
62*0Sstevel@tonic-gate 		struct t_bind *bind;
63*0Sstevel@tonic-gate 		struct t_call *call;
64*0Sstevel@tonic-gate 		struct t_discon *dis;
65*0Sstevel@tonic-gate 		struct t_optmgmt *opt;
66*0Sstevel@tonic-gate 		struct t_unitdata *udata;
67*0Sstevel@tonic-gate 		struct t_uderr *uderr;
68*0Sstevel@tonic-gate 		struct t_info *info;
69*0Sstevel@tonic-gate 	} p;
70*0Sstevel@tonic-gate 	unsigned int dsize;
71*0Sstevel@tonic-gate 	struct _ti_user *tiptr;
72*0Sstevel@tonic-gate 	int retval, sv_errno;
73*0Sstevel@tonic-gate 	t_scalar_t optsize;
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate 	trace4(TR_t_alloc, 0, fd, struct_type, fields);
76*0Sstevel@tonic-gate 	if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL) {
77*0Sstevel@tonic-gate 		sv_errno = errno;
78*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
79*0Sstevel@tonic-gate 		errno = sv_errno;
80*0Sstevel@tonic-gate 		return (NULL);
81*0Sstevel@tonic-gate 	}
82*0Sstevel@tonic-gate 	sig_mutex_lock(&tiptr->ti_lock);
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate 	/*
85*0Sstevel@tonic-gate 	 * Get size info for T_ADDR, T_OPT, and T_UDATA fields
86*0Sstevel@tonic-gate 	 */
87*0Sstevel@tonic-gate 	info.PRIM_type = T_INFO_REQ;
88*0Sstevel@tonic-gate 	strioc.ic_cmd = TI_GETINFO;
89*0Sstevel@tonic-gate 	strioc.ic_timout = -1;
90*0Sstevel@tonic-gate 	strioc.ic_len = (int)sizeof (struct T_info_req);
91*0Sstevel@tonic-gate 	strioc.ic_dp = (char *)&info;
92*0Sstevel@tonic-gate 	do {
93*0Sstevel@tonic-gate 		retval = _ioctl(fd, I_STR, &strioc);
94*0Sstevel@tonic-gate 	} while (retval < 0 && errno == EINTR);
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate 	if (retval < 0) {
97*0Sstevel@tonic-gate 		sv_errno = errno;
98*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
99*0Sstevel@tonic-gate 		t_errno = TSYSERR;
100*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
101*0Sstevel@tonic-gate 		errno = sv_errno;
102*0Sstevel@tonic-gate 		return (NULL);
103*0Sstevel@tonic-gate 	}
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate 	if (strioc.ic_len != (int)sizeof (struct T_info_ack)) {
106*0Sstevel@tonic-gate 		t_errno = TSYSERR;
107*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
108*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
109*0Sstevel@tonic-gate 		errno = EIO;
110*0Sstevel@tonic-gate 		return (NULL);
111*0Sstevel@tonic-gate 	}
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	/*
115*0Sstevel@tonic-gate 	 * Malloc appropriate structure and the specified
116*0Sstevel@tonic-gate 	 * fields within each structure.  Initialize the
117*0Sstevel@tonic-gate 	 * 'buf' and 'maxlen' fields of each.
118*0Sstevel@tonic-gate 	 */
119*0Sstevel@tonic-gate 	switch (struct_type) {
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	case T_BIND:
122*0Sstevel@tonic-gate 		if ((p.bind = (struct t_bind *)
123*0Sstevel@tonic-gate 		    calloc(1, sizeof (struct t_bind))) == NULL)
124*0Sstevel@tonic-gate 				goto errout;
125*0Sstevel@tonic-gate 		if (fields & T_ADDR) {
126*0Sstevel@tonic-gate 			if (_alloc_buf(&p.bind->addr,
127*0Sstevel@tonic-gate 			    info.ADDR_size,
128*0Sstevel@tonic-gate 			    fields, api_semantics) < 0)
129*0Sstevel@tonic-gate 				goto errout;
130*0Sstevel@tonic-gate 		}
131*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
132*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
133*0Sstevel@tonic-gate 		return ((char *)p.bind);
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 	case T_CALL:
136*0Sstevel@tonic-gate 		if ((p.call = (struct t_call *)
137*0Sstevel@tonic-gate 			calloc(1, sizeof (struct t_call))) == NULL)
138*0Sstevel@tonic-gate 				goto errout;
139*0Sstevel@tonic-gate 		if (fields & T_ADDR) {
140*0Sstevel@tonic-gate 			if (_alloc_buf(&p.call->addr,
141*0Sstevel@tonic-gate 			    info.ADDR_size,
142*0Sstevel@tonic-gate 			    fields, api_semantics) < 0)
143*0Sstevel@tonic-gate 				goto errout;
144*0Sstevel@tonic-gate 		}
145*0Sstevel@tonic-gate 		if (fields & T_OPT) {
146*0Sstevel@tonic-gate 			if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics))
147*0Sstevel@tonic-gate 				/* compensate for XTI level options */
148*0Sstevel@tonic-gate 				optsize = info.OPT_size +
149*0Sstevel@tonic-gate 				    TX_XTI_LEVEL_MAX_OPTBUF;
150*0Sstevel@tonic-gate 			else
151*0Sstevel@tonic-gate 				optsize = info.OPT_size;
152*0Sstevel@tonic-gate 			if (_alloc_buf(&p.call->opt, optsize,
153*0Sstevel@tonic-gate 			    fields, api_semantics) < 0)
154*0Sstevel@tonic-gate 				goto errout;
155*0Sstevel@tonic-gate 		}
156*0Sstevel@tonic-gate 		if (fields & T_UDATA) {
157*0Sstevel@tonic-gate 			dsize = _T_MAX((int)info.CDATA_size,
158*0Sstevel@tonic-gate 					(int)info.DDATA_size);
159*0Sstevel@tonic-gate 			if (_alloc_buf(&p.call->udata, (t_scalar_t)dsize,
160*0Sstevel@tonic-gate 					fields, api_semantics) < 0)
161*0Sstevel@tonic-gate 				goto errout;
162*0Sstevel@tonic-gate 		}
163*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
164*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
165*0Sstevel@tonic-gate 		return ((char *)p.call);
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 	case T_OPTMGMT:
168*0Sstevel@tonic-gate 		if ((p.opt = (struct t_optmgmt *)
169*0Sstevel@tonic-gate 			calloc(1, sizeof (struct t_optmgmt))) == NULL)
170*0Sstevel@tonic-gate 				goto errout;
171*0Sstevel@tonic-gate 		if (fields & T_OPT) {
172*0Sstevel@tonic-gate 			if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics))
173*0Sstevel@tonic-gate 				/* compensate for XTI level options */
174*0Sstevel@tonic-gate 				optsize = info.OPT_size +
175*0Sstevel@tonic-gate 				    TX_XTI_LEVEL_MAX_OPTBUF;
176*0Sstevel@tonic-gate 			else
177*0Sstevel@tonic-gate 				optsize = info.OPT_size;
178*0Sstevel@tonic-gate 			if (_alloc_buf(&p.opt->opt, optsize,
179*0Sstevel@tonic-gate 				fields, api_semantics) < 0)
180*0Sstevel@tonic-gate 				goto errout;
181*0Sstevel@tonic-gate 		}
182*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
183*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
184*0Sstevel@tonic-gate 		return ((char *)p.opt);
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 	case T_DIS:
187*0Sstevel@tonic-gate 		if ((p.dis = (struct t_discon *)
188*0Sstevel@tonic-gate 		    calloc(1, sizeof (struct t_discon))) == NULL)
189*0Sstevel@tonic-gate 			goto errout;
190*0Sstevel@tonic-gate 		if (fields & T_UDATA) {
191*0Sstevel@tonic-gate 			if (_alloc_buf(&p.dis->udata, info.DDATA_size,
192*0Sstevel@tonic-gate 				fields, api_semantics) < 0)
193*0Sstevel@tonic-gate 				goto errout;
194*0Sstevel@tonic-gate 		}
195*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
196*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
197*0Sstevel@tonic-gate 		return ((char *)p.dis);
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 	case T_UNITDATA:
200*0Sstevel@tonic-gate 		if ((p.udata = (struct t_unitdata *)
201*0Sstevel@tonic-gate 		    calloc(1, sizeof (struct t_unitdata))) == NULL)
202*0Sstevel@tonic-gate 				goto errout;
203*0Sstevel@tonic-gate 		if (fields & T_ADDR) {
204*0Sstevel@tonic-gate 			if (_alloc_buf(&p.udata->addr, info.ADDR_size,
205*0Sstevel@tonic-gate 				fields, api_semantics) < 0)
206*0Sstevel@tonic-gate 				goto errout;
207*0Sstevel@tonic-gate 		}
208*0Sstevel@tonic-gate 		if (fields & T_OPT) {
209*0Sstevel@tonic-gate 			if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics))
210*0Sstevel@tonic-gate 				/* compensate for XTI level options */
211*0Sstevel@tonic-gate 				optsize = info.OPT_size +
212*0Sstevel@tonic-gate 				    TX_XTI_LEVEL_MAX_OPTBUF;
213*0Sstevel@tonic-gate 			else
214*0Sstevel@tonic-gate 				optsize = info.OPT_size;
215*0Sstevel@tonic-gate 			if (_alloc_buf(&p.udata->opt, optsize,
216*0Sstevel@tonic-gate 				fields, api_semantics) < 0)
217*0Sstevel@tonic-gate 				goto errout;
218*0Sstevel@tonic-gate 		}
219*0Sstevel@tonic-gate 		if (fields & T_UDATA) {
220*0Sstevel@tonic-gate 			if (_alloc_buf(&p.udata->udata, info.TSDU_size,
221*0Sstevel@tonic-gate 				fields, api_semantics) < 0)
222*0Sstevel@tonic-gate 				goto errout;
223*0Sstevel@tonic-gate 		}
224*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
225*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
226*0Sstevel@tonic-gate 		return ((char *)p.udata);
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate 	case T_UDERROR:
229*0Sstevel@tonic-gate 		if ((p.uderr = (struct t_uderr *)
230*0Sstevel@tonic-gate 			calloc(1, sizeof (struct t_uderr))) == NULL)
231*0Sstevel@tonic-gate 				goto errout;
232*0Sstevel@tonic-gate 		if (fields & T_ADDR) {
233*0Sstevel@tonic-gate 			if (_alloc_buf(&p.uderr->addr, info.ADDR_size,
234*0Sstevel@tonic-gate 				fields, api_semantics) < 0)
235*0Sstevel@tonic-gate 				goto errout;
236*0Sstevel@tonic-gate 		}
237*0Sstevel@tonic-gate 		if (fields & T_OPT) {
238*0Sstevel@tonic-gate 			if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics))
239*0Sstevel@tonic-gate 				/* compensate for XTI level options */
240*0Sstevel@tonic-gate 				optsize = info.OPT_size +
241*0Sstevel@tonic-gate 				    TX_XTI_LEVEL_MAX_OPTBUF;
242*0Sstevel@tonic-gate 			else
243*0Sstevel@tonic-gate 				optsize = info.OPT_size;
244*0Sstevel@tonic-gate 			if (_alloc_buf(&p.uderr->opt, optsize,
245*0Sstevel@tonic-gate 				fields, api_semantics) < 0)
246*0Sstevel@tonic-gate 				goto errout;
247*0Sstevel@tonic-gate 		}
248*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
249*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
250*0Sstevel@tonic-gate 		return ((char *)p.uderr);
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate 	case T_INFO:
253*0Sstevel@tonic-gate 		if ((p.info = (struct t_info *)
254*0Sstevel@tonic-gate 			calloc(1, sizeof (struct t_info))) == NULL)
255*0Sstevel@tonic-gate 				goto errout;
256*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
257*0Sstevel@tonic-gate 		trace4(TR_t_alloc, 1, fd, struct_type, fields);
258*0Sstevel@tonic-gate 		return ((char *)p.info);
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	default:
261*0Sstevel@tonic-gate 		if (_T_IS_XTI(api_semantics)) {
262*0Sstevel@tonic-gate 			t_errno = TNOSTRUCTYPE;
263*0Sstevel@tonic-gate 			sig_mutex_unlock(&tiptr->ti_lock);
264*0Sstevel@tonic-gate 			trace4(TR_t_alloc, 1, fd, struct_type, fields);
265*0Sstevel@tonic-gate 		} else {	/* TX_TLI_API */
266*0Sstevel@tonic-gate 			t_errno = TSYSERR;
267*0Sstevel@tonic-gate 			sig_mutex_unlock(&tiptr->ti_lock);
268*0Sstevel@tonic-gate 			trace4(TR_t_alloc, 1, fd, struct_type, fields);
269*0Sstevel@tonic-gate 			errno = EINVAL;
270*0Sstevel@tonic-gate 		}
271*0Sstevel@tonic-gate 		return (NULL);
272*0Sstevel@tonic-gate 	}
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	/*
275*0Sstevel@tonic-gate 	 * Clean up. Set t_errno to TSYSERR.
276*0Sstevel@tonic-gate 	 * If it is because memory could not be allocated
277*0Sstevel@tonic-gate 	 * then errno already should have been set to
278*0Sstevel@tonic-gate 	 * ENOMEM
279*0Sstevel@tonic-gate 	 */
280*0Sstevel@tonic-gate errout:
281*0Sstevel@tonic-gate 	if (p.caddr)
282*0Sstevel@tonic-gate 		(void) t_free(p.caddr, struct_type);
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 	t_errno = TSYSERR;
285*0Sstevel@tonic-gate 	sig_mutex_unlock(&tiptr->ti_lock);
286*0Sstevel@tonic-gate 	trace4(TR_t_alloc, 1, fd, struct_type, fields);
287*0Sstevel@tonic-gate 	return (NULL);
288*0Sstevel@tonic-gate }
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate static int
291*0Sstevel@tonic-gate _alloc_buf(struct netbuf *buf, t_scalar_t n, int fields, int api_semantics)
292*0Sstevel@tonic-gate {
293*0Sstevel@tonic-gate 	trace2(TR__alloc_buf, 0, n);
294*0Sstevel@tonic-gate 	switch (n) {
295*0Sstevel@tonic-gate 	case T_INFINITE /* -1 */:
296*0Sstevel@tonic-gate 		if (_T_IS_XTI(api_semantics)) {
297*0Sstevel@tonic-gate 			buf->buf = NULL;
298*0Sstevel@tonic-gate 			buf->maxlen = 0;
299*0Sstevel@tonic-gate 			if (fields != T_ALL) {
300*0Sstevel@tonic-gate 				/*
301*0Sstevel@tonic-gate 				 * Do not return error
302*0Sstevel@tonic-gate 				 * if T_ALL is used.
303*0Sstevel@tonic-gate 				 */
304*0Sstevel@tonic-gate 				trace2(TR__alloc_buf, 1, n);
305*0Sstevel@tonic-gate 				errno = EINVAL;
306*0Sstevel@tonic-gate 				return (-1);
307*0Sstevel@tonic-gate 			}
308*0Sstevel@tonic-gate 		} else {	/* TX_TLI_API */
309*0Sstevel@tonic-gate 			/*
310*0Sstevel@tonic-gate 			 * retain TLI behavior
311*0Sstevel@tonic-gate 			 */
312*0Sstevel@tonic-gate 			if ((buf->buf = calloc(1, 1024)) == NULL) {
313*0Sstevel@tonic-gate 				trace2(TR__alloc_buf, 1, n);
314*0Sstevel@tonic-gate 				errno = ENOMEM;
315*0Sstevel@tonic-gate 				return (-1);
316*0Sstevel@tonic-gate 			} else
317*0Sstevel@tonic-gate 				buf->maxlen = 1024;
318*0Sstevel@tonic-gate 		}
319*0Sstevel@tonic-gate 		break;
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate 	case 0:
322*0Sstevel@tonic-gate 		buf->buf = NULL;
323*0Sstevel@tonic-gate 		buf->maxlen = 0;
324*0Sstevel@tonic-gate 		break;
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate 	case T_INVALID /* -2 */:
327*0Sstevel@tonic-gate 		if (_T_IS_XTI(api_semantics)) {
328*0Sstevel@tonic-gate 			buf->buf = NULL;
329*0Sstevel@tonic-gate 			buf->maxlen = 0;
330*0Sstevel@tonic-gate 			if (fields != T_ALL) {
331*0Sstevel@tonic-gate 				/*
332*0Sstevel@tonic-gate 				 * Do not return error
333*0Sstevel@tonic-gate 				 * if T_ALL is used.
334*0Sstevel@tonic-gate 				 */
335*0Sstevel@tonic-gate 				trace2(TR__alloc_buf, 1, n);
336*0Sstevel@tonic-gate 				errno = EINVAL;
337*0Sstevel@tonic-gate 				return (-1);
338*0Sstevel@tonic-gate 			}
339*0Sstevel@tonic-gate 		} else {	/* TX_TLI_API */
340*0Sstevel@tonic-gate 			/*
341*0Sstevel@tonic-gate 			 * retain TLI behavior
342*0Sstevel@tonic-gate 			 */
343*0Sstevel@tonic-gate 			buf->buf = NULL;
344*0Sstevel@tonic-gate 			buf->maxlen = 0;
345*0Sstevel@tonic-gate 		}
346*0Sstevel@tonic-gate 		break;
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	default:
349*0Sstevel@tonic-gate 		if ((buf->buf = calloc(1, (size_t)n)) == NULL) {
350*0Sstevel@tonic-gate 			trace2(TR__alloc_buf, 1, n);
351*0Sstevel@tonic-gate 			errno = ENOMEM;
352*0Sstevel@tonic-gate 			return (-1);
353*0Sstevel@tonic-gate 		} else
354*0Sstevel@tonic-gate 			buf->maxlen = n;
355*0Sstevel@tonic-gate 		break;
356*0Sstevel@tonic-gate 	}
357*0Sstevel@tonic-gate 	trace2(TR__alloc_buf, 1, n);
358*0Sstevel@tonic-gate 	return (0);
359*0Sstevel@tonic-gate }
360