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 2005 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.5 */ 32 33 #include "mt.h" 34 #include <errno.h> 35 #include <string.h> 36 #include <stdlib.h> 37 #include <stropts.h> 38 #include <sys/stream.h> 39 #define _SUN_TPI_VERSION 2 40 #include <sys/tihdr.h> 41 #include <sys/timod.h> 42 #include <xti.h> 43 #include <syslog.h> 44 #include <assert.h> 45 #include "tx.h" 46 47 int 48 _tx_rcvuderr(int fd, struct t_uderr *uderr, int api_semantics) 49 { 50 struct strbuf ctlbuf, databuf; 51 int flg; 52 int retval; 53 union T_primitives *pptr; 54 struct _ti_user *tiptr; 55 int sv_errno; 56 int didalloc; 57 int use_lookbufs = 0; 58 59 60 if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL) 61 return (-1); 62 sig_mutex_lock(&tiptr->ti_lock); 63 64 if (tiptr->ti_servtype != T_CLTS) { 65 t_errno = TNOTSUPPORT; 66 sig_mutex_unlock(&tiptr->ti_lock); 67 return (-1); 68 } 69 /* 70 * is there a unitdata error indication in look buffer 71 */ 72 if (tiptr->ti_lookcnt > 0) { 73 ctlbuf.len = tiptr->ti_lookbufs.tl_lookclen; 74 ctlbuf.buf = tiptr->ti_lookbufs.tl_lookcbuf; 75 /* Note: cltbuf.maxlen not used in this case */ 76 77 /* LINTED pointer cast */ 78 assert(((union T_primitives *)ctlbuf.buf)->type 79 == T_UDERROR_IND); 80 81 databuf.maxlen = 0; 82 databuf.len = 0; 83 databuf.buf = NULL; 84 85 use_lookbufs = 1; 86 87 } else { 88 if ((retval = _t_look_locked(fd, tiptr, 0, 89 api_semantics)) < 0) { 90 sv_errno = errno; 91 sig_mutex_unlock(&tiptr->ti_lock); 92 errno = sv_errno; 93 return (-1); 94 } 95 if (retval != T_UDERR) { 96 t_errno = TNOUDERR; 97 sig_mutex_unlock(&tiptr->ti_lock); 98 return (-1); 99 } 100 101 /* 102 * Acquire ctlbuf for use in sending/receiving control part 103 * of the message. 104 */ 105 if (_t_acquire_ctlbuf(tiptr, &ctlbuf, &didalloc) < 0) { 106 sv_errno = errno; 107 sig_mutex_unlock(&tiptr->ti_lock); 108 errno = sv_errno; 109 return (-1); 110 } 111 112 databuf.maxlen = 0; 113 databuf.len = 0; 114 databuf.buf = NULL; 115 116 flg = 0; 117 118 /* 119 * Since we already verified that a unitdata error 120 * indication is pending, we assume that this getmsg() 121 * will not block indefinitely. 122 */ 123 if ((retval = getmsg(fd, &ctlbuf, &databuf, &flg)) < 0) { 124 125 t_errno = TSYSERR; 126 goto err_out; 127 } 128 /* 129 * did I get entire message? 130 */ 131 if (retval > 0) { 132 t_errno = TSYSERR; 133 errno = EIO; 134 goto err_out; 135 } 136 137 } 138 139 /* LINTED pointer cast */ 140 pptr = (union T_primitives *)ctlbuf.buf; 141 142 if ((ctlbuf.len < (int)sizeof (struct T_uderror_ind)) || 143 (pptr->type != T_UDERROR_IND)) { 144 t_errno = TSYSERR; 145 errno = EPROTO; 146 goto err_out; 147 } 148 149 if (uderr) { 150 if (_T_IS_TLI(api_semantics) || uderr->addr.maxlen > 0) { 151 if (TLEN_GT_NLEN(pptr->uderror_ind.DEST_length, 152 uderr->addr.maxlen)) { 153 t_errno = TBUFOVFLW; 154 goto err_out; 155 } 156 (void) memcpy(uderr->addr.buf, ctlbuf.buf + 157 pptr->uderror_ind.DEST_offset, 158 (size_t)pptr->uderror_ind.DEST_length); 159 uderr->addr.len = 160 (unsigned int)pptr->uderror_ind.DEST_length; 161 } 162 if (_T_IS_TLI(api_semantics) || uderr->addr.maxlen > 0) { 163 if (TLEN_GT_NLEN(pptr->uderror_ind.OPT_length, 164 uderr->opt.maxlen)) { 165 t_errno = TBUFOVFLW; 166 goto err_out; 167 } 168 (void) memcpy(uderr->opt.buf, ctlbuf.buf + 169 pptr->uderror_ind.OPT_offset, 170 (size_t)pptr->uderror_ind.OPT_length); 171 uderr->opt.len = 172 (unsigned int)pptr->uderror_ind.OPT_length; 173 } 174 uderr->error = pptr->uderror_ind.ERROR_type; 175 } 176 177 _T_TX_NEXTSTATE(T_RCVUDERR, tiptr, 178 "t_rcvuderr: invalid state event T_RCVUDERR"); 179 if (use_lookbufs) 180 _t_free_looklist_head(tiptr); 181 else { 182 if (didalloc) 183 free(ctlbuf.buf); 184 else 185 tiptr->ti_ctlbuf = ctlbuf.buf; 186 } 187 sig_mutex_unlock(&tiptr->ti_lock); 188 return (0); 189 190 err_out: 191 sv_errno = errno; 192 193 if (use_lookbufs) 194 _t_free_looklist_head(tiptr); 195 else { 196 if (didalloc) 197 free(ctlbuf.buf); 198 else 199 tiptr->ti_ctlbuf = ctlbuf.buf; 200 } 201 sig_mutex_unlock(&tiptr->ti_lock); 202 errno = sv_errno; 203 return (-1); 204 } 205