diff options
Diffstat (limited to 'usr.bin/netstat/inet.c')
-rw-r--r-- | usr.bin/netstat/inet.c | 177 |
1 files changed, 115 insertions, 62 deletions
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index 0226107..f6ff5e5 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; */ static const char rcsid[] = - "$Id: inet.c,v 1.25 1997/02/22 19:56:21 peter Exp $"; + "$Id: inet.c,v 1.26 1997/08/25 16:57:05 wollman Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -67,16 +67,15 @@ static const char rcsid[] = #include <netinet/udp_var.h> #include <arpa/inet.h> +#include <err.h> +#include <errno.h> #include <netdb.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> #include "netstat.h" -struct inpcb inpcb; -struct tcpcb tcpcb; -struct socket sockb; - char *inetname __P((struct in_addr *)); void inetprint __P((struct in_addr *, int, char *, int)); @@ -87,50 +86,83 @@ void inetprint __P((struct in_addr *, int, char *, int)); * -a (all) flag is specified. */ void -protopr(off, name) - u_long off; +protopr(proto, name) + u_long proto; /* for sysctl version we pass proto # */ char *name; { - struct inpcbhead head; - register struct inpcb *prev, *next; int istcp; static int first = 1; + char *buf; + const char *mibvar; + struct tcpcb *tp; + struct inpcb *inp; + struct xinpgen *xig, *oxig; + struct xsocket *so; + size_t len; - if (off == 0) + istcp = 0; + switch (proto) { + case IPPROTO_TCP: + istcp = 1; + mibvar = "net.inet.tcp.pcblist"; + break; + case IPPROTO_UDP: + mibvar = "net.inet.udp.pcblist"; + break; + case IPPROTO_DIVERT: + mibvar = "net.inet.divert.pcblist"; + break; + default: + mibvar = "net.inet.raw.pcblist"; + break; + } + len = 0; + if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + warn("sysctl: %s", mibvar); return; + } + if ((buf = malloc(len)) == 0) { + warn("malloc %lu bytes", (u_long)len); + return; + } + if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + free(buf); + return; + } - istcp = strcmp(name, "tcp") == 0; - kread(off, (char *)&head, sizeof (struct inpcbhead)); - prev = (struct inpcb *)off; - - for (next = head.lh_first; next != NULL; next = inpcb.inp_list.le_next) { - if (kread((u_long)next, (char *)&inpcb, sizeof (inpcb))) { - printf("???\n"); - break; - } - if (!aflag && - inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) { - prev = next; - continue; - } - if (kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb))) { - printf("???\n"); - break; - }; + oxig = xig = (struct xinpgen *)buf; + for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); + xig->xig_len > sizeof(struct xinpgen); + xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { if (istcp) { - if (kread((u_long)inpcb.inp_ppcb, - (char *)&tcpcb, sizeof (tcpcb))) { - printf("???\n"); - break; - }; + tp = &((struct xtcpcb *)xig)->xt_tp; + inp = &((struct xtcpcb *)xig)->xt_inp; + so = &((struct xtcpcb *)xig)->xt_socket; + } else { + inp = &((struct xinpcb *)xig)->xi_inp; + so = &((struct xinpcb *)xig)->xi_socket; } + + /* Ignore sockets for protocols other than the desired one. */ + if (so->xso_protocol != proto) + continue; + + /* Ignore PCBs which were freed during copyout. */ + if (inp->inp_gencnt > oxig->xig_gen) + continue; + + if (!aflag && inet_lnaof(inp->inp_laddr) == INADDR_ANY) + continue; + if (first) { printf("Active Internet connections"); if (aflag) printf(" (including servers)"); putchar('\n'); if (Aflag) - printf("%-8.8s ", "PCB"); + printf("%-8.8s ", "Socket"); printf(Aflag ? "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", @@ -139,43 +171,52 @@ protopr(off, name) first = 0; } if (Aflag) - if (istcp) - printf("%8x ", (int)inpcb.inp_ppcb); - else - printf("%8x ", (int)next); - printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc, - sockb.so_snd.sb_cc); + printf("%8lx ", (u_long)so->so_pcb); + printf("%-5.5s %6ld %6ld ", name, so->so_rcv.sb_cc, + so->so_snd.sb_cc); if (nflag) { - inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, + inetprint(&inp->inp_laddr, (int)inp->inp_lport, name, 1); - inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, + inetprint(&inp->inp_faddr, (int)inp->inp_fport, name, 1); - } else if (inpcb.inp_flags & INP_ANONPORT) { - inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, + } else if (inp->inp_flags & INP_ANONPORT) { + inetprint(&inp->inp_laddr, (int)inp->inp_lport, name, 1); - inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, + inetprint(&inp->inp_faddr, (int)inp->inp_fport, name, 0); } else { - inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, + inetprint(&inp->inp_laddr, (int)inp->inp_lport, name, 0); - inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, - name, inpcb.inp_lport != inpcb.inp_fport); + inetprint(&inp->inp_faddr, (int)inp->inp_fport, + name, inp->inp_lport != inp->inp_fport); } if (istcp) { - if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) - printf(" %d", tcpcb.t_state); + if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) + printf(" %d", tp->t_state); else { - printf(" %s", tcpstates[tcpcb.t_state]); + printf(" %s", tcpstates[tp->t_state]); #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) /* Show T/TCP `hidden state' */ - if (tcpcb.t_flags & (TF_NEEDSYN|TF_NEEDFIN)) + if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) putchar('*'); #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ } } putchar('\n'); - prev = next; } + if (xig != oxig && xig->xig_gen != oxig->xig_gen) { + if (oxig->xig_count > xig->xig_count) { + printf("Some %s sockets may have been deleted.\n", + name); + } else if (oxig->xig_count < xig->xig_count) { + printf("Some %s sockets may have been created.\n", + name); + } else { + printf("Some %s sockets may have been created or deleted", + name); + } + } + free(buf); } /* @@ -187,11 +228,14 @@ tcp_stats(off, name) char *name; { struct tcpstat tcpstat; - - if (off == 0) + size_t len = sizeof tcpstat; + + if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) { + warn("sysctl: net.inet.tcp.stats"); return; + } + printf ("%s:\n", name); - kread(off, (char *)&tcpstat, sizeof (tcpstat)); #define p(f, m) if (tcpstat.f || sflag <= 1) \ printf(m, tcpstat.f, plural(tcpstat.f)) @@ -271,11 +315,14 @@ udp_stats(off, name) char *name; { struct udpstat udpstat; + size_t len = sizeof udpstat; u_long delivered; - if (off == 0) + if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) { + warn("sysctl: net.inet.udp.stats"); return; - kread(off, (char *)&udpstat, sizeof (udpstat)); + } + printf("%s:\n", name); #define p(f, m) if (udpstat.f || sflag <= 1) \ printf(m, udpstat.f, plural(udpstat.f)) @@ -309,10 +356,13 @@ ip_stats(off, name) char *name; { struct ipstat ipstat; + size_t len = sizeof ipstat; - if (off == 0) + if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) { + warn("sysctl: net.inet.ip.stats"); return; - kread(off, (char *)&ipstat, sizeof (ipstat)); + } + printf("%s:\n", name); #define p(f, m) if (ipstat.f || sflag <= 1) \ @@ -444,10 +494,13 @@ igmp_stats(off, name) char *name; { struct igmpstat igmpstat; + size_t len = sizeof igmpstat; - if (off == 0) + if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 0, 0) < 0) { + warn("sysctl: net.inet.igmp.stats"); return; - kread(off, (char *)&igmpstat, sizeof (igmpstat)); + } + printf("%s:\n", name); #define p(f, m) if (igmpstat.f || sflag <= 1) \ |