root/usr/src/uts/common/smbsrv/mbuf.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2019 Joyent, Inc.
 * Copyright 2011-2021 Tintri by DDN, Inc. All rights reserved.
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */
/*
 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
 * 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
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
 *
 */

#ifndef _SMBSRV_MBUF_H
#define _SMBSRV_MBUF_H

/*
 * This mbuf simulation should be replaced with (native) mblk_t support.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/kmem.h>
#include <smbsrv/string.h>

#ifdef __cplusplus
extern "C" {
#endif

#define MSIZE           256
#define MCLBYTES        8192

/*
 * Mbufs are of a single size, MSIZE (machine/machparam.h), which
 * includes overhead.  An mbuf may add a single "mbuf cluster" of size
 * MCLBYTES (also in machine/machparam.h), which has no additional overhead
 * and is used instead of the internal data area; this is done when
 * at least MINCLSIZE of data must be stored.
 */

#define MLEN            (MSIZE - sizeof (struct m_hdr)) /* normal data len */
#define MHLEN           (MLEN - sizeof (struct pkthdr)) /* data len w/pkthdr */

#define MINCLSIZE       (MHLEN + MLEN)  /* smallest amount to put in cluster */

/*
 * How much prepend space to put in the first mbuf of a chain.
 * In SMB we only prepend a 4-byte NBT header, but let's keep the
 * data part aligned the same as M_ALIGN() does below (8-byte)
 */
#define MH_PREPEND_SPACE        8

/*
 * Macros for type conversion
 * mtod(m,t) -  convert mbuf pointer to data pointer of correct type
 */
#define mtod(m, t)      ((t)((m)->m_data))

struct mbuf;
typedef void m_ext_free_t(struct mbuf *);

/* header at beginning of each mbuf: */
struct m_hdr {
        struct  mbuf *mh_next;          /* next buffer in chain */
        struct  mbuf *mh_nextpkt;       /* next chain in queue/record */
        int     mh_len;                 /* amount of data in this mbuf */
        caddr_t mh_data;                /* location of data */
        short   mh_type;                /* type of data in this mbuf */
        short   mh_flags;               /* flags; see below */
};

/* record/packet header in first mbuf of chain; valid if M_PKTHDR set */
struct  pkthdr {
        int     len;            /* total packet length */
};


/* description of external storage mapped into mbuf, valid if M_EXT set */
struct m_ext {
        caddr_t         ext_buf;        /* start of external buffer */
        uint_t          ext_size;       /* size of external buffer */
        m_ext_free_t    *ext_free;      /* free function */
        void            *ext_arg1;      /* free func arg */
};

typedef struct mbuf {
        struct  m_hdr m_hdr;
        union {
                struct {
                        struct  pkthdr MH_pkthdr;       /* M_PKTHDR set */
                        union {
                                struct  m_ext MH_ext;   /* M_EXT set */
                                char    MH_databuf[MHLEN];
                        } MH_dat;
                } MH;
                char    M_databuf[MLEN];                /* !M_PKTHDR, !M_EXT */
        } M_dat;
} mbuf_t;

#define m_next          m_hdr.mh_next
#define m_len           m_hdr.mh_len
#define m_data          m_hdr.mh_data
#define m_type          m_hdr.mh_type
#define m_flags         m_hdr.mh_flags
#define m_nextpkt       m_hdr.mh_nextpkt
#define m_act           m_nextpkt
#define m_pkthdr        M_dat.MH.MH_pkthdr
#define m_ext           M_dat.MH.MH_dat.MH_ext
#define m_pktdat        M_dat.MH.MH_dat.MH_databuf
#define m_dat           M_dat.M_databuf

/* mbuf flags */
#define M_EXT           0x0001  /* has associated external storage */
#define M_PKTHDR        0x0002  /* start of record */
#define M_EOR           0x0004  /* end of record */

/* mbuf pkthdr flags, also in m_flags */
#define M_BCAST         0x0100  /* send/received as link-level broadcast */
#define M_MCAST         0x0200  /* send/received as link-level multicast */

/* flags copied when copying m_pkthdr */
#define M_COPYFLAGS     (M_PKTHDR|M_EOR|M_BCAST|M_MCAST)

/* XXX probably only need MT_DATA */

/* mbuf types */
#define MT_FREE         0       /* should be on free list */
#define MT_DATA         1       /* dynamic (data) allocation */
#define MT_HEADER       2       /* packet header */
#define MT_SOCKET       3       /* socket structure */
#define MT_PCB          4       /* protocol control block */
#define MT_RTABLE       5       /* routing tables */
#define MT_HTABLE       6       /* IMP host tables */
#define MT_ATABLE       7       /* address resolution tables */
#define MT_SONAME       8       /* socket name */
#define MT_SOOPTS       10      /* socket options */
#define MT_FTABLE       11      /* fragment reassembly header */
#define MT_RIGHTS       12      /* access rights */
#define MT_IFADDR       13      /* interface address */
#define MT_CONTROL      14      /* extra-data protocol message */
#define MT_OOBDATA      15      /* expedited data  */

/*
 * flags to malloc: PBSHORTCUT
 */
#define M_WAITOK        0x0000
#define M_NOWAIT        0x0001

/* flags to m_get/MGET */
#define M_DONTWAIT      M_NOWAIT
#define M_WAIT          M_WAITOK

/* BEGIN CSTYLED */

/*
 * mbuf allocation/deallocation macros:
 *
 *      MGET(struct mbuf *m, int how, int type)
 * allocates an mbuf and initializes it to contain internal data.
 *
 *      MGETHDR(struct mbuf *m, int how, int type)
 * allocates an mbuf and initializes it to contain a packet header
 * and internal data.
 */

#define MGET(m, how, type) { \
        m = smb_mbuf_alloc(); \
        (m)->m_next = (struct mbuf *)NULL; \
        (m)->m_nextpkt = (struct mbuf *)NULL; \
        (m)->m_data = (m)->m_dat; \
        (m)->m_flags = 0; \
        (m)->m_type = (short)(type); \
}

#define MGETHDR(m, how, type) { \
        m = smb_mbuf_alloc(); \
        (m)->m_type = (MT_HEADER); \
        (m)->m_next = (struct mbuf *)NULL; \
        (m)->m_nextpkt = (struct mbuf *)NULL; \
        (m)->m_data = (m)->m_pktdat; \
        (m)->m_flags = M_PKTHDR; \
}

#define MCLGET(m, how) \
        { \
                (m)->m_ext.ext_buf = smb_mbufcl_alloc();        \
                (m)->m_data = (m)->m_ext.ext_buf;               \
                (m)->m_flags |= M_EXT;                          \
                (m)->m_ext.ext_size = MCLBYTES;                 \
                (m)->m_ext.ext_free = smb_mbufcl_free;          \
        }

/*
 * MFREE(struct mbuf *m, struct mbuf *nn)
 * Free a single mbuf and associated external storage.
 * Place the successor, if any, in nn.
 */
#define MFREE(m, nn) \
        { \
                if ((m)->m_flags & M_EXT) {                     \
                        (m)->m_ext.ext_free(m);                 \
                        (m)->m_ext.ext_buf = NULL;              \
                }                                               \
                (nn) = (m)->m_next;                             \
                (m)->m_next = 0;                                \
                smb_mbuf_free(m);                               \
        }

/*
 * Set the m_data pointer of a newly allocated mbuf to place an object of the
 * specified size at the end of the mbuf, longword aligned.
 */
#define M_ALIGN(m, len) \
        { (m)->m_data += (MLEN - (len)) &~ (sizeof (int64_t) - 1); }

/*
 * As above, for mbufs allocated with m_gethdr/MGETHDR
 * or initialized by M_COPY_PKTHDR.
 */
#define MH_ALIGN(m, len) \
        { (m)->m_data += (MHLEN - (len)) &~ (sizeof (int64_t) - 1); }

/*
 * Return the address of the start of the buffer associated with an mbuf,
 * handling external storage, packet-header mbufs, and regular data mbufs.
 * BSD calls this M_START but that conflicts with stream.h (sigh)
 */
#define MB_START(m)                                                     \
        (((m)->m_flags & M_EXT) ? (m)->m_ext.ext_buf :                  \
         ((m)->m_flags & M_PKTHDR) ? &(m)->m_pktdat[0] :                \
         &(m)->m_dat[0])

/*
 * Return the size of the buffer associated with an mbuf, handling external
 * storage, packet-header mbufs, and regular data mbufs.
 */
#define M_SIZE(m)                                                       \
        (((m)->m_flags & M_EXT) ? (m)->m_ext.ext_size :                 \
         ((m)->m_flags & M_PKTHDR) ? MHLEN : MLEN)

/*
 * Compute the amount of space available before the current start of data in
 * an mbuf.
 */
#define M_LEADINGSPACE(m)       ((m)->m_data - MB_START(m))

/*
 * Compute the amount of space available after the end of data in an mbuf.
 */
#define M_TRAILINGSPACE(m)                                              \
        ((MB_START(m) + M_SIZE(m)) - ((m)->m_data + (m)->m_len))

/* END CSTYLED */

#define SMB_MBC_MAGIC           0x4D42435F
#define SMB_MBC_VALID(p)        ASSERT((p)->mbc_magic == SMB_MBC_MAGIC)

typedef struct mbuf_chain {
        uint32_t                mbc_magic;
        volatile uint32_t       flags;          /* Various flags */
        struct mbuf_chain       *shadow_of;     /* I'm shadowing someone */
        mbuf_t                  *chain;         /* Start of chain */
        int32_t                 max_bytes;      /* max # of bytes for chain */
        int32_t                 chain_offset;   /* Current offset into chain */
} mbuf_chain_t;

mbuf_t *smb_mbuf_alloc_ext(caddr_t, int, m_ext_free_t, void *);

mbuf_t *smb_mbuf_alloc(void);
void smb_mbuf_free(mbuf_t *);

void *smb_mbufcl_alloc(void);
void smb_mbufcl_free(mbuf_t *);

mbuf_t *m_prepend(struct mbuf *m, int plen, int how);
void m_adjust(mbuf_t *, int);
mbuf_t *m_free(mbuf_t *);
void m_freem(mbuf_t *);
void smb_mbc_init(void);
void smb_mbc_fini(void);
mbuf_chain_t *smb_mbc_alloc(uint32_t);
void smb_mbc_free(mbuf_chain_t *);

#ifdef __cplusplus
}
#endif

#endif /* _SMBSRV_MBUF_H */