Index: lib/libprocstat/libprocstat.c =================================================================== --- lib/libprocstat/libprocstat.c +++ lib/libprocstat/libprocstat.c @@ -52,6 +52,7 @@ #include #include #include +#define _WANT_UNPCB #include #include #include Index: sys/kern/uipc_usrreq.c =================================================================== --- sys/kern/uipc_usrreq.c +++ sys/kern/uipc_usrreq.c @@ -1549,7 +1549,7 @@ unp_gen_t gencnt; struct xunpgen *xug; struct unp_head *head; - struct xunpcb *xu; + struct xunpcb xu; switch ((intptr_t)arg1) { case SOCK_STREAM: @@ -1622,30 +1622,38 @@ n = i; /* In case we lost some during malloc. */ error = 0; - xu = malloc(sizeof(*xu), M_TEMP, M_WAITOK | M_ZERO); for (i = 0; i < n; i++) { unp = unp_list[i]; UNP_PCB_LOCK(unp); unp->unp_refcount--; if (unp->unp_refcount != 0 && unp->unp_gencnt <= gencnt) { - xu->xu_len = sizeof *xu; - xu->xu_unpp = unp; + xu.xu_len = sizeof(xu); + xu.xu_unpp = unp; /* * XXX - need more locking here to protect against * connect/disconnect races for SMP. */ + xu.xu_gencnt = unp->unp_gencnt; + xu.xu_unpp = unp; + xu.xu_vnode = unp->unp_vnode; + xu.xu_conn = unp->unp_conn; + xu.xu_first_ref = LIST_FIRST(&unp->unp_refs); + xu.xu_next_ref = LIST_NEXT(unp, unp_reflink); if (unp->unp_addr != NULL) - bcopy(unp->unp_addr, &xu->xu_addr, + 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, + &xu.xu_caddr, unp->unp_conn->unp_addr->sun_len); - bcopy(unp, &xu->xu_unp, sizeof *unp); - sotoxsocket(unp->unp_socket, &xu->xu_socket); + else + bzero(&xu.xu_caddr, sizeof(xu.xu_caddr)); + sotoxsocket(unp->unp_socket, &xu.xu_socket); UNP_PCB_UNLOCK(unp); - error = SYSCTL_OUT(req, xu, sizeof *xu); + error = SYSCTL_OUT(req, &xu, sizeof(xu)); } else { freeunp = (unp->unp_refcount == 0); UNP_PCB_UNLOCK(unp); @@ -1655,7 +1663,6 @@ } } } - free(xu, M_TEMP); if (!error) { /* * Give the user an updated idea of our state. If the Index: sys/sys/unpcb.h =================================================================== --- sys/sys/unpcb.h +++ sys/sys/unpcb.h @@ -33,9 +33,9 @@ #ifndef _SYS_UNPCB_H_ #define _SYS_UNPCB_H_ -#include -#include +typedef uint64_t unp_gen_t; +#if defined(_KERNEL) || defined(_WANT_UNPCB) /* * Protocol control block for an active * instance of a UNIX internal protocol. @@ -61,7 +61,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 +73,6 @@ 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. */ @@ -115,33 +112,52 @@ #define UNPGC_IGNORE_RIGHTS 0x8 /* Attached rights are freed */ #define sotounpcb(so) ((struct unpcb *)((so)->so_pcb)) +#endif /* _KERNEL */ -/* Hack alert -- this structure depends on . */ -#ifdef _SYS_SOCKETVAR_H_ +/* + * Interface exported to userland. Hack alert -- only define if + * struct xsocket is in scope. + * + * 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 + */ +#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 */ + struct xsocket xu_socket; + unp_gen_t xu_gencnt; /* (s) */ union { - struct sockaddr_un xuu_addr; /* our bound address */ - char xu_dummy1[256]; - } xu_au; -#define xu_addr xu_au.xuu_addr + void *xu_unpp; /* (s) */ + int64_t ph_unpp; + }; union { - struct sockaddr_un xuu_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; -}; + void *xu_vnode; /* (s) */ + int64_t ph_vnode; + }; + union { + void *xu_conn; /* (s) */ + int64_t ph_conn; + }; + union { + void *xu_first_ref; /* (s) */ + int64_t ph_first_ref; + }; + union { + void *xu_next_ref; /* (s) */ + int64_t ph_next_ref; + }; + struct sockaddr_un xu_addr; + struct sockaddr_un xu_caddr; +} __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_ */ Index: usr.bin/netstat/main.c =================================================================== --- usr.bin/netstat/main.c +++ usr.bin/netstat/main.c @@ -540,9 +540,7 @@ printproto(tp, tp->pr_name, &first); #endif /* NETGRAPH */ if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) - unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, - nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value, - nl[N_UNP_SPHEAD].n_value, &first); + unixpr(&first); if (!first) xo_close_list("socket"); Index: usr.bin/netstat/netstat.h =================================================================== --- usr.bin/netstat/netstat.h +++ usr.bin/netstat/netstat.h @@ -150,7 +150,7 @@ void netgraphprotopr(u_long, const char *, int, int); #endif -void unixpr(u_long, u_long, u_long, u_long, u_long, bool *); +void unixpr(bool *); void mroutepr(void); void mrt_stats(void); Index: usr.bin/netstat/nlist_symbols =================================================================== --- usr.bin/netstat/nlist_symbols +++ usr.bin/netstat/nlist_symbols @@ -47,9 +47,4 @@ all _tcps_states all _udbinfo all _udpstat -all _unp_count -all _unp_dhead -all _unp_gencnt -all _unp_shead -all _unp_sphead all _viftable Index: usr.bin/netstat/unix.c =================================================================== --- usr.bin/netstat/unix.c +++ usr.bin/netstat/unix.c @@ -96,133 +96,18 @@ return (0); } -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; - u_char sun_len; - struct socket so; - struct xunpgen xug; - struct xunpcb xu; - unp_gen_t unp_gencnt; - u_int unp_count; - char *buf, *p; - size_t len; - - if (count_off == 0 || gencnt_off == 0) - return (-2); - if (head_off == 0) - return (-1); - kread(count_off, &unp_count, sizeof(unp_count)); - len = 2 * sizeof(xug) + (unp_count + unp_count / 8) * sizeof(xu); - if ((buf = malloc(len)) == NULL) { - xo_warnx("malloc %lu bytes", (u_long)len); - return (-2); - } - p = buf; - -#define COPYOUT(obj, size) do { \ - if (len < (size)) { \ - xo_warnx("buffer size exceeded"); \ - goto fail; \ - } \ - bcopy((obj), p, (size)); \ - len -= (size); \ - p += (size); \ -} while (0) - -#define KREAD(off, buf, len) do { \ - if (kread((uintptr_t)(off), (buf), (len)) != 0) \ - goto fail; \ -} while (0) - - /* Write out header. */ - kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt)); - xug.xug_len = sizeof xug; - xug.xug_count = unp_count; - xug.xug_gen = unp_gencnt; - xug.xug_sogen = 0; - COPYOUT(&xug, sizeof xug); - - /* Walk the PCB list. */ - xu.xu_len = sizeof xu; - 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; - - if (unp->unp_gencnt > unp_gencnt) - continue; - if (unp->unp_addr != NULL) { - KREAD(unp->unp_addr, &sun_len, sizeof(sun_len)); - KREAD(unp->unp_addr, &xu.xu_addr, sun_len); - } - if (unp->unp_conn != NULL) { - KREAD(unp->unp_conn, &unp_conn, sizeof(unp_conn)); - if (unp_conn.unp_addr != NULL) { - KREAD(unp_conn.unp_addr, &sun_len, - sizeof(sun_len)); - KREAD(unp_conn.unp_addr, &xu.xu_caddr, sun_len); - } - } - KREAD(unp->unp_socket, &so, sizeof(so)); - if (sotoxsocket(&so, &xu.xu_socket) != 0) - goto fail; - COPYOUT(&xu, sizeof(xu)); - } - - /* Reread the counts and write the footer. */ - kread(count_off, &unp_count, sizeof(unp_count)); - kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt)); - xug.xug_count = unp_count; - xug.xug_gen = unp_gencnt; - COPYOUT(&xug, sizeof xug); - - *bufp = buf; - return (0); - -fail: - free(buf); - return (-1); -#undef COPYOUT -#undef KREAD -} - void -unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off, - u_long sphead_off, bool *first) +unixpr(bool *first) { char *buf; int ret, type; struct xsocket *so; struct xunpgen *xug, *oxug; struct xunpcb *xunp; - u_long head_off; buf = NULL; for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) { - if (live) - ret = pcblist_sysctl(type, &buf); - else { - head_off = 0; - switch (type) { - case SOCK_STREAM: - head_off = shead_off; - break; - - case SOCK_DGRAM: - head_off = dhead_off; - break; - - case SOCK_SEQPACKET: - head_off = sphead_off; - break; - } - ret = pcblist_kvm(count_off, gencnt_off, head_off, - &buf); - } + ret = pcblist_sysctl(type, &buf); if (ret == -1) continue; if (ret < 0) @@ -236,7 +121,7 @@ so = &xunp->xu_socket; /* Ignore PCBs which were freed during copyout. */ - if (xunp->xu_unp.unp_gencnt > oxug->xug_gen) + if (xunp->xu_gencnt > oxug->xug_gen) continue; if (*first) { xo_open_list("socket"); @@ -268,7 +153,6 @@ static void unixdomainpr(struct xunpcb *xunp, struct xsocket *so) { - struct unpcb *unp; struct sockaddr_un *sa; static int first = 1; char buf1[33]; @@ -292,8 +176,7 @@ }; int fmt = (sizeof(void *) == 8) ? 1 : 0; - unp = &xunp->xu_unp; - if (unp->unp_addr) + if (xunp->xu_addr.sun_len > 0) sa = &xunp->xu_addr; else sa = (struct sockaddr_un *)0; @@ -318,10 +201,10 @@ } 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->xu_vnode, + (long)xunp->xu_conn, + (long)xunp->xu_first_ref, + (long)xunp->xu_next_ref); } if (sa) xo_emit(" {:path/%.*s}", Index: usr.bin/sockstat/sockstat.c =================================================================== --- usr.bin/sockstat/sockstat.c +++ usr.bin/sockstat/sockstat.c @@ -773,8 +773,8 @@ 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->xu_conn == NULL && !opt_l) || + (xup->xu_conn != NULL && !opt_c)) continue; if ((sock = calloc(1, sizeof(*sock))) == NULL) err(1, "malloc()"); @@ -787,11 +787,11 @@ sock->proto = proto; sock->family = AF_UNIX; sock->protoname = protoname; - if (xup->xu_unp.unp_addr != NULL) + if (xup->xu_addr.sun_len > 0) 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->xu_conn != NULL) + *(void **)&(faddr->address) = xup->xu_conn; laddr->next = NULL; faddr->next = NULL; sock->laddr = laddr;