diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2010-10-30 23:06:06 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2010-10-30 23:06:06 +0000 |
commit | 1f0613d3b46d523d998071f1a8eee83f8c3760ed (patch) | |
tree | 8e44992a6695f663f8b247998f3cbbce557fb90b /usr.bin | |
parent | 2bc46d1d3511a751229028b2ff09c8f6a4b0bdf4 (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.c | 9 | ||||
-rw-r--r-- | usr.bin/netstat/inet.c | 268 | ||||
-rw-r--r-- | usr.bin/netstat/main.c | 98 | ||||
-rw-r--r-- | usr.bin/netstat/netstat.1 | 19 | ||||
-rw-r--r-- | usr.bin/netstat/netstat.h | 11 | ||||
-rw-r--r-- | usr.bin/netstat/unix.c | 48 |
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 +} |