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