Changeset View
Changeset View
Standalone View
Standalone View
head/sys/sys/socketvar.h
Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
typedef int so_upcall_t(struct socket *, void *, int); | typedef int so_upcall_t(struct socket *, void *, int); | ||||
struct socket; | struct socket; | ||||
/*- | /*- | ||||
* 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). | * (cr) locked by SOCKBUF_LOCK(&so->so_rcv). | ||||
* (e) locked by ACCEPT_LOCK(). | * (cs) locked by SOCKBUF_LOCK(&so->so_rcv). | ||||
* (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. | ||||
*/ | */ | ||||
TAILQ_HEAD(accept_queue, socket); | |||||
struct socket { | struct socket { | ||||
int so_count; /* (b) reference count */ | struct mtx so_lock; | ||||
volatile u_int so_count; /* (b / refcount) */ | |||||
struct selinfo so_rdsel; /* (b/cr) for so_rcv/so_comp */ | |||||
struct selinfo so_wrsel; /* (b/cs) for so_snd */ | |||||
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; /* (b) from socket call, see socket.h */ | ||||
short so_linger; /* time to linger while closing */ | short so_linger; /* time to linger close(2) */ | ||||
short so_state; /* (b) internal state flags SS_* */ | short so_state; /* (b) internal state flags SS_* */ | ||||
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 */ | ||||
/* | |||||
* 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 */ | |||||
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 */ | |||||
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 */ | |||||
/* 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 */ | ||||
union { | |||||
/* Regular (data flow) socket. */ | |||||
struct { | |||||
/* (cr, cs) Receive and send buffers. */ | |||||
struct sockbuf so_rcv, so_snd; | |||||
void *so_pspare[2]; /* general use */ | /* (e) Our place on accept queue. */ | ||||
int so_ispare[2]; /* general use */ | TAILQ_ENTRY(socket) so_list; | ||||
}; | struct socket *so_listen; /* (b) */ | ||||
enum { | |||||
SQ_NONE = 0, | |||||
SQ_INCOMP = 0x0800, /* on sol_incomp */ | |||||
SQ_COMP = 0x1000, /* on sol_comp */ | |||||
} so_qstate; /* (b) */ | |||||
/* (b) cached MAC label for peer */ | |||||
struct label *so_peerlabel; | |||||
u_long so_oobmark; /* chars to oob mark */ | |||||
}; | |||||
/* | /* | ||||
* Global accept mutex to serialize access to accept queues and | * Listening socket, where accepts occur, is so_listen in all | ||||
* fields associated with multiple sockets. This allows us to | * subsidiary sockets. If so_listen is NULL, socket is not | ||||
* avoid defining a lock order between listen and accept sockets | * related to an accept. For a listening socket itself | ||||
* until such time as it proves to be a good idea. | * sol_incomp queues partially completed connections, while | ||||
* sol_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 sol_incomp or sol_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; | struct { | ||||
#define ACCEPT_LOCK_ASSERT() mtx_assert(&accept_mtx, MA_OWNED) | /* (e) queue of partial unaccepted connections */ | ||||
#define ACCEPT_UNLOCK_ASSERT() mtx_assert(&accept_mtx, MA_NOTOWNED) | struct accept_queue sol_incomp; | ||||
#define ACCEPT_LOCK() mtx_lock(&accept_mtx) | /* (e) queue of complete unaccepted connections */ | ||||
#define ACCEPT_UNLOCK() mtx_unlock(&accept_mtx) | struct accept_queue sol_comp; | ||||
u_int sol_qlen; /* (e) sol_comp length */ | |||||
u_int sol_incqlen; /* (e) sol_incomp length */ | |||||
u_int sol_qlimit; /* (e) queue limit */ | |||||
/* | /* accept_filter(9) optional data */ | ||||
* Per-socket mutex: we reuse the receive socket buffer mutex for space | struct accept_filter *sol_accept_filter; | ||||
* efficiency. This decision should probably be revisited as we optimize | void *sol_accept_filter_arg; /* saved filter args */ | ||||
* locking for the socket code. | char *sol_accept_filter_str; /* saved user args */ | ||||
*/ | |||||
#define SOCK_MTX(_so) SOCKBUF_MTX(&(_so)->so_rcv) | |||||
#define SOCK_LOCK(_so) SOCKBUF_LOCK(&(_so)->so_rcv) | |||||
#define SOCK_OWNED(_so) SOCKBUF_OWNED(&(_so)->so_rcv) | |||||
#define SOCK_UNLOCK(_so) SOCKBUF_UNLOCK(&(_so)->so_rcv) | |||||
#define SOCK_LOCK_ASSERT(_so) SOCKBUF_LOCK_ASSERT(&(_so)->so_rcv) | |||||
/* | /* Optional upcall, for kernel socket. */ | ||||
* Socket state bits stored in so_qstate. | so_upcall_t *sol_upcall; /* (e) */ | ||||
*/ | void *sol_upcallarg; /* (e) */ | ||||
#define SQ_INCOMP 0x0800 /* unaccepted, incomplete connection */ | |||||
#define SQ_COMP 0x1000 /* unaccepted, complete connection */ | |||||
/* Socket buffer parameters, to be copied to | |||||
* dataflow sockets, accepted from this one. */ | |||||
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; | |||||
}; | |||||
}; | |||||
}; | |||||
#define SOCK_MTX(so) &(so)->so_lock | |||||
#define SOCK_LOCK(so) mtx_lock(&(so)->so_lock) | |||||
#define SOCK_OWNED(so) mtx_owned(&(so)->so_lock) | |||||
#define SOCK_UNLOCK(so) mtx_unlock(&(so)->so_lock) | |||||
#define SOCK_LOCK_ASSERT(so) mtx_assert(&(so)->so_lock, MA_OWNED) | |||||
#define SOCK_UNLOCK_ASSERT(so) mtx_assert(&(so)->so_lock, MA_NOTOWNED) | |||||
#define SOLISTENING(sol) (((sol)->so_options & SO_ACCEPTCONN) != 0) | |||||
#define SOLISTEN_LOCK(sol) do { \ | |||||
mtx_lock(&(sol)->so_lock); \ | |||||
KASSERT(SOLISTENING(sol), \ | |||||
("%s: %p not listening", __func__, (sol))); \ | |||||
} while (0) | |||||
#define SOLISTEN_TRYLOCK(sol) mtx_trylock(&(sol)->so_lock) | |||||
#define SOLISTEN_UNLOCK(sol) do { \ | |||||
KASSERT(SOLISTENING(sol), \ | |||||
("%s: %p not listening", __func__, (sol))); \ | |||||
mtx_unlock(&(sol)->so_lock); \ | |||||
} while (0) | |||||
#define SOLISTEN_LOCK_ASSERT(sol) do { \ | |||||
mtx_assert(&(sol)->so_lock, MA_OWNED); \ | |||||
KASSERT(SOLISTENING(sol), \ | |||||
("%s: %p not listening", __func__, (sol))); \ | |||||
} while (0) | |||||
/* | /* | ||||
* Externalized form of struct socket used by the sysctl(3) interface. | * Externalized form of struct socket used by the sysctl(3) interface. | ||||
*/ | */ | ||||
struct xsocket { | struct xsocket { | ||||
size_t xso_len; /* length of this structure */ | size_t xso_len; /* length of this structure */ | ||||
struct socket *xso_so; /* makes a convenient handle sometimes */ | struct socket *xso_so; /* makes a convenient handle sometimes */ | ||||
short so_type; | short so_type; | ||||
short so_options; | short so_options; | ||||
Show All 33 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. | ||||
* still explicitly close the socket, but the last ref count will free | * soref() may be called without owning socket lock, but in that case a | ||||
* the structure. | * caller must own something that holds socket, and so_count must be not 0. | ||||
* Note that you must still explicitly close the socket, but the last ref | |||||
* count will free the structure. | |||||
*/ | */ | ||||
#define soref(so) do { \ | #define soref(so) refcount_acquire(&(so)->so_count) | ||||
SOCK_LOCK_ASSERT(so); \ | |||||
++(so)->so_count; \ | |||||
} 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 (refcount_release(&(so)->so_count)) \ | ||||
panic("sorele"); \ | |||||
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 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | 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); | int solisten(struct socket *so, int backlog, struct thread *td); | ||||
void solisten_proto(struct socket *so, int backlog); | void solisten_proto(struct socket *so, int backlog); | ||||
int solisten_proto_check(struct socket *so); | int solisten_proto_check(struct socket *so); | ||||
int solisten_dequeue(struct socket *, struct socket **, int); | |||||
struct socket * | struct socket * | ||||
sonewconn(struct socket *head, int connstatus); | sonewconn(struct socket *head, int connstatus); | ||||
struct socket * | |||||
sopeeloff(struct socket *); | |||||
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 14 Lines | int sosend_dgram(struct socket *so, struct sockaddr *addr, | ||||
int flags, struct thread *td); | int flags, struct thread *td); | ||||
int sosend_generic(struct socket *so, struct sockaddr *addr, | int sosend_generic(struct socket *so, struct sockaddr *addr, | ||||
struct uio *uio, struct mbuf *top, struct mbuf *control, | struct uio *uio, struct mbuf *top, struct mbuf *control, | ||||
int flags, struct thread *td); | int flags, struct thread *td); | ||||
int soshutdown(struct socket *so, int how); | int soshutdown(struct socket *so, int how); | ||||
void sotoxsocket(struct socket *so, struct xsocket *xso); | void sotoxsocket(struct socket *so, struct xsocket *xso); | ||||
void soupcall_clear(struct socket *, int); | void soupcall_clear(struct socket *, int); | ||||
void soupcall_set(struct socket *, int, so_upcall_t, void *); | void soupcall_set(struct socket *, int, so_upcall_t, void *); | ||||
void solisten_upcall_set(struct socket *, so_upcall_t, void *); | |||||
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); | ||||
void solisten_wakeup(struct socket *); | |||||
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); | ||||
/* | /* | ||||
* 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); | ||||
Show All 11 Lines |