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 2008 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 int 193 MBC_MAXBYTES(struct mbuf_chain *MBC) 194 { 195 return (MBC->max_bytes); 196 } 197 198 void 199 MBC_SETUP(struct mbuf_chain *MBC, uint32_t max_bytes) 200 { 201 bzero((MBC), sizeof (struct mbuf_chain)); 202 (MBC)->max_bytes = max_bytes ? max_bytes : smb_maxbufsize; 203 } 204 205 void 206 MBC_INIT(struct mbuf_chain *MBC, uint32_t max_bytes) 207 { 208 struct mbuf *m; 209 210 bzero((MBC), sizeof (struct mbuf_chain)); 211 212 if (max_bytes != 0) { 213 MGET(m, M_WAIT, MT_DATA); 214 m->m_len = 0; 215 (MBC)->chain = m; 216 if (max_bytes > MINCLSIZE) 217 MCLGET(m, M_WAIT); 218 } 219 (MBC)->max_bytes = max_bytes; 220 } 221 222 void 223 MBC_FLUSH(struct mbuf_chain *MBC) 224 { 225 extern void m_freem(struct mbuf *); 226 struct mbuf *m; 227 228 while ((m = (MBC)->chain) != 0) { 229 (MBC)->chain = m->m_nextpkt; 230 m->m_nextpkt = 0; 231 m_freem(m); 232 } 233 MBC_SETUP(MBC, (MBC)->max_bytes); 234 } 235 236 void 237 MBC_ATTACH_MBUF(struct mbuf_chain *MBC, struct mbuf *MBUF) 238 { 239 if (MBC->chain != 0) 240 MBC_FLUSH(MBC); 241 242 (MBC)->chain_offset = 0; 243 (MBC)->chain = (MBUF); 244 } 245 246 void 247 MBC_APPEND_MBUF(struct mbuf_chain *MBC, struct mbuf *MBUF) 248 { 249 struct mbuf *m; 250 251 if ((MBC)->chain == 0) { 252 (MBC)->chain = (MBUF); 253 } else { 254 m = (MBC)->chain; 255 while (m->m_next != 0) 256 m = m->m_next; 257 m->m_next = (MBUF); 258 } 259 } 260 261 262 void 263 MBC_ATTACH_BUF(struct mbuf_chain *MBC, unsigned char *BUF, int LEN) 264 { 265 MGET((MBC)->chain, M_WAIT, MT_DATA); 266 (MBC)->chain_offset = 0; 267 (MBC)->chain->m_flags |= M_EXT; 268 (MBC)->chain->m_data = (caddr_t)(BUF); 269 (MBC)->chain->m_ext.ext_buf = (caddr_t)(BUF); 270 (MBC)->chain->m_len = (LEN); 271 (MBC)->chain->m_ext.ext_size = (LEN); 272 (MBC)->chain->m_ext.ext_ref = smb_noop; 273 (MBC)->max_bytes = (LEN); 274 } 275 276 277 int 278 MBC_SHADOW_CHAIN(struct mbuf_chain *SUBMBC, struct mbuf_chain *MBC, 279 int OFF, int LEN) 280 { 281 if (((OFF) + (LEN)) > (MBC)->max_bytes) 282 return (EMSGSIZE); 283 284 *(SUBMBC) = *(MBC); 285 (SUBMBC)->chain_offset = (OFF); 286 (SUBMBC)->max_bytes = (OFF) + (LEN); 287 (SUBMBC)->shadow_of = (MBC); 288 return (0); 289 } 290 291 int 292 mbc_moveout(mbuf_chain_t *mbc, caddr_t buf, int buflen, int *tlen) 293 { 294 int rc = 0; 295 int len = 0; 296 297 if ((mbc != NULL) && (mbc->chain != NULL)) { 298 mbuf_t *m; 299 300 m = mbc->chain; 301 while (m) { 302 if ((len + m->m_len) <= buflen) { 303 bcopy(m->m_data, buf, m->m_len); 304 buf += m->m_len; 305 len += m->m_len; 306 m = m->m_next; 307 continue; 308 } 309 rc = EMSGSIZE; 310 break; 311 } 312 m_freem(mbc->chain); 313 mbc->chain = NULL; 314 mbc->flags = 0; 315 } 316 *tlen = len; 317 return (rc); 318 } 319 320 /* 321 * Free a single mbuf structure. Calls m->m_ext.ext_ref() to free any 322 * associated external buffers if present (indicated by m->m_flags & M_EXT) 323 */ 324 struct mbuf * 325 m_free(struct mbuf *m) 326 { 327 struct mbuf *n; 328 329 MFREE(m, n); 330 return (n); 331 } 332 333 /* 334 * Free a list of mbufs. Each mbuf in the list is freed similarly to m_free. 335 */ 336 void 337 m_freem(struct mbuf *m) 338 { 339 struct mbuf *n; 340 341 if (m == NULL) 342 return; 343 /* 344 * Lint doesn't like the m = n assignment at the close of the loop 345 * but it is correct. MFREE assigns n = (m)->m_next so the loop 346 * is effectively assigning m = (m)->m_next then exiting when 347 * m == NULL 348 */ 349 do { 350 MFREE(m, n); 351 } while ((m = n) != 0); 352 } 353 354 /* 355 * Mbuffer utility routines. 356 */ 357 358 int /*ARGSUSED*/ 359 mclref(caddr_t p, int size, int adj) /* size, adj are unused */ 360 { 361 MEM_FREE("mbuf", p); 362 return (0); 363 } 364 365 int /*ARGSUSED*/ 366 mclrefnoop(caddr_t p, int size, int adj) /* p, size, adj are unused */ 367 { 368 return (0); 369 } 370