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.5 */ 33 34 /* 35 * t_sndudata.c and t_sndvudata.c are very similar and contain common code. 36 * Any changes to either of them should be reviewed to see whether they 37 * are applicable to the other file. 38 */ 39 #include "mt.h" 40 #include <rpc/trace.h> 41 #include <stdlib.h> 42 #include <errno.h> 43 #include <stropts.h> 44 #include <sys/stream.h> 45 #define _SUN_TPI_VERSION 2 46 #include <sys/tihdr.h> 47 #include <sys/timod.h> 48 #include <xti.h> 49 #include <syslog.h> 50 #include "tx.h" 51 52 int 53 _tx_sndudata(int fd, const struct t_unitdata *unitdata, int api_semantics) 54 { 55 struct T_unitdata_req *udreq; 56 struct strbuf ctlbuf; 57 int size; 58 struct _ti_user *tiptr; 59 int sv_errno; 60 int didalloc; 61 62 trace2(TR_t_sndudata, 0, fd); 63 if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL) { 64 sv_errno = errno; 65 trace2(TR_t_sndudata, 1, fd); 66 errno = sv_errno; 67 return (-1); 68 } 69 sig_mutex_lock(&tiptr->ti_lock); 70 71 if (tiptr->ti_servtype != T_CLTS) { 72 t_errno = TNOTSUPPORT; 73 sig_mutex_unlock(&tiptr->ti_lock); 74 trace2(TR_t_sndudata, 1, fd); 75 return (-1); 76 } 77 78 if (_T_IS_XTI(api_semantics)) { 79 /* 80 * User level state verification only done for XTI 81 * because doing for TLI may break existing applications 82 */ 83 if (tiptr->ti_state != T_IDLE) { 84 t_errno = TOUTSTATE; 85 sig_mutex_unlock(&tiptr->ti_lock); 86 trace2(TR_t_sndudata, 1, fd); 87 return (-1); 88 } 89 } 90 91 if (((int)unitdata->udata.len == 0) && 92 !(tiptr->ti_prov_flag & (SENDZERO|OLD_SENDZERO))) { 93 t_errno = TBADDATA; 94 sig_mutex_unlock(&tiptr->ti_lock); 95 trace2(TR_t_sndudata, 1, fd); 96 return (-1); 97 } 98 99 if ((tiptr->ti_maxpsz > 0) && 100 (unitdata->udata.len > (uint32_t)tiptr->ti_maxpsz)) { 101 if (_T_IS_TLI(api_semantics)) { 102 t_errno = TSYSERR; 103 errno = EPROTO; 104 } else 105 t_errno = TBADDATA; 106 sv_errno = errno; 107 sig_mutex_unlock(&tiptr->ti_lock); 108 trace2(TR_t_sndudata, 1, fd); 109 errno = sv_errno; 110 return (-1); 111 } 112 113 /* 114 * Acquire ctlbuf for use in sending/receiving control part 115 * of the message. 116 */ 117 if (_t_acquire_ctlbuf(tiptr, &ctlbuf, &didalloc) < 0) { 118 sv_errno = errno; 119 sig_mutex_unlock(&tiptr->ti_lock); 120 trace2(TR_t_sndudata, 1, fd); 121 errno = sv_errno; 122 return (-1); 123 } 124 125 udreq = (struct T_unitdata_req *)ctlbuf.buf; 126 127 udreq->PRIM_type = T_UNITDATA_REQ; 128 udreq->DEST_length = unitdata->addr.len; 129 udreq->DEST_offset = 0; 130 udreq->OPT_length = unitdata->opt.len; 131 udreq->OPT_offset = 0; 132 size = (int)sizeof (struct T_unitdata_req); 133 134 if (unitdata->addr.len) { 135 if (_t_aligned_copy(&ctlbuf, unitdata->addr.len, size, 136 unitdata->addr.buf, &udreq->DEST_offset) < 0) { 137 /* 138 * Aligned copy based will overflow buffer 139 * allocated based on maximum transport address 140 * size information 141 */ 142 t_errno = TSYSERR; 143 errno = EPROTO; 144 goto err_out; 145 } 146 size = udreq->DEST_offset + udreq->DEST_length; 147 } 148 if (unitdata->opt.len) { 149 if (_t_aligned_copy(&ctlbuf, unitdata->opt.len, size, 150 unitdata->opt.buf, &udreq->OPT_offset) < 0) { 151 /* 152 * Aligned copy based will overflow buffer 153 * allocated based on maximum transport option 154 * size information 155 */ 156 t_errno = TSYSERR; 157 errno = EPROTO; 158 goto err_out; 159 } 160 size = udreq->OPT_offset + udreq->OPT_length; 161 } 162 163 if (size > (int)ctlbuf.maxlen) { 164 t_errno = TSYSERR; 165 errno = EIO; 166 goto err_out; 167 } 168 169 ctlbuf.len = size; 170 171 /* 172 * Calls to send data (write or putmsg) can potentially 173 * block, for MT case, we drop the lock and enable signals here 174 * and acquire it back. 175 * At this point, we are sure SENDZERO is supported and the 176 * putmsg below may send a zero length message, 177 * (i.e with valid control part, but zero data part) 178 */ 179 sig_mutex_unlock(&tiptr->ti_lock); 180 if (putmsg(fd, &ctlbuf, (struct strbuf *)&unitdata->udata, 0) < 0) { 181 if (errno == EAGAIN) 182 t_errno = TFLOW; 183 else 184 t_errno = TSYSERR; 185 sv_errno = errno; 186 sig_mutex_lock(&tiptr->ti_lock); 187 errno = sv_errno; 188 goto err_out; 189 } 190 sig_mutex_lock(&tiptr->ti_lock); 191 192 _T_TX_NEXTSTATE(T_SNDUDATA, tiptr, 193 "t_sndudata: invalid state event T_SNDUDATA"); 194 if (didalloc) 195 free(ctlbuf.buf); 196 else 197 tiptr->ti_ctlbuf = ctlbuf.buf; 198 sig_mutex_unlock(&tiptr->ti_lock); 199 trace2(TR_t_sndudata, 1, fd); 200 return (0); 201 err_out: 202 sv_errno = errno; 203 if (didalloc) 204 free(ctlbuf.buf); 205 else 206 tiptr->ti_ctlbuf = ctlbuf.buf; 207 sig_mutex_unlock(&tiptr->ti_lock); 208 trace2(TR_t_sndudata, 1, fd); 209 errno = sv_errno; 210 return (-1); 211 } 212