/* 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 #include #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 #if MACH #include #if SEC_ARCH #include #endif #endif #include #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