Changeset View
Changeset View
Standalone View
Standalone View
sys/sys/socketvar.h
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
* Kernel structure per socket. | * Kernel structure per socket. | ||||
* Contains send and receive buffer queues, | * Contains send and receive buffer queues, | ||||
* handle on protocol and pointer to protocol | * handle on protocol and pointer to protocol | ||||
* private data and error information. | * private data and error information. | ||||
*/ | */ | ||||
typedef u_quad_t so_gen_t; | typedef u_quad_t so_gen_t; | ||||
struct socket; | struct socket; | ||||
struct solisten; | |||||
/*- | /*- | ||||
* Locking key to struct socket: | * Locking key to struct socket: | ||||
* (a) constant after allocation, no locking required. | * (a) constant after allocation, no locking required. | ||||
* (b) locked by SOCK_LOCK(so). | * (b) locked by SOCK_LOCK(so). | ||||
* (c) locked by SOCKBUF_LOCK(&so->so_rcv). | * (c) locked by SOCKBUF_LOCK(&so->so_rcv). | ||||
* (e) locked by ACCEPT_LOCK(). | * (e) locked by SOLISTEN_LOCK() of corresponding listening socket. | ||||
* (f) not locked since integer reads/writes are atomic. | * (f) not locked since integer reads/writes are atomic. | ||||
* (g) used only as a sleep/wakeup address, no value. | * (g) used only as a sleep/wakeup address, no value. | ||||
* (h) locked by global mutex so_global_mtx. | * (h) locked by global mutex so_global_mtx. | ||||
*/ | */ | ||||
struct socket { | struct socket { | ||||
int so_count; /* (b) reference count */ | int so_count; /* (b) reference count */ | ||||
short so_type; /* (a) generic type, see socket.h */ | short so_type; /* (a) generic type, see socket.h */ | ||||
short so_options; /* from socket call, see socket.h */ | short so_options; /* from socket call, see socket.h */ | ||||
short so_linger; /* time to linger while closing */ | short so_linger; /* time to linger while closing */ | ||||
short so_state; /* (b) internal state flags SS_* */ | short so_state; /* (b) internal state flags SS_* */ | ||||
int so_qstate; /* (e) internal state flags SQ_* */ | int so_qstate; /* (e) internal state flags SQ_* */ | ||||
void *so_pcb; /* protocol control block */ | void *so_pcb; /* protocol control block */ | ||||
struct vnet *so_vnet; /* (a) network stack instance */ | struct vnet *so_vnet; /* (a) network stack instance */ | ||||
struct protosw *so_proto; /* (a) protocol handle */ | struct protosw *so_proto; /* (a) protocol handle */ | ||||
/* | struct solisten *so_listen; /* (e) back pointer to listen socket */ | ||||
* Variables for connection queuing. | |||||
* 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_incomp queues partially completed connections, | |||||
* while so_comp 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_incomp or so_comp. | |||||
* We allow connections to queue up based on current queue lengths | |||||
* and limit on number of queued connections for this socket. | |||||
*/ | |||||
struct socket *so_head; /* (e) back pointer to listen socket */ | |||||
TAILQ_HEAD(, socket) so_incomp; /* (e) queue of partial unaccepted connections */ | |||||
TAILQ_HEAD(, socket) so_comp; /* (e) queue of complete unaccepted connections */ | |||||
TAILQ_ENTRY(socket) so_list; /* (e) list of unaccepted connections */ | TAILQ_ENTRY(socket) so_list; /* (e) list of unaccepted connections */ | ||||
u_int so_qlen; /* (e) number of unaccepted connections */ | |||||
u_int so_incqlen; /* (e) number of unaccepted incomplete | |||||
connections */ | |||||
u_int so_qlimit; /* (e) max number queued connections */ | |||||
short so_timeo; /* (g) connection timeout */ | short so_timeo; /* (g) connection timeout */ | ||||
u_short so_error; /* (f) error affecting connection */ | u_short so_error; /* (f) error affecting connection */ | ||||
struct sigio *so_sigio; /* [sg] information for async I/O or | struct sigio *so_sigio; /* [sg] information for async I/O or | ||||
out of band data (SIGURG) */ | out of band data (SIGURG) */ | ||||
u_long so_oobmark; /* (c) chars to oob mark */ | u_long so_oobmark; /* (c) chars to oob mark */ | ||||
struct sockbuf so_rcv, so_snd; | struct sockbuf so_rcv, so_snd; | ||||
struct ucred *so_cred; /* (a) user credentials */ | struct ucred *so_cred; /* (a) user credentials */ | ||||
struct label *so_label; /* (b) MAC label for socket */ | struct label *so_label; /* (b) MAC label for socket */ | ||||
struct label *so_peerlabel; /* (b) cached MAC label for peer */ | struct label *so_peerlabel; /* (b) cached MAC label for peer */ | ||||
/* NB: generation count must not be first. */ | /* NB: generation count must not be first. */ | ||||
so_gen_t so_gencnt; /* (h) generation count */ | so_gen_t so_gencnt; /* (h) generation count */ | ||||
void *so_emuldata; /* (b) private data for emulators */ | void *so_emuldata; /* (b) private data for emulators */ | ||||
struct so_accf { | |||||
struct accept_filter *so_accept_filter; | |||||
void *so_accept_filter_arg; /* saved filter args */ | |||||
char *so_accept_filter_str; /* saved user args */ | |||||
} *so_accf; | |||||
struct osd osd; /* Object Specific extensions */ | struct osd osd; /* Object Specific extensions */ | ||||
/* | /* | ||||
* so_fibnum, so_user_cookie and friends can be used to attach | * so_fibnum, so_user_cookie and friends can be used to attach | ||||
* some user-specified metadata to a socket, which then can be | * some user-specified metadata to a socket, which then can be | ||||
* used by the kernel for various actions. | * used by the kernel for various actions. | ||||
* so_user_cookie is used by ipfw/dummynet. | * so_user_cookie is used by ipfw/dummynet. | ||||
*/ | */ | ||||
int so_fibnum; /* routing domain for this socket */ | int so_fibnum; /* routing domain for this socket */ | ||||
uint32_t so_user_cookie; | uint32_t so_user_cookie; | ||||
int so_ts_clock; /* type of the clock used for timestamps */ | int so_ts_clock; /* type of the clock used for timestamps */ | ||||
uint32_t so_max_pacing_rate; /* (f) TX rate limit in bytes/s */ | uint32_t so_max_pacing_rate; /* (f) TX rate limit in bytes/s */ | ||||
void *so_pspare[2]; /* general use */ | void *so_pspare[2]; /* general use */ | ||||
int so_ispare[2]; /* general use */ | int so_ispare[2]; /* general use */ | ||||
}; | }; | ||||
/* | /* | ||||
* Global accept mutex to serialize access to accept queues and | * Structure for listening socket. | ||||
* fields associated with multiple sockets. This allows us to | * Socket where accepts occur is so_listen in all subsidiary sockets. | ||||
* avoid defining a lock order between listen and accept sockets | * If so_listen is NULL, socket is not related to an accept. | ||||
* until such time as it proves to be a good idea. | * For head socket so_incomp queues partially completed connections, | ||||
* while so_comp is a queue of connections ready to be accepted. | |||||
* If a connection is aborted and it has so_listen set, then | |||||
* it has to be pulled out of either so_incomp or so_comp. | |||||
* We allow connections to queue up based on current queue lengths | |||||
* and limit on number of queued connections for this socket. | |||||
*/ | */ | ||||
extern struct mtx accept_mtx; | TAILQ_HEAD(accept_queue, socket); | ||||
#define ACCEPT_LOCK_ASSERT() mtx_assert(&accept_mtx, MA_OWNED) | struct solisten { | ||||
#define ACCEPT_UNLOCK_ASSERT() mtx_assert(&accept_mtx, MA_NOTOWNED) | /* | ||||
#define ACCEPT_LOCK() mtx_lock(&accept_mtx) | * Data inherited from 'struct socket' before listen(2) | ||||
#define ACCEPT_UNLOCK() mtx_unlock(&accept_mtx) | * mutation, to be copied to our children sockets. | ||||
*/ | |||||
short sol_type; | |||||
short sol_options; | |||||
short sol_linger; | |||||
short sol_state; | |||||
int sol_fibnum; | |||||
int sol_sbrcv_lowat; | |||||
int sol_sbsnd_lowat; | |||||
u_int sol_sbrcv_hiwat; | |||||
u_int sol_sbsnd_hiwat; | |||||
short sol_sbrcv_flags; | |||||
short sol_sbsnd_flags; | |||||
sbintime_t sol_sbrcv_timeo; | |||||
sbintime_t sol_sbsnd_timeo; | |||||
struct protosw *sol_proto; | |||||
struct vnet *sol_vnet; | |||||
struct ucred *sol_cred; | |||||
struct label *sol_label; | |||||
struct sigio *sol_sigio; | |||||
void *sol_pcb; | |||||
/* accept_filter(9) optional data */ | |||||
struct accept_filter *sol_accept_filter; | |||||
void *sol_accept_filter_arg; /* saved filter args */ | |||||
char *sol_accept_filter_str; /* saved user args */ | |||||
/* Actual queue management. */ | |||||
struct mtx sol_mutex; | |||||
struct selinfo sol_selinfo; | |||||
u_int sol_qlen; /* (e) number of unaccepted connections */ | |||||
u_int sol_incqlen; /* (e) number of unaccepted incomplete | |||||
connections */ | |||||
u_int sol_qlimit; /* (e) max number queued connections */ | |||||
u_int sol_error; | |||||
/* (e) queue of partial unaccepted connections */ | |||||
struct accept_queue sol_incomp; | |||||
/* (e) queue of complete unaccepted connections */ | |||||
struct accept_queue sol_comp; | |||||
}; | |||||
#define SOLISTEN_LOCK(sol) mtx_lock(&(sol)->sol_mutex) | |||||
#define SOLISTEN_UNLOCK(sol) mtx_unlock(&(sol)->sol_mutex) | |||||
/* | /* | ||||
* Per-socket mutex: we reuse the receive socket buffer mutex for space | * Per-socket mutex: we reuse the receive socket buffer mutex for space | ||||
* efficiency. This decision should probably be revisited as we optimize | * efficiency. This decision should probably be revisited as we optimize | ||||
* locking for the socket code. | * locking for the socket code. | ||||
*/ | */ | ||||
#define SOCK_MTX(_so) SOCKBUF_MTX(&(_so)->so_rcv) | #define SOCK_MTX(_so) SOCKBUF_MTX(&(_so)->so_rcv) | ||||
#define SOCK_LOCK(_so) SOCKBUF_LOCK(&(_so)->so_rcv) | #define SOCK_LOCK(_so) SOCKBUF_LOCK(&(_so)->so_rcv) | ||||
#define SOCK_OWNED(_so) SOCKBUF_OWNED(&(_so)->so_rcv) | #define SOCK_OWNED(_so) SOCKBUF_OWNED(&(_so)->so_rcv) | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | #define sb_notify(sb) (((sb)->sb_flags & (SB_WAIT | SB_SEL | SB_ASYNC | \ | ||||
SB_UPCALL | SB_AIO | SB_KNOTE)) != 0) | SB_UPCALL | SB_AIO | SB_KNOTE)) != 0) | ||||
/* do we have to send all at once on a socket? */ | /* do we have to send all at once on a socket? */ | ||||
#define sosendallatonce(so) \ | #define sosendallatonce(so) \ | ||||
((so)->so_proto->pr_flags & PR_ATOMIC) | ((so)->so_proto->pr_flags & PR_ATOMIC) | ||||
/* can we read something from so? */ | /* can we read something from so? */ | ||||
#define soreadabledata(so) \ | #define soreadabledata(so) \ | ||||
(sbavail(&(so)->so_rcv) >= (so)->so_rcv.sb_lowat || \ | (sbavail(&(so)->so_rcv) >= (so)->so_rcv.sb_lowat || (so)->so_error) | ||||
!TAILQ_EMPTY(&(so)->so_comp) || (so)->so_error) | |||||
#define soreadable(so) \ | #define soreadable(so) \ | ||||
(soreadabledata(so) || ((so)->so_rcv.sb_state & SBS_CANTRCVMORE)) | (soreadabledata(so) || ((so)->so_rcv.sb_state & SBS_CANTRCVMORE)) | ||||
/* can we write something to so? */ | /* can we write something to so? */ | ||||
#define sowriteable(so) \ | #define sowriteable(so) \ | ||||
((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && \ | ((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && \ | ||||
(((so)->so_state&SS_ISCONNECTED) || \ | (((so)->so_state&SS_ISCONNECTED) || \ | ||||
((so)->so_proto->pr_flags&PR_CONNREQUIRED)==0)) || \ | ((so)->so_proto->pr_flags&PR_CONNREQUIRED)==0)) || \ | ||||
((so)->so_snd.sb_state & SBS_CANTSENDMORE) || \ | ((so)->so_snd.sb_state & SBS_CANTSENDMORE) || \ | ||||
(so)->so_error) | (so)->so_error) | ||||
/* | /* | ||||
* soref()/sorele() ref-count the socket structure. Note that you must | * soref()/sorele() ref-count the socket structure. Note that you must | ||||
* still explicitly close the socket, but the last ref count will free | * still explicitly close the socket, but the last ref count will free | ||||
* the structure. | * the structure. | ||||
*/ | */ | ||||
#define soref(so) do { \ | #define soref(so) do { \ | ||||
SOCK_LOCK_ASSERT(so); \ | SOCK_LOCK_ASSERT(so); \ | ||||
++(so)->so_count; \ | ++(so)->so_count; \ | ||||
} while (0) | } while (0) | ||||
#define sorele(so) do { \ | #define sorele(so) do { \ | ||||
ACCEPT_LOCK_ASSERT(); \ | |||||
SOCK_LOCK_ASSERT(so); \ | SOCK_LOCK_ASSERT(so); \ | ||||
if ((so)->so_count <= 0) \ | if ((so)->so_count <= 0) \ | ||||
panic("sorele"); \ | panic("sorele"); \ | ||||
if (--(so)->so_count == 0) \ | if (--(so)->so_count == 0) \ | ||||
sofree(so); \ | sofree(so); \ | ||||
else { \ | else \ | ||||
SOCK_UNLOCK(so); \ | SOCK_UNLOCK(so); \ | ||||
ACCEPT_UNLOCK(); \ | |||||
} \ | |||||
} while (0) | } while (0) | ||||
/* | /* | ||||
* In sorwakeup() and sowwakeup(), acquire the socket buffer lock to | * In sorwakeup() and sowwakeup(), acquire the socket buffer lock to | ||||
* avoid a non-atomic test-and-wakeup. However, sowakeup is | * avoid a non-atomic test-and-wakeup. However, sowakeup is | ||||
* responsible for releasing the lock if it is called. We unlock only | * responsible for releasing the lock if it is called. We unlock only | ||||
* if we don't call into sowakeup. If any code is introduced that | * if we don't call into sowakeup. If any code is introduced that | ||||
* directly invokes the underlying sowakeup() primitives, it must | * directly invokes the underlying sowakeup() primitives, it must | ||||
Show All 23 Lines | |||||
#define sowwakeup(so) do { \ | #define sowwakeup(so) do { \ | ||||
SOCKBUF_LOCK(&(so)->so_snd); \ | SOCKBUF_LOCK(&(so)->so_snd); \ | ||||
sowwakeup_locked(so); \ | sowwakeup_locked(so); \ | ||||
} while (0) | } while (0) | ||||
struct accept_filter { | struct accept_filter { | ||||
char accf_name[16]; | char accf_name[16]; | ||||
int (*accf_callback) | int (*accf_callback) | ||||
(struct socket *so, void *arg, int waitflag); | (struct socket *, void *, int); | ||||
void * (*accf_create) | void * (*accf_create) | ||||
(struct socket *so, char *arg); | (struct solisten *, char *); | ||||
void (*accf_destroy) | void (*accf_destroy) | ||||
(struct socket *so); | (struct solisten *); | ||||
SLIST_ENTRY(accept_filter) accf_next; | SLIST_ENTRY(accept_filter) accf_next; | ||||
}; | }; | ||||
#ifdef MALLOC_DECLARE | #ifdef MALLOC_DECLARE | ||||
MALLOC_DECLARE(M_ACCF); | MALLOC_DECLARE(M_ACCF); | ||||
MALLOC_DECLARE(M_PCB); | MALLOC_DECLARE(M_PCB); | ||||
MALLOC_DECLARE(M_SOLISTEN); | |||||
MALLOC_DECLARE(M_SONAME); | MALLOC_DECLARE(M_SONAME); | ||||
#endif | #endif | ||||
/* | /* | ||||
* Socket specific helper hook point identifiers | * Socket specific helper hook point identifiers | ||||
* Do not leave holes in the sequence, hook registration is a loop. | * Do not leave holes in the sequence, hook registration is a loop. | ||||
*/ | */ | ||||
#define HHOOK_SOCKET_OPT 0 | #define HHOOK_SOCKET_OPT 0 | ||||
Show All 32 Lines | |||||
#define SU_OK 0 | #define SU_OK 0 | ||||
#define SU_ISCONNECTED 1 | #define SU_ISCONNECTED 1 | ||||
/* | /* | ||||
* From uipc_socket and friends | * From uipc_socket and friends | ||||
*/ | */ | ||||
int getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len); | int getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len); | ||||
int getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, | int getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, | ||||
struct file **fpp, u_int *fflagp, struct filecaps *havecaps); | struct file **fpp, u_int *fflagp, struct filecaps *havecaps, | ||||
short type); | |||||
void soabort(struct socket *so); | void soabort(struct socket *so); | ||||
int soaccept(struct socket *so, struct sockaddr **nam); | int soaccept(struct socket *so, struct sockaddr **nam); | ||||
void soaio_enqueue(struct task *task); | void soaio_enqueue(struct task *task); | ||||
void soaio_rcv(void *context, int pending); | void soaio_rcv(void *context, int pending); | ||||
void soaio_snd(void *context, int pending); | void soaio_snd(void *context, int pending); | ||||
int socheckuid(struct socket *so, uid_t uid); | int socheckuid(struct socket *so, uid_t uid); | ||||
int sobind(struct socket *so, struct sockaddr *nam, struct thread *td); | int sobind(struct socket *so, struct sockaddr *nam, struct thread *td); | ||||
int sobindat(int fd, struct socket *so, struct sockaddr *nam, | int sobindat(int fd, struct socket *so, struct sockaddr *nam, | ||||
struct thread *td); | struct thread *td); | ||||
int soclose(struct socket *so); | int soclose(struct socket *so); | ||||
int soconnect(struct socket *so, struct sockaddr *nam, struct thread *td); | int soconnect(struct socket *so, struct sockaddr *nam, struct thread *td); | ||||
int soconnectat(int fd, struct socket *so, struct sockaddr *nam, | int soconnectat(int fd, struct socket *so, struct sockaddr *nam, | ||||
struct thread *td); | struct thread *td); | ||||
int soconnect2(struct socket *so1, struct socket *so2); | int soconnect2(struct socket *so1, struct socket *so2); | ||||
int socreate(int dom, struct socket **aso, int type, int proto, | int socreate(int dom, struct socket **aso, int type, int proto, | ||||
struct ucred *cred, struct thread *td); | struct ucred *cred, struct thread *td); | ||||
int sodisconnect(struct socket *so); | int sodisconnect(struct socket *so); | ||||
struct sockaddr *sodupsockaddr(const struct sockaddr *sa, int mflags); | struct sockaddr *sodupsockaddr(const struct sockaddr *sa, int mflags); | ||||
void sofree(struct socket *so); | void sofree(struct socket *so); | ||||
void sohasoutofband(struct socket *so); | void sohasoutofband(struct socket *so); | ||||
int solisten(struct socket *so, int backlog, struct thread *td); | struct socket * sonewconn(struct solisten *, int); | ||||
void solisten_proto(struct socket *so, int backlog); | struct socket * sopeeloff(struct socket *); | ||||
int solisten_proto_check(struct socket *so); | |||||
struct socket * | |||||
sonewconn(struct socket *head, int connstatus); | |||||
int sopoll(struct socket *so, int events, struct ucred *active_cred, | int sopoll(struct socket *so, int events, struct ucred *active_cred, | ||||
struct thread *td); | struct thread *td); | ||||
int sopoll_generic(struct socket *so, int events, | int sopoll_generic(struct socket *so, int events, | ||||
struct ucred *active_cred, struct thread *td); | struct ucred *active_cred, struct thread *td); | ||||
int soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio, | int soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio, | ||||
struct mbuf **mp0, struct mbuf **controlp, int *flagsp); | struct mbuf **mp0, struct mbuf **controlp, int *flagsp); | ||||
int soreceive_stream(struct socket *so, struct sockaddr **paddr, | int soreceive_stream(struct socket *so, struct sockaddr **paddr, | ||||
struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, | struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, | ||||
Show All 19 Lines | |||||
void sotoxsocket(struct socket *so, struct xsocket *xso); | void sotoxsocket(struct socket *so, struct xsocket *xso); | ||||
void soupcall_clear(struct socket *so, int which); | void soupcall_clear(struct socket *so, int which); | ||||
void soupcall_set(struct socket *so, int which, | void soupcall_set(struct socket *so, int which, | ||||
int (*func)(struct socket *, void *, int), void *arg); | int (*func)(struct socket *, void *, int), void *arg); | ||||
void sowakeup(struct socket *so, struct sockbuf *sb); | void sowakeup(struct socket *so, struct sockbuf *sb); | ||||
void sowakeup_aio(struct socket *so, struct sockbuf *sb); | void sowakeup_aio(struct socket *so, struct sockbuf *sb); | ||||
int selsocket(struct socket *so, int events, struct timeval *tv, | int selsocket(struct socket *so, int events, struct timeval *tv, | ||||
struct thread *td); | struct thread *td); | ||||
/* | |||||
* Listening sockets. | |||||
*/ | |||||
int solisten(struct socket *so, int backlog, struct thread *td, | |||||
struct file *fp); | |||||
int sollisten(struct solisten *so, int backlog, struct thread *td, | |||||
struct file *fp); | |||||
int solistenpoll(struct solisten *, int, struct ucred *a, struct thread *); | |||||
int solistenclose(struct solisten *); | |||||
void soltoxsocket(struct solisten *so, struct xsocket *xso); | |||||
/* | /* | ||||
* Accept filter functions (duh). | * Accept filter functions (duh). | ||||
*/ | */ | ||||
int accept_filt_add(struct accept_filter *filt); | int accept_filt_add(struct accept_filter *filt); | ||||
int accept_filt_del(char *name); | int accept_filt_del(char *name); | ||||
struct accept_filter *accept_filt_get(char *name); | struct accept_filter *accept_filt_get(char *name); | ||||
#ifdef ACCEPT_FILTER_MOD | #ifdef ACCEPT_FILTER_MOD | ||||
Show All 9 Lines |