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 23 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 24 /* All Rights Reserved */ 25 26 /* 27 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.4.1.2 */ 32 33 #include "mt.h" 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <stropts.h> 37 #include <sys/stream.h> 38 #define _SUN_TPI_VERSION 2 39 #include <sys/tihdr.h> 40 #include <sys/timod.h> 41 #include <xti.h> 42 #include <stdio.h> 43 #include <errno.h> 44 #include <signal.h> 45 #include "tx.h" 46 47 /* 48 * Function protoypes 49 */ 50 static int _alloc_buf(struct netbuf *buf, t_scalar_t n, int fields, 51 int api_semantics); 52 53 char * 54 _tx_alloc(int fd, int struct_type, int fields, int api_semantics) 55 { 56 struct strioctl strioc; 57 struct T_info_ack info; 58 union structptrs { 59 char *caddr; 60 struct t_bind *bind; 61 struct t_call *call; 62 struct t_discon *dis; 63 struct t_optmgmt *opt; 64 struct t_unitdata *udata; 65 struct t_uderr *uderr; 66 struct t_info *info; 67 } p; 68 unsigned int dsize; 69 struct _ti_user *tiptr; 70 int retval, sv_errno; 71 t_scalar_t optsize; 72 73 if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL) 74 return (NULL); 75 sig_mutex_lock(&tiptr->ti_lock); 76 77 /* 78 * Get size info for T_ADDR, T_OPT, and T_UDATA fields 79 */ 80 info.PRIM_type = T_INFO_REQ; 81 strioc.ic_cmd = TI_GETINFO; 82 strioc.ic_timout = -1; 83 strioc.ic_len = (int)sizeof (struct T_info_req); 84 strioc.ic_dp = (char *)&info; 85 do { 86 retval = ioctl(fd, I_STR, &strioc); 87 } while (retval < 0 && errno == EINTR); 88 89 if (retval < 0) { 90 sv_errno = errno; 91 sig_mutex_unlock(&tiptr->ti_lock); 92 t_errno = TSYSERR; 93 errno = sv_errno; 94 return (NULL); 95 } 96 97 if (strioc.ic_len != (int)sizeof (struct T_info_ack)) { 98 t_errno = TSYSERR; 99 sig_mutex_unlock(&tiptr->ti_lock); 100 errno = EIO; 101 return (NULL); 102 } 103 104 105 /* 106 * Malloc appropriate structure and the specified 107 * fields within each structure. Initialize the 108 * 'buf' and 'maxlen' fields of each. 109 */ 110 switch (struct_type) { 111 112 case T_BIND: 113 if ((p.bind = calloc(1, sizeof (struct t_bind))) == NULL) 114 goto errout; 115 if (fields & T_ADDR) { 116 if (_alloc_buf(&p.bind->addr, 117 info.ADDR_size, 118 fields, api_semantics) < 0) 119 goto errout; 120 } 121 sig_mutex_unlock(&tiptr->ti_lock); 122 return ((char *)p.bind); 123 124 case T_CALL: 125 if ((p.call = calloc(1, sizeof (struct t_call))) == NULL) 126 goto errout; 127 if (fields & T_ADDR) { 128 if (_alloc_buf(&p.call->addr, 129 info.ADDR_size, 130 fields, api_semantics) < 0) 131 goto errout; 132 } 133 if (fields & T_OPT) { 134 if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics)) 135 /* compensate for XTI level options */ 136 optsize = info.OPT_size + 137 TX_XTI_LEVEL_MAX_OPTBUF; 138 else 139 optsize = info.OPT_size; 140 if (_alloc_buf(&p.call->opt, optsize, 141 fields, api_semantics) < 0) 142 goto errout; 143 } 144 if (fields & T_UDATA) { 145 dsize = _T_MAX((int)info.CDATA_size, 146 (int)info.DDATA_size); 147 if (_alloc_buf(&p.call->udata, (t_scalar_t)dsize, 148 fields, api_semantics) < 0) 149 goto errout; 150 } 151 sig_mutex_unlock(&tiptr->ti_lock); 152 return ((char *)p.call); 153 154 case T_OPTMGMT: 155 if ((p.opt = calloc(1, sizeof (struct t_optmgmt))) == NULL) 156 goto errout; 157 if (fields & T_OPT) { 158 if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics)) 159 /* compensate for XTI level options */ 160 optsize = info.OPT_size + 161 TX_XTI_LEVEL_MAX_OPTBUF; 162 else 163 optsize = info.OPT_size; 164 if (_alloc_buf(&p.opt->opt, optsize, 165 fields, api_semantics) < 0) 166 goto errout; 167 } 168 sig_mutex_unlock(&tiptr->ti_lock); 169 return ((char *)p.opt); 170 171 case T_DIS: 172 if ((p.dis = calloc(1, sizeof (struct t_discon))) == NULL) 173 goto errout; 174 if (fields & T_UDATA) { 175 if (_alloc_buf(&p.dis->udata, info.DDATA_size, 176 fields, api_semantics) < 0) 177 goto errout; 178 } 179 sig_mutex_unlock(&tiptr->ti_lock); 180 return ((char *)p.dis); 181 182 case T_UNITDATA: 183 if ((p.udata = calloc(1, sizeof (struct t_unitdata))) == NULL) 184 goto errout; 185 if (fields & T_ADDR) { 186 if (_alloc_buf(&p.udata->addr, info.ADDR_size, 187 fields, api_semantics) < 0) 188 goto errout; 189 } 190 if (fields & T_OPT) { 191 if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics)) 192 /* compensate for XTI level options */ 193 optsize = info.OPT_size + 194 TX_XTI_LEVEL_MAX_OPTBUF; 195 else 196 optsize = info.OPT_size; 197 if (_alloc_buf(&p.udata->opt, optsize, 198 fields, api_semantics) < 0) 199 goto errout; 200 } 201 if (fields & T_UDATA) { 202 if (_alloc_buf(&p.udata->udata, info.TSDU_size, 203 fields, api_semantics) < 0) 204 goto errout; 205 } 206 sig_mutex_unlock(&tiptr->ti_lock); 207 return ((char *)p.udata); 208 209 case T_UDERROR: 210 if ((p.uderr = calloc(1, sizeof (struct t_uderr))) == NULL) 211 goto errout; 212 if (fields & T_ADDR) { 213 if (_alloc_buf(&p.uderr->addr, info.ADDR_size, 214 fields, api_semantics) < 0) 215 goto errout; 216 } 217 if (fields & T_OPT) { 218 if (info.OPT_size >= 0 && _T_IS_XTI(api_semantics)) 219 /* compensate for XTI level options */ 220 optsize = info.OPT_size + 221 TX_XTI_LEVEL_MAX_OPTBUF; 222 else 223 optsize = info.OPT_size; 224 if (_alloc_buf(&p.uderr->opt, optsize, 225 fields, api_semantics) < 0) 226 goto errout; 227 } 228 sig_mutex_unlock(&tiptr->ti_lock); 229 return ((char *)p.uderr); 230 231 case T_INFO: 232 if ((p.info = calloc(1, sizeof (struct t_info))) == NULL) 233 goto errout; 234 sig_mutex_unlock(&tiptr->ti_lock); 235 return ((char *)p.info); 236 237 default: 238 if (_T_IS_XTI(api_semantics)) { 239 t_errno = TNOSTRUCTYPE; 240 sig_mutex_unlock(&tiptr->ti_lock); 241 } else { /* TX_TLI_API */ 242 t_errno = TSYSERR; 243 sig_mutex_unlock(&tiptr->ti_lock); 244 errno = EINVAL; 245 } 246 return (NULL); 247 } 248 249 /* 250 * Clean up. Set t_errno to TSYSERR. 251 * If it is because memory could not be allocated 252 * then errno already should have been set to 253 * ENOMEM 254 */ 255 errout: 256 if (p.caddr) 257 (void) t_free(p.caddr, struct_type); 258 259 t_errno = TSYSERR; 260 sig_mutex_unlock(&tiptr->ti_lock); 261 return (NULL); 262 } 263 264 static int 265 _alloc_buf(struct netbuf *buf, t_scalar_t n, int fields, int api_semantics) 266 { 267 switch (n) { 268 case T_INFINITE /* -1 */: 269 if (_T_IS_XTI(api_semantics)) { 270 buf->buf = NULL; 271 buf->maxlen = 0; 272 if (fields != T_ALL) { 273 /* 274 * Do not return error 275 * if T_ALL is used. 276 */ 277 errno = EINVAL; 278 return (-1); 279 } 280 } else { /* TX_TLI_API */ 281 /* 282 * retain TLI behavior 283 */ 284 if ((buf->buf = calloc(1, 1024)) == NULL) { 285 errno = ENOMEM; 286 return (-1); 287 } else 288 buf->maxlen = 1024; 289 } 290 break; 291 292 case 0: 293 buf->buf = NULL; 294 buf->maxlen = 0; 295 break; 296 297 case T_INVALID /* -2 */: 298 if (_T_IS_XTI(api_semantics)) { 299 buf->buf = NULL; 300 buf->maxlen = 0; 301 if (fields != T_ALL) { 302 /* 303 * Do not return error 304 * if T_ALL is used. 305 */ 306 errno = EINVAL; 307 return (-1); 308 } 309 } else { /* TX_TLI_API */ 310 /* 311 * retain TLI behavior 312 */ 313 buf->buf = NULL; 314 buf->maxlen = 0; 315 } 316 break; 317 318 default: 319 if ((buf->buf = calloc(1, (size_t)n)) == NULL) { 320 errno = ENOMEM; 321 return (-1); 322 } else 323 buf->maxlen = n; 324 break; 325 } 326 return (0); 327 } 328