import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / nsl / t_alloc.c
blob67d1204afc2e533b56eb3aa42af71d5816258513
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
26 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
30 #include "mt.h"
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <stropts.h>
34 #include <sys/stream.h>
35 #define _SUN_TPI_VERSION 2
36 #include <sys/tihdr.h>
37 #include <sys/timod.h>
38 #include <xti.h>
39 #include <stdio.h>
40 #include <errno.h>
41 #include <ucred.h>
42 #include <signal.h>
43 #include "tx.h"
46 * Function protoypes
48 static int _alloc_buf(struct netbuf *buf, t_scalar_t n, int fields,
49 int api_semantics, boolean_t option);
51 char *
52 _tx_alloc(int fd, int struct_type, int fields, int api_semantics)
54 struct strioctl strioc;
55 struct T_info_ack info;
56 union structptrs {
57 char *caddr;
58 struct t_bind *bind;
59 struct t_call *call;
60 struct t_discon *dis;
61 struct t_optmgmt *opt;
62 struct t_unitdata *udata;
63 struct t_uderr *uderr;
64 struct t_info *info;
65 } p;
66 unsigned int dsize;
67 struct _ti_user *tiptr;
68 int retval, sv_errno;
69 t_scalar_t optsize;
71 if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL)
72 return (NULL);
73 sig_mutex_lock(&tiptr->ti_lock);
76 * Get size info for T_ADDR, T_OPT, and T_UDATA fields
78 info.PRIM_type = T_INFO_REQ;
79 strioc.ic_cmd = TI_GETINFO;
80 strioc.ic_timout = -1;
81 strioc.ic_len = (int)sizeof (struct T_info_req);
82 strioc.ic_dp = (char *)&info;
83 do {
84 retval = ioctl(fd, I_STR, &strioc);
85 } while (retval < 0 && errno == EINTR);
87 if (retval < 0) {
88 sv_errno = errno;
89 sig_mutex_unlock(&tiptr->ti_lock);
90 t_errno = TSYSERR;
91 errno = sv_errno;
92 return (NULL);
95 if (strioc.ic_len != (int)sizeof (struct T_info_ack)) {
96 t_errno = TSYSERR;
97 sig_mutex_unlock(&tiptr->ti_lock);
98 errno = EIO;
99 return (NULL);
104 * Malloc appropriate structure and the specified
105 * fields within each structure. Initialize the
106 * 'buf' and 'maxlen' fields of each.
108 switch (struct_type) {
110 case T_BIND:
111 if ((p.bind = calloc(1, sizeof (struct t_bind))) == NULL)
112 goto errout;
113 if (fields & T_ADDR) {
114 if (_alloc_buf(&p.bind->addr,
115 info.ADDR_size,
116 fields, api_semantics, B_FALSE) < 0)
117 goto errout;
119 sig_mutex_unlock(&tiptr->ti_lock);
120 return ((char *)p.bind);
122 case T_CALL:
123 if ((p.call = calloc(1, sizeof (struct t_call))) == NULL)
124 goto errout;
125 if (fields & T_ADDR) {
126 if (_alloc_buf(&p.call->addr,
127 info.ADDR_size,
128 fields, api_semantics, B_FALSE) < 0)
129 goto errout;
131 if (fields & T_OPT) {
132 if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics))
133 /* compensate for XTI level options */
134 optsize = info.OPT_size +
135 TX_XTI_LEVEL_MAX_OPTBUF;
136 else
137 optsize = info.OPT_size;
138 if (_alloc_buf(&p.call->opt, optsize,
139 fields, api_semantics, B_TRUE) < 0)
140 goto errout;
142 if (fields & T_UDATA) {
143 dsize = _T_MAX((int)info.CDATA_size,
144 (int)info.DDATA_size);
145 if (_alloc_buf(&p.call->udata, (t_scalar_t)dsize,
146 fields, api_semantics, B_FALSE) < 0)
147 goto errout;
149 sig_mutex_unlock(&tiptr->ti_lock);
150 return ((char *)p.call);
152 case T_OPTMGMT:
153 if ((p.opt = calloc(1, sizeof (struct t_optmgmt))) == NULL)
154 goto errout;
155 if (fields & T_OPT) {
156 if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics))
157 /* compensate for XTI level options */
158 optsize = info.OPT_size +
159 TX_XTI_LEVEL_MAX_OPTBUF;
160 else
161 optsize = info.OPT_size;
162 if (_alloc_buf(&p.opt->opt, optsize,
163 fields, api_semantics, B_TRUE) < 0)
164 goto errout;
166 sig_mutex_unlock(&tiptr->ti_lock);
167 return ((char *)p.opt);
169 case T_DIS:
170 if ((p.dis = calloc(1, sizeof (struct t_discon))) == NULL)
171 goto errout;
172 if (fields & T_UDATA) {
173 if (_alloc_buf(&p.dis->udata, info.DDATA_size,
174 fields, api_semantics, B_FALSE) < 0)
175 goto errout;
177 sig_mutex_unlock(&tiptr->ti_lock);
178 return ((char *)p.dis);
180 case T_UNITDATA:
181 if ((p.udata = calloc(1, sizeof (struct t_unitdata))) == NULL)
182 goto errout;
183 if (fields & T_ADDR) {
184 if (_alloc_buf(&p.udata->addr, info.ADDR_size,
185 fields, api_semantics, B_FALSE) < 0)
186 goto errout;
188 if (fields & T_OPT) {
189 if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics))
190 /* compensate for XTI level options */
191 optsize = info.OPT_size +
192 TX_XTI_LEVEL_MAX_OPTBUF;
193 else
194 optsize = info.OPT_size;
195 if (_alloc_buf(&p.udata->opt, optsize,
196 fields, api_semantics, B_TRUE) < 0)
197 goto errout;
199 if (fields & T_UDATA) {
200 if (_alloc_buf(&p.udata->udata, info.TSDU_size,
201 fields, api_semantics, B_FALSE) < 0)
202 goto errout;
204 sig_mutex_unlock(&tiptr->ti_lock);
205 return ((char *)p.udata);
207 case T_UDERROR:
208 if ((p.uderr = calloc(1, sizeof (struct t_uderr))) == NULL)
209 goto errout;
210 if (fields & T_ADDR) {
211 if (_alloc_buf(&p.uderr->addr, info.ADDR_size,
212 fields, api_semantics, B_FALSE) < 0)
213 goto errout;
215 if (fields & T_OPT) {
216 if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics))
217 /* compensate for XTI level options */
218 optsize = info.OPT_size +
219 TX_XTI_LEVEL_MAX_OPTBUF;
220 else
221 optsize = info.OPT_size;
222 if (_alloc_buf(&p.uderr->opt, optsize,
223 fields, api_semantics, B_FALSE) < 0)
224 goto errout;
226 sig_mutex_unlock(&tiptr->ti_lock);
227 return ((char *)p.uderr);
229 case T_INFO:
230 if ((p.info = calloc(1, sizeof (struct t_info))) == NULL)
231 goto errout;
232 sig_mutex_unlock(&tiptr->ti_lock);
233 return ((char *)p.info);
235 default:
236 if (_T_IS_XTI(api_semantics)) {
237 t_errno = TNOSTRUCTYPE;
238 sig_mutex_unlock(&tiptr->ti_lock);
239 } else { /* TX_TLI_API */
240 t_errno = TSYSERR;
241 sig_mutex_unlock(&tiptr->ti_lock);
242 errno = EINVAL;
244 return (NULL);
248 * Clean up. Set t_errno to TSYSERR.
249 * If it is because memory could not be allocated
250 * then errno already should have been set to
251 * ENOMEM
253 errout:
254 if (p.caddr)
255 (void) t_free(p.caddr, struct_type);
257 t_errno = TSYSERR;
258 sig_mutex_unlock(&tiptr->ti_lock);
259 return (NULL);
262 static int
263 _alloc_buf(struct netbuf *buf, t_scalar_t n, int fields, int api_semantics,
264 boolean_t option)
266 switch (n) {
267 case T_INFINITE /* -1 */:
268 if (_T_IS_XTI(api_semantics)) {
269 buf->buf = NULL;
270 buf->maxlen = 0;
271 if (fields != T_ALL) {
273 * Do not return error
274 * if T_ALL is used.
276 errno = EINVAL;
277 return (-1);
279 } else if (option) { /* TX_TLI_API */
280 static size_t infalloc;
283 * retain TLI behavior; ucred_t can vary in size,
284 * we need to make sure that we can receive one.
286 if (infalloc == 0) {
287 size_t uc = ucred_size();
288 if (uc < 1024/2)
289 infalloc = 1024;
290 else
291 infalloc = uc + 1024/2;
293 if ((buf->buf = calloc(1, infalloc)) == NULL) {
294 errno = ENOMEM;
295 return (-1);
296 } else
297 buf->maxlen = infalloc;
298 } else { /* TX_TLI_API */
300 * retain TLI behavior
302 if ((buf->buf = calloc(1, 1024)) == NULL) {
303 errno = ENOMEM;
304 return (-1);
305 } else
306 buf->maxlen = 1024;
308 break;
310 case 0:
311 buf->buf = NULL;
312 buf->maxlen = 0;
313 break;
315 case T_INVALID /* -2 */:
316 if (_T_IS_XTI(api_semantics)) {
317 buf->buf = NULL;
318 buf->maxlen = 0;
319 if (fields != T_ALL) {
321 * Do not return error
322 * if T_ALL is used.
324 errno = EINVAL;
325 return (-1);
327 } else { /* TX_TLI_API */
329 * retain TLI behavior
331 buf->buf = NULL;
332 buf->maxlen = 0;
334 break;
336 default:
337 if ((buf->buf = calloc(1, (size_t)n)) == NULL) {
338 errno = ENOMEM;
339 return (-1);
340 } else
341 buf->maxlen = n;
342 break;
344 return (0);