subr_mchain.c revision 613a2f6ba31e891e3d947a356daf5e563d43c1ce
/*
* Copyright (c) 2000, 2001 Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Boris Popov.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/kern/subr_mchain.c,v 1.1 2001/02/24 15:44:29 bp Exp $
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifdef APPLE
#include <sys/smb_apple.h>
#else
#include <netsmb/smb_osdep.h>
#endif
#include <netsmb/smb_conn.h>
#include <netsmb/smb_subr.h>
/* BEGIN CSTYLED */
/*
* BSD-style mbufs, vs SysV-style mblks:
* One big difference: the mbuf payload is:
* m_data ... (m_data + m_len)
* In Unix STREAMS, the mblk payload is:
* b_rptr ... b_wptr
*
* Here are some handy conversion notes:
*
* struct mbuf struct mblk
* m->m_next m->b_cont
* m->m_nextpkt m->b_next
* m->m_data m->b_rptr
* m->m_len MBLKL(m)
* m->m_dat[] m->b_datap->db_base
* &m->m_dat[MLEN] m->b_datap->db_lim
* M_TRAILINGSPACE(m) MBLKTAIL(m)
* m_freem(m) freemsg(m)
*
* Note that mbufs chains also have a special "packet" header,
* which has the length of the whole message. In STREAMS one
* typically just calls msgdsize(m) to get that.
*/
/* END CSTYLED */
/*
*
* MODULE_VERSION(libmchain, 1);
*/
#ifdef __GNUC__
#else
#define MBERROR(...) \
#define MBPANIC(...) \
#endif
/*
* MLEN: The smallest mblk we'll allocate.
*
* There's more to MLEN than you might think.
* Some ethernet drivers may send each mblk as a
* separate frame, so we want MLEN at least 1K.
* We could have used 1K here, but that might
* hurt transports that support larger frames.
* 4K fits nicely in 3 Ethernet frames (3 * 1500)
* leaving about 500 bytes for protocol headers.
*
* XXX: Would Ethernet drivers be happier
* (more efficient) if we used 1K here?
*/
#define MLEN 4096
/*
* Some UIO routines.
* Taken from Darwin Sourcecs.
*/
/*
* uio_isuserspace - non zero value if the address space
* flag is for a user address space (could be 32 or 64 bit).
*/
/*
* uio_curriovbase - return the base address of the current iovec associated
* with the given uio_t. May return 0.
*/
{
return (0);
}
}
/*
* uio_curriovlen - return the length value of the current iovec associated
* with the given uio_t.
*/
{
return (0);
}
}
/*
* uio_update - update the given uio_t for a_count of completed IO.
* This call decrements the current iovec length and residual IO value
* and increments the current iovec base address and offset value.
* If the current iovec length is 0 then advance to the next
* iovec (if any).
* If the a_count passed in is 0, than only do the advancement
* over any 0 length iovec's.
*/
void
{
return;
}
/*
* if a_count == 0, then we are asking to skip over
* any empty iovs
*/
if (a_count) {
} else {
}
}
} else {
}
}
/*
* advance to next iovec if current one is totally consumed
*/
a_uio->uio_iovcnt--;
if (a_uio->uio_iovcnt > 0) {
}
}
}
/*
* This is now used only to extend an existing mblk chain,
* so don't need to use allocb_cred_wait here.
*/
/*ARGSUSED*/
mblk_t *
{
int error;
/* Make size at least MLEN. */
return (mblk);
}
void
{
}
/* Avoid dangling references */
}
unsigned int
{
return ((unsigned int)diff);
}
void
{
}
int
{
int error;
/*
* This message will be the head of a new mblk chain,
* so we'd like its db_credp set. If we extend this
* chain later, we'll just use allocb_wait()
*/
cr = ddi_get_cred();
/*
* Leave room in this first mblk so we can
* prepend a 4-byte NetBIOS header.
* See smb_nbst_send()
*/
return (0);
}
/*
* mb_detach() function returns the value of mbp->mb_top field
* and sets its * value to NULL.
*/
mblk_t *
{
mblk_t *m;
return (m);
}
/*
* Returns the length of the mblk_t data.
* Should be m_totlen() perhaps?
*/
int
{
return ((int)dsz);
}
/*
* BSD code set the message header length here, and
* returned the length. We don't have that field, so
* just return the message length.
*/
int
{
}
/*
* Check if object of size 'size' fit to the current position and
* allocate new mbuf if not. Advance pointers and increase len. of mbuf(s).
* Return pointer to the object placeholder or NULL if any error occured.
* Note: size should be <= MLEN
*/
void *
{
void *bpos;
/*
* If the requested size is more than the space left.
* Allocate and appenad a new mblk.
*/
return (NULL);
m = mn;
}
/*
* If 'size' bytes fits into the buffer, then
* 1. increment the write pointer to the size.
* 2. return the position from where the memory is reserved.
*/
return (bpos);
}
/*
* All mb_put_*() functions perform an actual copy of the data into mbuf
* chain. Functions which have le or be suffixes will perform conversion to
* the little- or big-endian data formats.
*
* Inline version of mb_put_mem(). Handles the easy case in-line,
* and calls mb_put_mem() if crossing mblk boundaries, etc.
*
* We build with -xspace, which causes these inline functions
* to not be inlined. Using macros instead for now.
*/
#ifdef INLINE_WORKS
static inline int
{
int n = size;
while (n--)
*(m->b_wptr)++ = *p++;
return (0);
}
}
#else /* INLINE_WORKS */
int n = SZ; \
while (n--) \
*(m->b_wptr)++ = *p++; \
return (0); \
} \
#endif /* INLINE_WORKS */
/*
* Assumes total data length in previous mblks is EVEN.
* Might need to compute the offset from mb_top instead.
*/
int
{
char v = 0;
/* only add padding if address is odd */
if (dst & 1) {
MB_PUT_INLINE(mbp, &v, sizeof (v));
}
return (0);
}
int
{
u_int8_t v = x;
MB_PUT_INLINE(mbp, &v, sizeof (v));
}
int
{
MB_PUT_INLINE(mbp, &v, sizeof (v));
}
int
{
MB_PUT_INLINE(mbp, &v, sizeof (v));
}
int
{
MB_PUT_INLINE(mbp, &v, sizeof (v));
}
int
{
MB_PUT_INLINE(mbp, &v, sizeof (v));
}
int
{
MB_PUT_INLINE(mbp, &v, sizeof (v));
}
int
{
MB_PUT_INLINE(mbp, &v, sizeof (v));
}
/*
* mb_put_mem() function copies size bytes of data specified by the source
* argument to an mbuf chain. The type argument specifies the method used
* to perform a copy
*/
int
{
while (size > 0) {
if (mleft == 0) {
/*
* Changed m_getm() to m_getblk()
* with the requested size, so we
* don't need m_getm() anymore.
*/
if (n == NULL)
return (ENOBUFS);
m->b_cont = n;
}
m = m->b_cont;
continue;
}
switch (type) {
case MB_MINLINE:
break;
case MB_MSYSTEM:
break;
case MB_MUSER:
return (EFAULT);
break;
case MB_MZERO:
break;
}
}
return (0);
}
/*
* Append an mblk to the chain.
*/
int
{
/* See: linkb(9f) */
;
return (0);
}
/*
*/
int
{
if (uiop->uio_iovcnt <= 0 ||
return (EFBIG);
if (error)
return (error);
}
return (0);
}
/*
* Routines for fetching data from an mbuf chain
*/
void
{
}
void
{
mblk_t *m;
/*
* Deal with the fact that we can error out of
* smb_t2_reply or smb_nt_reply without using up
* all the "records" added by md_append_record().
*/
freemsg(m);
}
/* Avoid dangling references */
}
/*
* Append a new message (separate mbuf chain).
* It is caller responsibility to prevent
* XXX: Note (mis)use of mblk->b_next here.
*/
void
{
mblk_t *m;
return;
}
/* Get to last message (not b_cont chain) */
while (m->b_next)
m = m->b_next;
}
/*
* Advance mdp->md_top to the next message.
* XXX: Note (mis)use of mblk->b_next here.
*/
int
{
mblk_t *m;
return (ENOENT);
/* Get to next message (not b_cont chain) */
if (m == NULL)
return (ENOENT);
return (0);
}
/*
* Inline version of md_get_mem(). Handles the easy case in-line,
* and calls md_get_mem() if crossing mblk boundaries, etc.
*/
#ifdef INLINE_WORKS /* see above */
static inline int
{
int n = size;
while (n--)
/* no md_count += size */
return (0);
}
}
#else /* INLINE_WORKS */
/* Note, sets variable: error */
int n = SZ; \
while (n--) \
/* no md_count += SZ */ \
error = 0; \
} else \
#endif /* INLINE_WORKS */
int
{
uint8_t v;
int error;
MD_GET_INLINE(mdp, &v, sizeof (v));
if (x)
*x = v;
return (error);
}
int
u_int16_t v;
int error;
MD_GET_INLINE(mdp, &v, sizeof (v));
if (x)
*x = betohs(v);
return (error);
}
int
{
u_int16_t v;
int error;
MD_GET_INLINE(mdp, &v, sizeof (v));
if (x)
*x = letohs(v);
return (error);
}
int
{
u_int32_t v;
int error;
MD_GET_INLINE(mdp, &v, sizeof (v));
if (x)
*x = betohl(v);
return (error);
}
int
{
u_int32_t v;
int error;
MD_GET_INLINE(mdp, &v, sizeof (v));
if (x)
*x = letohl(v);
return (error);
}
int
{
u_int64_t v;
int error;
MD_GET_INLINE(mdp, &v, sizeof (v));
if (x)
*x = betohq(v);
return (error);
}
int
{
u_int64_t v;
int error;
MD_GET_INLINE(mdp, &v, sizeof (v));
if (x)
*x = letohq(v);
return (error);
}
int
{
unsigned char *s;
int count;
while (size > 0) {
if (m == NULL) {
SMBSDEBUG("incomplete copy\n");
return (EBADRPC);
}
/*
* Offset in the current MBUF.
*/
/* Data remaining. */
/*
* Check if the no. of bytes remaining is less than
* the bytes requested.
*/
if (count == 0) {
m = m->b_cont;
if (m) {
}
continue;
}
continue;
switch (type) {
case MB_MUSER:
return (EFAULT);
break;
case MB_MSYSTEM:
break;
case MB_MINLINE:
while (count--)
*target++ = *s++;
continue;
}
}
return (0);
}
/*
* Get the next SIZE bytes as a separate mblk.
*/
int
{
unsigned char *s;
int off;
/*
* Offset in the current MBUF.
*/
return (EBADRPC);
return (0);
}
int
{
if (uiop->uio_iovcnt <= 0 ||
return (EFBIG);
if (error)
return (error);
}
return (0);
}
/*
* Additions for Solaris
*/
/*
* concatenate mblk chain n to m.
* go till end of data in m.
* then add the link of b_cont to n.
* See: linkb(9f)
*/
void m_cat(
mblk_t *m,
mblk_t *n)
{
if (!n)
return;
while (m->b_cont) {
m = m->b_cont;
}
m->b_cont = n;
}
/*ARGSUSED*/
mblk_t *
{
mblk_t *n;
return (0);
} else {
return (0);
}
return (0);
/* trim from head */
freemsg(n);
return (0);
}
/* trim from tail */
}
}
return (n);
}
/*
* Get "rqlen" contiguous bytes into the first mblk of a chain.
*/
mblk_t *
mblk_t *m,
int rqlen)
{
/* This should be rare. */
SMBSDEBUG("pullupmsg failed!\n");
freemsg(m);
return (NULL);
}
}
return (m);
}
/*
* m_split : split the mblk from the offset(len0) to the end.
* Partition an mbuf chain in two pieces, returning the tail --
* all but the first len0 bytes. In case of failure, it returns NULL and
* attempts to restore the chain to its original state.
* Similar to dupmsg() + adjmsg() on Solaris.
*/
/*ARGSUSED*/
mblk_t *
int len0,
int wait)
{
mblk_t *m, *n;
#if 0 /* If life were simple, this would be: */
#else /* but with LP64 and picky lint we have: */
break;
}
#endif
if (m == 0)
return (0);
/* This is the one to split (dupb, adjust) */
if ((n = dupb(m)) == 0)
return (0);
/* Move any b_cont (tail) to the new head. */
return (n);
}