summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2010-10-30 23:06:06 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2010-10-30 23:06:06 +0000
commit1f0613d3b46d523d998071f1a8eee83f8c3760ed (patch)
tree8e44992a6695f663f8b247998f3cbbce557fb90b /usr.bin
parent2bc46d1d3511a751229028b2ff09c8f6a4b0bdf4 (diff)
Print socket structure internals when netstat -P pcbaddr is called
with -v. Also netstat -P supports more than TCP now. ok markus@ jmc@
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/netstat/atalk.c9
-rw-r--r--usr.bin/netstat/inet.c268
-rw-r--r--usr.bin/netstat/main.c98
-rw-r--r--usr.bin/netstat/netstat.119
-rw-r--r--usr.bin/netstat/netstat.h11
-rw-r--r--usr.bin/netstat/unix.c48
6 files changed, 348 insertions, 105 deletions
diff --git a/usr.bin/netstat/atalk.c b/usr.bin/netstat/atalk.c
index 8a41f3bc649..73126f4b1ff 100644
--- a/usr.bin/netstat/atalk.c
+++ b/usr.bin/netstat/atalk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atalk.c,v 1.19 2010/06/29 03:09:29 blambert Exp $ */
+/* $OpenBSD: atalk.c,v 1.20 2010/10/30 23:06:05 bluhm Exp $ */
/* $NetBSD: atalk.c,v 1.2 1997/05/22 17:21:26 christos Exp $ */
/*
@@ -196,7 +196,7 @@ atalk_print(const struct sockaddr *sa, int what)
}
void
-atalkprotopr(u_long off, char *name, int af)
+atalkprotopr(u_long off, char *name, int af, u_long pcbaddr)
{
struct ddpcb cb;
struct ddpcb *prev, *next;
@@ -214,6 +214,11 @@ atalkprotopr(u_long off, char *name, int af)
if (kread((u_long) next, &ddpcb, sizeof(ddpcb)) < 0)
return;
next = ddpcb.ddp_next;
+ if (Pflag) {
+ if (pcbaddr == ppcb)
+ socket_dump((u_long)ddpcb.ddp_socket);
+ continue;
+ }
#if 0
if (!aflag && atalk_nullhost(ddpcb.ddp_lsat)) {
continue;
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index bbd6b9300bc..037b231390f 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: inet.c,v 1.113 2010/06/29 03:09:29 blambert Exp $ */
+/* $OpenBSD: inet.c,v 1.114 2010/10/30 23:06:05 bluhm Exp $ */
/* $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $ */
/*
@@ -35,6 +35,7 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/mbuf.h>
+#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/sysctl.h>
@@ -94,6 +95,11 @@ char *inetname(struct in_addr *);
void inetprint(struct in_addr *, in_port_t, char *, int);
char *inet6name(struct in6_addr *);
void inet6print(struct in6_addr *, int, char *);
+void sockbuf_dump(struct sockbuf *, const char *);
+void protosw_dump(u_long, u_long);
+void domain_dump(u_long, u_long, short);
+void inpcb_dump(u_long, short, int);
+void tcpcb_dump(u_long);
/*
* Print a summary of connections related to an Internet
@@ -102,7 +108,7 @@ void inet6print(struct in6_addr *, int, char *);
* -a (all) flag is specified.
*/
void
-protopr(u_long off, char *name, int af)
+protopr(u_long off, char *name, int af, u_long pcbaddr)
{
struct inpcbtable table;
struct inpcb *head, *next, *prev;
@@ -147,6 +153,21 @@ protopr(u_long off, char *name, int af)
break;
}
+ if (Pflag) {
+ if (istcp && pcbaddr == (u_long)inpcb.inp_ppcb) {
+ if (vflag)
+ socket_dump((u_long)inpcb.inp_socket);
+ else
+ tcpcb_dump(pcbaddr);
+ } else if (pcbaddr == (u_long)prev) {
+ if (vflag)
+ socket_dump((u_long)inpcb.inp_socket);
+ else
+ inpcb_dump(pcbaddr, 0, af);
+ }
+ continue;
+ }
+
kread((u_long)inpcb.inp_socket, &sockb, sizeof (sockb));
if (istcp) {
kread((u_long)inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
@@ -1130,10 +1151,193 @@ ipcomp_stats(char *name)
}
/*
- * Dump the contents of a TCPCB
+ * Dump the contents of a socket structure
+ */
+void
+socket_dump(u_long off)
+{
+ struct socket so;
+
+ if (off == 0)
+ return;
+ kread(off, &so, sizeof(so));
+
+#define p(fmt, v, sep) printf(#v " " fmt sep, so.v);
+ printf("socket %#lx\n ", off);
+ p("%#0.4x", so_type, "\n ");
+ p("%#0.4x", so_options, "\n ");
+ p("%d", so_linger, "\n ");
+ p("%#0.4x", so_state, "\n ");
+ p("%p", so_pcb, ", ");
+ p("%p", so_proto, ", ");
+ p("%p", so_head, "\n ");
+ p("%d", so_q0len, ", ");
+ p("%d", so_qlen, ", ");
+ p("%d", so_qlimit, "\n ");
+ p("%d", so_timeo, "\n ");
+ p("%u", so_error, "\n ");
+ p("%d", so_pgid, ", ");
+ p("%u", so_siguid, ", ");
+ p("%u", so_sigeuid, "\n ");
+ p("%lu", so_oobmark, "\n ");
+ sockbuf_dump(&so.so_rcv, "so_rcv");
+ sockbuf_dump(&so.so_snd, "so_snd");
+ p("%u", so_euid, ", ");
+ p("%u", so_ruid, ", ");
+ p("%u", so_egid, ", ");
+ p("%u", so_rgid, "\n ");
+ p("%d", so_cpid, "\n");
+#undef p
+
+ if (!vflag)
+ return;
+ protosw_dump((u_long)so.so_proto, (u_long)so.so_pcb);
+}
+
+/*
+ * Dump the contents of a socket buffer
+ */
+void
+sockbuf_dump(struct sockbuf *sb, const char *name)
+{
+#define p(fmt, v, sep) printf(#v " " fmt sep, sb->v);
+ printf("%s ", name);
+ p("%lu", sb_cc, ", ");
+ p("%lu", sb_datacc, ", ");
+ p("%lu", sb_hiwat, ", ");
+ p("%lu", sb_wat, "\n ");
+ printf("%s ", name);
+ p("%lu", sb_mbcnt, ", ");
+ p("%lu", sb_mbmax, ", ");
+ p("%ld", sb_lowat, "\n ");
+ printf("%s ", name);
+ p("%#0.4x", sb_flags, ", ");
+ p("%u", sb_timeo, "\n ");
+#undef p
+}
+
+/*
+ * Dump the contents of a protosw structure
+ */
+void
+protosw_dump(u_long off, u_long pcb)
+{
+ struct protosw proto;
+
+ if (off == 0)
+ return;
+ kread(off, &proto, sizeof(proto));
+
+#define p(fmt, v, sep) printf(#v " " fmt sep, proto.v);
+ printf("protosw %#lx\n ", off);
+ p("%#0.4x", pr_type, "\n ");
+ p("%p", pr_domain, "\n ");
+ p("%d", pr_protocol, "\n ");
+ p("%#0.4x", pr_flags, "\n");
+#undef p
+
+ domain_dump((u_long)proto.pr_domain, pcb, proto.pr_protocol);
+}
+
+/*
+ * Dump the contents of a domain structure
+ */
+void
+domain_dump(u_long off, u_long pcb, short protocol)
+{
+ struct domain dom;
+ char name[256];
+
+ if (off == 0)
+ return;
+ kread(off, &dom, sizeof(dom));
+ kread((u_long)dom.dom_name, name, sizeof(name));
+
+#define p(fmt, v, sep) printf(#v " " fmt sep, dom.v);
+ printf("domain %#lx\n ", off);
+ p("%d", dom_family, "\n ");
+ printf("dom_name %.*s\n", sizeof(name), name);
+#undef p
+
+ switch (dom.dom_family) {
+ case AF_INET:
+ case AF_INET6:
+ inpcb_dump(pcb, protocol, dom.dom_family);
+ break;
+ case AF_UNIX:
+ unpcb_dump(pcb);
+ break;
+ }
+}
+
+/*
+ * Dump the contents of a internet PCB
+ */
+void
+inpcb_dump(u_long off, short protocol, int af)
+{
+ struct inpcb inp;
+ char faddr[256], laddr[256];
+
+ if (off == 0)
+ return;
+ kread(off, &inp, sizeof(inp));
+ switch (af) {
+ case AF_INET:
+ inet_ntop(af, &inp.inp_faddr, faddr, sizeof(faddr));
+ inet_ntop(af, &inp.inp_laddr, laddr, sizeof(laddr));
+ break;
+ case AF_INET6:
+ inet_ntop(af, &inp.inp_faddr6, faddr, sizeof(faddr));
+ inet_ntop(af, &inp.inp_laddr6, laddr, sizeof(laddr));
+ break;
+ default:
+ faddr[0] = laddr[0] = '\0';
+ }
+
+#define p(fmt, v, sep) printf(#v " " fmt sep, inp.v);
+ printf("inpcb %#lx\n ", off);
+ p("%p", inp_table, "\n ");
+ printf("inp_faddru %s, inp_laddru %s\n ", faddr, laddr);
+ HTONS(inp.inp_fport);
+ HTONS(inp.inp_lport);
+ p("%u", inp_fport, ", ");
+ p("%u", inp_lport, "\n ");
+ p("%p", inp_socket, ", ");
+ p("%p", inp_ppcb, "\n ");
+ p("%#0.8x", inp_flags, "\n ");
+ p("%d", inp_hops, "\n ");
+ p("%u", inp_seclevel[0], ", ");
+ p("%u", inp_seclevel[1], ", ");
+ p("%u", inp_seclevel[2], ", ");
+ p("%u", inp_seclevel[3], "\n ");
+ p("%#x", inp_secrequire, ", ");
+ p("%#x", inp_secresult, "\n ");
+ p("%u", inp_ip_minttl, "\n ");
+ p("%p", inp_tdb_in, ", ");
+ p("%p", inp_tdb_out, ", ");
+ p("%p", inp_ipo, "\n ");
+ p("%p", inp_ipsec_remotecred, ", ");
+ p("%p", inp_ipsec_remoteauth, "\n ");
+ p("%d", in6p_cksum, "\n ");
+ p("%p", inp_icmp6filt, "\n ");
+ p("%p", inp_pf_sk, "\n ");
+ p("%u", inp_rtableid, "\n ");
+ p("%d", inp_pipex, "\n");
+#undef p
+
+ switch (protocol) {
+ case IPPROTO_TCP:
+ tcpcb_dump((u_long)inp.inp_ppcb);
+ break;
+ }
+}
+
+/*
+ * Dump the contents of a TCP PCB
*/
void
-tcp_dump(u_long off)
+tcpcb_dump(u_long off)
{
struct tcpcb tcpcb;
@@ -1142,68 +1346,68 @@ tcp_dump(u_long off)
kread(off, (char *)&tcpcb, sizeof (tcpcb));
#define p(fmt, v, sep) printf(#v " " fmt sep, tcpcb.v);
- printf("pcb %#lx, ", off);
- p("%p", t_inpcb, "\n");
+ printf("tcpcb %#lx\n ", off);
+ p("%p", t_inpcb, "\n ");
p("%d", t_state, "");
- if (tcpcb.t_state >= 0 && tcpcb.t_state < TCP_NSTATES)
+ if (tcpcb.t_state >= 0 && tcpcb.t_state < TCP_NSTATES)
printf(" (%s)", tcpstates[tcpcb.t_state]);
- printf("\n");
+ printf("\n ");
p("%d", t_rxtshift, ", ");
p("%d", t_rxtcur, ", ");
- p("%d", t_dupacks, "\n");
+ p("%d", t_dupacks, "\n ");
p("%u", t_maxseg, ", ");
p("%u", t_maxopd, ", ");
- p("%u", t_peermss, "\n");
+ p("%u", t_peermss, "\n ");
p("0x%x", t_flags, ", ");
- p("%u", t_force, "\n");
- p("%u", iss, "\n");
+ p("%u", t_force, "\n ");
+ p("%u", iss, "\n ");
p("%u", snd_una, ", ");
p("%u", snd_nxt, ", ");
- p("%u", snd_up, "\n");
+ p("%u", snd_up, "\n ");
p("%u", snd_wl1, ", ");
p("%u", snd_wl2, ", ");
- p("%lu", snd_wnd, "\n");
+ p("%lu", snd_wnd, "\n ");
p("%d", sack_enable, ", ");
p("%d", snd_numholes, ", ");
p("%u", snd_fack, ", ");
- p("%lu",snd_awnd, "\n");
+ p("%lu",snd_awnd, "\n ");
p("%u", retran_data, ", ");
- p("%u", snd_last, "\n");
- p("%u", irs, "\n");
+ p("%u", snd_last, "\n ");
+ p("%u", irs, "\n ");
p("%u", rcv_nxt, ", ");
p("%u", rcv_up, ", ");
- p("%lu", rcv_wnd, "\n");
- p("%u", rcv_lastsack, "\n");
- p("%d", rcv_numsacks, "\n");
+ p("%lu", rcv_wnd, "\n ");
+ p("%u", rcv_lastsack, "\n ");
+ p("%d", rcv_numsacks, "\n ");
p("%u", rcv_adv, ", ");
- p("%u", snd_max, "\n");
+ p("%u", snd_max, "\n ");
p("%lu", snd_cwnd, ", ");
p("%lu", snd_ssthresh, ", ");
- p("%lu", max_sndwnd, "\n");
+ p("%lu", max_sndwnd, "\n ");
p("%u", t_rcvtime, ", ");
p("%u", t_rtttime, ", ");
- p("%u", t_rtseq, "\n");
+ p("%u", t_rtseq, "\n ");
p("%u", t_srtt, ", ");
p("%u", t_rttvar, ", ");
- p("%u", t_rttmin, "\n");
+ p("%u", t_rttmin, "\n ");
p("%u", t_oobflags, ", ");
- p("%u", t_iobc, "\n");
- p("%u", t_softerror, "\n");
+ p("%u", t_iobc, "\n ");
+ p("%u", t_softerror, "\n ");
p("%u", snd_scale, ", ");
p("%u", rcv_scale, ", ");
p("%u", request_r_scale, ", ");
- p("%u", requested_s_scale, "\n");
+ p("%u", requested_s_scale, "\n ");
p("%u", ts_recent, ", ");
- p("%u", ts_recent_age, "\n");
- p("%u", last_ack_sent, "\n");
+ p("%u", ts_recent_age, "\n ");
+ p("%u", last_ack_sent, "\n ");
HTONS(tcpcb.t_pmtud_ip_len);
HTONS(tcpcb.t_pmtud_nextmtu);
p("%u", t_pmtud_mss_acked, ", ");
- p("%u", t_pmtud_mtu_sent, "\n");
+ p("%u", t_pmtud_mtu_sent, "\n ");
p("%u", t_pmtud_nextmtu, ", ");
p("%u", t_pmtud_ip_len, ", ");
- p("%u", t_pmtud_ip_hl, "\n");
- p("%u", t_pmtud_th_seq, "\n");
+ p("%u", t_pmtud_ip_hl, "\n ");
+ p("%u", t_pmtud_th_seq, "\n ");
p("%u", pf, "\n");
#undef p
}
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c
index 2ddd0d64cc7..5f3fd0059e5 100644
--- a/usr.bin/netstat/main.c
+++ b/usr.bin/netstat/main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: main.c,v 1.86 2010/10/11 12:33:36 claudio Exp $ */
+/* $OpenBSD: main.c,v 1.87 2010/10/30 23:06:05 bluhm Exp $ */
/* $NetBSD: main.c,v 1.9 1996/05/07 02:55:02 thorpej Exp $ */
/*
@@ -93,55 +93,55 @@ struct nlist nl[] = {
#define N_DIVB6TABLE 16
{ "_divb6table" },
- { ""}
+ { "" }
};
struct protox {
- u_char pr_index; /* index into nlist of cb head */
- void (*pr_cblocks)(u_long, char *, int); /* control blocks printing routine */
- void (*pr_stats)(char *); /* statistics printing routine */
- void (*pr_dump)(u_long); /* pcb printing routine */
- char *pr_name; /* well-known name */
+ u_char pr_index; /* index into nlist of cb head */
+ void (*pr_cblocks)(u_long, char *, int, u_long);
+ /* control blocks printing routine */
+ void (*pr_stats)(char *); /* statistics printing routine */
+ char *pr_name; /* well-known name */
} protox[] = {
- { N_TCBTABLE, protopr, tcp_stats, tcp_dump, "tcp" },
- { N_UDBTABLE, protopr, udp_stats, NULL, "udp" },
- { N_RAWIPTABLE, protopr, ip_stats, NULL, "ip" },
- { N_DIVBTABLE, protopr, div_stats, NULL, "divert" },
- { -1, NULL, icmp_stats, NULL, "icmp" },
- { -1, NULL, igmp_stats, NULL, "igmp" },
- { -1, NULL, ah_stats, NULL, "ah" },
- { -1, NULL, esp_stats, NULL, "esp" },
- { -1, NULL, ipip_stats, NULL, "ipencap" },
- { -1, NULL, etherip_stats, NULL, "etherip" },
- { -1, NULL, ipcomp_stats, NULL, "ipcomp" },
- { -1, NULL, carp_stats, NULL, "carp" },
- { -1, NULL, pfsync_stats, NULL, "pfsync" },
- { -1, NULL, pim_stats, NULL, "pim" },
- { -1, NULL, pflow_stats, NULL, "pflow" },
- { -1, NULL, NULL, NULL, NULL }
+ { N_TCBTABLE, protopr, tcp_stats, "tcp" },
+ { N_UDBTABLE, protopr, udp_stats, "udp" },
+ { N_RAWIPTABLE, protopr, ip_stats, "ip" },
+ { N_DIVBTABLE, protopr, div_stats, "divert" },
+ { -1, NULL, icmp_stats, "icmp" },
+ { -1, NULL, igmp_stats, "igmp" },
+ { -1, NULL, ah_stats, "ah" },
+ { -1, NULL, esp_stats, "esp" },
+ { -1, NULL, ipip_stats, "ipencap" },
+ { -1, NULL, etherip_stats, "etherip" },
+ { -1, NULL, ipcomp_stats, "ipcomp" },
+ { -1, NULL, carp_stats, "carp" },
+ { -1, NULL, pfsync_stats, "pfsync" },
+ { -1, NULL, pim_stats, "pim" },
+ { -1, NULL, pflow_stats, "pflow" },
+ { -1, NULL, NULL, NULL }
};
struct protox ip6protox[] = {
- { N_TCBTABLE, protopr, NULL, tcp_dump, "tcp" },
- { N_UDBTABLE, protopr, NULL, NULL, "udp" },
- { N_RAWIP6TABLE,protopr, ip6_stats, NULL, "ip6" },
- { N_DIVB6TABLE, protopr, div6_stats, NULL, "divert6" },
- { -1, NULL, icmp6_stats, NULL, "icmp6" },
- { -1, NULL, pim6_stats, NULL, "pim6" },
- { -1, NULL, rip6_stats, NULL, "rip6" },
- { -1, NULL, NULL, NULL, NULL }
+ { N_TCBTABLE, protopr, NULL, "tcp" },
+ { N_UDBTABLE, protopr, NULL, "udp" },
+ { N_RAWIP6TABLE,protopr, ip6_stats, "ip6" },
+ { N_DIVB6TABLE, protopr, div6_stats, "divert6" },
+ { -1, NULL, icmp6_stats, "icmp6" },
+ { -1, NULL, pim6_stats, "pim6" },
+ { -1, NULL, rip6_stats, "rip6" },
+ { -1, NULL, NULL, NULL }
};
struct protox atalkprotox[] = {
- { N_DDPCB, atalkprotopr, ddp_stats, NULL, "ddp" },
- { -1, NULL, NULL, NULL, NULL }
+ { N_DDPCB, atalkprotopr, ddp_stats, "ddp" },
+ { -1, NULL, NULL, NULL }
};
struct protox *protoprotox[] = {
protox, ip6protox, atalkprotox, NULL
};
-static void printproto(struct protox *, char *, int);
+static void printproto(struct protox *, char *, int, u_long);
static void usage(void);
static struct protox *name2protox(char *);
static struct protox *knownname(char *);
@@ -360,18 +360,7 @@ main(int argc, char *argv[])
exit(0);
}
if (pflag) {
- printproto(tp, tp->pr_name, af);
- exit(0);
- }
- if (Pflag) {
- if (tp == NULL && (tp = name2protox("tcp")) == NULL) {
- (void)fprintf(stderr,
- "%s: %s: unknown protocol\n",
- __progname, "tcp");
- exit(1);
- }
- if (tp->pr_dump)
- (tp->pr_dump)(pcbaddr);
+ printproto(tp, tp->pr_name, af, pcbaddr);
exit(0);
}
/*
@@ -423,22 +412,22 @@ main(int argc, char *argv[])
break;
if (tp->pr_name == 0)
continue;
- printproto(tp, p->p_name, AF_INET);
+ printproto(tp, p->p_name, AF_INET, pcbaddr);
}
endprotoent();
}
if (af == PF_PFLOW || af == AF_UNSPEC) {
tp = name2protox("pflow");
- printproto(tp, tp->pr_name, af);
+ printproto(tp, tp->pr_name, af, pcbaddr);
}
if (af == AF_INET6 || af == AF_UNSPEC)
for (tp = ip6protox; tp->pr_name; tp++)
- printproto(tp, tp->pr_name, AF_INET6);
+ printproto(tp, tp->pr_name, AF_INET6, pcbaddr);
if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
- unixpr(nl[N_UNIXSW].n_value);
+ unixpr(nl[N_UNIXSW].n_value, pcbaddr);
if (af == AF_APPLETALK || af == AF_UNSPEC)
for (tp = atalkprotox; tp->pr_name; tp++)
- printproto(tp, tp->pr_name, af);
+ printproto(tp, tp->pr_name, af, pcbaddr);
exit(0);
}
@@ -448,7 +437,7 @@ main(int argc, char *argv[])
* is not in the namelist, ignore this one.
*/
static void
-printproto(struct protox *tp, char *name, int af)
+printproto(struct protox *tp, char *name, int af, u_long pcbaddr)
{
if (sflag) {
if (tp->pr_stats != NULL)
@@ -458,7 +447,7 @@ printproto(struct protox *tp, char *name, int af)
if (tp->pr_cblocks != NULL &&
i < sizeof(nl) / sizeof(nl[0]) &&
(nl[i].n_value || af != AF_UNSPEC))
- (*tp->pr_cblocks)(nl[i].n_value, name, af);
+ (*tp->pr_cblocks)(nl[i].n_value, name, af, pcbaddr);
}
}
@@ -542,7 +531,7 @@ usage(void)
" %s [-bdFgilmnqrstu] [-f address_family] [-M core] [-N system]\n"
" [-T tableid]\n"
" %s [-bdn] [-c count] [-I interface] [-M core] [-N system] [-w wait]\n"
- " %s [-M core] [-N system] -P pcbaddr\n"
+ " %s [-v] [-M core] [-N system] -P pcbaddr\n"
" %s [-s] [-M core] [-N system] [-p protocol]\n"
" %s [-a] [-f address_family] [-i | -I interface]\n"
" %s [-W interface]\n",
@@ -577,4 +566,3 @@ gettable(const char *s)
return (tableid);
}
-
diff --git a/usr.bin/netstat/netstat.1 b/usr.bin/netstat/netstat.1
index ffcdb716d5b..337ad190834 100644
--- a/usr.bin/netstat/netstat.1
+++ b/usr.bin/netstat/netstat.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: netstat.1,v 1.60 2010/07/31 14:25:37 sobrado Exp $
+.\" $OpenBSD: netstat.1,v 1.61 2010/10/30 23:06:05 bluhm Exp $
.\" $NetBSD: netstat.1,v 1.11 1995/10/03 21:42:43 thorpej Exp $
.\"
.\" Copyright (c) 1983, 1990, 1992, 1993
@@ -30,7 +30,7 @@
.\"
.\" from: @(#)netstat.1 8.8 (Berkeley) 4/18/94
.\"
-.Dd $Mdocdate: July 31 2010 $
+.Dd $Mdocdate: October 30 2010 $
.Dt NETSTAT 1
.Os
.Sh NAME
@@ -60,6 +60,7 @@
.Op Fl N Ar system
.Op Fl w Ar wait
.Nm netstat
+.Op Fl v
.Op Fl M Ar core
.Op Fl N Ar system
.Fl P Ar pcbaddr
@@ -93,7 +94,8 @@ interval specified,
.Nm
will continuously display the information regarding packet
traffic on the configured network interfaces.
-The fourth form displays statistics about the protocol control block (PCB).
+The fourth form displays internals of the protocol control block (PCB)
+and the socket structure.
The fifth form displays statistics about the named protocol.
The sixth form displays per interface statistics for
the specified address family.
@@ -229,13 +231,15 @@ interprets addresses and attempts to display them
symbolically).
This option may be used with any of the display formats.
.It Fl P Ar pcbaddr
-Display the contents of the protocol control block (PCB) located at
-the kernel virtual address
+Display the contents of the socket or protocol control block (PCB)
+located at the kernel virtual address
.Ar pcbaddr .
PCB addresses can be obtained using the
.Fl A
flag.
-This option can currently only be used to display TCP control blocks.
+When used with the
+.Fl v
+option, also print socket, domain and protocol specific structures.
.It Fl p Ar protocol
Restrict the output to
.Ar protocol ,
@@ -279,6 +283,9 @@ address family.
Show extra (verbose) detail for the routing tables
.Pq Fl r ,
or avoid truncation of long addresses.
+When used with the
+.Fl P
+option, also print socket, domain and protocol specific structures.
.It Fl W Ar interface
(IEEE 802.11 devices only)
Show per-interface IEEE 802.11 wireless statistics.
diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h
index 9aecd55bd16..3de27669ecc 100644
--- a/usr.bin/netstat/netstat.h
+++ b/usr.bin/netstat/netstat.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: netstat.h,v 1.57 2010/10/11 12:33:36 claudio Exp $ */
+/* $OpenBSD: netstat.h,v 1.58 2010/10/30 23:06:05 bluhm Exp $ */
/* $NetBSD: netstat.h,v 1.6 1996/05/07 02:55:05 thorpej Exp $ */
/*
@@ -69,7 +69,7 @@ int kread(u_long addr, void *buf, int size);
char *plural(u_int64_t);
char *plurales(u_int64_t);
-void protopr(u_long, char *, int);
+void protopr(u_long, char *, int, u_long);
void tcp_stats(char *);
void udp_stats(char *);
void ip_stats(char *);
@@ -88,7 +88,8 @@ void ipcomp_stats(char *);
void net80211_ifstats(char *);
-void tcp_dump(u_long);
+void socket_dump(u_long);
+void unpcb_dump(u_long);
void mbpr(void);
@@ -130,11 +131,11 @@ void nsprotopr(u_long, char *);
void intpr(int, int);
-void unixpr(u_long);
+void unixpr(u_long, u_long);
void mroutepr(u_long, u_long, u_long);
void mrt_stats(void);
-void atalkprotopr(u_long, char *, int);
+void atalkprotopr(u_long, char *, int, u_long);
void ddp_stats(char *);
char *atalk_print(const struct sockaddr *, int);
diff --git a/usr.bin/netstat/unix.c b/usr.bin/netstat/unix.c
index 61575badda4..e80c917f0d4 100644
--- a/usr.bin/netstat/unix.c
+++ b/usr.bin/netstat/unix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: unix.c,v 1.14 2010/04/28 18:22:11 jsg Exp $ */
+/* $OpenBSD: unix.c,v 1.15 2010/10/30 23:06:05 bluhm Exp $ */
/* $NetBSD: unix.c,v 1.13 1995/10/03 21:42:48 thorpej Exp $ */
/*-
@@ -54,14 +54,14 @@ struct proc;
#include <kvm.h>
#include "netstat.h"
-static void unixdomainpr(struct socket *, caddr_t);
+static void unixdomainpr(struct socket *, caddr_t, u_long);
static struct file *file, *fileNFILE;
static int fcnt;
extern kvm_t *kvmd;
void
-unixpr(u_long off)
+unixpr(u_long off, u_long pcbaddr)
{
struct file *fp;
struct socket sock, *so = &sock;
@@ -83,7 +83,7 @@ unixpr(u_long off)
/* kludge */
if (so->so_proto >= unixsw && so->so_proto <= unixsw + 2)
if (so->so_pcb)
- unixdomainpr(so, fp->f_data);
+ unixdomainpr(so, fp->f_data, pcbaddr);
}
}
@@ -91,13 +91,19 @@ static char *socktype[] =
{ "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
static void
-unixdomainpr(struct socket *so, caddr_t soaddr)
+unixdomainpr(struct socket *so, caddr_t soaddr, u_long pcbaddr)
{
struct unpcb unpcb, *unp = &unpcb;
struct mbuf mbuf, *m;
struct sockaddr_un *sa = NULL;
static int first = 1;
+ if (Pflag) {
+ if (pcbaddr == (u_long)soaddr)
+ socket_dump(pcbaddr);
+ return;
+ }
+
if (kread((u_long)so->so_pcb, unp, sizeof (*unp)))
return;
if (unp->unp_addr) {
@@ -125,3 +131,35 @@ unixdomainpr(struct socket *so, caddr_t soaddr)
sa->sun_path);
putchar('\n');
}
+
+/*
+ * Dump the contents of a UNIX PCB
+ */
+void
+unpcb_dump(u_long off)
+{
+ struct unpcb unp;
+
+ if (off == 0)
+ return;
+ kread(off, &unp, sizeof(unp));
+
+#define p(fmt, v, sep) printf(#v " " fmt sep, unp.v);
+ printf("unpcb %#lx\n ", off);
+ p("%p", unp_socket, "\n ");
+ p("%p", unp_vnode, ", ");
+ p("%u", unp_ino, "\n ");
+ p("%p", unp_conn, ", ");
+ p("%p", unp_refs, ", ");
+ p("%p", unp_nextref, "\n ");
+ p("%p", unp_addr, "\n ");
+ p("%#0.8x", unp_flags, "\n ");
+ p("%u", unp_connid.uid, ", ");
+ p("%u", unp_connid.gid, ", ");
+ p("%d", unp_connid.pid, "\n ");
+ p("%d", unp_cc, ", ");
+ p("%d", unp_mbcnt, "\n ");
+ p("%d", unp_ctime.tv_sec, ", ");
+ p("%ld", unp_ctime.tv_nsec, "\n");
+#undef p
+}