Deleted Added
full compact
41c41
< __FBSDID("$FreeBSD: head/usr.bin/netstat/unix.c 160787 2006-07-28 16:09:19Z yar $");
---
> __FBSDID("$FreeBSD: head/usr.bin/netstat/unix.c 171465 2007-07-16 17:15:55Z jhb $");
63a64
> #include <strings.h>
72,73c73,74
< void
< unixpr(void)
---
> static int
> pcblist_sysctl(int type, char **bufp)
76d76
< int type;
77a78,199
> char mibvar[sizeof "net.local.seqpacket.pcblist"];
>
> sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
>
> len = 0;
> if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
> if (errno != ENOENT)
> warn("sysctl: %s", mibvar);
> return (-1);
> }
> if ((buf = malloc(len)) == 0) {
> warnx("malloc %lu bytes", (u_long)len);
> return (-2);
> }
> if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
> warn("sysctl: %s", mibvar);
> free(buf);
> return (-2);
> }
> *bufp = buf;
> 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)) == 0) {
> warnx("malloc %lu bytes", (u_long)len);
> return (-2);
> }
> p = buf;
>
> #define COPYOUT(obj, size) do { \
> if (len < (size)) { \
> 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)
> {
> char *buf;
> int ret, type;
81d202
< char mibvar[sizeof "net.local.seqpacket.pcblist"];
84,89c205,211
< sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
<
< len = 0;
< if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
< if (errno != ENOENT)
< warn("sysctl: %s", mibvar);
---
> if (live)
> ret = pcblist_sysctl(type, &buf);
> else
> ret = pcblist_kvm(count_off, gencnt_off,
> type == SOCK_STREAM ? shead_off :
> (type == SOCK_DGRAM ? dhead_off : 0), &buf);
> if (ret == -1)
91,93c213
< }
< if ((buf = malloc(len)) == 0) {
< warnx("malloc %lu bytes", (u_long)len);
---
> if (ret < 0)
95,100d214
< }
< if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
< warn("sysctl: %s", mibvar);
< free(buf);
< return;
< }