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