diff options
Diffstat (limited to 'usr.bin/netstat')
| -rw-r--r-- | usr.bin/netstat/Makefile | 2 | ||||
| -rw-r--r-- | usr.bin/netstat/if.c | 92 | ||||
| -rw-r--r-- | usr.bin/netstat/inet.c | 44 | ||||
| -rw-r--r-- | usr.bin/netstat/main.c | 33 | ||||
| -rw-r--r-- | usr.bin/netstat/mroute.c | 211 | ||||
| -rw-r--r-- | usr.bin/netstat/netstat.1 | 6 |
6 files changed, 380 insertions, 8 deletions
diff --git a/usr.bin/netstat/Makefile b/usr.bin/netstat/Makefile index e2db444a1835..8f0933dac7d1 100644 --- a/usr.bin/netstat/Makefile +++ b/usr.bin/netstat/Makefile @@ -1,7 +1,7 @@ # @(#)Makefile 5.14 (Berkeley) 6/18/90 PROG= netstat -SRCS= inet.c if.c main.c mbuf.c route.c unix.c +SRCS= inet.c if.c main.c mbuf.c route.c unix.c mroute.c #SRCS+= host.c #CFLAGS+= -DIMP diff --git a/usr.bin/netstat/if.c b/usr.bin/netstat/if.c index 8e75e41c7c1e..e7942115dad2 100644 --- a/usr.bin/netstat/if.c +++ b/usr.bin/netstat/if.c @@ -34,7 +34,7 @@ #ifndef lint /* From: static char sccsid[] = "@(#)if.c 5.15 (Berkeley) 3/1/91"; */ static const char if_c_rcsid[] = - "$Id: if.c,v 1.3 1994/02/21 11:35:23 rgrimes Exp $"; + "$Id: if.c,v 1.4 1994/05/17 21:10:14 jkh Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -61,6 +61,7 @@ static const char if_c_rcsid[] = #define YES 1 #define NO 0 +extern int aflag; extern int tflag; extern int dflag; extern int nflag; @@ -70,6 +71,21 @@ extern char *routename(), *netname(), *ns_phost(); char *index(); /* + * Return a printable string representation of an Ethernet address. + */ +char *etherprint(enaddr) + char enaddr[6]; +{ + static char string[18]; + unsigned char *en = (unsigned char *)enaddr; + + sprintf(string, "%02x:%02x:%02x:%02x:%02x:%02x", + en[0], en[1], en[2], en[3], en[4], en[5] ); + string[17] = '\0'; + return(string); +} + +/* * Print a description of the network interfaces. */ intpr(interval, ifnetaddr) @@ -87,7 +103,7 @@ intpr(interval, ifnetaddr) struct iso_ifaddr iso; #endif } ifaddr; - off_t ifaddraddr; + off_t ifaddraddr, ifaddrfound, ifnetfound; struct sockaddr *sa; char name[16]; @@ -110,12 +126,14 @@ intpr(interval, ifnetaddr) printf(" %s", "Drop"); putchar('\n'); ifaddraddr = 0; + ifnetfound = 0; while (ifnetaddr || ifaddraddr) { struct sockaddr_in *sin; register char *cp; int n, m; struct in_addr inet_makeaddr(); + ifnetfound = ifnetaddr; if (ifaddraddr == 0) { kvm_read(ifnetaddr, (char *)&ifnet, sizeof ifnet); kvm_read((off_t)ifnet.if_name, name, 16); @@ -132,6 +150,7 @@ intpr(interval, ifnetaddr) ifaddraddr = (off_t)ifnet.if_addrlist; } printf("%-5.5s %-5d ", name, ifnet.if_mtu); + ifaddrfound = ifaddraddr; if (ifaddraddr == 0) { printf("%-11.11s ", "none"); printf("%-15.15s ", "none"); @@ -213,6 +232,75 @@ intpr(interval, ifnetaddr) if (dflag) printf(" %3d", ifnet.if_snd.ifq_drops); putchar('\n'); + + /*XXX this needs work for bsdi */ + if (aflag && ifaddrfound) { + /* + * print any internet multicast addresses + */ + switch (sa->sa_family) { + case AF_INET: + { + off_t multiaddr; + struct in_multi inm; + + multiaddr = (off_t)ifaddr.in.ia_multiaddrs; + while (multiaddr != 0) { + kvm_read(multiaddr, (char *)&inm, + sizeof inm); + multiaddr = (off_t)inm.inm_next; + printf("%23s %-19.19s\n", "", + routename(inm.inm_addr.s_addr)); + } + break; + } + default: + break; + } + } +#ifdef notyet + if (aflag && ifaddraddr == 0) { + /* + * print link-level addresses + * (Is there a better way to determine + * the type of network??) + */ + if (strncmp(name, "qe", 2) == 0 || /* Ethernet */ + strncmp(name, "de", 2) == 0 || + strncmp(name, "ex", 2) == 0 || + strncmp(name, "il", 2) == 0 || + strncmp(name, "le", 2) == 0 || + strncmp(name, "se", 2) == 0 || + strncmp(name, "ie", 2) == 0) { + strncmp(name, "we", 2) == 0) { + strncmp(name, "el", 2) == 0) { + /* "ec", the 3Com interface for Suns, is not */ + /* included, although it does handle multicast, */ + /* because it does not filter specific ethernet */ + /* multicast addresses, but just accepts all. */ + off_t multiaddr; + struct arpcom ac; + struct ether_multi enm; + + kvm_read(ifnetfound, (char *)&ac, sizeof ac); + printf("%23s %s\n", "", + etherprint(&ac.ac_enaddr)); + multiaddr = (off_t)ac.ac_multiaddrs; + while (multiaddr != 0) { + kvm_read(multiaddr, (char *)&enm, + sizeof enm); + multiaddr = (off_t)enm.enm_next; + printf("%23s %s", "", + etherprint(&enm.enm_addrlo)); + if (bcmp(&enm.enm_addrlo, + &enm.enm_addrhi, 6) != 0) + printf(" to %s", + etherprint(&enm.enm_addrhi)); + printf("\n"); + } + } + } +#endif } } diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index ed80baea14c5..cb7a29eeb1c5 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -34,7 +34,7 @@ #ifndef lint /* From: static char sccsid[] = "@(#)inet.c 5.15 (Berkeley) 6/18/90"; */ static const char inet_c_rcsid[] = - "$Id: inet.c,v 1.2 1993/11/17 20:19:20 wollman Exp $"; + "$Id: inet.c,v 1.3 1994/05/17 21:10:15 jkh Exp $"; #endif /* not lint */ @@ -51,6 +51,7 @@ static const char inet_c_rcsid[] = #include <netinet/in_pcb.h> #include <netinet/ip_icmp.h> #include <netinet/icmp_var.h> +#include <netinet/igmp_var.h> #include <netinet/ip_var.h> #include <netinet/tcp.h> #include <netinet/tcpip.h> @@ -342,6 +343,47 @@ icmp_stats(off, name) printf("\t%u message response%s generated\n", icmpstat.icps_reflect, plural(icmpstat.icps_reflect)); } + +char* +pluraly(n) +{ + return (n == 1? "y" : "ies"); +} + +/* + * Dump IGMP statistics. + */ +void +igmp_stats(off, name) + off_t off; + char *name; +{ + struct igmpstat igmpstat; + register int i, first; + + if (off == 0) + return; + kvm_read(off, (char *)&igmpstat, sizeof (igmpstat)); + printf("%s:\n", name ); + printf("\t%u message%s received\n", + igmpstat.igps_rcv_total, plural(igmpstat.igps_rcv_total)); + printf("\t%u message%s received with too few bytes\n", + igmpstat.igps_rcv_tooshort, plural(igmpstat.igps_rcv_tooshort)); + printf("\t%u message%s received with bad checksum\n", + igmpstat.igps_rcv_badsum, plural(igmpstat.igps_rcv_badsum)); + printf("\t%u membership quer%s received\n", + igmpstat.igps_rcv_queries, pluraly(igmpstat.igps_rcv_queries)); + printf("\t%u membership quer%s received with invalid field(s)\n", + igmpstat.igps_rcv_badqueries, pluraly(igmpstat.igps_rcv_badqueries)); + printf("\t%u membership report%s received\n", + igmpstat.igps_rcv_reports, plural(igmpstat.igps_rcv_reports)); + printf("\t%u membership report%s received with invalid field(s)\n", + igmpstat.igps_rcv_badreports, plural(igmpstat.igps_rcv_badreports)); + printf("\t%u membership report%s received for groups to which we belong\n", + igmpstat.igps_rcv_ourreports, plural(igmpstat.igps_rcv_ourreports)); + printf("\t%u membership report%s sent\n", + igmpstat.igps_snd_reports, plural(igmpstat.igps_snd_reports)); +} /* * Pretty print an Internet address (net address + port). diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c index 6809f4c0475c..09d984c8118b 100644 --- a/usr.bin/netstat/main.c +++ b/usr.bin/netstat/main.c @@ -40,7 +40,7 @@ char copyright[] = #ifndef lint /* From: static char sccsid[] = "@(#)main.c 5.23 (Berkeley) 7/1/91"; */ const char main_c_rcsid[] = - "$Id: main.c,v 1.2 1993/11/17 20:19:22 wollman Exp $"; + "$Id: main.c,v 1.5 1994/05/17 21:50:41 wollman Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -115,12 +115,23 @@ struct nlist nl[] = { { "_cltb"}, #define N_CLTPSTAT 28 { "_cltpstat"}, +#define N_IGMPSTAT 29 + { "_igmpstat" }, +#define N_MRTPROTO 30 + { "_ip_mrtproto" }, +#define N_MRTSTAT 31 + { "_mrtstat" }, +#define N_MRTTABLE 32 + { "_mrttable" }, +#define N_VIFTABLE 33 + { "_viftable" }, "", }; /* internet protocols */ extern int protopr(); extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats(); +extern int igmp_stats(); #ifdef NS /* ns protocols */ extern int nsprotopr(); @@ -152,6 +163,8 @@ struct protox { ip_stats, "ip" }, { -1, N_ICMPSTAT, 1, 0, icmp_stats, "icmp" }, + { -1, N_IGMPSTAT, 1, 0, + igmp_stats, "igmp"}, { -1, -1, 0, 0, 0, 0 } }; @@ -208,6 +221,7 @@ int mflag; int nflag; int pflag; int rflag; +int Rflag; /* Multicast routing stats */ int sflag; int tflag; int dflag; @@ -229,7 +243,7 @@ main(argc, argv) int ch; void usage(); - while ((ch = getopt(argc, argv, "Aadf:hI:iM:mN:np:rstuw")) != EOF) + while ((ch = getopt(argc, argv, "Aadf:ghI:iM:mN:np:rstuw:")) != EOF) switch((char)ch) { case 'A': Aflag = 1; @@ -295,6 +309,9 @@ main(argc, argv) case 'r': rflag = 1; break; + case 'g': + Rflag = 1; + break; case 's': sflag = 1; break; @@ -381,6 +398,16 @@ main(argc, argv) (off_t)nl[N_RTREE].n_value); exit(0); } + if (Rflag) { + if (sflag) + mrt_stats((off_t)nl[N_MRTPROTO].n_value, + (off_t)nl[N_MRTSTAT].n_value); + else + mroutepr((off_t)nl[N_MRTPROTO].n_value, + (off_t)nl[N_MRTTABLE].n_value, + (off_t)nl[N_VIFTABLE].n_value); + exit(0); + } if (af == AF_INET || af == AF_UNSPEC) { setprotoent(1); setservent(1); @@ -500,7 +527,7 @@ usage() (void)fprintf(stderr, "usage: netstat [-Aan] [-f address_family] [-M core] [-N system]\n"); (void)fprintf(stderr, -" [-himnrs] [-f address_family] [-M core] [-N system]\n"); +" [-himnrRs] [-f address_family] [-M core] [-N system]\n"); (void)fprintf(stderr, " [-n] [-I interface] [-M core] [-N system] [-w wait]\n"); (void)fprintf(stderr, diff --git a/usr.bin/netstat/mroute.c b/usr.bin/netstat/mroute.c new file mode 100644 index 000000000000..33a5d00f9f0f --- /dev/null +++ b/usr.bin/netstat/mroute.c @@ -0,0 +1,211 @@ +/* + * Print DVMRP multicast routing structures and statistics. + * + * MROUTING 1.0 + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/mbuf.h> +#include <netinet/in.h> +#include <netinet/igmp.h> +#define KERNEL 1 +#include <sys/socketvar.h> +#include <netinet/ip_mroute.h> +#undef KERNEL + +extern int kmem; +extern int nflag; +extern char *routename(); +extern char *netname(); +extern char *plural(); + +char *plurales(n) + int n; +{ + return (n == 1? "" : "es"); +} + +mroutepr(mrpaddr, mrtaddr, vifaddr) + off_t mrpaddr, mrtaddr, vifaddr; +{ + u_int mrtproto; +#if BSD >= 199006 + struct mrt *mrttable[MRTHASHSIZ]; + struct mrt *mp; + struct mrt mb; + struct mrt *mrt = &mb; +#else + struct mbuf *mrttable[MRTHASHSIZ]; + struct mbuf *mp; + struct mbuf mb; + struct mrt *mrt = mtod(&mb, struct mrt *); +#endif + struct vif viftable[MAXVIFS]; + register struct vif *v; + register vifi_t vifi; + struct in_addr *grp; + int i, n; + int banner_printed; + int saved_nflag; + + if(mrpaddr == 0) { + printf("ip_mrtproto: symbol not in namelist\n"); + return; + } + + kvm_read(mrpaddr, (char *)&mrtproto, sizeof(mrtproto)); + switch (mrtproto) { + case 0: + printf("no multicast routing compiled into this system\n"); + return; + + case IGMP_DVMRP: + break; + + default: + printf("multicast routing protocol %u, unknown\n", mrtproto); + return; + } + + if (mrtaddr == 0) { + printf("mrttable: symbol not in namelist\n"); + return; + } + if (vifaddr == 0) { + printf("viftable: symbol not in namelist\n"); + return; + } + + saved_nflag = nflag; + nflag = 1; + + kvm_read(vifaddr, (char *)viftable, sizeof(viftable)); + banner_printed = 0; + for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) { + struct in_addr v_lcl_grps[1024]; + + if (v->v_lcl_addr.s_addr == 0) continue; + + if (!banner_printed) { + printf("\nVirtual Interface Table\n%s%s", + " Vif Threshold Local-Address ", + "Remote-Address Groups\n"); + banner_printed = 1; + } + + printf(" %2u %3u %-15.15s", + vifi, v->v_threshold, routename(v->v_lcl_addr)); + printf(" %-15.15s\n", + (v->v_flags & VIFF_TUNNEL) ? + routename(v->v_rmt_addr) : ""); + + n = v->v_lcl_grps_n; + if (n == 0) + continue; + if (n < 0 || n > 1024) + printf("[v_lcl_grps_n = %d!]\n", n); + + kvm_read(v->v_lcl_grps, (char *)v_lcl_grps, + n * sizeof(struct in_addr)); + for (i = 0; i < n; ++i) + printf("%51s %-15.15s\n", "", + routename(v_lcl_grps[i])); + } + if (!banner_printed) printf("\nVirtual Interface Table is empty\n"); + + kvm_read(mrtaddr, (char *)mrttable, sizeof(mrttable)); + banner_printed = 0; + for (i = 0; i < MRTHASHSIZ; ++i) { + for (mp = mrttable[i]; mp != NULL; +#if BSD >= 199006 + mp = mb.mrt_next +#else + mp = mb.m_next +#endif + ) { + + if (!banner_printed) { + printf("\nMulticast Routing Table\n%s", + " Hash Origin-Subnet In-Vif Out-Vifs\n"); + banner_printed = 1; + } + kvm_read(mp, (char *)&mb, sizeof(mb)); + + + printf(" %3u %-15.15s %2u ", + i, + netname(mrt->mrt_origin.s_addr, + ntohl(mrt->mrt_originmask.s_addr)), + mrt->mrt_parent); + for (vifi = 0; vifi < MAXVIFS; ++vifi) { + if (viftable[vifi].v_lcl_addr.s_addr) { + if (VIFM_ISSET(vifi, mrt->mrt_children)) { + printf(" %u%c", + vifi, + VIFM_ISSET(vifi, + mrt->mrt_leaves) ? + '*' : ' '); + } else + printf(" "); + } + } + printf("\n"); + } + } + if (!banner_printed) printf("\nMulticast Routing Table is empty\n"); + + printf("\n"); + nflag = saved_nflag; +} + + +mrt_stats(mrpaddr, mstaddr) + off_t mrpaddr, mstaddr; +{ + u_int mrtproto; + struct mrtstat mrtstat; + + if(mrpaddr == 0) { + printf("ip_mrtproto: symbol not in namelist\n"); + return; + } + + kvm_read(mrpaddr, (char *)&mrtproto, sizeof(mrtproto)); + switch (mrtproto) { + case 0: + printf("no multicast routing compiled into this system\n"); + return; + + case IGMP_DVMRP: + break; + + default: + printf("multicast routing protocol %u, unknown\n", mrtproto); + return; + } + + if (mstaddr == 0) { + printf("mrtstat: symbol not in namelist\n"); + return; + } + + kvm_read(mstaddr, (char *)&mrtstat, sizeof(mrtstat)); + printf("multicast routing:\n"); + printf(" %10u multicast route lookup%s\n", + mrtstat.mrts_mrt_lookups, plural(mrtstat.mrts_mrt_lookups)); + printf(" %10u multicast route cache miss%s\n", + mrtstat.mrts_mrt_misses, plurales(mrtstat.mrts_mrt_misses)); + printf(" %10u group address lookup%s\n", + mrtstat.mrts_grp_lookups, plural(mrtstat.mrts_grp_lookups)); + printf(" %10u group address cache miss%s\n", + mrtstat.mrts_grp_misses, plurales(mrtstat.mrts_grp_misses)); + printf(" %10u datagram%s with no route for origin\n", + mrtstat.mrts_no_route, plural(mrtstat.mrts_no_route)); + printf(" %10u datagram%s with malformed tunnel options\n", + mrtstat.mrts_bad_tunnel, plural(mrtstat.mrts_bad_tunnel)); + printf(" %10u datagram%s with no room for tunnel options\n", + mrtstat.mrts_cant_tunnel, plural(mrtstat.mrts_cant_tunnel)); + printf(" %10u datagram%s arrived on wrong interface\n", + mrtstat.mrts_wrong_if, plural(mrtstat.mrts_wrong_if)); +} diff --git a/usr.bin/netstat/netstat.1 b/usr.bin/netstat/netstat.1 index 25c3943ac35b..62c553a75583 100644 --- a/usr.bin/netstat/netstat.1 +++ b/usr.bin/netstat/netstat.1 @@ -44,7 +44,7 @@ .Op Ar system .Op Ar core .Nm netstat -.Op Fl himnrs +.Op Fl himnrRs .Op Fl f Ar address_family .Op Fl M Ar core .Op Fl N Ar system @@ -92,6 +92,10 @@ With either interface display (option .Fl i or an interval, as described below), show the number of dropped packets. +.It Fl g +Show multicast routing statistics. When +.Fl s +is also present, show multicast routing statistics instead. .It Fl h Show the state of the .Tn IMP |
