diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c index c348df1ea2f7..b6a7e839ff2c 100644 --- a/lib/libprocstat/libprocstat.c +++ b/lib/libprocstat/libprocstat.c @@ -48,10 +48,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#define _WANT_SOCKET #include #include #include #include +#define _WANT_UNPCB #include #include #include diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 26bbb2f09623..f594dbba4ef8 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1646,12 +1646,20 @@ unp_pcblist(SYSCTL_HANDLER_ARGS) if (unp->unp_addr != NULL) bcopy(unp->unp_addr, &xu->xu_addr, unp->unp_addr->sun_len); + else + bzero(&xu->xu_addr, sizeof(xu->xu_addr)); if (unp->unp_conn != NULL && unp->unp_conn->unp_addr != NULL) bcopy(unp->unp_conn->unp_addr, &xu->xu_caddr, unp->unp_conn->unp_addr->sun_len); - bcopy(unp, &xu->xu_unp, sizeof *unp); + else + bzero(&xu->xu_caddr, sizeof(xu->xu_caddr)); + xu->unp_vnode = unp->unp_vnode; + xu->unp_conn = unp->unp_conn; + xu->xu_firstref = LIST_FIRST(&unp->unp_refs); + xu->xu_nextref = LIST_NEXT(unp, unp_reflink); + xu->unp_gencnt = unp->unp_gencnt; sotoxsocket(unp->unp_socket, &xu->xu_socket); UNP_PCB_UNLOCK(unp); error = SYSCTL_OUT(req, xu, sizeof *xu); diff --git a/sys/netinet6/send.c b/sys/netinet6/send.c index 66b36db7827b..df07c0f18b33 100644 --- a/sys/netinet6/send.c +++ b/sys/netinet6/send.c @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/sys/param.h b/sys/sys/param.h index 49d10f569acf..16a40ff2e04d 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1200047 /* Master, propagated to newvers */ +#define __FreeBSD_version 1200048 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h index a4ed33274d79..c864937f0002 100644 --- a/sys/sys/sockbuf.h +++ b/sys/sys/sockbuf.h @@ -65,18 +65,6 @@ struct socket; struct thread; struct selinfo; -struct xsockbuf { - u_int sb_cc; - u_int sb_hiwat; - u_int sb_mbcnt; - u_int sb_mcnt; - u_int sb_ccnt; - u_int sb_mbmax; - int sb_lowat; - int sb_timeo; - short sb_flags; -}; - /* * Variables for socket buffering. * @@ -174,7 +162,6 @@ struct mbuf * sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff); struct mbuf * sbsndmbuf(struct sockbuf *sb, u_int off, u_int *moff); -void sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb); int sbwait(struct sockbuf *sb); int sblock(struct sockbuf *sb, int flags); void sbunlock(struct sockbuf *sb); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 1780bb197fce..9c5709fb4230 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -34,6 +34,12 @@ #ifndef _SYS_SOCKETVAR_H_ #define _SYS_SOCKETVAR_H_ +/* + * Socket generation count type. Also used in xinpcb, xtcpcb, xunpcb. + */ +typedef uint64_t so_gen_t; + +#if defined(_KERNEL) || defined(_WANT_SOCKET) #include /* for TAILQ macros */ #include /* for struct selinfo */ #include @@ -41,7 +47,6 @@ #include #include #include -#include #ifdef _KERNEL #include #include @@ -55,7 +60,6 @@ struct vnet; * handle on protocol and pointer to protocol * private data and error information. */ -typedef uint64_t so_gen_t; typedef int so_upcall_t(struct socket *, void *, int); struct socket; @@ -167,6 +171,39 @@ struct socket { }; }; }; +#endif /* defined(_KERNEL) || defined(_WANT_SOCKET) */ + +/* + * Socket state bits. + * + * Historically, this bits were all kept in the so_state field. For + * locking reasons, they are now in multiple fields, as they are + * locked differently. so_state maintains basic socket state protected + * by the socket lock. so_qstate holds information about the socket + * accept queues. Each socket buffer also has a state field holding + * information relevant to that socket buffer (can't send, rcv). Many + * fields will be read without locks to improve performance and avoid + * lock order issues. However, this approach must be used with caution. + */ +#define SS_NOFDREF 0x0001 /* no file table ref any more */ +#define SS_ISCONNECTED 0x0002 /* socket connected to a peer */ +#define SS_ISCONNECTING 0x0004 /* in process of connecting to peer */ +#define SS_ISDISCONNECTING 0x0008 /* in process of disconnecting */ +#define SS_NBIO 0x0100 /* non-blocking ops */ +#define SS_ASYNC 0x0200 /* async i/o notify */ +#define SS_ISCONFIRMING 0x0400 /* deciding to accept connection req */ +#define SS_ISDISCONNECTED 0x2000 /* socket disconnected from peer */ + +/* + * Protocols can mark a socket as SS_PROTOREF to indicate that, following + * pru_detach, they still want the socket to persist, and will free it + * themselves when they are done. Protocols should only ever call sofree() + * following setting this flag in pru_detach(), and never otherwise, as + * sofree() bypasses socket reference counting. + */ +#define SS_PROTOREF 0x4000 /* strong protocol reference */ + +#ifdef _KERNEL #define SOCK_MTX(so) &(so)->so_lock #define SOCK_LOCK(so) mtx_lock(&(so)->so_lock) @@ -193,32 +230,6 @@ struct socket { ("%s: %p not listening", __func__, (sol))); \ } while (0) -/* - * Externalized form of struct socket used by the sysctl(3) interface. - */ -struct xsocket { - size_t xso_len; /* length of this structure */ - struct socket *xso_so; /* makes a convenient handle sometimes */ - short so_type; - short so_options; - short so_linger; - short so_state; - caddr_t so_pcb; /* another convenient handle */ - int xso_protocol; - int xso_family; - u_int so_qlen; - u_int so_incqlen; - u_int so_qlimit; - short so_timeo; - u_short so_error; - pid_t so_pgid; - u_long so_oobmark; - struct xsockbuf so_rcv, so_snd; - uid_t so_uid; /* XXX */ -}; - -#ifdef _KERNEL - /* * Macros for sockets and socket buffering. */ @@ -422,7 +433,6 @@ int sosend_generic(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags, struct thread *td); int soshutdown(struct socket *so, int how); -void sotoxsocket(struct socket *so, struct xsocket *xso); void soupcall_clear(struct socket *, int); void soupcall_set(struct socket *, int, so_upcall_t, void *); void solisten_upcall_set(struct socket *, so_upcall_t, void *); @@ -431,6 +441,14 @@ void sowakeup_aio(struct socket *so, struct sockbuf *sb); void solisten_wakeup(struct socket *); int selsocket(struct socket *so, int events, struct timeval *tv, struct thread *td); +void soisconnected(struct socket *so); +void soisconnecting(struct socket *so); +void soisdisconnected(struct socket *so); +void soisdisconnecting(struct socket *so); +void socantrcvmore(struct socket *so); +void socantrcvmore_locked(struct socket *so); +void socantsendmore(struct socket *so); +void socantsendmore_locked(struct socket *so); /* * Accept filter functions (duh). @@ -447,4 +465,58 @@ int accept_filt_generic_mod_event(module_t mod, int event, void *data); #endif /* _KERNEL */ +/* + * Structure to export socket from kernel to utilities, via sysctl(3). + */ +struct xsocket { + size_t xso_len; /* length of this structure */ + union { + void *xso_so; /* kernel address of struct socket */ + int64_t ph_so; + }; + union { + void *so_pcb; /* kernel address of struct inpcb */ + int64_t ph_pcb; + }; + uint64_t so_oobmark; + int64_t so_spare64[8]; + int32_t xso_protocol; + int32_t xso_family; + uint32_t so_qlen; + uint32_t so_incqlen; + uint32_t so_qlimit; + pid_t so_pgid; + uid_t so_uid; + int32_t so_spare32[8]; + int16_t so_type; + int16_t so_options; + int16_t so_linger; + int16_t so_state; + int16_t so_timeo; + uint16_t so_error; + struct xsockbuf { + uint32_t sb_cc; + uint32_t sb_hiwat; + uint32_t sb_mbcnt; + uint32_t sb_mcnt; + uint32_t sb_ccnt; + uint32_t sb_mbmax; + int32_t sb_lowat; + int32_t sb_timeo; + int16_t sb_flags; + } so_rcv, so_snd; +}; + +#ifdef _KERNEL +void sotoxsocket(struct socket *so, struct xsocket *xso); +void sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb); +#endif + +/* + * Socket buffer state bits. Exported via libprocstat(3). + */ +#define SBS_CANTSENDMORE 0x0010 /* can't send more data to peer */ +#define SBS_CANTRCVMORE 0x0020 /* can't receive more data from peer */ +#define SBS_RCVATMARK 0x0040 /* at mark on input */ + #endif /* !_SYS_SOCKETVAR_H_ */ diff --git a/sys/sys/sockstate.h b/sys/sys/sockstate.h deleted file mode 100644 index 9648f5a32052..000000000000 --- a/sys/sys/sockstate.h +++ /dev/null @@ -1,83 +0,0 @@ -/*- - * Copyright (c) 1982, 1986, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)socketvar.h 8.3 (Berkeley) 2/19/95 - * - * $FreeBSD$ - */ -#ifndef _SYS_SOCKTATE_H_ -#define _SYS_SOCKTATE_H_ - -/* - * Socket state bits. - * - * Historically, this bits were all kept in the so_state field. For - * locking reasons, they are now in multiple fields, as they are - * locked differently. so_state maintains basic socket state protected - * by the socket lock. so_qstate holds information about the socket - * accept queues. Each socket buffer also has a state field holding - * information relevant to that socket buffer (can't send, rcv). Many - * fields will be read without locks to improve performance and avoid - * lock order issues. However, this approach must be used with caution. - */ -#define SS_NOFDREF 0x0001 /* no file table ref any more */ -#define SS_ISCONNECTED 0x0002 /* socket connected to a peer */ -#define SS_ISCONNECTING 0x0004 /* in process of connecting to peer */ -#define SS_ISDISCONNECTING 0x0008 /* in process of disconnecting */ -#define SS_NBIO 0x0100 /* non-blocking ops */ -#define SS_ASYNC 0x0200 /* async i/o notify */ -#define SS_ISCONFIRMING 0x0400 /* deciding to accept connection req */ -#define SS_ISDISCONNECTED 0x2000 /* socket disconnected from peer */ - -/* - * Protocols can mark a socket as SS_PROTOREF to indicate that, following - * pru_detach, they still want the socket to persist, and will free it - * themselves when they are done. Protocols should only ever call sofree() - * following setting this flag in pru_detach(), and never otherwise, as - * sofree() bypasses socket reference counting. - */ -#define SS_PROTOREF 0x4000 /* strong protocol reference */ - -/* - * Socket state bits now stored in the socket buffer state field. - */ -#define SBS_CANTSENDMORE 0x0010 /* can't send more data to peer */ -#define SBS_CANTRCVMORE 0x0020 /* can't receive more data from peer */ -#define SBS_RCVATMARK 0x0040 /* at mark on input */ - -struct socket; - -void soisconnected(struct socket *so); -void soisconnecting(struct socket *so); -void soisdisconnected(struct socket *so); -void soisdisconnecting(struct socket *so); -void socantrcvmore(struct socket *so); -void socantrcvmore_locked(struct socket *so); -void socantsendmore(struct socket *so); -void socantsendmore_locked(struct socket *so); -#endif /* _SYS_SOCKTATE_H_ */ diff --git a/sys/sys/unpcb.h b/sys/sys/unpcb.h index f18786553de4..34a4d7392488 100644 --- a/sys/sys/unpcb.h +++ b/sys/sys/unpcb.h @@ -33,6 +33,9 @@ #ifndef _SYS_UNPCB_H_ #define _SYS_UNPCB_H_ +typedef uint64_t unp_gen_t; + +#if defined(_KERNEL) || defined(_WANT_UNPCB) #include #include @@ -61,7 +64,6 @@ * so that changes in the sockbuf may be computed to modify * back pressure on the sender accordingly. */ -typedef u_quad_t unp_gen_t; LIST_HEAD(unp_head, unpcb); struct unpcb { @@ -74,8 +76,6 @@ struct unpcb { struct unp_head unp_refs; /* referencing socket linked list */ LIST_ENTRY(unpcb) unp_reflink; /* link in unp_refs list */ struct sockaddr_un *unp_addr; /* bound address of socket */ - int reserved1; - int reserved2; unp_gen_t unp_gencnt; /* generation count of this instance */ short unp_flags; /* flags */ short unp_gcflag; /* Garbage collector flags. */ @@ -116,32 +116,50 @@ struct unpcb { #define sotounpcb(so) ((struct unpcb *)((so)->so_pcb)) -/* Hack alert -- this structure depends on . */ +#endif /* _KERNEL || _WANT_UNPCB */ + +/* + * UNPCB structure exported to user-land via sysctl(3). + * + * Fields prefixed with "xu_" are unique to the export structure, and fields + * with "unp_" or other prefixes match corresponding fields of 'struct unpcb'. + * + * Legend: + * (s) - used by userland utilities in src + * (p) - used by utilities in ports + * (3) - is known to be used by third party software not in ports + * (n) - no known usage + * + * Evil hack: declare only if sys/socketvar.h have been included. + */ #ifdef _SYS_SOCKETVAR_H_ struct xunpcb { - size_t xu_len; /* length of this structure */ - struct unpcb *xu_unpp; /* to help netstat, fstat */ - struct unpcb xu_unp; /* our information */ + size_t xu_len; /* length of this structure */ + void *xu_unpp; /* to help netstat, fstat */ + void *unp_vnode; /* (s) */ + void *unp_conn; /* (s) */ + void *xu_firstref; /* (s) */ + void *xu_nextref; /* (s) */ + unp_gen_t unp_gencnt; /* (s) */ + int64_t xu_spare64[8]; + int32_t xu_spare32[8]; union { - struct sockaddr_un xuu_addr; /* our bound address */ + struct sockaddr_un xu_addr; /* our bound address */ char xu_dummy1[256]; - } xu_au; -#define xu_addr xu_au.xuu_addr + }; union { - struct sockaddr_un xuu_caddr; /* their bound address */ + struct sockaddr_un xu_caddr; /* their bound address */ char xu_dummy2[256]; - } xu_cau; -#define xu_caddr xu_cau.xuu_caddr - struct xsocket xu_socket; - u_quad_t xu_alignment_hack; -}; + }; + struct xsocket xu_socket; +} __aligned(8); struct xunpgen { size_t xug_len; u_int xug_count; unp_gen_t xug_gen; so_gen_t xug_sogen; -}; +} __aligned(8);; #endif /* _SYS_SOCKETVAR_H_ */ #endif /* _SYS_UNPCB_H_ */ diff --git a/usr.bin/bluetooth/btsockstat/btsockstat.c b/usr.bin/bluetooth/btsockstat/btsockstat.c index 78f61279d47c..67d95f295b04 100644 --- a/usr.bin/bluetooth/btsockstat/btsockstat.c +++ b/usr.bin/bluetooth/btsockstat/btsockstat.c @@ -35,6 +35,7 @@ #include #include #include +#define _WANT_SOCKET #include #include diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index d0c56006b0e3..03c779dcad70 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#define _WANT_SOCKET #include #include @@ -172,7 +173,7 @@ sotoxsocket(struct socket *so, struct xsocket *xso) xso->xso_family = domain.dom_family; xso->so_timeo = so->so_timeo; xso->so_error = so->so_error; - if (SOLISTENING(so)) { + if ((so->so_options & SO_ACCEPTCONN) != 0) { xso->so_qlen = so->sol_qlen; xso->so_incqlen = so->sol_incqlen; xso->so_qlimit = so->sol_qlimit; diff --git a/usr.bin/netstat/netgraph.c b/usr.bin/netstat/netgraph.c index dc3ad829ef62..68ebcf7eff0a 100644 --- a/usr.bin/netstat/netgraph.c +++ b/usr.bin/netstat/netgraph.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#define _WANT_SOCKET #include #include #include diff --git a/usr.bin/netstat/unix.c b/usr.bin/netstat/unix.c index 3b83f2ca006a..34e6b3977b1f 100644 --- a/usr.bin/netstat/unix.c +++ b/usr.bin/netstat/unix.c @@ -43,10 +43,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#define _WANT_SOCKET #include #include #include #include +#define _WANT_UNPCB #include #include @@ -100,7 +102,7 @@ static int pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp) { struct unp_head head; - struct unpcb *unp, unp_conn; + struct unpcb *unp, unp0, unp_conn; u_char sun_len; struct socket so; struct xunpgen xug; @@ -150,8 +152,8 @@ pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp) KREAD(head_off, &head, sizeof(head)); LIST_FOREACH(unp, &head, unp_link) { xu.xu_unpp = unp; - KREAD(unp, &xu.xu_unp, sizeof (*unp)); - unp = &xu.xu_unp; + KREAD(unp, &unp0, sizeof (*unp)); + unp = &unp0; if (unp->unp_gencnt > unp_gencnt) continue; @@ -236,7 +238,7 @@ unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off, so = &xunp->xu_socket; /* Ignore PCBs which were freed during copyout. */ - if (xunp->xu_unp.unp_gencnt > oxug->xug_gen) + if (xunp->unp_gencnt > oxug->xug_gen) continue; if (*first) { xo_open_list("socket"); @@ -268,7 +270,6 @@ unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off, static void unixdomainpr(struct xunpcb *xunp, struct xsocket *so) { - struct unpcb *unp; struct sockaddr_un *sa; static int first = 1; char buf1[33]; @@ -292,11 +293,7 @@ unixdomainpr(struct xunpcb *xunp, struct xsocket *so) }; int fmt = (sizeof(void *) == 8) ? 1 : 0; - unp = &xunp->xu_unp; - if (unp->unp_addr) - sa = &xunp->xu_addr; - else - sa = (struct sockaddr_un *)0; + sa = (xunp->xu_addr.sun_family == AF_UNIX) ? &xunp->xu_addr : NULL; if (first && !Lflag) { xo_emit("{T:Active UNIX domain sockets}\n"); @@ -318,10 +315,9 @@ unixdomainpr(struct xunpcb *xunp, struct xsocket *so) } else { xo_emit(format[fmt], (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc, - so->so_snd.sb_cc, (long)unp->unp_vnode, - (long)unp->unp_conn, - (long)LIST_FIRST(&unp->unp_refs), - (long)LIST_NEXT(unp, unp_reflink)); + so->so_snd.sb_cc, (long)xunp->unp_vnode, + (long)xunp->unp_conn, (long)xunp->xu_firstref, + (long)xunp->xu_nextref); } if (sa) xo_emit(" {:path/%.*s}", diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c index ea439dc8d1f1..02b43b81374c 100644 --- a/usr.bin/sockstat/sockstat.c +++ b/usr.bin/sockstat/sockstat.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#define _WANT_UNPCB #include #include @@ -784,8 +785,8 @@ gather_unix(int proto) warnx("struct xunpcb size mismatch"); goto out; } - if ((xup->xu_unp.unp_conn == NULL && !opt_l) || - (xup->xu_unp.unp_conn != NULL && !opt_c)) + if ((xup->unp_conn == NULL && !opt_l) || + (xup->unp_conn != NULL && !opt_c)) continue; if ((sock = calloc(1, sizeof(*sock))) == NULL) err(1, "malloc()"); @@ -798,11 +799,11 @@ gather_unix(int proto) sock->proto = proto; sock->family = AF_UNIX; sock->protoname = protoname; - if (xup->xu_unp.unp_addr != NULL) + if (xup->xu_addr.sun_family == AF_UNIX) laddr->address = *(struct sockaddr_storage *)(void *)&xup->xu_addr; - else if (xup->xu_unp.unp_conn != NULL) - *(void **)&(faddr->address) = xup->xu_unp.unp_conn; + else if (xup->unp_conn != NULL) + *(void **)&(faddr->address) = xup->unp_conn; laddr->next = NULL; faddr->next = NULL; sock->laddr = laddr; diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c index 5ab367a0a878..704df8a9dbf1 100644 --- a/usr.bin/systat/netstat.c +++ b/usr.bin/systat/netstat.c @@ -41,6 +41,7 @@ static const char sccsid[] = "@(#)netstat.c 8.1 (Berkeley) 6/6/93"; #include #include #include +#define _WANT_SOCKET #include #include