#ifndef _NETINET_IN_PCB_H_
#define _NETINET_IN_PCB_H_
#include <sys/queue.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/_rwlock.h>
#ifdef _KERNEL
#include <sys/lock.h>
#include <sys/rwlock.h>
#include <net/vnet.h>
#include <vm/uma.h>
#endif
#define in6pcb inpcb
#define in6p_sp inp_sp
struct inpcbpolicy;
LIST_HEAD(inpcbhead, inpcb);
LIST_HEAD(inpcbporthead, inpcbport);
typedef u_quad_t inp_gen_t;
struct in_addr_4in6 {
u_int32_t ia46_pad32[3];
struct in_addr ia46_addr4;
};
struct in_endpoints {
u_int16_t ie_fport;
u_int16_t ie_lport;
union {
struct in_addr_4in6 ie46_foreign;
struct in6_addr ie6_foreign;
} ie_dependfaddr;
union {
struct in_addr_4in6 ie46_local;
struct in6_addr ie6_local;
} ie_dependladdr;
u_int32_t ie6_zoneid;
};
#define ie_faddr ie_dependfaddr.ie46_foreign.ia46_addr4
#define ie_laddr ie_dependladdr.ie46_local.ia46_addr4
#define ie6_faddr ie_dependfaddr.ie6_foreign
#define ie6_laddr ie_dependladdr.ie6_local
struct in_conninfo {
u_int8_t inc_flags;
u_int8_t inc_len;
u_int16_t inc_fibnum;
struct in_endpoints inc_ie;
};
#define INC_ISIPV6 0x01
#define inc_isipv6 inc_flags
#define inc_fport inc_ie.ie_fport
#define inc_lport inc_ie.ie_lport
#define inc_faddr inc_ie.ie_faddr
#define inc_laddr inc_ie.ie_laddr
#define inc6_faddr inc_ie.ie6_faddr
#define inc6_laddr inc_ie.ie6_laddr
#define inc6_zoneid inc_ie.ie6_zoneid
struct icmp6_filter;
struct inpcb {
LIST_ENTRY(inpcb) inp_hash;
LIST_ENTRY(inpcb) inp_pcbgrouphash;
LIST_ENTRY(inpcb) inp_list;
void *inp_ppcb;
struct inpcbinfo *inp_pcbinfo;
struct inpcbgroup *inp_pcbgroup;
LIST_ENTRY(inpcb) inp_pcbgroup_wild;
struct socket *inp_socket;
struct ucred *inp_cred;
u_int32_t inp_flow;
int inp_flags;
int inp_flags2;
u_char inp_vflag;
u_char inp_ip_ttl;
u_char inp_ip_p;
u_char inp_ip_minttl;
uint32_t inp_flowid;
u_int inp_refcount;
void *inp_pspare[5];
uint32_t inp_flowtype;
uint32_t inp_rss_listen_bucket;
u_int inp_ispare[4];
struct in_conninfo inp_inc;
struct label *inp_label;
struct inpcbpolicy *inp_sp;
struct {
u_char inp4_ip_tos;
struct mbuf *inp4_options;
struct ip_moptions *inp4_moptions;
} inp_depend4;
struct {
struct mbuf *inp6_options;
struct ip6_pktopts *inp6_outputopts;
struct ip6_moptions *inp6_moptions;
struct icmp6_filter *inp6_icmp6filt;
int inp6_cksum;
short inp6_hops;
} inp_depend6;
LIST_ENTRY(inpcb) inp_portlist;
struct inpcbport *inp_phd;
#define inp_zero_size offsetof(struct inpcb, inp_gencnt)
inp_gen_t inp_gencnt;
struct llentry *inp_lle;
struct rtentry *inp_rt;
struct rwlock inp_lock;
};
#define inp_fport inp_inc.inc_fport
#define inp_lport inp_inc.inc_lport
#define inp_faddr inp_inc.inc_faddr
#define inp_laddr inp_inc.inc_laddr
#define inp_ip_tos inp_depend4.inp4_ip_tos
#define inp_options inp_depend4.inp4_options
#define inp_moptions inp_depend4.inp4_moptions
#define in6p_faddr inp_inc.inc6_faddr
#define in6p_laddr inp_inc.inc6_laddr
#define in6p_zoneid inp_inc.inc6_zoneid
#define in6p_hops inp_depend6.inp6_hops
#define in6p_flowinfo inp_flow
#define in6p_options inp_depend6.inp6_options
#define in6p_outputopts inp_depend6.inp6_outputopts
#define in6p_moptions inp_depend6.inp6_moptions
#define in6p_icmp6filt inp_depend6.inp6_icmp6filt
#define in6p_cksum inp_depend6.inp6_cksum
#define inp_vnet inp_pcbinfo->ipi_vnet
#ifdef _SYS_SOCKETVAR_H_
struct xinpcb {
size_t xi_len;
struct inpcb xi_inp;
struct xsocket xi_socket;
u_quad_t xi_alignment_hack;
};
struct xinpgen {
size_t xig_len;
u_int xig_count;
inp_gen_t xig_gen;
so_gen_t xig_sogen;
};
#endif
struct inpcbport {
LIST_ENTRY(inpcbport) phd_hash;
struct inpcbhead phd_pcblist;
u_short phd_port;
};
struct inpcbinfo {
struct rwlock ipi_lock;
struct inpcbhead *ipi_listhead;
u_int ipi_count;
u_quad_t ipi_gencnt;
u_short ipi_lastport;
u_short ipi_lastlow;
u_short ipi_lasthi;
struct uma_zone *ipi_zone;
struct inpcbgroup *ipi_pcbgroups;
u_int ipi_npcbgroups;
u_int ipi_hashfields;
struct rwlock ipi_hash_lock;
struct inpcbhead *ipi_hashbase;
u_long ipi_hashmask;
struct inpcbporthead *ipi_porthashbase;
u_long ipi_porthashmask;
struct inpcbhead *ipi_wildbase;
u_long ipi_wildmask;
struct vnet *ipi_vnet;
void *ipi_pspare[2];
struct rwlock ipi_list_lock;
};
#ifdef _KERNEL
struct inpcbgroup {
struct inpcbhead *ipg_hashbase;
u_long ipg_hashmask;
u_int ipg_cpu;
struct mtx ipg_lock;
} __aligned(CACHE_LINE_SIZE);
#define INP_LOCK_INIT(inp, d, t) \
rw_init_flags(&(inp)->inp_lock, (t), RW_RECURSE | RW_DUPOK)
#define INP_LOCK_DESTROY(inp) rw_destroy(&(inp)->inp_lock)
#define INP_RLOCK(inp) rw_rlock(&(inp)->inp_lock)
#define INP_WLOCK(inp) rw_wlock(&(inp)->inp_lock)
#define INP_TRY_RLOCK(inp) rw_try_rlock(&(inp)->inp_lock)
#define INP_TRY_WLOCK(inp) rw_try_wlock(&(inp)->inp_lock)
#define INP_RUNLOCK(inp) rw_runlock(&(inp)->inp_lock)
#define INP_WUNLOCK(inp) rw_wunlock(&(inp)->inp_lock)
#define INP_TRY_UPGRADE(inp) rw_try_upgrade(&(inp)->inp_lock)
#define INP_DOWNGRADE(inp) rw_downgrade(&(inp)->inp_lock)
#define INP_WLOCKED(inp) rw_wowned(&(inp)->inp_lock)
#define INP_LOCK_ASSERT(inp) rw_assert(&(inp)->inp_lock, RA_LOCKED)
#define INP_RLOCK_ASSERT(inp) rw_assert(&(inp)->inp_lock, RA_RLOCKED)
#define INP_WLOCK_ASSERT(inp) rw_assert(&(inp)->inp_lock, RA_WLOCKED)
#define INP_UNLOCK_ASSERT(inp) rw_assert(&(inp)->inp_lock, RA_UNLOCKED)
void inp_wlock(struct inpcb *);
void inp_wunlock(struct inpcb *);
void inp_rlock(struct inpcb *);
void inp_runlock(struct inpcb *);
#ifdef INVARIANTS
void inp_lock_assert(struct inpcb *);
void inp_unlock_assert(struct inpcb *);
#else
static __inline void
inp_lock_assert(struct inpcb *inp __unused)
{
}
static __inline void
inp_unlock_assert(struct inpcb *inp __unused)
{
}
#endif
void inp_apply_all(void (*func)(struct inpcb *, void *), void *arg);
int inp_ip_tos_get(const struct inpcb *inp);
void inp_ip_tos_set(struct inpcb *inp, int val);
struct socket *
inp_inpcbtosocket(struct inpcb *inp);
struct tcpcb *
inp_inpcbtotcpcb(struct inpcb *inp);
void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
uint32_t *faddr, uint16_t *fp);
short inp_so_options(const struct inpcb *inp);
#endif
#define INP_INFO_LOCK_INIT(ipi, d) \
rw_init_flags(&(ipi)->ipi_lock, (d), RW_RECURSE)
#define INP_INFO_LOCK_DESTROY(ipi) rw_destroy(&(ipi)->ipi_lock)
#define INP_INFO_RLOCK(ipi) rw_rlock(&(ipi)->ipi_lock)
#define INP_INFO_WLOCK(ipi) rw_wlock(&(ipi)->ipi_lock)
#define INP_INFO_TRY_RLOCK(ipi) rw_try_rlock(&(ipi)->ipi_lock)
#define INP_INFO_TRY_WLOCK(ipi) rw_try_wlock(&(ipi)->ipi_lock)
#define INP_INFO_TRY_UPGRADE(ipi) rw_try_upgrade(&(ipi)->ipi_lock)
#define INP_INFO_WLOCKED(ipi) rw_wowned(&(ipi)->ipi_lock)
#define INP_INFO_RUNLOCK(ipi) rw_runlock(&(ipi)->ipi_lock)
#define INP_INFO_WUNLOCK(ipi) rw_wunlock(&(ipi)->ipi_lock)
#define INP_INFO_LOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_LOCKED)
#define INP_INFO_RLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_RLOCKED)
#define INP_INFO_WLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_WLOCKED)
#define INP_INFO_UNLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_UNLOCKED)
#define INP_LIST_LOCK_INIT(ipi, d) \
rw_init_flags(&(ipi)->ipi_list_lock, (d), 0)
#define INP_LIST_LOCK_DESTROY(ipi) rw_destroy(&(ipi)->ipi_list_lock)
#define INP_LIST_RLOCK(ipi) rw_rlock(&(ipi)->ipi_list_lock)
#define INP_LIST_WLOCK(ipi) rw_wlock(&(ipi)->ipi_list_lock)
#define INP_LIST_TRY_RLOCK(ipi) rw_try_rlock(&(ipi)->ipi_list_lock)
#define INP_LIST_TRY_WLOCK(ipi) rw_try_wlock(&(ipi)->ipi_list_lock)
#define INP_LIST_TRY_UPGRADE(ipi) rw_try_upgrade(&(ipi)->ipi_list_lock)
#define INP_LIST_RUNLOCK(ipi) rw_runlock(&(ipi)->ipi_list_lock)
#define INP_LIST_WUNLOCK(ipi) rw_wunlock(&(ipi)->ipi_list_lock)
#define INP_LIST_LOCK_ASSERT(ipi) \
rw_assert(&(ipi)->ipi_list_lock, RA_LOCKED)
#define INP_LIST_RLOCK_ASSERT(ipi) \
rw_assert(&(ipi)->ipi_list_lock, RA_RLOCKED)
#define INP_LIST_WLOCK_ASSERT(ipi) \
rw_assert(&(ipi)->ipi_list_lock, RA_WLOCKED)
#define INP_LIST_UNLOCK_ASSERT(ipi) \
rw_assert(&(ipi)->ipi_list_lock, RA_UNLOCKED)
#define INP_HASH_LOCK_INIT(ipi, d) \
rw_init_flags(&(ipi)->ipi_hash_lock, (d), 0)
#define INP_HASH_LOCK_DESTROY(ipi) rw_destroy(&(ipi)->ipi_hash_lock)
#define INP_HASH_RLOCK(ipi) rw_rlock(&(ipi)->ipi_hash_lock)
#define INP_HASH_WLOCK(ipi) rw_wlock(&(ipi)->ipi_hash_lock)
#define INP_HASH_RUNLOCK(ipi) rw_runlock(&(ipi)->ipi_hash_lock)
#define INP_HASH_WUNLOCK(ipi) rw_wunlock(&(ipi)->ipi_hash_lock)
#define INP_HASH_LOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_hash_lock, \
RA_LOCKED)
#define INP_HASH_WLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_hash_lock, \
RA_WLOCKED)
#define INP_GROUP_LOCK_INIT(ipg, d) mtx_init(&(ipg)->ipg_lock, (d), NULL, \
MTX_DEF | MTX_DUPOK)
#define INP_GROUP_LOCK_DESTROY(ipg) mtx_destroy(&(ipg)->ipg_lock)
#define INP_GROUP_LOCK(ipg) mtx_lock(&(ipg)->ipg_lock)
#define INP_GROUP_LOCK_ASSERT(ipg) mtx_assert(&(ipg)->ipg_lock, MA_OWNED)
#define INP_GROUP_UNLOCK(ipg) mtx_unlock(&(ipg)->ipg_lock)
#define INP_PCBHASH(faddr, lport, fport, mask) \
(((faddr) ^ ((faddr) >> 16) ^ ntohs((lport) ^ (fport))) & (mask))
#define INP_PCBPORTHASH(lport, mask) \
(ntohs((lport)) & (mask))
#define INP6_PCBHASHKEY(faddr) ((faddr)->s6_addr32[3])
#define INP_IPV4 0x1
#define INP_IPV6 0x2
#define INP_IPV6PROTO 0x4
#define INP_RECVOPTS 0x00000001
#define INP_RECVRETOPTS 0x00000002
#define INP_RECVDSTADDR 0x00000004
#define INP_HDRINCL 0x00000008
#define INP_HIGHPORT 0x00000010
#define INP_LOWPORT 0x00000020
#define INP_ANONPORT 0x00000040
#define INP_RECVIF 0x00000080
#define INP_MTUDISC 0x00000100
#define INP_RECVTTL 0x00000400
#define INP_DONTFRAG 0x00000800
#define INP_BINDANY 0x00001000
#define INP_INHASHLIST 0x00002000
#define INP_RECVTOS 0x00004000
#define IN6P_IPV6_V6ONLY 0x00008000
#define IN6P_PKTINFO 0x00010000
#define IN6P_HOPLIMIT 0x00020000
#define IN6P_HOPOPTS 0x00040000
#define IN6P_DSTOPTS 0x00080000
#define IN6P_RTHDR 0x00100000
#define IN6P_RTHDRDSTOPTS 0x00200000
#define IN6P_TCLASS 0x00400000
#define IN6P_AUTOFLOWLABEL 0x00800000
#define INP_TIMEWAIT 0x01000000
#define INP_ONESBCAST 0x02000000
#define INP_DROPPED 0x04000000
#define INP_SOCKREF 0x08000000
#define INP_RESERVED_0 0x10000000
#define INP_RESERVED_1 0x20000000
#define IN6P_RFC2292 0x40000000
#define IN6P_MTU 0x80000000
#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR|\
INP_RECVIF|INP_RECVTTL|INP_RECVTOS|\
IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_HOPOPTS|\
IN6P_DSTOPTS|IN6P_RTHDR|IN6P_RTHDRDSTOPTS|\
IN6P_TCLASS|IN6P_AUTOFLOWLABEL|IN6P_RFC2292|\
IN6P_MTU)
#define INP_LLE_VALID 0x00000001
#define INP_RT_VALID 0x00000002
#define INP_PCBGROUPWILD 0x00000004
#define INP_REUSEPORT 0x00000008
#define INP_FREED 0x00000010
#define INP_REUSEADDR 0x00000020
#define INP_BINDMULTI 0x00000040
#define INP_RSS_BUCKET_SET 0x00000080
#define INP_RECVFLOWID 0x00000100
#define INP_RECVRSSBUCKETID 0x00000200
#define INPLOOKUP_WILDCARD 0x00000001
#define INPLOOKUP_RLOCKPCB 0x00000002
#define INPLOOKUP_WLOCKPCB 0x00000004
#define INPLOOKUP_MASK (INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB | \
INPLOOKUP_WLOCKPCB)
#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb)
#define sotoin6pcb(so) sotoinpcb(so)
#define INP_SOCKAF(so) so->so_proto->pr_domain->dom_family
#define INP_CHECK_SOCKAF(so, af) (INP_SOCKAF(so) == af)
#define IPI_HASHFIELDS_NONE 0
#define IPI_HASHFIELDS_2TUPLE 1
#define IPI_HASHFIELDS_4TUPLE 2
#ifdef _KERNEL
VNET_DECLARE(int, ipport_reservedhigh);
VNET_DECLARE(int, ipport_reservedlow);
VNET_DECLARE(int, ipport_lowfirstauto);
VNET_DECLARE(int, ipport_lowlastauto);
VNET_DECLARE(int, ipport_firstauto);
VNET_DECLARE(int, ipport_lastauto);
VNET_DECLARE(int, ipport_hifirstauto);
VNET_DECLARE(int, ipport_hilastauto);
VNET_DECLARE(int, ipport_randomized);
VNET_DECLARE(int, ipport_randomcps);
VNET_DECLARE(int, ipport_randomtime);
VNET_DECLARE(int, ipport_stoprandom);
VNET_DECLARE(int, ipport_tcpallocs);
#define V_ipport_reservedhigh VNET(ipport_reservedhigh)
#define V_ipport_reservedlow VNET(ipport_reservedlow)
#define V_ipport_lowfirstauto VNET(ipport_lowfirstauto)
#define V_ipport_lowlastauto VNET(ipport_lowlastauto)
#define V_ipport_firstauto VNET(ipport_firstauto)
#define V_ipport_lastauto VNET(ipport_lastauto)
#define V_ipport_hifirstauto VNET(ipport_hifirstauto)
#define V_ipport_hilastauto VNET(ipport_hilastauto)
#define V_ipport_randomized VNET(ipport_randomized)
#define V_ipport_randomcps VNET(ipport_randomcps)
#define V_ipport_randomtime VNET(ipport_randomtime)
#define V_ipport_stoprandom VNET(ipport_stoprandom)
#define V_ipport_tcpallocs VNET(ipport_tcpallocs)
void in_pcbinfo_destroy(struct inpcbinfo *);
void in_pcbinfo_init(struct inpcbinfo *, const char *, struct inpcbhead *,
int, int, char *, uma_init, uma_fini, uint32_t, u_int);
int in_pcbbind_check_bindmulti(const struct inpcb *ni,
const struct inpcb *oi);
struct inpcbgroup *
in_pcbgroup_byhash(struct inpcbinfo *, u_int, uint32_t);
struct inpcbgroup *
in_pcbgroup_byinpcb(struct inpcb *);
struct inpcbgroup *
in_pcbgroup_bytuple(struct inpcbinfo *, struct in_addr, u_short,
struct in_addr, u_short);
void in_pcbgroup_destroy(struct inpcbinfo *);
int in_pcbgroup_enabled(struct inpcbinfo *);
void in_pcbgroup_init(struct inpcbinfo *, u_int, int);
void in_pcbgroup_remove(struct inpcb *);
void in_pcbgroup_update(struct inpcb *);
void in_pcbgroup_update_mbuf(struct inpcb *, struct mbuf *);
void in_pcbpurgeif0(struct inpcbinfo *, struct ifnet *);
int in_pcballoc(struct socket *, struct inpcbinfo *);
int in_pcbbind(struct inpcb *, struct sockaddr *, struct ucred *);
int in_pcb_lport(struct inpcb *, struct in_addr *, u_short *,
struct ucred *, int);
int in_pcbbind_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
u_short *, struct ucred *);
int in_pcbconnect(struct inpcb *, struct sockaddr *, struct ucred *);
int in_pcbconnect_mbuf(struct inpcb *, struct sockaddr *, struct ucred *,
struct mbuf *);
int in_pcbconnect_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
u_short *, in_addr_t *, u_short *, struct inpcb **,
struct ucred *);
void in_pcbdetach(struct inpcb *);
void in_pcbdisconnect(struct inpcb *);
void in_pcbdrop(struct inpcb *);
void in_pcbfree(struct inpcb *);
int in_pcbinshash(struct inpcb *);
int in_pcbinshash_nopcbgroup(struct inpcb *);
int in_pcbladdr(struct inpcb *, struct in_addr *, struct in_addr *,
struct ucred *);
struct inpcb *
in_pcblookup_local(struct inpcbinfo *,
struct in_addr, u_short, int, struct ucred *);
struct inpcb *
in_pcblookup(struct inpcbinfo *, struct in_addr, u_int,
struct in_addr, u_int, int, struct ifnet *);
struct inpcb *
in_pcblookup_mbuf(struct inpcbinfo *, struct in_addr, u_int,
struct in_addr, u_int, int, struct ifnet *, struct mbuf *);
void in_pcbnotifyall(struct inpcbinfo *pcbinfo, struct in_addr,
int, struct inpcb *(*)(struct inpcb *, int));
void in_pcbref(struct inpcb *);
void in_pcbrehash(struct inpcb *);
void in_pcbrehash_mbuf(struct inpcb *, struct mbuf *);
int in_pcbrele(struct inpcb *);
int in_pcbrele_rlocked(struct inpcb *);
int in_pcbrele_wlocked(struct inpcb *);
void in_pcbsetsolabel(struct socket *so);
int in_getpeeraddr(struct socket *so, struct sockaddr **nam);
int in_getsockaddr(struct socket *so, struct sockaddr **nam);
struct sockaddr *
in_sockaddr(in_port_t port, struct in_addr *addr);
void in_pcbsosetlabel(struct socket *so);
#endif
#endif