19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1983, 1988, 1993 39b50d902SRodney W. Grimes * Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 139b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 149b50d902SRodney W. Grimes * must display the following acknowledgement: 159b50d902SRodney W. Grimes * This product includes software developed by the University of 169b50d902SRodney W. Grimes * California, Berkeley and its contributors. 179b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 189b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 199b50d902SRodney W. Grimes * without specific prior written permission. 209b50d902SRodney W. Grimes * 219b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 229b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 259b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319b50d902SRodney W. Grimes * SUCH DAMAGE. 329b50d902SRodney W. Grimes */ 339b50d902SRodney W. Grimes 349b50d902SRodney W. Grimes #ifndef lint 355d422d6aSPhilippe Charnier char const copyright[] = 369b50d902SRodney W. Grimes "@(#) Copyright (c) 1983, 1988, 1993\n\ 379b50d902SRodney W. Grimes Regents of the University of California. All rights reserved.\n"; 389b50d902SRodney W. Grimes #endif /* not lint */ 399b50d902SRodney W. Grimes 409b50d902SRodney W. Grimes #ifndef lint 415d422d6aSPhilippe Charnier #if 0 429b50d902SRodney W. Grimes static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94"; 435d422d6aSPhilippe Charnier #endif 445d422d6aSPhilippe Charnier static const char rcsid[] = 45c3aac50fSPeter Wemm "$FreeBSD$"; 469b50d902SRodney W. Grimes #endif /* not lint */ 479b50d902SRodney W. Grimes 489b50d902SRodney W. Grimes #include <sys/param.h> 499b50d902SRodney W. Grimes #include <sys/file.h> 509b50d902SRodney W. Grimes #include <sys/protosw.h> 519b50d902SRodney W. Grimes #include <sys/socket.h> 529b50d902SRodney W. Grimes 539b50d902SRodney W. Grimes #include <netinet/in.h> 549b50d902SRodney W. Grimes 554cf49a43SJulian Elischer #include <netgraph/ng_socket.h> 564cf49a43SJulian Elischer 579b50d902SRodney W. Grimes #include <ctype.h> 585d422d6aSPhilippe Charnier #include <err.h> 599b50d902SRodney W. Grimes #include <errno.h> 609b50d902SRodney W. Grimes #include <kvm.h> 619b50d902SRodney W. Grimes #include <limits.h> 629b50d902SRodney W. Grimes #include <netdb.h> 639b50d902SRodney W. Grimes #include <nlist.h> 649b50d902SRodney W. Grimes #include <paths.h> 659b50d902SRodney W. Grimes #include <stdio.h> 669b50d902SRodney W. Grimes #include <stdlib.h> 679b50d902SRodney W. Grimes #include <string.h> 689b50d902SRodney W. Grimes #include <unistd.h> 699b50d902SRodney W. Grimes #include "netstat.h" 709b50d902SRodney W. Grimes 71c6620a13SPoul-Henning Kamp static struct nlist nl[] = { 724f81ef50SGarrett Wollman #define N_IFNET 0 739b50d902SRodney W. Grimes { "_ifnet" }, 74ab54ea99SPeter Wemm #define N_RTSTAT 1 759b50d902SRodney W. Grimes { "_rtstat" }, 76ab54ea99SPeter Wemm #define N_RTREE 2 779b50d902SRodney W. Grimes { "_rt_tables"}, 78ab54ea99SPeter Wemm #define N_MRTSTAT 3 799b50d902SRodney W. Grimes { "_mrtstat" }, 80ab54ea99SPeter Wemm #define N_MFCTABLE 4 81ef105c25SGarrett Wollman { "_mfctable" }, 82ab54ea99SPeter Wemm #define N_VIFTABLE 5 839b50d902SRodney W. Grimes { "_viftable" }, 84ab54ea99SPeter Wemm #define N_IPX 6 85cc6a66f2SJulian Elischer { "_ipxpcb"}, 86ab54ea99SPeter Wemm #define N_IPXSTAT 7 87cc6a66f2SJulian Elischer { "_ipxstat"}, 88ab54ea99SPeter Wemm #define N_SPXSTAT 8 89cc6a66f2SJulian Elischer { "_spx_istat"}, 90ab54ea99SPeter Wemm #define N_DDPSTAT 9 9163bf4575SJulian Elischer { "_ddpstat"}, 92ab54ea99SPeter Wemm #define N_DDPCB 10 9363bf4575SJulian Elischer { "_ddpcb"}, 94ab54ea99SPeter Wemm #define N_NGSOCKS 11 954cf49a43SJulian Elischer { "_ngsocklist"}, 96ab54ea99SPeter Wemm #define N_IP6STAT 12 97cfa1ca9dSYoshinobu Inoue { "_ip6stat" }, 98ab54ea99SPeter Wemm #define N_ICMP6STAT 13 99cfa1ca9dSYoshinobu Inoue { "_icmp6stat" }, 100ab54ea99SPeter Wemm #define N_IPSECSTAT 14 101cfa1ca9dSYoshinobu Inoue { "_ipsecstat" }, 102ab54ea99SPeter Wemm #define N_IPSEC6STAT 15 103cfa1ca9dSYoshinobu Inoue { "_ipsec6stat" }, 104ab54ea99SPeter Wemm #define N_PIM6STAT 16 105cfa1ca9dSYoshinobu Inoue { "_pim6stat" }, 106ab54ea99SPeter Wemm #define N_MRT6STAT 17 107cfa1ca9dSYoshinobu Inoue { "_mrt6stat" }, 108ab54ea99SPeter Wemm #define N_MF6CTABLE 18 109cfa1ca9dSYoshinobu Inoue { "_mf6ctable" }, 110ab54ea99SPeter Wemm #define N_MIF6TABLE 19 111cfa1ca9dSYoshinobu Inoue { "_mif6table" }, 112ab54ea99SPeter Wemm #define N_PFKEYSTAT 20 1133b8a8567SJun-ichiro itojun Hagino { "_pfkeystat" }, 114ab54ea99SPeter Wemm #define N_MBSTAT 21 115d15c5f56SRuslan Ermilov { "_mbstat" }, 116ab54ea99SPeter Wemm #define N_MBTYPES 22 117d15c5f56SRuslan Ermilov { "_mbtypes" }, 118ab54ea99SPeter Wemm #define N_NMBCLUSTERS 23 119d15c5f56SRuslan Ermilov { "_nmbclusters" }, 120ab54ea99SPeter Wemm #define N_NMBUFS 24 121d15c5f56SRuslan Ermilov { "_nmbufs" }, 122ab54ea99SPeter Wemm #define N_MBHI 25 123025b4be1SBosko Milekic { "_mbuf_hiwm" }, 124ab54ea99SPeter Wemm #define N_CLHI 26 125025b4be1SBosko Milekic { "_clust_hiwm" }, 126ab54ea99SPeter Wemm #define N_NCPUS 27 12708442f8aSBosko Milekic { "_smp_cpus" }, 128ab54ea99SPeter Wemm #define N_PAGESZ 28 12908442f8aSBosko Milekic { "_pagesize" }, 130ab54ea99SPeter Wemm #define N_MBPSTAT 29 13108442f8aSBosko Milekic { "_mb_statpcpu" }, 132ab54ea99SPeter Wemm #define N_RTTRASH 30 1331093cc31SRuslan Ermilov { "_rttrash" }, 134ab54ea99SPeter Wemm #define N_MBLO 31 135025b4be1SBosko Milekic { "_mbuf_lowm" }, 136ab54ea99SPeter Wemm #define N_CLLO 32 137025b4be1SBosko Milekic { "_clust_lowm" }, 1387d56c0eeSAlexander Langer { "" }, 1399b50d902SRodney W. Grimes }; 1409b50d902SRodney W. Grimes 1419b50d902SRodney W. Grimes struct protox { 1429b50d902SRodney W. Grimes u_char pr_index; /* index into nlist of cb head */ 1439b50d902SRodney W. Grimes u_char pr_sindex; /* index into nlist of stat block */ 1449b50d902SRodney W. Grimes u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 145a01e3379SDavid Malone void (*pr_cblocks)(u_long, const char *, int); 1465e051718SAssar Westerlund /* control blocks printing routine */ 147a01e3379SDavid Malone void (*pr_stats)(u_long, const char *, int); 1485e051718SAssar Westerlund /* statistics printing routine */ 1495e051718SAssar Westerlund void (*pr_istats)(char *); /* per/if statistics printing routine */ 150fa6d48c0SMark Murray const char *pr_name; /* well-known name */ 1516bb3f207SRuslan Ermilov u_long pr_usesysctl; /* non-zero if we use sysctl, not kvm */ 1529b50d902SRodney W. Grimes } protox[] = { 1534f81ef50SGarrett Wollman { -1, -1, 1, protopr, 154cfa1ca9dSYoshinobu Inoue tcp_stats, NULL, "tcp", IPPROTO_TCP }, 1554f81ef50SGarrett Wollman { -1, -1, 1, protopr, 156cfa1ca9dSYoshinobu Inoue udp_stats, NULL, "udp", IPPROTO_UDP }, 1574f81ef50SGarrett Wollman { -1, -1, 1, protopr, 158cfa1ca9dSYoshinobu Inoue NULL, NULL, "divert",IPPROTO_DIVERT }, 1594f81ef50SGarrett Wollman { -1, -1, 1, protopr, 160cfa1ca9dSYoshinobu Inoue ip_stats, NULL, "ip", IPPROTO_RAW }, 1614f81ef50SGarrett Wollman { -1, -1, 1, protopr, 162cfa1ca9dSYoshinobu Inoue icmp_stats, NULL, "icmp", IPPROTO_ICMP }, 1634f81ef50SGarrett Wollman { -1, -1, 1, protopr, 164cfa1ca9dSYoshinobu Inoue igmp_stats, NULL, "igmp", IPPROTO_IGMP }, 165cfa1ca9dSYoshinobu Inoue #ifdef IPSEC 1666bb3f207SRuslan Ermilov { -1, N_IPSECSTAT, 1, NULL, 167cfa1ca9dSYoshinobu Inoue ipsec_stats, NULL, "ipsec", 0}, 168cfa1ca9dSYoshinobu Inoue #endif 1696bb3f207SRuslan Ermilov { -1, -1, 1, NULL, 170cfa1ca9dSYoshinobu Inoue bdg_stats, NULL, "bdg", 1 /* bridging... */ }, 171c7b9b5bbSJeffrey Hsu { -1, -1, 1, protopr, 172c7b9b5bbSJeffrey Hsu pim_stats, NULL, "pim", IPPROTO_PIM }, 1736bb3f207SRuslan Ermilov { -1, -1, 0, NULL, 1746bb3f207SRuslan Ermilov NULL, NULL, NULL, 0 } 1759b50d902SRodney W. Grimes }; 1769b50d902SRodney W. Grimes 177cfa1ca9dSYoshinobu Inoue #ifdef INET6 178cfa1ca9dSYoshinobu Inoue struct protox ip6protox[] = { 179cfa1ca9dSYoshinobu Inoue { -1, -1, 1, protopr, 180cfa1ca9dSYoshinobu Inoue tcp_stats, NULL, "tcp", IPPROTO_TCP }, 181cfa1ca9dSYoshinobu Inoue { -1, -1, 1, protopr, 182cfa1ca9dSYoshinobu Inoue udp_stats, NULL, "udp", IPPROTO_UDP }, 183785d213dSHajimu UMEMOTO { -1, N_IP6STAT, 1, protopr, 184785d213dSHajimu UMEMOTO ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW }, 185785d213dSHajimu UMEMOTO { -1, N_ICMP6STAT, 1, protopr, 186785d213dSHajimu UMEMOTO icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 }, 187cfa1ca9dSYoshinobu Inoue #ifdef IPSEC 1886bb3f207SRuslan Ermilov { -1, N_IPSEC6STAT, 1, NULL, 189cfa1ca9dSYoshinobu Inoue ipsec_stats, NULL, "ipsec6",0 }, 190cfa1ca9dSYoshinobu Inoue #endif 191cfa1ca9dSYoshinobu Inoue #ifdef notyet 1926bb3f207SRuslan Ermilov { -1, N_PIM6STAT, 1, NULL, 193cfa1ca9dSYoshinobu Inoue pim6_stats, NULL, "pim6", 0 }, 194cfa1ca9dSYoshinobu Inoue #endif 1956bb3f207SRuslan Ermilov { -1, -1, 1, NULL, 19633841545SHajimu UMEMOTO rip6_stats, NULL, "rip6", 0 }, 1976bb3f207SRuslan Ermilov { -1, -1, 1, NULL, 198cfa1ca9dSYoshinobu Inoue bdg_stats, NULL, "bdg", 1 /* bridging... */ }, 1996bb3f207SRuslan Ermilov { -1, -1, 0, NULL, 2006bb3f207SRuslan Ermilov NULL, NULL, NULL, 0 } 201cfa1ca9dSYoshinobu Inoue }; 202cfa1ca9dSYoshinobu Inoue #endif /*INET6*/ 203cfa1ca9dSYoshinobu Inoue 2043b8a8567SJun-ichiro itojun Hagino #ifdef IPSEC 2053b8a8567SJun-ichiro itojun Hagino struct protox pfkeyprotox[] = { 2066bb3f207SRuslan Ermilov { -1, N_PFKEYSTAT, 1, NULL, 2073b8a8567SJun-ichiro itojun Hagino pfkey_stats, NULL, "pfkey", 0 }, 2086bb3f207SRuslan Ermilov { -1, -1, 0, NULL, 2096bb3f207SRuslan Ermilov NULL, NULL, NULL, 0 } 2103b8a8567SJun-ichiro itojun Hagino }; 2113b8a8567SJun-ichiro itojun Hagino #endif 2123b8a8567SJun-ichiro itojun Hagino 21363bf4575SJulian Elischer struct protox atalkprotox[] = { 21463bf4575SJulian Elischer { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, 215a01e3379SDavid Malone ddp_stats, NULL, "ddp", 0 }, 2166bb3f207SRuslan Ermilov { -1, -1, 0, NULL, 2176bb3f207SRuslan Ermilov NULL, NULL, NULL, 0 } 21863bf4575SJulian Elischer }; 21963bf4575SJulian Elischer 2204cf49a43SJulian Elischer struct protox netgraphprotox[] = { 2214cf49a43SJulian Elischer { N_NGSOCKS, -1, 1, netgraphprotopr, 222a01e3379SDavid Malone NULL, NULL, "ctrl", 0 }, 2234cf49a43SJulian Elischer { N_NGSOCKS, -1, 1, netgraphprotopr, 224a01e3379SDavid Malone NULL, NULL, "data", 0 }, 2256bb3f207SRuslan Ermilov { -1, -1, 0, NULL, 2266bb3f207SRuslan Ermilov NULL, NULL, NULL, 0 } 2274cf49a43SJulian Elischer }; 2284cf49a43SJulian Elischer 229cc6a66f2SJulian Elischer struct protox ipxprotox[] = { 230cc6a66f2SJulian Elischer { N_IPX, N_IPXSTAT, 1, ipxprotopr, 231cfa1ca9dSYoshinobu Inoue ipx_stats, NULL, "ipx", 0 }, 232cc6a66f2SJulian Elischer { N_IPX, N_SPXSTAT, 1, ipxprotopr, 233cfa1ca9dSYoshinobu Inoue spx_stats, NULL, "spx", 0 }, 2346bb3f207SRuslan Ermilov { -1, -1, 0, NULL, 2356bb3f207SRuslan Ermilov NULL, NULL, 0, 0 } 236cc6a66f2SJulian Elischer }; 237cc6a66f2SJulian Elischer 238cfa1ca9dSYoshinobu Inoue struct protox *protoprotox[] = { 239cfa1ca9dSYoshinobu Inoue protox, 240cfa1ca9dSYoshinobu Inoue #ifdef INET6 241cfa1ca9dSYoshinobu Inoue ip6protox, 242cfa1ca9dSYoshinobu Inoue #endif 2433b8a8567SJun-ichiro itojun Hagino #ifdef IPSEC 2443b8a8567SJun-ichiro itojun Hagino pfkeyprotox, 2453b8a8567SJun-ichiro itojun Hagino #endif 246ab54ea99SPeter Wemm ipxprotox, atalkprotox, NULL }; 2479b50d902SRodney W. Grimes 248fa6d48c0SMark Murray static void printproto (struct protox *, const char *); 2495e051718SAssar Westerlund static void usage (void); 2505e051718SAssar Westerlund static struct protox *name2protox (char *); 2515e051718SAssar Westerlund static struct protox *knownname (char *); 2529b50d902SRodney W. Grimes 253c6620a13SPoul-Henning Kamp static kvm_t *kvmd; 254080b7f49SDag-Erling Smørgrav static char *nlistf = NULL, *memf = NULL; 255080b7f49SDag-Erling Smørgrav 256080b7f49SDag-Erling Smørgrav int Aflag; /* show addresses of protocol control block */ 257080b7f49SDag-Erling Smørgrav int aflag; /* show all sockets (including servers) */ 258080b7f49SDag-Erling Smørgrav int bflag; /* show i/f total bytes in/out */ 259dbe0253aSAlfred Perlstein int cflag; /* show mbuf cache information */ 260080b7f49SDag-Erling Smørgrav int dflag; /* show i/f dropped packets */ 261080b7f49SDag-Erling Smørgrav int gflag; /* show group (multicast) routing or stats */ 262080b7f49SDag-Erling Smørgrav int iflag; /* show interfaces */ 263080b7f49SDag-Erling Smørgrav int Lflag; /* show size of listen queues */ 264080b7f49SDag-Erling Smørgrav int mflag; /* show memory stats */ 26565ea0024SAssar Westerlund int numeric_addr; /* show addresses numerically */ 26665ea0024SAssar Westerlund int numeric_port; /* show ports numerically */ 267cf5e44f8SRuslan Ermilov static int pflag; /* show given protocol */ 268080b7f49SDag-Erling Smørgrav int rflag; /* show routing tables (or routing stats) */ 269080b7f49SDag-Erling Smørgrav int sflag; /* show protocol statistics */ 270080b7f49SDag-Erling Smørgrav int tflag; /* show i/f watchdog timers */ 271080b7f49SDag-Erling Smørgrav int Wflag; /* wide display */ 272c73d99b5SRuslan Ermilov int zflag; /* zero stats */ 273080b7f49SDag-Erling Smørgrav 274080b7f49SDag-Erling Smørgrav int interval; /* repeat interval for i/f stats */ 275080b7f49SDag-Erling Smørgrav 276080b7f49SDag-Erling Smørgrav char *interface; /* desired i/f for stats, or NULL for all i/fs */ 277080b7f49SDag-Erling Smørgrav int unit; /* unit number for above */ 278080b7f49SDag-Erling Smørgrav 279080b7f49SDag-Erling Smørgrav int af; /* address family */ 2809b50d902SRodney W. Grimes 2819b50d902SRodney W. Grimes int 282a01e3379SDavid Malone main(int argc, char *argv[]) 2839b50d902SRodney W. Grimes { 284a01e3379SDavid Malone struct protox *tp = NULL; /* for printing cblocks & stats */ 2859b50d902SRodney W. Grimes int ch; 2869b50d902SRodney W. Grimes 2879b50d902SRodney W. Grimes af = AF_UNSPEC; 2889b50d902SRodney W. Grimes 289dbe0253aSAlfred Perlstein while ((ch = getopt(argc, argv, "Aabcdf:gI:iLlM:mN:np:rSstuWw:z")) != -1) 2909b50d902SRodney W. Grimes switch(ch) { 2919b50d902SRodney W. Grimes case 'A': 2929b50d902SRodney W. Grimes Aflag = 1; 2939b50d902SRodney W. Grimes break; 2949b50d902SRodney W. Grimes case 'a': 2959b50d902SRodney W. Grimes aflag = 1; 2969b50d902SRodney W. Grimes break; 297e1e293a5SDavid Greenman case 'b': 298e1e293a5SDavid Greenman bflag = 1; 299e1e293a5SDavid Greenman break; 300dbe0253aSAlfred Perlstein case 'c': 301dbe0253aSAlfred Perlstein cflag = 1; 302dbe0253aSAlfred Perlstein break; 3039b50d902SRodney W. Grimes case 'd': 3049b50d902SRodney W. Grimes dflag = 1; 3059b50d902SRodney W. Grimes break; 3069b50d902SRodney W. Grimes case 'f': 307cbc17e71SGarrett Wollman if (strcmp(optarg, "ipx") == 0) 308cc6a66f2SJulian Elischer af = AF_IPX; 3099b50d902SRodney W. Grimes else if (strcmp(optarg, "inet") == 0) 3109b50d902SRodney W. Grimes af = AF_INET; 311cfa1ca9dSYoshinobu Inoue #ifdef INET6 312cfa1ca9dSYoshinobu Inoue else if (strcmp(optarg, "inet6") == 0) 313cfa1ca9dSYoshinobu Inoue af = AF_INET6; 314cfa1ca9dSYoshinobu Inoue #endif /*INET6*/ 3153b8a8567SJun-ichiro itojun Hagino #ifdef INET6 3163b8a8567SJun-ichiro itojun Hagino else if (strcmp(optarg, "pfkey") == 0) 3173b8a8567SJun-ichiro itojun Hagino af = PF_KEY; 3183b8a8567SJun-ichiro itojun Hagino #endif /*INET6*/ 3199b50d902SRodney W. Grimes else if (strcmp(optarg, "unix") == 0) 3209b50d902SRodney W. Grimes af = AF_UNIX; 32163bf4575SJulian Elischer else if (strcmp(optarg, "atalk") == 0) 32263bf4575SJulian Elischer af = AF_APPLETALK; 3234cf49a43SJulian Elischer else if (strcmp(optarg, "ng") == 0 3244cf49a43SJulian Elischer || strcmp(optarg, "netgraph") == 0) 3254cf49a43SJulian Elischer af = AF_NETGRAPH; 326d44ddba9SRuslan Ermilov else if (strcmp(optarg, "link") == 0) 327d44ddba9SRuslan Ermilov af = AF_LINK; 3289b50d902SRodney W. Grimes else { 32951e7d42cSGarrett Wollman errx(1, "%s: unknown address family", optarg); 3309b50d902SRodney W. Grimes } 3319b50d902SRodney W. Grimes break; 3329b50d902SRodney W. Grimes case 'g': 3339b50d902SRodney W. Grimes gflag = 1; 3349b50d902SRodney W. Grimes break; 3359b50d902SRodney W. Grimes case 'I': { 3369b50d902SRodney W. Grimes char *cp; 3379b50d902SRodney W. Grimes 3389b50d902SRodney W. Grimes iflag = 1; 3399b50d902SRodney W. Grimes for (cp = interface = optarg; isalpha(*cp); cp++) 3409b50d902SRodney W. Grimes continue; 3419b50d902SRodney W. Grimes unit = atoi(cp); 3429b50d902SRodney W. Grimes break; 3439b50d902SRodney W. Grimes } 3449b50d902SRodney W. Grimes case 'i': 3459b50d902SRodney W. Grimes iflag = 1; 3469b50d902SRodney W. Grimes break; 347ac55add0SGuido van Rooij case 'L': 348ac55add0SGuido van Rooij Lflag = 1; 349ac55add0SGuido van Rooij break; 3509b50d902SRodney W. Grimes case 'M': 3519b50d902SRodney W. Grimes memf = optarg; 3529b50d902SRodney W. Grimes break; 3539b50d902SRodney W. Grimes case 'm': 3549b50d902SRodney W. Grimes mflag = 1; 3559b50d902SRodney W. Grimes break; 3569b50d902SRodney W. Grimes case 'N': 3579b50d902SRodney W. Grimes nlistf = optarg; 3589b50d902SRodney W. Grimes break; 3599b50d902SRodney W. Grimes case 'n': 36065ea0024SAssar Westerlund numeric_addr = numeric_port = 1; 3619b50d902SRodney W. Grimes break; 3629b50d902SRodney W. Grimes case 'p': 3639b50d902SRodney W. Grimes if ((tp = name2protox(optarg)) == NULL) { 36451e7d42cSGarrett Wollman errx(1, 36551e7d42cSGarrett Wollman "%s: unknown or uninstrumented protocol", 36651e7d42cSGarrett Wollman optarg); 3679b50d902SRodney W. Grimes } 3689b50d902SRodney W. Grimes pflag = 1; 3699b50d902SRodney W. Grimes break; 3709b50d902SRodney W. Grimes case 'r': 3719b50d902SRodney W. Grimes rflag = 1; 3729b50d902SRodney W. Grimes break; 3739b50d902SRodney W. Grimes case 's': 3749b50d902SRodney W. Grimes ++sflag; 3759b50d902SRodney W. Grimes break; 37665ea0024SAssar Westerlund case 'S': 37765ea0024SAssar Westerlund numeric_addr = 1; 37865ea0024SAssar Westerlund break; 3799b50d902SRodney W. Grimes case 't': 3809b50d902SRodney W. Grimes tflag = 1; 3819b50d902SRodney W. Grimes break; 3829b50d902SRodney W. Grimes case 'u': 3839b50d902SRodney W. Grimes af = AF_UNIX; 3849b50d902SRodney W. Grimes break; 385080b7f49SDag-Erling Smørgrav case 'W': 38670057abfSRuslan Ermilov case 'l': 387080b7f49SDag-Erling Smørgrav Wflag = 1; 388080b7f49SDag-Erling Smørgrav break; 3899b50d902SRodney W. Grimes case 'w': 3909b50d902SRodney W. Grimes interval = atoi(optarg); 3919b50d902SRodney W. Grimes iflag = 1; 3929b50d902SRodney W. Grimes break; 393c73d99b5SRuslan Ermilov case 'z': 394c73d99b5SRuslan Ermilov zflag = 1; 395c73d99b5SRuslan Ermilov break; 3969b50d902SRodney W. Grimes case '?': 3979b50d902SRodney W. Grimes default: 3989b50d902SRodney W. Grimes usage(); 3999b50d902SRodney W. Grimes } 4009b50d902SRodney W. Grimes argv += optind; 4019b50d902SRodney W. Grimes argc -= optind; 4029b50d902SRodney W. Grimes 4039b50d902SRodney W. Grimes #define BACKWARD_COMPATIBILITY 4049b50d902SRodney W. Grimes #ifdef BACKWARD_COMPATIBILITY 4059b50d902SRodney W. Grimes if (*argv) { 4069b50d902SRodney W. Grimes if (isdigit(**argv)) { 4079b50d902SRodney W. Grimes interval = atoi(*argv); 4089b50d902SRodney W. Grimes if (interval <= 0) 4099b50d902SRodney W. Grimes usage(); 4109b50d902SRodney W. Grimes ++argv; 4119b50d902SRodney W. Grimes iflag = 1; 4129b50d902SRodney W. Grimes } 4139b50d902SRodney W. Grimes if (*argv) { 4149b50d902SRodney W. Grimes nlistf = *argv; 4159b50d902SRodney W. Grimes if (*++argv) 4169b50d902SRodney W. Grimes memf = *argv; 4179b50d902SRodney W. Grimes } 4189b50d902SRodney W. Grimes } 4199b50d902SRodney W. Grimes #endif 4209b50d902SRodney W. Grimes 4219b50d902SRodney W. Grimes /* 4229b50d902SRodney W. Grimes * Discard setgid privileges if not the running kernel so that bad 4239b50d902SRodney W. Grimes * guys can't print interesting stuff from kernel memory. 4249b50d902SRodney W. Grimes */ 4259b50d902SRodney W. Grimes if (nlistf != NULL || memf != NULL) 4269b50d902SRodney W. Grimes setgid(getgid()); 4279b50d902SRodney W. Grimes 428dbe0253aSAlfred Perlstein if (cflag && !mflag) { 429dbe0253aSAlfred Perlstein (void)fprintf(stderr, "-c only valid with -m\n"); 430dbe0253aSAlfred Perlstein usage(); 431dbe0253aSAlfred Perlstein } 4329b50d902SRodney W. Grimes if (mflag) { 433d15c5f56SRuslan Ermilov if (memf != NULL) { 434d15c5f56SRuslan Ermilov if (kread(0, 0, 0) == 0) 435d15c5f56SRuslan Ermilov mbpr(nl[N_MBSTAT].n_value, 436d15c5f56SRuslan Ermilov nl[N_MBTYPES].n_value, 437d15c5f56SRuslan Ermilov nl[N_NMBCLUSTERS].n_value, 43808442f8aSBosko Milekic nl[N_NMBUFS].n_value, 439025b4be1SBosko Milekic nl[N_MBHI].n_value, 440025b4be1SBosko Milekic nl[N_CLHI].n_value, 441025b4be1SBosko Milekic nl[N_MBLO].n_value, 442025b4be1SBosko Milekic nl[N_CLLO].n_value, 44308442f8aSBosko Milekic nl[N_NCPUS].n_value, 44408442f8aSBosko Milekic nl[N_PAGESZ].n_value, 44508442f8aSBosko Milekic nl[N_MBPSTAT].n_value); 446d15c5f56SRuslan Ermilov } else 447025b4be1SBosko Milekic mbpr(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 4489b50d902SRodney W. Grimes exit(0); 4499b50d902SRodney W. Grimes } 450cc63cd56SPeter Wemm #if 0 4519b50d902SRodney W. Grimes /* 4529b50d902SRodney W. Grimes * Keep file descriptors open to avoid overhead 4539b50d902SRodney W. Grimes * of open/close on each call to get* routines. 4549b50d902SRodney W. Grimes */ 4559b50d902SRodney W. Grimes sethostent(1); 4569b50d902SRodney W. Grimes setnetent(1); 457cc63cd56SPeter Wemm #else 458cc63cd56SPeter Wemm /* 459cc63cd56SPeter Wemm * This does not make sense any more with DNS being default over 460cc63cd56SPeter Wemm * the files. Doing a setXXXXent(1) causes a tcp connection to be 461cc63cd56SPeter Wemm * used for the queries, which is slower. 462cc63cd56SPeter Wemm */ 463cc63cd56SPeter Wemm #endif 464cf5e44f8SRuslan Ermilov if (iflag && !sflag) { 465c6620a13SPoul-Henning Kamp kread(0, 0, 0); 466cfa1ca9dSYoshinobu Inoue intpr(interval, nl[N_IFNET].n_value, NULL); 4679b50d902SRodney W. Grimes exit(0); 4689b50d902SRodney W. Grimes } 4699b50d902SRodney W. Grimes if (rflag) { 470c6620a13SPoul-Henning Kamp kread(0, 0, 0); 4719b50d902SRodney W. Grimes if (sflag) 4721093cc31SRuslan Ermilov rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value); 4739b50d902SRodney W. Grimes else 4749b50d902SRodney W. Grimes routepr(nl[N_RTREE].n_value); 4759b50d902SRodney W. Grimes exit(0); 4769b50d902SRodney W. Grimes } 4779b50d902SRodney W. Grimes if (gflag) { 478c6620a13SPoul-Henning Kamp kread(0, 0, 0); 479cfa1ca9dSYoshinobu Inoue if (sflag) { 480cfa1ca9dSYoshinobu Inoue if (af == AF_INET || af == AF_UNSPEC) 48167a451ccSBill Fenner mrt_stats(nl[N_MRTSTAT].n_value); 482cfa1ca9dSYoshinobu Inoue #ifdef INET6 483cfa1ca9dSYoshinobu Inoue if (af == AF_INET6 || af == AF_UNSPEC) 484cfa1ca9dSYoshinobu Inoue mrt6_stats(nl[N_MRT6STAT].n_value); 485cfa1ca9dSYoshinobu Inoue #endif 486cfa1ca9dSYoshinobu Inoue } else { 487cfa1ca9dSYoshinobu Inoue if (af == AF_INET || af == AF_UNSPEC) 48867a451ccSBill Fenner mroutepr(nl[N_MFCTABLE].n_value, 4899b50d902SRodney W. Grimes nl[N_VIFTABLE].n_value); 490cfa1ca9dSYoshinobu Inoue #ifdef INET6 491cfa1ca9dSYoshinobu Inoue if (af == AF_INET6 || af == AF_UNSPEC) 492cfa1ca9dSYoshinobu Inoue mroute6pr(nl[N_MF6CTABLE].n_value, 493cfa1ca9dSYoshinobu Inoue nl[N_MIF6TABLE].n_value); 494cfa1ca9dSYoshinobu Inoue #endif 495cfa1ca9dSYoshinobu Inoue } 4969b50d902SRodney W. Grimes exit(0); 4979b50d902SRodney W. Grimes } 498cfa1ca9dSYoshinobu Inoue 499cfa1ca9dSYoshinobu Inoue kread(0, 0, 0); 500cf5e44f8SRuslan Ermilov if (tp) { 501cf5e44f8SRuslan Ermilov printproto(tp, tp->pr_name); 502cf5e44f8SRuslan Ermilov exit(0); 503cf5e44f8SRuslan Ermilov } 504cfa1ca9dSYoshinobu Inoue if (af == AF_INET || af == AF_UNSPEC) 5059b50d902SRodney W. Grimes for (tp = protox; tp->pr_name; tp++) 506cfa1ca9dSYoshinobu Inoue printproto(tp, tp->pr_name); 507cfa1ca9dSYoshinobu Inoue #ifdef INET6 508cfa1ca9dSYoshinobu Inoue if (af == AF_INET6 || af == AF_UNSPEC) 509cfa1ca9dSYoshinobu Inoue for (tp = ip6protox; tp->pr_name; tp++) 510cfa1ca9dSYoshinobu Inoue printproto(tp, tp->pr_name); 511cfa1ca9dSYoshinobu Inoue #endif /*INET6*/ 5123b8a8567SJun-ichiro itojun Hagino #ifdef IPSEC 5133b8a8567SJun-ichiro itojun Hagino if (af == PF_KEY || af == AF_UNSPEC) 5143b8a8567SJun-ichiro itojun Hagino for (tp = pfkeyprotox; tp->pr_name; tp++) 5153b8a8567SJun-ichiro itojun Hagino printproto(tp, tp->pr_name); 5163b8a8567SJun-ichiro itojun Hagino #endif /*IPSEC*/ 517e30e913cSJohn Hay if (af == AF_IPX || af == AF_UNSPEC) { 518e30e913cSJohn Hay kread(0, 0, 0); 519cc6a66f2SJulian Elischer for (tp = ipxprotox; tp->pr_name; tp++) 520cc6a66f2SJulian Elischer printproto(tp, tp->pr_name); 521e30e913cSJohn Hay } 52263bf4575SJulian Elischer if (af == AF_APPLETALK || af == AF_UNSPEC) 52363bf4575SJulian Elischer for (tp = atalkprotox; tp->pr_name; tp++) 52463bf4575SJulian Elischer printproto(tp, tp->pr_name); 5254cf49a43SJulian Elischer if (af == AF_NETGRAPH || af == AF_UNSPEC) 5264cf49a43SJulian Elischer for (tp = netgraphprotox; tp->pr_name; tp++) 5274cf49a43SJulian Elischer printproto(tp, tp->pr_name); 528ac55add0SGuido van Rooij if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag) 5294f81ef50SGarrett Wollman unixpr(); 5309b50d902SRodney W. Grimes exit(0); 5319b50d902SRodney W. Grimes } 5329b50d902SRodney W. Grimes 5339b50d902SRodney W. Grimes /* 5349b50d902SRodney W. Grimes * Print out protocol statistics or control blocks (per sflag). 5359b50d902SRodney W. Grimes * If the interface was not specifically requested, and the symbol 5369b50d902SRodney W. Grimes * is not in the namelist, ignore this one. 5379b50d902SRodney W. Grimes */ 5389b50d902SRodney W. Grimes static void 5399b50d902SRodney W. Grimes printproto(tp, name) 540a01e3379SDavid Malone struct protox *tp; 541fa6d48c0SMark Murray const char *name; 5429b50d902SRodney W. Grimes { 543a01e3379SDavid Malone void (*pr)(u_long, const char *, int); 5449b50d902SRodney W. Grimes u_long off; 5459b50d902SRodney W. Grimes 5469b50d902SRodney W. Grimes if (sflag) { 547cfa1ca9dSYoshinobu Inoue if (iflag) { 548cfa1ca9dSYoshinobu Inoue if (tp->pr_istats) 549cfa1ca9dSYoshinobu Inoue intpr(interval, nl[N_IFNET].n_value, 550cfa1ca9dSYoshinobu Inoue tp->pr_istats); 551cf5e44f8SRuslan Ermilov else if (pflag) 552cf5e44f8SRuslan Ermilov printf("%s: no per-interface stats routine\n", 553cf5e44f8SRuslan Ermilov tp->pr_name); 554cfa1ca9dSYoshinobu Inoue return; 555cfa1ca9dSYoshinobu Inoue } 556cfa1ca9dSYoshinobu Inoue else { 5579b50d902SRodney W. Grimes pr = tp->pr_stats; 558cf5e44f8SRuslan Ermilov if (!pr) { 559cf5e44f8SRuslan Ermilov if (pflag) 560cf5e44f8SRuslan Ermilov printf("%s: no stats routine\n", 561cf5e44f8SRuslan Ermilov tp->pr_name); 562cf5e44f8SRuslan Ermilov return; 563cf5e44f8SRuslan Ermilov } 5644f81ef50SGarrett Wollman off = tp->pr_usesysctl ? tp->pr_usesysctl 5654f81ef50SGarrett Wollman : nl[tp->pr_sindex].n_value; 566cfa1ca9dSYoshinobu Inoue } 5679b50d902SRodney W. Grimes } else { 5689b50d902SRodney W. Grimes pr = tp->pr_cblocks; 569cf5e44f8SRuslan Ermilov if (!pr) { 570cf5e44f8SRuslan Ermilov if (pflag) 571cf5e44f8SRuslan Ermilov printf("%s: no PCB routine\n", tp->pr_name); 572cf5e44f8SRuslan Ermilov return; 573cf5e44f8SRuslan Ermilov } 5744f81ef50SGarrett Wollman off = tp->pr_usesysctl ? tp->pr_usesysctl 5754f81ef50SGarrett Wollman : nl[tp->pr_index].n_value; 5769b50d902SRodney W. Grimes } 5779b50d902SRodney W. Grimes if (pr != NULL && (off || af != AF_UNSPEC)) 578cfa1ca9dSYoshinobu Inoue (*pr)(off, name, af); 5799b50d902SRodney W. Grimes } 5809b50d902SRodney W. Grimes 5819b50d902SRodney W. Grimes /* 5829b50d902SRodney W. Grimes * Read kernel memory, return 0 on success. 5839b50d902SRodney W. Grimes */ 5849b50d902SRodney W. Grimes int 5855e051718SAssar Westerlund kread(u_long addr, char *buf, int size) 5869b50d902SRodney W. Grimes { 5874f81ef50SGarrett Wollman if (kvmd == 0) { 58899453c6aSPoul-Henning Kamp /* 58999453c6aSPoul-Henning Kamp * XXX. 59099453c6aSPoul-Henning Kamp */ 59199453c6aSPoul-Henning Kamp kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf); 5923b7e5cccSRuslan Ermilov setgid(getgid()); 59399453c6aSPoul-Henning Kamp if (kvmd != NULL) { 59499453c6aSPoul-Henning Kamp if (kvm_nlist(kvmd, nl) < 0) { 59599453c6aSPoul-Henning Kamp if(nlistf) 59699453c6aSPoul-Henning Kamp errx(1, "%s: kvm_nlist: %s", nlistf, 59799453c6aSPoul-Henning Kamp kvm_geterr(kvmd)); 59899453c6aSPoul-Henning Kamp else 59999453c6aSPoul-Henning Kamp errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); 60099453c6aSPoul-Henning Kamp } 60199453c6aSPoul-Henning Kamp 60299453c6aSPoul-Henning Kamp if (nl[0].n_type == 0) { 60399453c6aSPoul-Henning Kamp if(nlistf) 60499453c6aSPoul-Henning Kamp errx(1, "%s: no namelist", nlistf); 60599453c6aSPoul-Henning Kamp else 60699453c6aSPoul-Henning Kamp errx(1, "no namelist"); 60799453c6aSPoul-Henning Kamp } 60899453c6aSPoul-Henning Kamp } else { 60999453c6aSPoul-Henning Kamp warnx("kvm not available"); 61099453c6aSPoul-Henning Kamp return(-1); 61199453c6aSPoul-Henning Kamp } 6124f81ef50SGarrett Wollman } 613c6620a13SPoul-Henning Kamp if (!buf) 614c6620a13SPoul-Henning Kamp return (0); 6159b50d902SRodney W. Grimes if (kvm_read(kvmd, addr, buf, size) != size) { 6163aa80b1dSDavid Greenman warnx("%s", kvm_geterr(kvmd)); 6179b50d902SRodney W. Grimes return (-1); 6189b50d902SRodney W. Grimes } 6199b50d902SRodney W. Grimes return (0); 6209b50d902SRodney W. Grimes } 6219b50d902SRodney W. Grimes 622a01e3379SDavid Malone const char * 6235e051718SAssar Westerlund plural(int n) 6249b50d902SRodney W. Grimes { 6259b50d902SRodney W. Grimes return (n != 1 ? "s" : ""); 6269b50d902SRodney W. Grimes } 6279b50d902SRodney W. Grimes 628a01e3379SDavid Malone const char * 6295e051718SAssar Westerlund plurales(int n) 6309b50d902SRodney W. Grimes { 6319b50d902SRodney W. Grimes return (n != 1 ? "es" : ""); 6329b50d902SRodney W. Grimes } 6339b50d902SRodney W. Grimes 634f99a4046SMike Makonnen const char * 635f99a4046SMike Makonnen pluralies(int n) 636f99a4046SMike Makonnen { 637f99a4046SMike Makonnen return (n != 1 ? "ies" : "y"); 638f99a4046SMike Makonnen } 639f99a4046SMike Makonnen 6409b50d902SRodney W. Grimes /* 6419b50d902SRodney W. Grimes * Find the protox for the given "well-known" name. 6429b50d902SRodney W. Grimes */ 6439b50d902SRodney W. Grimes static struct protox * 6445e051718SAssar Westerlund knownname(char *name) 6459b50d902SRodney W. Grimes { 6469b50d902SRodney W. Grimes struct protox **tpp, *tp; 6479b50d902SRodney W. Grimes 6489b50d902SRodney W. Grimes for (tpp = protoprotox; *tpp; tpp++) 6499b50d902SRodney W. Grimes for (tp = *tpp; tp->pr_name; tp++) 6509b50d902SRodney W. Grimes if (strcmp(tp->pr_name, name) == 0) 6519b50d902SRodney W. Grimes return (tp); 6529b50d902SRodney W. Grimes return (NULL); 6539b50d902SRodney W. Grimes } 6549b50d902SRodney W. Grimes 6559b50d902SRodney W. Grimes /* 6569b50d902SRodney W. Grimes * Find the protox corresponding to name. 6579b50d902SRodney W. Grimes */ 6589b50d902SRodney W. Grimes static struct protox * 6595e051718SAssar Westerlund name2protox(char *name) 6609b50d902SRodney W. Grimes { 6619b50d902SRodney W. Grimes struct protox *tp; 6629b50d902SRodney W. Grimes char **alias; /* alias from p->aliases */ 6639b50d902SRodney W. Grimes struct protoent *p; 6649b50d902SRodney W. Grimes 6659b50d902SRodney W. Grimes /* 6669b50d902SRodney W. Grimes * Try to find the name in the list of "well-known" names. If that 6679b50d902SRodney W. Grimes * fails, check if name is an alias for an Internet protocol. 6689b50d902SRodney W. Grimes */ 669cfa1ca9dSYoshinobu Inoue if ((tp = knownname(name)) != NULL) 6709b50d902SRodney W. Grimes return (tp); 6719b50d902SRodney W. Grimes 6729b50d902SRodney W. Grimes setprotoent(1); /* make protocol lookup cheaper */ 673cfa1ca9dSYoshinobu Inoue while ((p = getprotoent()) != NULL) { 6749b50d902SRodney W. Grimes /* assert: name not same as p->name */ 6759b50d902SRodney W. Grimes for (alias = p->p_aliases; *alias; alias++) 6769b50d902SRodney W. Grimes if (strcmp(name, *alias) == 0) { 6779b50d902SRodney W. Grimes endprotoent(); 6789b50d902SRodney W. Grimes return (knownname(p->p_name)); 6799b50d902SRodney W. Grimes } 6809b50d902SRodney W. Grimes } 6819b50d902SRodney W. Grimes endprotoent(); 6829b50d902SRodney W. Grimes return (NULL); 6839b50d902SRodney W. Grimes } 6849b50d902SRodney W. Grimes 6859b50d902SRodney W. Grimes static void 6865e051718SAssar Westerlund usage(void) 6879b50d902SRodney W. Grimes { 6881cb467b1SRuslan Ermilov (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 6891cb467b1SRuslan Ermilov "usage: netstat [-AaLnSW] [-f protocol_family | -p protocol]\n" 6901cb467b1SRuslan Ermilov " [-M core] [-N system]", 691d44ddba9SRuslan Ermilov " netstat -i | -I interface [-abdnt] [-f address_family]\n" 692d44ddba9SRuslan Ermilov " [-M core] [-N system]", 6931cb467b1SRuslan Ermilov " netstat -w wait [-I interface] [-d] [-M core] [-N system]", 6941cb467b1SRuslan Ermilov " netstat -s [-s] [-z] [-f protocol_family | -p protocol] [-M core]", 6951cb467b1SRuslan Ermilov " netstat -i | -I interface -s [-f protocol_family | -p protocol]\n" 6961cb467b1SRuslan Ermilov " [-M core] [-N system]", 697dbe0253aSAlfred Perlstein " netstat -m [-c] [-M core] [-N system]", 698dbe0253aSAlfred Perlstein " netstat -r [-AenW] [-f address_family] [-M core] [-N system]", 6991cb467b1SRuslan Ermilov " netstat -rs [-s] [-M core] [-N system]", 7001cb467b1SRuslan Ermilov " netstat -g [-W] [-f address_family] [-M core] [-N system]", 7011cb467b1SRuslan Ermilov " netstat -gs [-s] [-f address_family] [-M core] [-N system]"); 7029b50d902SRodney W. Grimes exit(1); 7039b50d902SRodney W. Grimes } 704