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 #include <smbsrv/smb_incl.h> 61 #include <smbsrv/mbuf.h> 62 63 /* 64 * smb_mbuf_get 65 * 66 * Allocate mbufs to hold the amount of data specified. 67 * A pointer to the head of the mbuf list is returned. 68 */ 69 struct mbuf * 70 smb_mbuf_get(uchar_t *buf, int nbytes) 71 { 72 struct mbuf *mhead = 0; 73 struct mbuf *m = 0; 74 int count; 75 int offset = 0; 76 77 while (nbytes) { 78 count = (nbytes > MCLBYTES) ? MCLBYTES : nbytes; 79 nbytes -= count; 80 81 if (mhead == 0) { 82 MGET(mhead, M_WAIT, MT_DATA); 83 m = mhead; 84 } else { 85 MGET(m->m_next, M_WAIT, MT_DATA); 86 m = m->m_next; 87 } 88 89 if (count > MLEN) { 90 MCLGET(m, M_WAIT); 91 } 92 93 m->m_len = count; 94 bcopy(buf + offset, m->m_data, count); 95 offset += count; 96 } 97 return (mhead); 98 } 99 100 /* 101 * Allocate enough mbufs to accommodate the residual count in a uio. 102 */ 103 struct mbuf * 104 smb_mbuf_allocate(struct uio *uio) 105 { 106 struct iovec *iovp; 107 struct mbuf *mhead = 0; 108 struct mbuf *m = 0; 109 int count, iovs, resid; 110 111 iovp = uio->uio_iov; 112 iovs = uio->uio_iovcnt; 113 resid = uio->uio_resid; 114 115 while ((resid > 0) && (iovs > 0)) { 116 count = (resid > MCLBYTES) ? MCLBYTES : resid; 117 resid -= count; 118 119 if (mhead == 0) { 120 MGET(mhead, M_WAIT, MT_DATA); 121 m = mhead; 122 } else { 123 MGET(m->m_next, M_WAIT, MT_DATA); 124 m = m->m_next; 125 } 126 127 if (count > MLEN) { 128 MCLGET(m, M_WAIT); 129 } 130 131 iovp->iov_base = m->m_data; 132 iovp->iov_len = m->m_len = count; 133 iovs--; 134 iovp++; 135 } 136 137 uio->uio_iovcnt -= iovs; 138 return (mhead); 139 } 140 141 /* 142 * Trim an mbuf chain to nbytes. 143 */ 144 void 145 smb_mbuf_trim(struct mbuf *mhead, int nbytes) 146 { 147 struct mbuf *m = mhead; 148 149 while (m != 0) { 150 if (nbytes <= m->m_len) { 151 m->m_len = nbytes; 152 if (m->m_next != 0) { 153 m_freem(m->m_next); 154 m->m_next = 0; 155 } 156 break; 157 } 158 nbytes -= m->m_len; 159 m = m->m_next; 160 } 161 } 162 163 int 164 MBC_LENGTH(struct mbuf_chain *MBC) 165 { 166 struct mbuf *m = (MBC)->chain; 167 int used = 0; 168 169 while (m != 0) { 170 used += m->m_len; 171 m = m->m_next; 172 } 173 return (used); 174 } 175 176 int 177 MBC_MAXBYTES(struct mbuf_chain *MBC) 178 { 179 return (MBC->max_bytes); 180 } 181 182 void 183 MBC_SETUP(struct mbuf_chain *MBC, uint32_t max_bytes) 184 { 185 bzero((MBC), sizeof (struct mbuf_chain)); 186 (MBC)->max_bytes = max_bytes ? max_bytes : smb_maxbufsize; 187 } 188 189 void 190 MBC_INIT(struct mbuf_chain *MBC, uint32_t max_bytes) 191 { 192 struct mbuf *m; 193 194 bzero((MBC), sizeof (struct mbuf_chain)); 195 196 if (max_bytes != 0) { 197 MGET(m, M_WAIT, MT_DATA); 198 m->m_len = 0; 199 (MBC)->chain = m; 200 if (max_bytes > MINCLSIZE) 201 MCLGET(m, M_WAIT); 202 } 203 (MBC)->max_bytes = max_bytes; 204 } 205 206 void 207 MBC_FLUSH(struct mbuf_chain *MBC) 208 { 209 extern void m_freem(struct mbuf *); 210 struct mbuf *m; 211 212 while ((m = (MBC)->chain) != 0) { 213 (MBC)->chain = m->m_nextpkt; 214 m->m_nextpkt = 0; 215 m_freem(m); 216 } 217 MBC_SETUP(MBC, (MBC)->max_bytes); 218 } 219 220 void 221 MBC_ATTACH_MBUF(struct mbuf_chain *MBC, struct mbuf *MBUF) 222 { 223 if (MBC->chain != 0) 224 MBC_FLUSH(MBC); 225 226 (MBC)->chain_offset = 0; 227 (MBC)->chain = (MBUF); 228 } 229 230 void 231 MBC_APPEND_MBUF(struct mbuf_chain *MBC, struct mbuf *MBUF) 232 { 233 struct mbuf *m; 234 235 if ((MBC)->chain == 0) { 236 (MBC)->chain = (MBUF); 237 } else { 238 m = (MBC)->chain; 239 while (m->m_next != 0) 240 m = m->m_next; 241 m->m_next = (MBUF); 242 } 243 } 244 245 246 void 247 MBC_ATTACH_BUF(struct mbuf_chain *MBC, unsigned char *BUF, int LEN) 248 { 249 MGET((MBC)->chain, M_WAIT, MT_DATA); 250 (MBC)->chain_offset = 0; 251 (MBC)->chain->m_flags |= M_EXT; 252 (MBC)->chain->m_data = (caddr_t)(BUF); 253 (MBC)->chain->m_ext.ext_buf = (caddr_t)(BUF); 254 (MBC)->chain->m_len = (LEN); 255 (MBC)->chain->m_ext.ext_size = (LEN); 256 (MBC)->chain->m_ext.ext_ref = smb_noop; 257 (MBC)->max_bytes = (LEN); 258 } 259 260 261 int 262 MBC_SHADOW_CHAIN(struct mbuf_chain *SUBMBC, struct mbuf_chain *MBC, 263 int OFF, int LEN) 264 { 265 if (((OFF) + (LEN)) > (MBC)->max_bytes) 266 return (EMSGSIZE); 267 268 *(SUBMBC) = *(MBC); 269 (SUBMBC)->chain_offset = (OFF); 270 (SUBMBC)->max_bytes = (OFF) + (LEN); 271 (SUBMBC)->shadow_of = (MBC); 272 return (0); 273 } 274 275 int 276 mbc_moveout(mbuf_chain_t *mbc, caddr_t buf, int buflen, int *tlen) 277 { 278 int rc = 0; 279 int len = 0; 280 281 if ((mbc != NULL) && (mbc->chain != NULL)) { 282 mbuf_t *m; 283 284 m = mbc->chain; 285 while (m) { 286 if ((len + m->m_len) <= buflen) { 287 bcopy(m->m_data, buf, m->m_len); 288 buf += m->m_len; 289 len += m->m_len; 290 m = m->m_next; 291 continue; 292 } 293 rc = EMSGSIZE; 294 break; 295 } 296 m_freem(mbc->chain); 297 mbc->chain = NULL; 298 mbc->flags = 0; 299 } 300 *tlen = len; 301 return (rc); 302 } 303 304 /* 305 * Free a single mbuf structure. Calls m->m_ext.ext_ref() to free any 306 * associated external buffers if present (indicated by m->m_flags & M_EXT) 307 */ 308 struct mbuf * 309 m_free(struct mbuf *m) 310 { 311 struct mbuf *n; 312 313 MFREE(m, n); 314 return (n); 315 } 316 317 /* 318 * Free a list of mbufs. Each mbuf in the list is freed similarly to m_free. 319 */ 320 void 321 m_freem(struct mbuf *m) 322 { 323 struct mbuf *n; 324 325 if (m == NULL) 326 return; 327 /* 328 * Lint doesn't like the m = n assignment at the close of the loop 329 * but it is correct. MFREE assigns n = (m)->m_next so the loop 330 * is effectively assigning m = (m)->m_next then exiting when 331 * m == NULL 332 */ 333 do { 334 MFREE(m, n); 335 } while ((m = n) != 0); 336 } 337 338 /* 339 * Mbuffer utility routines. 340 */ 341 342 int /*ARGSUSED*/ 343 mclref(caddr_t p, int size, int adj) /* size, adj are unused */ 344 { 345 MEM_FREE("mbuf", p); 346 return (0); 347 } 348 349 int /*ARGSUSED*/ 350 mclrefnoop(caddr_t p, int size, int adj) /* p, size, adj are unused */ 351 { 352 return (0); 353 } 354