xref: /illumos-gate/usr/src/uts/common/ktli/t_ksndudat.c (revision 8b80e8cb6855118d46f605e91b5ed4ce83417395)
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