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 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 int 286 mbc_moveout(mbuf_chain_t *mbc, caddr_t buf, int buflen, int *tlen) 287 { 288 int rc = 0; 289 int len = 0; 290 291 if ((mbc != NULL) && (mbc->chain != NULL)) { 292 mbuf_t *m; 293 294 m = mbc->chain; 295 while (m) { 296 if ((len + m->m_len) <= buflen) { 297 bcopy(m->m_data, buf, m->m_len); 298 buf += m->m_len; 299 len += m->m_len; 300 m = m->m_next; 301 continue; 302 } 303 rc = EMSGSIZE; 304 break; 305 } 306 m_freem(mbc->chain); 307 mbc->chain = NULL; 308 mbc->flags = 0; 309 } 310 *tlen = len; 311 return (rc); 312 } 313 314 /* 315 * Free a single mbuf structure. Calls m->m_ext.ext_ref() to free any 316 * associated external buffers if present (indicated by m->m_flags & M_EXT) 317 */ 318 struct mbuf * 319 m_free(struct mbuf *m) 320 { 321 struct mbuf *n; 322 323 MFREE(m, n); 324 return (n); 325 } 326 327 /* 328 * Free a list of mbufs. Each mbuf in the list is freed similarly to m_free. 329 */ 330 void 331 m_freem(struct mbuf *m) 332 { 333 struct mbuf *n; 334 335 if (m == NULL) 336 return; 337 /* 338 * Lint doesn't like the m = n assignment at the close of the loop 339 * but it is correct. MFREE assigns n = (m)->m_next so the loop 340 * is effectively assigning m = (m)->m_next then exiting when 341 * m == NULL 342 */ 343 do { 344 MFREE(m, n); 345 } while ((m = n) != 0); 346 } 347 348 /* 349 * Mbuffer utility routines. 350 */ 351 352 int /*ARGSUSED*/ 353 mclref(caddr_t p, int size, int adj) /* size, adj are unused */ 354 { 355 MEM_FREE("mbuf", p); 356 return (0); 357 } 358 359 int /*ARGSUSED*/ 360 mclrefnoop(caddr_t p, int size, int adj) /* p, size, adj are unused */ 361 { 362 return (0); 363 } 364