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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 /* 40 * TLI-like function to send datagrams over a specified 41 * transport endpoint. 42 * 43 * Returns: 44 * 0 on success or positive error code. 45 */ 46 47 #include <sys/param.h> 48 #include <sys/types.h> 49 #include <sys/user.h> 50 #include <sys/file.h> 51 #include <sys/errno.h> 52 #include <sys/stream.h> 53 #include <sys/strsubr.h> 54 #include <sys/vnode.h> 55 #include <sys/ioctl.h> 56 #include <sys/stropts.h> 57 #include <sys/tihdr.h> 58 #include <sys/timod.h> 59 #include <sys/tiuser.h> 60 #include <sys/t_kuser.h> 61 #include <sys/debug.h> 62 63 64 int 65 t_ksndudata(TIUSER *tiptr, struct t_kunitdata *unitdata, frtn_t *frtn) 66 { 67 int msgsz; 68 file_t *fp; 69 mblk_t *bp; 70 mblk_t *dbp; 71 struct T_unitdata_req *udreq; 72 int error; 73 int flag; 74 75 error = 0; 76 fp = tiptr->fp; 77 msgsz = unitdata->udata.len; 78 79 /* 80 * See if Class 0 is required 81 */ 82 if (frtn != NULL) { 83 ASSERT(unitdata->udata.udata_mp == NULL); 84 ASSERT(unitdata->udata.buf != NULL); 85 /* 86 * user has supplied their own buffer, all we have to 87 * do is allocate a class 0 streams buffer and set it 88 * up. 89 */ 90 if ((dbp = (mblk_t *)esballoc((uchar_t *)unitdata->udata.buf, 91 (size_t)msgsz, BPRI_LO, frtn)) == NULL) 92 return (ENOSR); 93 94 dbp->b_datap->db_type = M_DATA; 95 KTLILOG(2, "t_ksndudata: bp %x, ", dbp); 96 KTLILOG(2, "len %d, ", msgsz); 97 KTLILOG(2, "free func %x\n", frtn->free_func); 98 99 } else if (unitdata->udata.buf) { 100 ASSERT(unitdata->udata.udata_mp == NULL); 101 while (!(dbp = allocb(msgsz, BPRI_LO))) 102 if (strwaitbuf((size_t)msgsz, BPRI_LO)) 103 return (ENOSR); 104 105 bcopy(unitdata->udata.buf, dbp->b_wptr, unitdata->udata.len); 106 dbp->b_datap->db_type = M_DATA; 107 108 } else if (unitdata->udata.udata_mp) { 109 ASSERT(unitdata->udata.buf == NULL); 110 /* 111 * user has done it all 112 */ 113 dbp = unitdata->udata.udata_mp; 114 goto gotdp; 115 116 } else { 117 /* 118 * zero length message. 119 */ 120 dbp = NULL; 121 } 122 123 if (dbp) 124 dbp->b_wptr += msgsz; /* on behalf of the user */ 125 126 /* 127 * Okay, put the control part in 128 */ 129 gotdp: 130 msgsz = (int)TUNITDATAREQSZ; 131 /* 132 * Usually sendto()s are performed with the credential of the caller; 133 * in this particular case we specifically use the credential of 134 * the opener as this call is typically done in the context of a user 135 * process but on behalf of the kernel, e.g., a client connection 136 * to a server which is later shared by different users. 137 * At open time, we make sure to set fp->f_cred to kcred if such is 138 * the case. 139 * 140 * Note: if the receiver uses SCM_UCRED/getpeerucred the pid will 141 * appear as -1. 142 */ 143 while (!(bp = allocb_cred(msgsz + unitdata->addr.len + 144 unitdata->opt.len, fp->f_cred, NOPID))) { 145 if (strwaitbuf(msgsz + unitdata->addr.len + unitdata->opt.len, 146 BPRI_LO)) { 147 if (dbp && (dbp != unitdata->udata.udata_mp)) 148 freeb(dbp); 149 return (ENOSR); 150 } 151 } 152 153 /* LINTED pointer alignment */ 154 udreq = (struct T_unitdata_req *)bp->b_wptr; 155 udreq->PRIM_type = T_UNITDATA_REQ; 156 udreq->DEST_length = unitdata->addr.len; 157 if (unitdata->addr.len) { 158 bcopy(unitdata->addr.buf, bp->b_wptr + msgsz, 159 unitdata->addr.len); 160 udreq->DEST_offset = (t_scalar_t)msgsz; 161 msgsz += unitdata->addr.len; 162 } else 163 udreq->DEST_offset = 0; 164 165 udreq->OPT_length = unitdata->opt.len; 166 if (unitdata->opt.len) { 167 bcopy(unitdata->opt.buf, bp->b_wptr + msgsz, unitdata->opt.len); 168 udreq->OPT_offset = (t_scalar_t)msgsz; 169 msgsz += unitdata->opt.len; 170 } else 171 udreq->OPT_offset = 0; 172 173 bp->b_datap->db_type = M_PROTO; 174 bp->b_wptr += msgsz; 175 176 /* 177 * link the two. 178 */ 179 linkb(bp, dbp); 180 181 /* 182 * Put it to the transport provider. 183 * tli_send() always consumes the message. 184 */ 185 flag = fp->f_flag; 186 error = tli_send(tiptr, bp, flag); 187 unitdata->udata.udata_mp = NULL; 188 189 return (error); 190 } 191