#ifndef _SYS_SOCKETVAR_H_
#define _SYS_SOCKETVAR_H_
#include <sys/select.h>
#include <sys/selinfo.h>
#include <sys/queue.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#if !defined(_KERNEL)
struct uio;
struct lwp;
struct uidinfo;
#else
#include <sys/atomic.h>
#include <sys/uidinfo.h>
#endif
TAILQ_HEAD(soqhead, socket);
struct sockbuf {
struct selinfo sb_sel;
struct mowner *sb_mowner;
struct socket *sb_so;
kcondvar_t sb_cv;
#define sb_startzero sb_cc
u_long sb_cc;
u_long sb_hiwat;
u_long sb_mbcnt;
u_long sb_mbmax;
u_long sb_lowat;
struct mbuf *sb_mb;
struct mbuf *sb_mbtail;
struct mbuf *sb_lastrecord;
int sb_flags;
int sb_timeo;
u_long sb_overflowed;
};
#ifndef SB_MAX
#define SB_MAX (256*1024)
#endif
#define SB_LOCK 0x01
#define SB_NOTIFY 0x04
#define SB_ASYNC 0x10
#define SB_UPCALL 0x20
#define SB_NOINTR 0x40
#define SB_KNOTE 0x100
#define SB_AUTOSIZE 0x800
struct so_accf {
struct accept_filter *so_accept_filter;
void *so_accept_filter_arg;
char *so_accept_filter_str;
};
struct sockaddr;
struct socket {
kmutex_t * volatile so_lock;
kcondvar_t so_cv;
short so_type;
short so_options;
u_short so_linger;
short so_state;
int so_unused;
void *so_pcb;
const struct protosw *so_proto;
struct socket *so_head;
struct soqhead *so_onq;
struct soqhead so_q0;
struct soqhead so_q;
TAILQ_ENTRY(socket) so_qe;
short so_q0len;
short so_qlen;
short so_qlimit;
short so_timeo;
u_short so_error;
u_short so_rerror;
u_short so_aborting;
pid_t so_pgid;
u_long so_oobmark;
struct sockbuf so_snd;
struct sockbuf so_rcv;
void *so_internal;
void (*so_upcall) (struct socket *, void *, int, int);
void * so_upcallarg;
int (*so_send) (struct socket *, struct sockaddr *,
struct uio *, struct mbuf *,
struct mbuf *, int, struct lwp *);
int (*so_receive) (struct socket *,
struct mbuf **,
struct uio *, struct mbuf **,
struct mbuf **, int *);
struct mowner *so_mowner;
struct uidinfo *so_uidinfo;
gid_t so_egid;
pid_t so_cpid;
struct so_accf *so_accf;
kauth_cred_t so_cred;
};
#define SS_NOFDREF 0x001
#define SS_ISCONNECTED 0x002
#define SS_ISCONNECTING 0x004
#define SS_ISDISCONNECTING 0x008
#define SS_CANTSENDMORE 0x010
#define SS_CANTRCVMORE 0x020
#define SS_RCVATMARK 0x040
#define SS_ISABORTING 0x080
#define SS_RESTARTSYS 0x100
#define SS_POLLRDBAND 0x200
#define SS_MORETOCOME 0x400
#define SS_ISDISCONNECTED 0x800
#define SS_ISAPIPE 0x1000
#define SS_NBIO 0x2000
#ifdef _KERNEL
struct accept_filter {
char accf_name[16];
void (*accf_callback)
(struct socket *, void *, int, int);
void * (*accf_create)
(struct socket *, char *);
void (*accf_destroy)
(struct socket *);
LIST_ENTRY(accept_filter) accf_next;
u_int accf_refcnt;
};
struct sockopt {
int sopt_level;
int sopt_name;
size_t sopt_size;
size_t sopt_retsize;
void * sopt_data;
uint8_t sopt_buf[sizeof(int)];
};
#define SB_EMPTY_FIXUP(sb) \
do { \
KASSERT(solocked((sb)->sb_so)); \
if ((sb)->sb_mb == NULL) { \
(sb)->sb_mbtail = NULL; \
(sb)->sb_lastrecord = NULL; \
} \
} while (0)
extern u_long sb_max;
extern int somaxkva;
extern int sock_loan_thresh;
extern kmutex_t *softnet_lock;
struct mbuf;
struct lwp;
struct msghdr;
struct stat;
struct knote;
struct sockaddr_big;
enum uio_seg;
#define SOOPT_TIMESTAMP(o) ((o) & (SO_TIMESTAMP | 0x400))
int soo_read(file_t *, off_t *, struct uio *, kauth_cred_t, int);
int soo_write(file_t *, off_t *, struct uio *, kauth_cred_t, int);
int soo_fcntl(file_t *, u_int cmd, void *);
int soo_ioctl(file_t *, u_long cmd, void *);
int soo_poll(file_t *, int);
int soo_kqfilter(file_t *, struct knote *);
int soo_close(file_t *);
int soo_stat(file_t *, struct stat *);
void soo_restart(file_t *);
void sbappend(struct sockbuf *, struct mbuf *);
void sbappendstream(struct sockbuf *, struct mbuf *);
int sbappendaddr(struct sockbuf *, const struct sockaddr *, struct mbuf *,
struct mbuf *);
int sbappendaddrchain(struct sockbuf *, const struct sockaddr *,
struct mbuf *, int);
int sbappendcontrol(struct sockbuf *, struct mbuf *, struct mbuf *);
void sbappendrecord(struct sockbuf *, struct mbuf *);
void sbcheck(struct sockbuf *);
void sbcompress(struct sockbuf *, struct mbuf *, struct mbuf *);
struct mbuf *
sbcreatecontrol(void *, int, int, int);
struct mbuf *
sbcreatecontrol1(void **, int, int, int, int);
struct mbuf **
sbsavetimestamp(int, struct mbuf **);
void sbdrop(struct sockbuf *, int);
void sbdroprecord(struct sockbuf *);
void sbflush(struct sockbuf *);
void sbinsertoob(struct sockbuf *, struct mbuf *);
void sbrelease(struct sockbuf *, struct socket *);
int sbreserve(struct sockbuf *, u_long, struct socket *);
int sbwait(struct sockbuf *);
int sb_max_set(u_long);
void soinit(void);
void soinit1(void);
void soinit2(void);
int soabort(struct socket *);
int soaccept(struct socket *, struct sockaddr *);
int sofamily(const struct socket *);
int sobind(struct socket *, struct sockaddr *, struct lwp *);
void socantrcvmore(struct socket *);
void socantsendmore(struct socket *);
void soroverflow(struct socket *);
int soclose(struct socket *);
int soconnect(struct socket *, struct sockaddr *, struct lwp *);
int soconnect2(struct socket *, struct socket *);
int socreate(int, struct socket **, int, int, struct lwp *,
struct socket *);
int fsocreate(int, struct socket **, int, int, int *, file_t **,
struct socket *);
int sodisconnect(struct socket *);
void sofree(struct socket *);
int sogetopt(struct socket *, struct sockopt *);
void sohasoutofband(struct socket *);
void soisconnected(struct socket *);
void soisconnecting(struct socket *);
void soisdisconnected(struct socket *);
void soisdisconnecting(struct socket *);
int solisten(struct socket *, int, struct lwp *);
struct socket *
sonewconn(struct socket *, bool);
void soqinsque(struct socket *, struct socket *, int);
bool soqremque(struct socket *, int);
int soreceive(struct socket *, struct mbuf **, struct uio *,
struct mbuf **, struct mbuf **, int *);
int soreserve(struct socket *, u_long, u_long);
void sorflush(struct socket *);
int sosend(struct socket *, struct sockaddr *, struct uio *,
struct mbuf *, struct mbuf *, int, struct lwp *);
int sosetopt(struct socket *, struct sockopt *);
int so_setsockopt(struct lwp *, struct socket *, int, int, const void *, size_t);
int soshutdown(struct socket *, int);
void sorestart(struct socket *);
void sowakeup(struct socket *, struct sockbuf *, int);
int sockargs(struct mbuf **, const void *, size_t, enum uio_seg, int);
int sopoll(struct socket *, int);
struct socket *soget(bool);
void soput(struct socket *);
bool solocked(const struct socket *);
bool solocked2(const struct socket *, const struct socket *);
int sblock(struct sockbuf *, int);
void sbunlock(struct sockbuf *);
int sowait(struct socket *, bool, int);
void solockretry(struct socket *, kmutex_t *);
void sosetlock(struct socket *);
void solockreset(struct socket *, kmutex_t *);
void sockopt_init(struct sockopt *, int, int, size_t);
void sockopt_destroy(struct sockopt *);
int sockopt_set(struct sockopt *, const void *, size_t);
int sockopt_setint(struct sockopt *, int);
int sockopt_get(const struct sockopt *, void *, size_t);
int sockopt_getint(const struct sockopt *, int *);
int sockopt_setmbuf(struct sockopt *, struct mbuf *);
struct mbuf *sockopt_getmbuf(const struct sockopt *);
int copyout_sockname(struct sockaddr *, unsigned int *, int, struct mbuf *);
int copyout_sockname_sb(struct sockaddr *, unsigned int *,
int , struct sockaddr_big *);
int copyout_msg_control(struct lwp *, struct msghdr *, struct mbuf *);
void free_control_mbuf(struct lwp *, struct mbuf *, struct mbuf *);
int do_sys_getpeername(int, struct sockaddr *);
int do_sys_getsockname(int, struct sockaddr *);
int do_sys_sendmsg(struct lwp *, int, struct msghdr *, int, register_t *);
int do_sys_sendmsg_so(struct lwp *, int, struct socket *, file_t *,
struct msghdr *, int, register_t *);
int do_sys_recvmsg(struct lwp *, int, struct msghdr *,
struct mbuf **, struct mbuf **, register_t *);
int do_sys_recvmsg_so(struct lwp *, int, struct socket *,
struct msghdr *mp, struct mbuf **, struct mbuf **, register_t *);
int do_sys_bind(struct lwp *, int, struct sockaddr *);
int do_sys_connect(struct lwp *, int, struct sockaddr *);
int do_sys_accept(struct lwp *, int, struct sockaddr *, register_t *,
const sigset_t *, int, int);
int do_sys_peeloff(struct socket *, void *);
#include <sys/protosw.h>
#include <sys/mbuf.h>
static __inline int
sb_notify(struct sockbuf *sb)
{
KASSERT(solocked(sb->sb_so));
return sb->sb_flags & (SB_NOTIFY | SB_ASYNC | SB_UPCALL | SB_KNOTE);
}
static __inline u_long
sbspace(const struct sockbuf *sb)
{
KASSERT(solocked(sb->sb_so));
if (sb->sb_hiwat <= sb->sb_cc || sb->sb_mbmax <= sb->sb_mbcnt)
return 0;
return lmin(sb->sb_hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt);
}
static __inline u_long
sbspace_oob(const struct sockbuf *sb)
{
u_long hiwat = sb->sb_hiwat;
if (hiwat < ULONG_MAX - 1024)
hiwat += 1024;
KASSERT(solocked(sb->sb_so));
if (hiwat <= sb->sb_cc || sb->sb_mbmax <= sb->sb_mbcnt)
return 0;
return lmin(hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt);
}
static __inline u_long
sbused(const struct sockbuf *sb)
{
KASSERT(solocked(sb->sb_so));
return sb->sb_cc;
}
static __inline int
sosendallatonce(const struct socket *so)
{
return so->so_proto->pr_flags & PR_ATOMIC;
}
static __inline int
soreadable(const struct socket *so)
{
KASSERT(solocked(so));
return so->so_rcv.sb_cc >= so->so_rcv.sb_lowat ||
(so->so_state & SS_CANTRCVMORE) != 0 ||
so->so_qlen != 0 || so->so_error != 0 || so->so_rerror != 0;
}
static __inline int
sowritable(const struct socket *so)
{
KASSERT(solocked(so));
return (sbspace(&so->so_snd) >= so->so_snd.sb_lowat &&
((so->so_state & SS_ISCONNECTED) != 0 ||
(so->so_proto->pr_flags & PR_CONNREQUIRED) == 0)) ||
(so->so_state & SS_CANTSENDMORE) != 0 ||
so->so_error != 0;
}
static __inline void
sballoc(struct sockbuf *sb, struct mbuf *m)
{
KASSERT(solocked(sb->sb_so));
sb->sb_cc += m->m_len;
sb->sb_mbcnt += MSIZE;
if (m->m_flags & M_EXT)
sb->sb_mbcnt += m->m_ext.ext_size;
}
static __inline void
sbfree(struct sockbuf *sb, struct mbuf *m)
{
KASSERT(solocked(sb->sb_so));
sb->sb_cc -= m->m_len;
sb->sb_mbcnt -= MSIZE;
if (m->m_flags & M_EXT)
sb->sb_mbcnt -= m->m_ext.ext_size;
}
static __inline void
sorwakeup(struct socket *so)
{
KASSERT(solocked(so));
if (sb_notify(&so->so_rcv))
sowakeup(so, &so->so_rcv, POLL_IN);
}
static __inline void
sowwakeup(struct socket *so)
{
KASSERT(solocked(so));
if (sb_notify(&so->so_snd))
sowakeup(so, &so->so_snd, POLL_OUT);
}
static __inline void
solock(struct socket *so)
{
kmutex_t *lock;
lock = atomic_load_consume(&so->so_lock);
mutex_enter(lock);
if (__predict_false(lock != atomic_load_relaxed(&so->so_lock)))
solockretry(so, lock);
}
static __inline void
sounlock(struct socket *so)
{
mutex_exit(so->so_lock);
}
#ifdef SOCKBUF_DEBUG
void sblastrecordchk(struct sockbuf *, const char *);
#define SBLASTRECORDCHK(sb, where) sblastrecordchk((sb), (where))
void sblastmbufchk(struct sockbuf *, const char *);
#define SBLASTMBUFCHK(sb, where) sblastmbufchk((sb), (where))
#define SBCHECK(sb) sbcheck(sb)
#else
#define SBLASTRECORDCHK(sb, where)
#define SBLASTMBUFCHK(sb, where)
#define SBCHECK(sb)
#endif
vaddr_t sokvaalloc(vaddr_t, vsize_t, struct socket *);
void sokvafree(vaddr_t, vsize_t);
void soloanfree(struct mbuf *, void *, size_t, void *);
#define SB_PRIO_NONE 0
#define SB_PRIO_ONESHOT_OVERFLOW 1
#define SB_PRIO_OVERDRAFT 2
#define SB_PRIO_BESTEFFORT 3
int accept_filt_getopt(struct socket *, struct sockopt *);
int accept_filt_setopt(struct socket *, const struct sockopt *);
int accept_filt_clear(struct socket *);
int accept_filt_add(struct accept_filter *);
int accept_filt_del(struct accept_filter *);
struct accept_filter *accept_filt_get(char *);
#ifdef ACCEPT_FILTER_MOD
#ifdef SYSCTL_DECL
SYSCTL_DECL(_net_inet_accf);
#endif
void accept_filter_init(void);
#endif
#ifdef DDB
int sofindproc(struct socket *so, int all, void (*pr)(const char *, ...));
void socket_print(const char *modif, void (*pr)(const char *, ...));
#endif
#endif
#endif