/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos72L src/bos/kernel/sys/socketvar.h 1.12.18.12                       */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 1988,2017              */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/* @(#)74       1.12.18.12  src/bos/kernel/sys/socketvar.h, sockinc, bos72L, l2017_48A4 11/6/17 13:01:35 */

/*
 *   NAME: socketvar.h
 *
 *   DESC: kernel socket structure definitions
 *
 *   COMPONENT_NAME: SYSUIPC
 *
 *   MACROS: FREE_SOCK_HASH
 *           FREE_SOCK_ISLOCKED
 *           FREE_SOCK_ISLOCKED
 *           FREE_SOCK_LOCK
 *           FREE_SOCK_LOCK_INIT
 *           FREE_SOCK_UNLOCK
 *           QOS_IS_LOADED
 *           SAIOQ_LOCK
 *           SAIOQ_UNLOCK
 *           SAME_SOCKET_LOCK
 *           SOANDFIELD
 *           SOCKBUF_LOCK
 *           SOCKBUF_UNLOCK
 *           SOCKET_INTERIM_RELOCK
 *           SOCKET_INTERIM_UNLOCK
 *           SOCKET_ISLOCKED
 *           SOCKET_ISLOCKED
 *           SOCKET_LOCK
 *           SOCKET_LOCK
 *           SOCKET_LOCK2
 *           SOCKET_LOCKINIT
 *           SOCKET_LOCK_IS_LOWER
 *           SOCKET_LOCK_MINE
 *           SOCKET_REF
 *           SOCKET_TRY_LOCK
 *           SOCKET_UNLOCK
 *           SOCKET_UNLOCK2
 *           SOCKET_UNREF
 *           SOFREE
 *           SOHASUAREA
 *           SOORFIELD
 *           SOSETFIELD
 *           SOSETRCVWAKEARG
 *           sb_sel
 *           sb_selq
 *           sballoc
 *           sbfree
 *           sbspace
 *           so2gidstruct
 *           soandfield
 *           sodomain
 *           soisrds
 *           sonewconn
 *           soorfield
 *           soreadable
 *           sorwakeup
 *           sosendallatonce
 *           sosetfield
 *           sosetrcvwakearg
 *           sotosop
 *           sowriteable
 *           sowwakeup
 *
 *   ORIGINS: 26,27,85
 *
 */

/*
 *
 * (c) Copyright 1991, OPEN SOFTWARE FOUNDATION, INC.
 * ALL RIGHTS RESERVED
 *
 */
/*
 * OSF/1 1.2
 */
/* socketvar.h  2.1 16:08:08 4/20/90 SecureWare */
/*
 * Copyright (C) 1988,1989 Encore Computer Corporation.  All Rights Reserved
 *
 * Property of Encore Computer Corporation.
 * This software is made available solely pursuant to the terms of
 * a software license agreement which governs its use. Unauthorized
 * duplication, distribution or sale are strictly prohibited.
 *
 */
/*
 * Copyright (c) 1982, 1986, 1990 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted provided
 * that: (1) source distributions retain this entire copyright notice and
 * comment, and (2) distributions including binaries display the following
 * acknowledgement:  ``This product includes software developed by the
 * University of California, Berkeley and its contributors'' in the
 * documentation or other materials provided with the distribution and in
 * all advertising materials mentioning features or use of this software.
 * 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *      Base:   socketvar.h     7.6 (Berkeley) 9/4/89
 *      Merged: socketvar.h     7.11 (Berkeley) 6/30/90
 */

#ifndef _SYS_SOCKETVAR_H_
#define _SYS_SOCKETVAR_H_

#include <sys/corralid.h>
#include <sys/bypass.h>

#ifdef __cplusplus
extern "C" {
struct protosw;
struct mbuf;
struct proc;
#endif

#if defined(_KERNEL) && !defined(_NET_GLOBALS_H_)
#include "net/net_globals.h"
#endif

#include <sys/time.h>

#if MACH
#include <sys/secdefines.h>
#if SEC_ARCH
#include <sys/security.h>
#endif
#endif
#include <sys/ras_trace.h>

#define SOMAXBUFSIZE    (65536)

/* -------------------------------------------------------------------------------------
// External References
*/

#ifdef  _KERNEL

/* Hash table of sockets waiting to be freed. */
extern struct free_sock_hash_bucket free_sock_hash_table[];

extern u_long   sb_max;

#endif /* _KERNEL */

/* -------------------------------------------------------------------------------------
// Structure Defines
*/

/*----------------------------------------------
//
// prid
//
// Structure inside the socket structure to store the pid and tid
// of the associated process and thread.
//
*/
struct prid
{
    pid_t               pid;
    tid_t               tid;
};

/*----------------------------------------------
//
// so_extension
//
// The so_extension is an allocated 
// structure attached to a socket during 
// socreate and destroyed during FREE
// At this point in time it is only allocated
// for datagram type sockets and if the 
// udp send performance changes are enabled.
//
// This may be used for future storage needs
// since it avoids binary incompability issues
// if the base socket structure size is changed. 
//
*/
#define EYEC_SOCKETX 0x25736F636B657458ull  /* %socketX */

struct so_extension
{
    eye_catch8b_t       so_eyecat;
    struct mbuf         *so_udp_toaddr;     /* cache the to addr for sendto etc. */
    void                *so_inhdr_info;     /* cache the inp information */

    /*
     * Per socket mbuf pools. We have two arrays of mbuf chains. Buckets are 
     * for these cluster sizes. We also use clusters, even for mbufs that would
     * fit into MHLEN, as we must have M_EXT set up.
     *
     *    0    64 (MINBUCKET in net_malloc is 6, for 2^6 size bucket)
     *    1   128
     *    2   256
     *    3   512
     *    4  1024
     *    5  2048
     *    6  4096
     *    7  8192
     *    8 16384
     *    9 32768
     *   10 65536
     *
     * One set of buckets is used for allocation, another for deallocation.
     * When the allocation bucket is empty, move the free bucket pointer to the
     * allocation bucket and set the free bucket to NULL. If the allocation
     * bucket is still empty, allocate with m_gethdr or m_getclustm. Set the 
     * M_EXT2 flag and set m_extfree to a free routine that will free to the 
     * socket's free pool.
     *
     * When freeing, mbufs with no cluster go to bucket 0. For mbufs with 
     * clusters use BUCKETINDX(ext_size) - 8 to determine the bucket array
     * index.
     */

#define MAXMBBUCKET 10
#define MBBUCKETINDX(size) ((size) <= 64 ? 0 :                          \
                            (size) > (64*1024) ? MAXMBBUCKET :          \
                            (64 - cntlz64((size)-1) - 6))
#define MBPOOLSIZE (MAXMBBUCKET+1)

    struct mbuf         *so_mbpool[MBPOOLSIZE]; /* mbuf pool */
    struct mbuf         *so_mbfree[MBPOOLSIZE]; /* free pool */

#define MBFREE_LOCK_DECL  int __mbl
#define MBFREE_LOCK(so)   __mbl = disable_lock(PL_IMP, &(so)->extension->so_mbfreelock)
#define MBFREE_UNLOCK(so) unlock_enable(__mbl, &(so)->extension->so_mbfreelock)
#define MBFREE_INITLOCK(so) \
        do {                                                            \
                lock_alloc(&(so)->extension->so_mbfreelock, LOCK_ALLOC_PIN, \
                           SOCKET_LOCK_FAMILY, (uint)(so));             \
                simple_lock_init(&(so)->extension->so_mbfreelock);      \
        } while (0)
        
#ifndef	_KERNEL
#define simple_lock_data_t long
#endif
    simple_lock_data_t  so_mbfreelock;          /* free pool lock */

    /* Total size of struct is 512 bytes with these reserved fields. */
    long                so_reserved[2];         /* Room to grow... */
	void                *bypass_proto_ptr;      /* my bypass protocol table pointer */
    void                *bypass_proto_data;	    /* pointer used to store bypass protocol specific information */
	struct sockbuf      *bypass_proto_so_snd;   /* socket send buffer counters for bypass protocol */
	struct sockbuf      *bypass_proto_so_rcv;   /* socket recv buffer counters for bypass protol */
};

/*----------------------------------------------
//
// saioq
//
// Strucutres used for socket async queueing
//
*/

struct saioq
{
    struct saioq        *next;
    int                 count;
    int                 freeflag;
    int                 sigval;
};

struct saioq_head
{
    struct saioq        *anchor;
    struct saioq        *last;
};

/*----------------------------------------------
//
// sockbuf
//
// Structure for socket buffering
//
*/
struct sockbuf
{
    u_long              sb_cc;              /* actual chars in buffer */
    u_long              sb_hiwat;           /* max actual char count */
    u_long              sb_mbcnt;           /* chars of mbufs used */
    u_long              sb_mbmax;           /* max chars of mbufs to use */
    long                sb_lowat;           /* low water mark */
    struct mbuf         *sb_mb;             /* the mbuf chain */
    union                                   /* process selecting read/write */
    {
        struct proc     *sb_selproc;        /* UNIX */
        struct sbselque                     /* MACH */
        {
            struct sbselque *next;
            struct sbselque *prev;

        } sb_selque;

    } sb_select;

    ushort              sb_reqevents;       /* current pending events */
    int                 (*sb_iodone)();     /* I/O done function */
    caddr_t             sb_ioarg;           /* arg for sb_iodone */
    struct  mbuf        *sb_lastpkt;        /* last packet of mbuf chain */
    tid_t               sb_wakeone;         /* SB_WAKEONE sleep event */
    caddr_t             sb_timer;           /* pre-allocated trb */
    short               sb_flags;           /* flags, see below */
    ushort              sb_timeo;           /* timeout for read/write */
#ifdef  _KERNEL
    void                (*sb_wakeup)(caddr_t, int);
#else
    void                (*sb_wakeup)();     /* upcall instead of sowakeup */
#endif /* _KERNEL */
    caddr_t             sb_wakearg;         /* (*sb_wakeup)(sb_wakearg, state) */
    tid_t               sb_lockwaiting;     /* list of threads waiting for SB_LOCK flag */
};

#ifdef  _KERNEL
/*----------------------------------------------
//
// socklocks
//
// Structure for socket locking
//
*/
struct socklocks
{
    simple_lock_data_t  sock_lock;
    simple_lock_data_t  snd_lock;           /* not used */
    simple_lock_data_t  rcv_lock;           /* not used */
    int                 refcnt;
    struct socket       *sp_wake;
    struct socket       *so;                /* back pointer */
    int                 spl;
    struct socklocks    *freelist;
};

/*----------------------------------------------
//
// sndbufpool
//
// socket send buffer pool
//
*/
struct sndbufpool
{
    struct mclust_pool  *sb_pool;
    int                 sb_freecnt;         /* Timer free count */
};
#endif /* _KERNEL */

/*----------------------------------------------
//
// socket
//
// Kernel structure per socket.
// Contains send and receive buffer queues,
// handle on protocol and pointer to protocol
// private data and error information.
//
// NOTE #1:
//
//  so_head and so_q0 are variables for connection queueing.
//  Socket where accepts occur is so_head in all subsidiary sockets.
//  If so_head is 0, socket is not related to an accept.
//  For head socket so_q0 queues partially completed connections,
//  while so_q is a queue of connections ready to be accepted.
//  If a connection is aborted and it has so_head set, then
//  it has to be pulled out of either so_q0 or so_q.
//  We allow connections to queue up based on current queue lengths
//  and limit on number of queued connections for this socket.
//
// NOTE #2:
//
//  so_q is used as an array of sockets for socketgroup.
//  It is defined as a queue of incoming connections -or-
//  a pointer to main socketgroup socket.
//
// NOTE #3:
//
//  so_q0len can be used as the partials on so_q0  -or-
//  the number of sockets in socketgroup
//
// NOTE #4:
//
//  These belong in the sockbufs, but we can't change those. We use
//  these to set the sb_timeo field in the sockbufs.
//
*/
struct socket
{
    short               so_type;            /* generic type, see socket.h */
    short               so_options;         /* from socket call, see socket.h */
    ushort              so_linger;          /* time to linger while closing */
    short               so_state;           /* internal state flags SS_*, below */
    caddr_t             so_pcb;             /* protocol control block */
    struct protosw      *so_proto;          /* protocol handle */
    struct socklocks    *so_lock;           /* socket structure lock(s) */
    struct socket       *so_head;           /* (NOTE #1) */
    struct socket       *so_q0;             /* (NOTE #1) */
    struct socket       *so_q;              /* (NOTE #2) */
    long                so_refcnt;          /* Socket and pcb can't be freed if refcnt != 0 */
    short               so_q0len;           /* (NOTE #3)*/
    short               so_qlen;            /* number of connections on so_q */
    short               so_qlimit;          /* max number queued connections */
    short               so_dqlen;           /* unused */
    short               so_timeo;           /* connection timeout */
    u_short             so_error;           /* error affecting connection */
    short               so_special;         /* special state flags SP_*, below */
    short               so_special2;        /* special state flags SP2_*, below */
    pid_t               so_pgid;            /* pgid for signals */
    u_long              so_oobmark;         /* chars to oob mark */
    struct sockbuf      so_rcv;             /* receive socket buffer */
    struct sockbuf      so_snd;             /* send socket buffer */
    caddr_t             so_tpcb;            /* Wisc. protocol control block XXX */
    void                *fdev_chain_f;      /* anchor of chain of fsel_cb's */
    caddr_t             so_sec_info;        /* BESTX security info */
    void                *so_qos;            /* Quality Of Service cookie */
    struct gidstruct    *so_gidlist;        /* Group ID list for socket owner */
    caddr_t             so_private;         /* Used by NFS */
    uid_t               so_uid;             /* UID of socket owner */
    ushort              so_bufsize;         /* Size of interface-supplied buffer */
    ushort              so_threadcnt;       /* Semaphore used for freeing socket */
    struct socket       *so_nextfree;       /* Link for free_sockets list */
    int                 so_siguid;
    int                 so_sigeuid;
    int                 so_sigpriv;
    struct timeval      so_sndtimeval;      /* (NOTE #4) */
    struct timeval      so_rcvtimeval;      /* (NOTE #4) */
    struct saioq        *so_saioq;
    struct saioq_head   *so_saioq_head;
    tid_t               so_accept;          /* Chain of threads accepting */
    int                 so_frcatime;        /* FRCA Connection Time */
    int                 so_isnoflags;       /* Don't use isno options if set by setsockopt */
    u_long              so_rcvlen;          /* used by MSG_WAITALL */
    struct socket       *so_frca_backup;    /* used by frca to recall listen so */
    struct socket       *so_frca_assoc;     /* used by frca to find assoc so */
    long                so_frca_bucket;     /* used by frca to alloc more bytes..*/
    int                 (*so_iodone)();     /* I/O done function */
    short               so_iodoneflags;     /* flags, see below */
    short               so_trclev;          /* trace level for the socket */
    caddr_t             so_ioarg;           /* arg for so_iodone */
    tid_t               so_inprogwaiting;   /* list of threads waiting for SP_INPROGRESS flag */
    struct socklocks    *so_lpfreelist;     /* Chain of socklocks to be freed.   */
    struct prid         prid;               /* proces id and thread id */
    cid_t               so_kcid;            /* CORRAL of socket */
    caddr_t             so_cred;            /* MLS security label info */
    u_long              so_flag;            /* Flag to use for any socket options. D746955 */
    struct so_extension *extension;         /* Pointer to extension area. (LI:1NN) */	
    long                so_reserved[1];     /* Room to grow...		    */
    tid_t               so_inprogress_owner_tid;/* thread that sets the SP_INPROGRESS flag */
};

/*----------------------------------------------
//
// socket_plus
//
// Eyecatcher wrapper for socket structure
//
*/

#define EYEC_SOCKETA    0x25736F636B657441ull   /* %socketA */
#define EYEC_SOCKETF    0x25736F636B657446ull   /* %socketF */

struct socket_plus
{
    eye_catch8b_t       sop_eyecat;
    struct socket       sop_so;
};

#ifdef  _KERNEL

/*----------------------------------------------
//
// free_sock_hash_bucket
//
*/

#define FREE_SOCK_HASH_SZ   103

struct free_sock_hash_bucket
{
    int                 fsh_freecnt;
    simple_lock_data_t  fsh_lock;
    int                 fsh_intrlvl;
    struct socket       *fsh_freelist;
};

/*----------------------------------------------
//
// qos_socket_funcs
//
// QOS extensions register these functions with the socket layer.
//
*/
struct qos_socket_funcs
{
    int  (*qos_alloc)(struct socket *, ushort, uchar, struct mbuf **); /* QOS buffer allocation, policing, shaping */
    int  (*qos_buf_alloc)();                    /* QOS buffer allocation */
    int  (*qos_ctrl_flow)();                    /* QOS tcp policing, shaping by tcp_timer */
    void (*qos_isconnected)();                  /* QOS connect notification */
    void (*qos_isdisconnected)();               /* QOS disconnect notification */
    int  (*qos_input)(struct mbuf *, int);
    int  (*qos_usrreq)(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *);
    void (*qos_ctlinput)(int, struct ifnet *, caddr_t);
    void (*qos_classify)(struct socket *);
    int  (*qos_applied)(struct socket *, ushort, uchar, struct mbuf **);
};
extern struct qos_socket_funcs qos_fns;

/*
 * The following data structure definition is used between the pr_receive vector
 * and it's calling function as a subsitute pointer for the first passed arg. This
 * convention is used only when the MSG_ARGEXT flag is passed down and the protocol
 * advertises this capability with the PR_ARGEXT flag.
 */
typedef struct
{
	struct socket 		*so;
	struct timeval 		*timeout;

} ARGEXT;

#endif /* _KERNEL */

/*----------------------------------------------
// so_state values
*/

#define SS_NOFDREF              0x001       /* no file table ref any more */
#define SS_ISCONNECTED          0x002       /* socket connected to a peer */
#define SS_ISCONNECTING         0x004       /* in process of connecting to peer */
#define SS_ISDISCONNECTING      0x008       /* in process of disconnecting */
#define SS_CANTSENDMORE         0x010       /* can't send more data to peer */
#define SS_CANTRCVMORE          0x020       /* can't receive more data from peer */
#define SS_RCVATMARK            0x040       /* at mark on input */
#define SS_PRIV                 0x080       /* privileged for broadcast, raw... */
#define SS_NBIO                 0x100       /* non-blocking ops */
#define SS_ASYNC                0x200       /* async i/o notify */
#define SS_QUEUE                0x800       /* async queueing */
#define SS_SPLICED              0x1000      /* spliced socket */
#define SS_NOCONN               0x2000      /* connection is closed (or never existed) */
#define SS_PORT_PRIV            0x8000      /* privileged for reserved port bind */

/*----------------------------------------------
// so_special values
*/
#define SP_NOUAREA              0x0004      /* no u-area available (XTI - XXX) */
#define SP_LOCKABLE             0x0008      /* socket of parallel domain */
#define SP_CLOSING              0x0010      /* closing a listening socket */
#define SP_RWAKEUP              0x0020      /* sorwakeup pending release of lock */
#define SP_WWAKEUP              0x0040      /* sowwakeup pending release of lock */
#define SP_EXTPRIV              0x0080      /* SS_PRIV managed externally */
#define SP_XPG1170              0x0100      /* Follow SPEC1170 semantics */
#define SP_MEMCOMPRESS          0x0200      /* socket+gidlist+inpcb+tcpcb grouped */
#define SP_ACCEPT               0x0400      /* accepting threads are on so_accept */
#define SP_DISABLE              0x0800      /* use disable_lock for serialization */
#define SP_GROUP                0x1000      /* part of a socket group */
#define SP_INPROGRESS           0x2000      /* serialized operation is in progress */
#define SP_ONFREELIST           0x4000      /* the socket is already in freelist */
#define SP_QCONN_RESET          0x8000      /* completed connection in listener's queue got reset */
#define SP_HAS_FPREF            0x0002      /* A file pointer's f_data is pointing to this socket */

#define SP_INHERIT              (SP_NOUAREA|SP_LOCKABLE|SP_DISABLE|SP_XPG1170)

/*----------------------------------------------
// so_special2 values
*/
#define SP2_PROC                0x0001      /* socket created by a process */
#define SP2_MSGWAITALL          0x0002      /* if the recv() used MSG_WAITALL flag */
#define SP2_LOCAL               0x0004      /* The socket is a local connection  */
#define SP2_BIND2ADDRSEL        0x0008      /* bind using specified remote address */
#define SP2_ACCEPT_CLOSE        0x0010      /* soo_preclose for accepting socket */
#define SP2_SND_RCV_CLOSE       0x0020      /* soo_preclose for snd/rcv socket */
#define SP2_UDP_IMPROVE         0x0100      /* bypass mbuf alloc for socket addr */
#define SP2_RECV_STACK_MBUFS    0x0200      /* Use stack mbufs on receive path */
#define SP2_FRCA_BACKDOOR_BUSY  0x1000
#define SP2_FRCA_BACKDOOR       0x2000
#define SP2_FRCA_BUCKET         0x4000
#define SP2_FRCA_BACKDOOR_DONE  0x8000

#define SP2_INHERIT             (SP2_PROC)

/*----------------------------------------------
// sockbuf definitions
*/

#define SB_MAX                  (1024*1024)     /* default for max chars in sockbuf */
#define sb_sel                  sb_select.sb_selproc
#define sb_selq                 sb_select.sb_selque

/*----------------------------------------------
// sb_flags values
*/
#define SB_LOCK                 0x01        /* lock on data queue */
#define SB_WANT                 0x02        /* someone is waiting to lock */
#define SB_WAIT                 0x04        /* someone is waiting for data/space */
#define SB_SEL                  0x08        /* someone is selecting */
#define SB_ASYNC                0x10        /* ASYNC I/O, need signals */
#define SB_NOINTR               0x40        /* operations not interruptible */
#define SB_WAKEONE              0x80        /* wakeup only one on notify */
#define SB_WAITING              0x100       /* MSG_WAITALL receive in progress */
#define SB_PSEG                 0x200       /* buffers may be in private segment */
#define SB_KIODONE              0x400       /* socket kernel iodone */
#define SB_NOSELECT             0x800
#define SB_NOBUFS               0x1000      /* No space left in the socket buffer */

#define SB_INHERIT              (SB_NOINTR|SB_WAKEONE)
#define SB_NOTIFY               (SB_WAIT|SB_SEL|SB_ASYNC|SB_WAKEONE|SB_KIODONE)

/*----------------------------------------------
// so_flag values (D746955)
*/
#define SO_FLAG_TCPTR           0X01        /* TCPTR flag to monitor socket connections */
#define SO_FILTER               0x10000     /* Flag to enable Filtered Tracing */
#define SO_FILTERDEBUG          0x20000     /* Flag to enable socket debugging */
#define SO_FILTER_MBUF_TRACE    0x40000     /* Flag to enable Filter Mbuf Tracing */
#define SO_IODONE_KACCEPT       0x01
#define SO_IODONE_KREAD         0x02
#define SO_IODONE_KWRITE        0x04
#define SO_BYPASS_SMCR_CLIENT	0x10
#define SO_BYPASS_SMCR_SERVER	0x20
#define SO_BYPASS_ACTIVE		0x40
#define SO_BYPASS_ISCONNECTING  0x80
#define SO_USING_HWTS           0x100       /* Socket is using the Hardware Timestamp facility */

/*----------------------------------------------
// so_isnoflags values
*/
#define SO_NOISNO_TCP_SENDSPACE 0x00000001
#define SO_NOISNO_TCP_RECVSPACE 0x00000002
#define SO_NOISNO_TCP_NODELAY   0x00000004
#define SO_NOISNO_RFC1323       0x00000008

/*----------------------------------------------
// so_trclev values
*/
#define SO_TRC_NONE             0
#define SO_TRC_MIN              CT_LVL_MINIMAL
#define SO_TRC_NORM             CT_LVL_NORMAL
#define SO_TRC_DTL              CT_LVL_DETAIL

/*----------------------------------------------
// sb_wakeup values for network events
*/
#define SE_ERROR                0x0001      /* so_error non-0 */
#define SE_HAVEDATA             0x0002      /* data in send or recv q */
#define SE_HAVEOOB              0x0004      /* oob data in recv q */
#define SE_DATAFULL             0x0008      /* send or recv q is full */
#define SE_CONNOUT              0x0010      /* outgoing connect complete (connect) */
#define SE_CONNIN               0x0020      /* incoming connect complete (listen)  */
#define SE_SENDCONN             0x0040      /* connected for send */
#define SE_RECVCONN             0x0080      /* connected for recv */
#define SE_POLL                 0x4000      /* wakeup is synchronous poll */
#define SE_STATUS               0x8000      /* above status bits valid */

/* -------------------------------------------------------------------------------------
// Macro Definitions
*/

/* -------------------------------------------------------------------------------------
//
// NAME:    SOORFIELD
//
// DESC:    Perform 'or' operation on a variable for a socket group
//
// ARGS:    so              socket pointer
//          field           socket field name
//          value           value
//
// ------------------------------------------------------------------------------------ */
#define soorfield SOORFIELD
#define SOORFIELD(so, field, value)                                             \
{                                                                               \
    so->field## |= value;                                                       \
    if (so->so_special & SP_GROUP && so->so_q0)                                 \
    {                                                                           \
        int z2;                                                                 \
        struct socket *sg2;                                                     \
        for (z2 = 1; z2 < so->so_q0len; z2++)                                   \
        {                                                                       \
            sg2 = ((struct socket **)so->so_q0)[z2];                            \
            sg2->field## |= value;                                              \
        }                                                                       \
    }                                                                           \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    SOANDFIELD
//
// DESC:    Perform 'and' operation on a variable for a socket group
//
// ARGS:    so              socket pointer
//          field           socket field name
//          value           value
//
// ------------------------------------------------------------------------------------ */
#define soandfield SOANDFIELD
#define SOANDFIELD(so, field, value)                                            \
{                                                                               \
    so->field## &= value;                                                       \
    if (so->so_special & SP_GROUP && so->so_q0)                                 \
    {                                                                           \
        int z2;                                                                 \
        struct socket *sg2;                                                     \
        for (z2 = 1; z2 < so->so_q0len; z2++)                                   \
        {                                                                       \
            sg2 = ((struct socket **)so->so_q0)[z2];                            \
            sg2->field## &= value;                                              \
        }                                                                       \
    }                                                                           \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    SOSETRCVWAKEARG
//
// DESC:    Setup the sb_wakearg variable for a socket group
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define sosetrcvwakearg SOSETRCVWAKEARG
#define SOSETRCVWAKEARG(so)                                                     \
{                                                                               \
    so->so_rcv.sb_wakearg = (caddr_t)so;                                        \
    if (so->so_special & SP_GROUP && so->so_q0)                                 \
    {                                                                           \
        int z2;                                                                 \
        struct socket *sg2;                                                     \
        for (z2 = 1; z2 < so->so_q0len; z2++)                                   \
        {                                                                       \
            sg2 = ((struct socket **)so->so_q0)[z2];                            \
            sg2->so_rcv.sb_wakearg = (caddr_t)sg2;                              \
        }                                                                       \
    }                                                                           \
}

#ifdef _KERNEL
/* -------------------------------------------------------------------------------------
//
// NAME:    SOSETFIELD
//
// DESC:    Set a variable value for a socket group
//
// ARGS:    so              socket pointer
//          field           socket field name
//          value           value
//
// ------------------------------------------------------------------------------------ */
#define sosetfield SOSETFIELD
#define SOSETFIELD(so, field, value)                                            \
{                                                                               \
    so->field## = value;                                                        \
    if (so->so_special & SP_GROUP && so->so_q0)                                 \
    {                                                                           \
        int z2;                                                                 \
        struct socket *sg2;                                                     \
        for (z2 = 1; z2 < so->so_q0len; z2++)                                   \
        {                                                                       \
            sg2 = ((struct socket **)so->so_q0)[z2];                            \
            SOCKET_LOCK(sg2);                                                   \
            sg2->field## = value;                                               \
            SOCKET_UNLOCK(sg2);                                                 \
        }                                                                       \
    }                                                                           \
}
#endif /* _KERNEL */

/* -------------------------------------------------------------------------------------
//
// NAME:    sotosop
//
// DESC:    Calculate the begining of the eye-catcher region for a socket struct.
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define sotosop(so) ((struct socket_plus *)((char *)(so) - sizeof(eye_catch8b_t)))

/* -------------------------------------------------------------------------------------
//
// NAME:    SOFREE
//
// DESC:    Free a socket structure.
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define SOFREE(so)                                                              \
{                                                                               \
    if (so->extension != NULL)                                                  \
	{																			\
    	if (so->extension->bypass_proto_ptr != NULL)							\
		{																		\
		    NET_FREE(so->extension->bypass_proto_ptr, M_SOCKET);                \
			so->extension->bypass_proto_ptr = NULL;								\
		}																		\
	    NET_FREE(so->extension, M_SOCKET);                                      \
    }																			\
	soplus = sotosop(so);                                                       \
    soplus->sop_eyecat = EYEC_SOCKETF;                                          \
    NET_FREE(soplus, M_SOCKET);                                                 \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    SAIOQ_LOCK
//
// DESC:    Lock the global async queue and return old priority
//
// ------------------------------------------------------------------------------------ */
#define SAIOQ_LOCK              disable_lock(PL_IMP, &saioq_lock)

/* -------------------------------------------------------------------------------------
//
// NAME:    SAIOQ_UNLOCK
//
// DESC:    Unlock the global async queue
//
// ARGS:    x               old priority
//
// ------------------------------------------------------------------------------------ */
#define SAIOQ_UNLOCK(x)         unlock_enable(x, &saioq_lock)

#ifdef _KERNEL

/* -------------------------------------------------------------------------------------
//
// NAME:    FREE_SOCK_HASH
//
// DESC:    Calculate a hash value based on a socket struct address.
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define FREE_SOCK_HASH(so)      (((ulong)(so)) % FREE_SOCK_HASH_SZ)

/* -------------------------------------------------------------------------------------
//
// NAME:    FREE_SOCK_LOCK_INIT
//
// DESC:    Initialization for the global free_sock_hash_table struct.
//
// ------------------------------------------------------------------------------------ */
#define FREE_SOCK_LOCK_INIT()                                                   \
{                                                                               \
    int _free_sock_index;                                                       \
                                                                                \
    for (_free_sock_index = 0;                                                  \
         _free_sock_index < FREE_SOCK_HASH_SZ;                                  \
         _free_sock_index++)                                                    \
    {                                                                           \
        lock_alloc(&free_sock_hash_table[_free_sock_index].fsh_lock,            \
                   LOCK_ALLOC_PIN,                                              \
                   UNPMISC_LOCK_FAMILY,                                         \
                   (uint)_free_sock_index);                                     \
                                                                                \
        simple_lock_init(&free_sock_hash_table[_free_sock_index].fsh_lock);     \
    }                                                                           \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    FREE_SOCK_LOCK
//
// DESC:    Lock the global free_sock_hash_table at index.
//
// ARGS:    index           table index
//
// ------------------------------------------------------------------------------------ */
#define FREE_SOCK_LOCK(index)                                                   \
{                                                                               \
   free_sock_hash_table[(index)].fsh_intrlvl =                                  \
        disable_lock(PL_IMP, &free_sock_hash_table[(index)].fsh_lock);          \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    FREE_SOCK_UNLOCK
//
// DESC:    Unlock the global free_sock_hash_table at index.
//
// ARGS:    index           table index
//
// ------------------------------------------------------------------------------------ */
#define FREE_SOCK_UNLOCK(index)                                                 \
{                                                                               \
    unlock_enable(free_sock_hash_table[(index)].fsh_intrlvl,                    \
    &free_sock_hash_table[(index)].fsh_lock);                                   \
}


#if DEBUG && POWER_MP
#define FREE_SOCK_ISLOCKED(lp)  lock_mine(lp)
#else
#define FREE_SOCK_ISLOCKED(lp)  1
#endif

#if DEBUG && _POWER_MP
#define SOCKET_ISLOCKED(so)     lock_mine(&((so)->so_lock->sock_lock))
#else
#define SOCKET_ISLOCKED(so)     1
#endif

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_LOCKINIT
//
// DESC:    Initialization for a lock in the socket structure.
//
// ARGS:    so              socket pointer
//          lp              pointer to lock variable
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_LOCKINIT(so, lp)                                                 \
{                                                                               \
    (so)->so_lock   = (lp);                                                     \
    (lp)->refcnt    = 0;                                                        \
    (lp)->sp_wake   = 0;                                                        \
    (lp)->so        = so;                                                       \
    (lp)->freelist  = 0;                                                        \
                                                                                \
    lock_alloc(&((lp)->sock_lock),                                              \
               LOCK_ALLOC_PIN,                                                  \
               SOCKET_LOCK_FAMILY,                                              \
               (uint)so);                                                       \
                                                                                \
    simple_lock_init(&((lp)->sock_lock));                                       \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    SAME_SOCKET_LOCK
//
// DESC:    Checks if the two sockets share the same lock. 1 is True, 0 otherwise.
//
// ARGS:    so1             socket pointer 1
//          so2             socket pointer 2
//
// ------------------------------------------------------------------------------------ */
#define SAME_SOCKET_LOCK(so1, so2)      ((so1)->so_lock == (so2)->so_lock)

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_LOCK2
//
// DESC:    Lock set of unpaired sockets (critical to avoid deadlock)
//
// ARGS:    so1             socket pointer 1
//          so2             socket pointer 2
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_LOCK2(so1, so2)                                                  \
{                                                                               \
    if (SOCKET_LOCK_IS_LOWER(so1, so2))                                         \
    {                                                                           \
        SOCKET_LOCK(so1);                                                       \
        SOCKET_LOCK(so2);                                                       \
    }                                                                           \
    else                                                                        \
    {                                                                           \
        SOCKET_LOCK(so2);                                                       \
        if ((so1)->so_lock != (so2)->so_lock)                                   \
        {                                                                       \
          SOCKET_LOCK(so1);                                                     \
        }                                                                       \
    }                                                                           \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_UNLOCK2
//
// DESC:    Unlock set of unpaired sockets (critical to avoid deadlock)
//
// ARGS:    so1             socket pointer 1
//          so2             socket pointer 2
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_UNLOCK2(so1, so2)                                                \
{                                                                               \
    if (SOCKET_LOCK_IS_LOWER(so1, so2))                                         \
    {                                                                           \
        SOCKET_UNLOCK(so2);                                                     \
        SOCKET_UNLOCK(so1);                                                     \
    }                                                                           \
    else                                                                        \
    {                                                                           \
        SOCKET_UNLOCK(so1);                                                     \
        if ((so1)->so_lock != (so2)->so_lock)                                   \
        {                                                                       \
            SOCKET_UNLOCK(so2);                                                 \
        }                                                                       \
    }                                                                           \
}


/* -------------------------------------------------------------------------------------
//
// NAME:    UNP_SOCKET_LOCK2
//
// DESC:    Lock set of unpaired sockets (critical to avoid deadlock)
//	    Enforcing lock order in case of unix dgram sockets is difficult
//	    as we allow server socket to communicate with another client
//	    simultaneously. Due to this, server socket might have different
//	    lock than client socket lock. If this sequence happens while we
//	    wait for server socket lock,  there is possibility to have deadlock
//	    when another thread tries to take 2 sockets lock (one socket may be
//	    this server and another socket might be new client) by enforcing
//	    lock order.
// ARGS:    so1             socket pointer 1
//          so2             socket pointer 2
//
// ------------------------------------------------------------------------------------ */
#define UNP_SOCKET_LOCK2(so1, so2) 						 \
{										 \
	struct  socklocks *solk1 = (so1)->so_lock;				 \
	struct  socklocks *solk2 = (so2)->so_lock;				 \
	while (1) 								 \
	{									 \
		solk1 = (so1)->so_lock; 					 \
		solk2 = (so2)->so_lock; 					 \
		if ( solk1 < solk2 ) 						 \
		{								 \
			SOCKET_LOCK(so1); 					 \
			if ( (so1)->so_lock > solk1) 				 \
			{							 \
				 SOCKET_UNLOCK(so1); 				 \
				 continue; 				 	 \
			} 							 \
			if ((so2)->so_lock != (so1)->so_lock)	 		 \
			{							 \
				if ((so2)->so_lock > (so1)->so_lock) 		 \
				{						 \
					SOCKET_LOCK(so2); 			 \
				}						 \ 
				else 						 \
				{ 					 	 \
					SOCKET_UNLOCK(so1); 			 \
					continue; 				 \
				} 						 \
			} 							 \
			break;	 						 \
		} 								 \
		else 								 \
		{	 							 \
			SOCKET_LOCK(so2); 					 \
			if ( (so2)->so_lock > solk2) 				 \
			{							 \
				SOCKET_UNLOCK(so2); 				 \
				continue; 					 \
			} 							 \
			if ((so2)->so_lock != (so1)->so_lock)	 		 \
			{							 \
				if ((so1)->so_lock > (so2)->so_lock) 		 \
				{						 \
					SOCKET_LOCK(so1); 			 \
				} 						 \
				else 						 \
				{	 					 \
					SOCKET_UNLOCK(so2); 			 \
					continue; 				 \
				} 						 \
			} 							 \
			break; 							 \
		} 								 \
	 } 									 \
} 


/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_LOCK
//
// DESC:    Lock a socket structure
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#ifdef __64BIT__

#define SOCKET_LOCK(so)                                                         \
{                                                                               \
    if ((so)->so_special & SP_DISABLE)                                          \
    {                                                                           \
        simple_lock_data_t *lw = &((so)->so_lock->sock_lock);                   \
        int intpri;                                                             \
                                                                                \
        intpri = disable_lock(PL_IMP, lw);                                      \
        while (lw != &((so)->so_lock->sock_lock)) {                             \
                simple_unlock(lw);                                              \
                lw = &((so)->so_lock->sock_lock);                               \
                simple_lock(lw);                                                \
        }                                                                       \
        (so)->so_lock->spl = intpri;                                            \
    }                                                                           \
    else                                                                        \
    {                                                                           \
        simple_lock_data_t *lw = &((so)->so_lock->sock_lock);                   \
                                                                                \
        simple_lock(lw);                                                        \
        while (lw != &((so)->so_lock->sock_lock))                               \
        {                                                                       \
            simple_unlock(lw);                                                  \
            lw = &((so)->so_lock->sock_lock);                                   \
            simple_lock(lw);                                                    \
        }                                                                       \
    }                                                                           \
}

#else

#define SOCKET_LOCK(so)                                                         \
{                                                                               \
    if ((so)->so_special & SP_DISABLE)                                          \
    {                                                                           \
        so_pin_more_stack(so);                                                  \
    }                                                                           \
    else                                                                        \
    {                                                                           \
        simple_lock_data_t *lw = &((so)->so_lock->sock_lock);                   \
                                                                                \
        simple_lock(lw);                                                        \
        while (lw != &((so)->so_lock->sock_lock))                               \
        {                                                                       \
            simple_unlock(lw);                                                  \
            lw = &((so)->so_lock->sock_lock);                                   \
            simple_lock(lw);                                                    \
        }                                                                       \
    }                                                                           \
}
#endif

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_UNLOCK
//
// DESC:    Unlock a socket structure
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_UNLOCK(so)           sounlock(so);

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_TRY_LOCK
//
// DESC:    Try to acquire a socket lock.
//          Return TRUE if success, FALSE otherwise.
//
// ARGS:    _so             socket pointer
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_TRY_LOCK(_so)        \
        socket_try_lock(_so)

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_REF
//
// DESC:    Adda reference to a socket structure.
//          This is an atomic operation and locking is not needed.
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_REF(so)              fetch_and_addlp(&((so)->so_refcnt),1);

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_UNREF
//
// DESC:    Removes reference from a socket structure.
//          This is an atomic operation and locking is not needed.
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_UNREF(so)            fetch_and_addlp(&((so)->so_refcnt),-1);

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_INTERIM_UNLOCK
//
// DESC:    Unlock the socket lock temporarily. Hold a reference to the socket
//          to prevent the socket from going away
//
//          This macro assumes that the socket lock is currently held
//          A call to this macro must be eventually followed by a call to
//          SOCKET_INTERIM_RELOCK().
//
// ARGS:    _so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_INTERIM_UNLOCK(_so)                                              \
{                                                                               \
    do                                                                          \
    {                                                                           \
        SOCKET_REF(_so);                                                        \
        SOCKET_UNLOCK(_so);                                                     \
                                                                                \
    } while (0);                                                                \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_INTERIM_RELOCK
//
// DESC:    Relock the socket lock after a temporary unlock. Release the socket
//          reference previously held.
//
//          A call to this macro must be preceded by a call to
//          SOCKET_INTERIM_UNLOCK().
//
// ARGS:    _so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_INTERIM_RELOCK(_so)                                              \
{                                                                               \
    do                                                                          \
    {                                                                           \
        SOCKET_LOCK(_so);                                                       \
        SOCKET_UNREF(_so);                                                      \
                                                                                \
    } while (0);                                                                \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_LOCK_MINE
//
// DESC:    Returns TRUE if caller is holding the socket lock
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_LOCK_MINE(so)     lock_mine(&((so)->so_lock->sock_lock))

/* -------------------------------------------------------------------------------------
//
// NAME:    SOCKET_LOCK_IS_LOWER
//
// DESC:    Returns TRUE if _so1's socket lock has lower locking order than
//          _so2's socket lock.
//
// ARGS:    _so1             socket pointer 1
//          _so2             socket pointer 2
//
// ------------------------------------------------------------------------------------ */
#define SOCKET_LOCK_IS_LOWER(_so1, _so2) \
    ((uintptr_t)((_so1)->so_lock) < (uintptr_t)((_so2)->so_lock))

#define SOCKBUF_LOCK(sb)        /* unused, symbol kept for compat */
#define SOCKBUF_UNLOCK(sb)      /* unused, symbol kept for compat */

/* -------------------------------------------------------------------------------------
//
// NAME:    SOHASUAREA
//
// DESC:    Does socket have a valid u-area associated? (for stats, security, etc)
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define SOHASUAREA(so)  (!((so)->so_special & SP_NOUAREA))

/* -------------------------------------------------------------------------------------
//
// NAME:    sodomain
//
// DESC:    what is the domain associated with this socket?
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define sodomain(so)    ((so)->so_proto->pr_domain)

/* -------------------------------------------------------------------------------------
//
// NAME:    soisrds
//
// DESC:    Is this an RDS socket, TRUE if so
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define soisrds(so)	    ((so)->so_proto->pr_type == SOCK_SEQPACKET &&           \
                         (so)->so_proto->pr_protocol == BYPASSPROTO_RDS)

/* -------------------------------------------------------------------------------------
//
// NAME:    soissmcr
//
// DESC:    Is this an SMCR socket, TRUE if so
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define soissmcr(so)	    (((so)->so_flag & SO_BYPASS_ACTIVE) && \
                            ((so)->so_flag & (SO_BYPASS_SMCR_CLIENT|SO_BYPASS_SMCR_SERVER)))

/* -------------------------------------------------------------------------------------
//
// NAME:    sbspace
//
// DESC:    How much space is there in a socket buffer (so->so_snd or so->so_rcv)?
//          This is problematical if the fields are unsigned, as the space might
//          still be negative (cc > hiwat or mbcnt > mbmax).  Should detect
//          overflow and return 0.  Should use "lmin" but it doesn't exist now.
//
// ARGS:    sb              socket buffer pointer
//
// ------------------------------------------------------------------------------------ */
#define sbspace(sb)     (MIN((int)((sb)->sb_hiwat - (sb)->sb_cc),(int)((sb)->sb_mbmax - (sb)->sb_mbcnt)))                               

/* -------------------------------------------------------------------------------------
//
// NAME:    sosendallatonce
//
// DESC:    Do we have to send all at once on a socket?
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define sosendallatonce(so) ((so)->so_proto->pr_flags & PR_ATOMIC)

/* -------------------------------------------------------------------------------------
//
// NAME:    soreadable
//
// DESC:    Can we read something from so?
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define soreadable(so)   (((so)->so_rcv.sb_cc >= (so)->so_rcv.sb_lowat) ||      \
                          ((so)->so_state & SS_CANTRCVMORE) ||                  \
                          (so)->so_qlen ||                                      \
						  (so)->so_error ||                                     \
                          (soisrds(so) && (so)->so_rcv.sb_mbcnt) ||             \
                          (soissmcr(so) && ((so)->extension->bypass_proto_so_rcv->sb_cc >= \
                                           (so)->extension->bypass_proto_so_rcv->sb_lowat)))

/* -------------------------------------------------------------------------------------
//
// NAME:    sowriteable
//
// DESC:    Can we write something to so?
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define sowriteable(so)  (sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat &&     \
                          (((so)->so_state & SS_ISCONNECTED &&                   \
                            !((so)->so_flag & SO_BYPASS_ISCONNECTING)) ||        \
                           ((so)->so_proto->pr_flags & PR_CONNREQUIRED) == 0) || \
                          ((so)->so_state & SS_CANTSENDMORE) ||                  \
                          (so)->so_error ||                                      \
                          (soissmcr(so) && ((so)->extension->bypass_proto_so_snd->sb_cc >= \
                                           (so)->extension->bypass_proto_so_snd->sb_lowat)))

/* -------------------------------------------------------------------------------------
//
// NAME:    sballoc
//
// DESC:    adjust counters in sb reflecting allocation of m
//
// ARGS:    sb              socket buffer pointer
//          m               mbuf pointer
//
// ------------------------------------------------------------------------------------ */
#define sballoc(sb, m)                                                          \
{                                                                               \
    (sb)->sb_cc += (m)->m_len;                                                  \
    (sb)->sb_mbcnt += MSIZE;                                                    \
    if ((m)->m_flags & M_EXT)                                                   \
        (sb)->sb_mbcnt += (m)->m_ext.ext_size;                                  \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    sbfree
//
// DESC:    adjust counters in sb reflecting freeing of m
//
// ARGS:    sb              socket buffer pointer
//          m               mbuf pointer
//
// ------------------------------------------------------------------------------------ */
#define sbfree(sb, m)                                                           \
{                                                                               \
    (sb)->sb_cc -= (m)->m_len;                                                  \
    (sb)->sb_mbcnt -= MSIZE;                                                    \
    if ((m)->m_flags & M_EXT)                                                   \
        (sb)->sb_mbcnt -= (m)->m_ext.ext_size;                                  \
}

/* -------------------------------------------------------------------------------------
//
// NAME:    sorwakeup
//
// DESC:    Wakeup waiters on the receive queue
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define sorwakeup(so)   sowakeup((so), &(so)->so_rcv)

/* -------------------------------------------------------------------------------------
//
// NAME:    sowwakeup
//
// DESC:    Wakeup waiters on the send queue
//
// ARGS:    so              socket pointer
//
// ------------------------------------------------------------------------------------ */
#define sowwakeup(so)   sowakeup((so), &(so)->so_snd)

/* -------------------------------------------------------------------------------------
//
// NAME:    sonewconn
//
// DESC:    To catch callers missing new second argument to sonewconn:
//
// ARGS:    head            socket pointer
//          connstatus      connection status value
//
// ------------------------------------------------------------------------------------ */
#define sonewconn(head, connstatus)     sonewsock((head), (connstatus))

/* -------------------------------------------------------------------------------------
//
// NAME:    QOS_IS_LOADED
//
// DESC:    Is the qos allocated? TRUE if so
//
// ------------------------------------------------------------------------------------ */
#define QOS_IS_LOADED (qos_fns.qos_alloc != NULL)

#define so2gidstruct(so) (struct gidstruct *) ((struct socket *)(so) + 1)

#endif  /* _KERNEL */

#ifdef __cplusplus
}
#endif

#endif
