Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / ktli / t_ksndudat.c
blobc5d443548d13ae11effdeae7ff3f5d17c6448512
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
32 * All Rights Reserved
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
36 * contributors.
40 * TLI-like function to send datagrams over a specified
41 * transport endpoint.
43 * Returns:
44 * 0 on success or positive error code.
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>
64 int
65 t_ksndudata(TIUSER *tiptr, struct t_kunitdata *unitdata, frtn_t *frtn)
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;
75 error = 0;
76 fp = tiptr->fp;
77 msgsz = unitdata->udata.len;
80 * See if Class 0 is required
82 if (frtn != NULL) {
83 ASSERT(unitdata->udata.udata_mp == NULL);
84 ASSERT(unitdata->udata.buf != NULL);
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.
90 if ((dbp = (mblk_t *)esballoc((uchar_t *)unitdata->udata.buf,
91 (size_t)msgsz, BPRI_LO, frtn)) == NULL)
92 return (ENOSR);
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);
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);
105 bcopy(unitdata->udata.buf, dbp->b_wptr, unitdata->udata.len);
106 dbp->b_datap->db_type = M_DATA;
108 } else if (unitdata->udata.udata_mp) {
109 ASSERT(unitdata->udata.buf == NULL);
111 * user has done it all
113 dbp = unitdata->udata.udata_mp;
114 goto gotdp;
116 } else {
118 * zero length message.
120 dbp = NULL;
123 if (dbp)
124 dbp->b_wptr += msgsz; /* on behalf of the user */
127 * Okay, put the control part in
129 gotdp:
130 msgsz = (int)TUNITDATAREQSZ;
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.
140 * Note: if the receiver uses SCM_UCRED/getpeerucred the pid will
141 * appear as -1.
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);
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;
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;
173 bp->b_datap->db_type = M_PROTO;
174 bp->b_wptr += msgsz;
177 * link the two.
179 linkb(bp, dbp);
182 * Put it to the transport provider.
183 * tli_send() always consumes the message.
185 flag = fp->f_flag;
186 error = tli_send(tiptr, bp, flag);
187 unitdata->udata.udata_mp = NULL;
189 return (error);