xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c (revision 03100a6332bd4edc7a53091fcf7c9a7131bcdaa7)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * Copyright (c) 1982, 1986, 1988, 1991, 1993
28  *	The Regents of the University of California.  All rights reserved.
29  *
30  * Redistribution and use in source and binary forms, with or without
31  * modification, are permitted provided that the following conditions
32  * are met:
33  * 1. Redistributions of source code must retain the above copyright
34  *    notice, this list of conditions and the following disclaimer.
35  * 2. Redistributions in binary form must reproduce the above copyright
36  *    notice, this list of conditions and the following disclaimer in the
37  *    documentation and/or other materials provided with the distribution.
38  * 3. All advertising materials mentioning features or use of this software
39  *    must display the following acknowledgement:
40  *	This product includes software developed by the University of
41  *	California, Berkeley and its contributors.
42  * 4. Neither the name of the University nor the names of its contributors
43  *    may be used to endorse or promote products derived from this software
44  *    without specific prior written permission.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  *
58  */
59 
60 #pragma ident	"%Z%%M%	%I%	%E% SMI"
61 
62 /*
63  * MLRPC server-side library processing. This is where we decode the
64  * request header to figure out what type of request is being made,
65  * call the server stub, if appropriate, and build the response header.
66  */
67 
68 #include <smbsrv/smb_incl.h>
69 #include <smbsrv/mbuf.h>
70 
71 /*
72  * Fragment size (5680: NT style). Tuning parameter
73  * used during development of multiple fragment support.
74  */
75 
76 #define	MLRPC_FRAG_SIZE 5680
77 #define	MLRPC_RSP_HDR_SIZE 24
78 
79 /*
80  * smb_mbuf_get
81  *
82  * Allocate mbufs to hold the amount of data specified.
83  * A pointer to the head of the mbuf list is returned.
84  */
85 struct mbuf *
86 smb_mbuf_get(uchar_t *buf, int nbytes)
87 {
88 	struct mbuf *mhead = 0;
89 	struct mbuf *m = 0;
90 	int count;
91 	int offset = 0;
92 
93 	while (nbytes) {
94 		count = (nbytes > MCLBYTES) ? MCLBYTES : nbytes;
95 		nbytes -= count;
96 
97 		if (mhead == 0) {
98 			MGET(mhead, M_WAIT, MT_DATA);
99 			m = mhead;
100 		} else {
101 			MGET(m->m_next, M_WAIT, MT_DATA);
102 			m = m->m_next;
103 		}
104 
105 		if (count > MLEN) {
106 			MCLGET(m, M_WAIT);
107 		}
108 
109 		m->m_len = count;
110 		bcopy(buf + offset, m->m_data, count);
111 		offset += count;
112 	}
113 	return (mhead);
114 }
115 
116 /*
117  * Allocate enough mbufs to accommodate the residual count in a uio.
118  */
119 struct mbuf *
120 smb_mbuf_allocate(struct uio *uio)
121 {
122 	struct iovec *iovp;
123 	struct mbuf	*mhead = 0;
124 	struct mbuf	*m = 0;
125 	int	count, iovs, resid;
126 
127 	iovp = uio->uio_iov;
128 	iovs = uio->uio_iovcnt;
129 	resid = uio->uio_resid;
130 
131 	while ((resid > 0) && (iovs > 0)) {
132 		count = (resid > MCLBYTES) ? MCLBYTES : resid;
133 		resid -= count;
134 
135 		if (mhead == 0) {
136 			MGET(mhead, M_WAIT, MT_DATA);
137 			m = mhead;
138 		} else {
139 			MGET(m->m_next, M_WAIT, MT_DATA);
140 			m = m->m_next;
141 		}
142 
143 		if (count > MLEN) {
144 			MCLGET(m, M_WAIT);
145 		}
146 
147 		iovp->iov_base = m->m_data;
148 		iovp->iov_len = m->m_len = count;
149 		iovs--;
150 		iovp++;
151 	}
152 
153 	uio->uio_iovcnt -= iovs;
154 	return (mhead);
155 }
156 
157 /*
158  * Trim an mbuf chain to nbytes.
159  */
160 void
161 smb_mbuf_trim(struct mbuf *mhead, int nbytes)
162 {
163 	struct mbuf	*m = mhead;
164 
165 	while (m != 0) {
166 		if (nbytes <= m->m_len) {
167 			m->m_len = nbytes;
168 			if (m->m_next != 0) {
169 				m_freem(m->m_next);
170 				m->m_next = 0;
171 			}
172 			break;
173 		}
174 		nbytes -= m->m_len;
175 		m = m->m_next;
176 	}
177 }
178 
179 int
180 MBC_LENGTH(struct mbuf_chain *MBC)
181 {
182 	struct mbuf	*m = (MBC)->chain;
183 	int		used = 0;
184 
185 	while (m != 0) {
186 		used += m->m_len;
187 		m = m->m_next;
188 	}
189 	return (used);
190 }
191 
192 void
193 MBC_SETUP(struct mbuf_chain *MBC, uint32_t max_bytes)
194 {
195 	bzero((MBC), sizeof (struct mbuf_chain));
196 	(MBC)->max_bytes = max_bytes ? max_bytes : smb_maxbufsize;
197 }
198 
199 void
200 MBC_INIT(struct mbuf_chain *MBC, uint32_t max_bytes)
201 {
202 	struct mbuf *m;
203 
204 	bzero((MBC), sizeof (struct mbuf_chain));
205 
206 	if (max_bytes != 0) {
207 		MGET(m, M_WAIT, MT_DATA);
208 		m->m_len = 0;
209 		(MBC)->chain = m;
210 		if (max_bytes > MINCLSIZE)
211 			MCLGET(m, M_WAIT);
212 	}
213 	(MBC)->max_bytes = max_bytes;
214 }
215 
216 void
217 MBC_FLUSH(struct mbuf_chain *MBC)
218 {
219 	extern void	m_freem(struct mbuf *);
220 	struct mbuf	*m;
221 
222 	while ((m = (MBC)->chain) != 0) {
223 		(MBC)->chain = m->m_nextpkt;
224 		m->m_nextpkt = 0;
225 		m_freem(m);
226 	}
227 	MBC_SETUP(MBC, (MBC)->max_bytes);
228 }
229 
230 void
231 MBC_ATTACH_MBUF(struct mbuf_chain *MBC, struct mbuf *MBUF)
232 {
233 	if (MBC->chain != 0)
234 		MBC_FLUSH(MBC);
235 
236 	(MBC)->chain_offset = 0;
237 	(MBC)->chain = (MBUF);
238 }
239 
240 void
241 MBC_APPEND_MBUF(struct mbuf_chain *MBC, struct mbuf *MBUF)
242 {
243 	struct mbuf	*m;
244 
245 	if ((MBC)->chain == 0) {
246 		(MBC)->chain = (MBUF);
247 	} else {
248 		m = (MBC)->chain;
249 		while (m->m_next != 0)
250 			m = m->m_next;
251 		m->m_next = (MBUF);
252 	}
253 }
254 
255 
256 void
257 MBC_ATTACH_BUF(struct mbuf_chain *MBC, unsigned char *BUF, int LEN)
258 {
259 	MGET((MBC)->chain, M_WAIT, MT_DATA);
260 	(MBC)->chain_offset = 0;
261 	(MBC)->chain->m_flags |= M_EXT;
262 	(MBC)->chain->m_data = (caddr_t)(BUF);
263 	(MBC)->chain->m_ext.ext_buf = (caddr_t)(BUF);
264 	(MBC)->chain->m_len = (LEN);
265 	(MBC)->chain->m_ext.ext_size = (LEN);
266 	(MBC)->chain->m_ext.ext_ref = smb_noop;
267 	(MBC)->max_bytes = (LEN);
268 }
269 
270 
271 int
272 MBC_SHADOW_CHAIN(struct mbuf_chain *SUBMBC, struct mbuf_chain *MBC,
273     int OFF, int LEN)
274 {
275 	if (((OFF) + (LEN)) > (MBC)->max_bytes)
276 		return (EMSGSIZE);
277 
278 	*(SUBMBC) = *(MBC);
279 	(SUBMBC)->chain_offset = (OFF);
280 	(SUBMBC)->max_bytes = (OFF) + (LEN);
281 	(SUBMBC)->shadow_of = (MBC);
282 	return (0);
283 }
284 
285 /*
286  * Free a single mbuf structure.  Calls m->m_ext.ext_ref() to free any
287  * associated external buffers if present (indicated by m->m_flags & M_EXT)
288  */
289 struct mbuf *
290 m_free(struct mbuf *m)
291 {
292 	struct mbuf *n;
293 
294 	MFREE(m, n);
295 	return (n);
296 }
297 
298 /*
299  * Free a list of mbufs.  Each mbuf in the list is freed similarly to m_free.
300  */
301 void
302 m_freem(struct mbuf *m)
303 {
304 	struct mbuf *n;
305 
306 	if (m == NULL)
307 		return;
308 	/*
309 	 * Lint doesn't like the m = n assignment at the close of the loop
310 	 * but it is correct.  MFREE assigns n = (m)->m_next so the loop
311 	 * is effectively assigning m = (m)->m_next then exiting when
312 	 * m == NULL
313 	 */
314 	do {
315 		MFREE(m, n);
316 	} while ((m = n) != 0);
317 }
318 
319 /*
320  * Mbuffer utility routines.
321  */
322 
323 int /*ARGSUSED*/
324 mclref(caddr_t p, int size, int adj) /* size, adj are unused */
325 {
326 	MEM_FREE("mbuf", p);
327 	return (0);
328 }
329 
330 int /*ARGSUSED*/
331 mclrefnoop(caddr_t p, int size, int adj) /* p, size, adj are unused */
332 {
333 	return (0);
334 }
335