]> git.saurik.com Git - apple/network_cmds.git/blobdiff - netstat.tproj/main.c
network_cmds-511.50.3.tar.gz
[apple/network_cmds.git] / netstat.tproj / main.c
index 8ca3a725171db41237d9ca2caeec87012417fc98..6830b67d810ca127a72a775e7fc930b483434fcd 100644 (file)
@@ -1,25 +1,29 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2008-2015 Apple Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
  * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  * Copyright (c) 1983, 1988, 1993
@@ -60,25 +64,17 @@ char const copyright[] =
        Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)main.c     8.4 (Berkeley) 3/1/94";
-#endif
-static const char rcsid[] =
-       "$Id: main.c,v 1.2 2000/06/16 03:37:29 lindak Exp $";
-#endif /* not lint */
-
 #include <sys/param.h>
 #include <sys/file.h>
-#include <sys/protosw.h>
 #include <sys/socket.h>
+#include <sys/sys_domain.h>
 
 #include <netinet/in.h>
+#include <net/pfkeyv2.h>
 
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
-#include <kvm.h>
 #include <limits.h>
 #include <netdb.h>
 #include <nlist.h>
@@ -91,6 +87,9 @@ static const char rcsid[] =
 #include <sys/types.h>
 #include <sys/sysctl.h>
 
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
 
 /*
  * ----------------------------------------------------------------------------
@@ -100,184 +99,142 @@ static const char rcsid[] =
  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
  * ----------------------------------------------------------------------------
  *
- * $Id: main.c,v 1.2 2000/06/16 03:37:29 lindak Exp $
+ * $Id: main.c,v 1.8 2004/10/14 22:24:09 lindak Exp $
  *
  */
 
-
-static struct nlist nl[] = {
-#define        N_IFNET         0
-       { "_ifnet" },
-#define        N_IMP           1
-       { "_imp_softc" },
-#define        N_RTSTAT        2
-       { "_rtstat" },
-#define        N_UNIXSW        3
-       { "_localsw" },
-#define N_IDP          4
-       { "_nspcb"},
-#define N_IDPSTAT      5
-       { "_idpstat"},
-#define N_SPPSTAT      6
-       { "_spp_istat"},
-#define N_NSERR                7
-       { "_ns_errstat"},
-#define        N_CLNPSTAT      8
-       { "_clnp_stat"},
-#define        IN_NOTUSED      9
-       { "_tp_inpcb" },
-#define        ISO_TP          10
-       { "_tp_refinfo" },
-#define        N_TPSTAT        11
-       { "_tp_stat" },
-#define        N_ESISSTAT      12
-       { "_esis_stat"},
-#define N_NIMP         13
-       { "_nimp"},
-#define N_RTREE                14
-       { "_rt_tables"},
-#define N_CLTP         15
-       { "_cltb"},
-#define N_CLTPSTAT     16
-       { "_cltpstat"},
-#define        N_NFILE         17
-       { "_nfile" },
-#define        N_FILE          18
-       { "_file" },
-#define N_MRTSTAT      19
-       { "_mrtstat" },
-#define N_MFCTABLE     20
-       { "_mfctable" },
-#define N_VIFTABLE     21
-       { "_viftable" },
-#define N_IPX          22
-       { "_ipxpcb"},
-#define N_IPXSTAT      23
-       { "_ipxstat"},
-#define N_SPXSTAT      24
-       { "_spx_istat"},
-#define N_DDPSTAT      25
-       { "_ddpstat"},
-#define N_DDPCB                26
-       { "_ddpcb"},
-#define N_MBSTAT       27
-       {"_mbstat"},
-       { "" },
-};
-
-
-
 struct protox {
-       u_char  pr_index;               /* index into nlist of cb head */
-       u_char  pr_sindex;              /* index into nlist of stat block */
-       u_char  pr_wanted;              /* 1 if wanted, 0 otherwise */
-       void    (*pr_cblocks)();        /* control blocks printing routine */
-       void    (*pr_stats)();          /* statistics printing routine */
+       void    (*pr_cblocks)(uint32_t, char *, int);
+                                       /* control blocks printing routine */
+       void    (*pr_stats)(uint32_t, char *, int);
+                                       /* statistics printing routine */
+       void    (*pr_istats)(char *);   /* per/if statistics printing routine */
        char    *pr_name;               /* well-known name */
-       int     pr_usesysctl;           /* true if we use sysctl, not kvm */
+       int     pr_protocol;
 } protox[] = {
-       { -1,           -1,             1,      protopr,
-         tcp_stats,    "tcp",          IPPROTO_TCP },
-       { -1,           -1,             1,      protopr,
-         udp_stats,    "udp",          IPPROTO_UDP },
-       { -1,           -1,             1,      protopr,
-         NULL,         "divert",       IPPROTO_DIVERT },
-       { -1,           -1,             1,      protopr,
-         ip_stats,     "ip",           IPPROTO_RAW },
-       { -1,           -1,             1,      protopr,
-         icmp_stats,   "icmp",         IPPROTO_ICMP },
-       { -1,           -1,             1,      protopr,
-         igmp_stats,   "igmp",         IPPROTO_IGMP },
-       { -1,           -1,             0,      0,
-         0,            0 }
+       { protopr,      tcp_stats,      NULL,   "tcp",  IPPROTO_TCP },
+       { protopr,      udp_stats,      NULL,   "udp",  IPPROTO_UDP },
+       { protopr,      NULL,           NULL,   "divert", IPPROTO_DIVERT },
+       { protopr,      ip_stats,       NULL,   "ip",   IPPROTO_RAW },
+       { protopr,      icmp_stats,     NULL,   "icmp", IPPROTO_ICMP },
+       { protopr,      igmp_stats,     NULL,   "igmp", IPPROTO_IGMP },
+#ifdef IPSEC
+       { NULL,         ipsec_stats,    NULL,   "ipsec", IPPROTO_ESP},
+#endif
+       { NULL,         arp_stats,      NULL,   "arp",  0 },
+       { mptcppr,      mptcp_stats,    NULL,   "mptcp", IPPROTO_TCP },
+       { NULL,         NULL,           NULL,   NULL,   0 }
 };
 
-#ifdef UNIX_ATALK
-struct protox atalkprotox[] = {
-       { N_DDPCB,      N_DDPSTAT,      1,      atalkprotopr,
-         ddp_stats,    "ddp" },
-       { -1,           -1,             0,      0,
-         0,            0 }
-};
+#ifdef INET6
+struct protox ip6protox[] = {
+       { protopr,      tcp_stats,      NULL,   "tcp",  IPPROTO_TCP },
+       { protopr,      udp_stats,      NULL,   "udp",  IPPROTO_UDP },
+       { protopr,      ip6_stats,      ip6_ifstats,    "ip6",  IPPROTO_RAW },
+       { protopr,      icmp6_stats,    icmp6_ifstats,  "icmp6",IPPROTO_ICMPV6 },
+#ifdef IPSEC
+       { NULL,         ipsec_stats,    NULL,   "ipsec6", IPPROTO_ESP },
 #endif
-
-#ifdef IPX
-struct protox ipxprotox[] = {
-       { N_IPX,        N_IPXSTAT,      1,      ipxprotopr,
-         ipx_stats,    "ipx",          0 },
-       { N_IPX,        N_SPXSTAT,      1,      ipxprotopr,
-         spx_stats,    "spx",          0 },
-       { -1,           -1,             0,      0,
-         0,            0,              0 }
+       { NULL,         rip6_stats,     NULL,   "rip6", IPPROTO_RAW },
+       { mptcppr,      mptcp_stats,    NULL,   "mptcp", IPPROTO_TCP },
+       { NULL,         NULL,           NULL,   NULL,   0 }
 };
-#endif
+#endif /*INET6*/
 
-#ifdef NS
-struct protox nsprotox[] = {
-       { N_IDP,        N_IDPSTAT,      1,      nsprotopr,
-         idp_stats,    "idp" },
-       { N_IDP,        N_SPPSTAT,      1,      nsprotopr,
-         spp_stats,    "spp" },
-       { -1,           N_NSERR,        1,      0,
-         nserr_stats,  "ns_err" },
-       { -1,           -1,             0,      0,
-         0,            0 }
+#ifdef IPSEC
+struct protox pfkeyprotox[] = {
+       { NULL,         pfkey_stats,    NULL,   "pfkey", PF_KEY_V2 },
+       { NULL,         NULL,           NULL,   NULL,   0 }
 };
 #endif
 
-#ifdef ISO
-struct protox isoprotox[] = {
-       { ISO_TP,       N_TPSTAT,       1,      iso_protopr,
-         tp_stats,     "tp" },
-       { N_CLTP,       N_CLTPSTAT,     1,      iso_protopr,
-         cltp_stats,   "cltp" },
-       { -1,           N_CLNPSTAT,     1,       0,
-         clnp_stats,   "clnp"},
-       { -1,           N_ESISSTAT,     1,       0,
-         esis_stats,   "esis"},
-       { -1,           -1,             0,      0,
-         0,            0 }
+
+struct protox systmprotox[] = {
+       { systmpr,      NULL,           NULL,   "reg", 0 },
+       { systmpr,      kevt_stats,             NULL,   "kevt", SYSPROTO_EVENT },
+       { systmpr,      kctl_stats,     NULL,   "kctl", SYSPROTO_CONTROL },
+       { NULL,         NULL,           NULL,   NULL,   0 }
 };
-#endif
 
-struct protox *protoprotox[] = { protox, 
+struct protox nstatprotox[] = {
+       { NULL,         print_nstat_stats,      NULL,   "nstat", 0 },
+       { NULL,         NULL,           NULL,   NULL,   0 }
+};
 
-#ifdef IPX
-ipxprotox, 
-#endif
+struct protox ipcprotox[] = {
+       { NULL,         print_extbkidle_stats,  NULL,   "xbkidle", 0 },
+       { NULL,         NULL,           NULL,   NULL,   0 }
+};
 
-#ifdef UNIX_ATALK
-atalkprotox,
-#endif
 
-#ifdef NS
-                                        nsprotox, 
+struct protox *protoprotox[] = {
+       protox,
+#ifdef INET6
+       ip6protox,
 #endif
-#ifdef ISO
-                                        isoprotox, 
+#ifdef IPSEC
+       pfkeyprotox,
 #endif
-                                        NULL };
+       systmprotox,
+       nstatprotox,
+       ipcprotox,
+       NULL
+};
 
-static void printproto __P((struct protox *, char *));
-static void usage __P((void));
-static struct protox *name2protox __P((char *));
-static struct protox *knownname __P((char *));
+static void printproto (struct protox *, char *);
+static void usage (void);
+static struct protox *name2protox (char *);
+static struct protox *knownname (char *);
+#ifdef SRVCACHE
+extern void _serv_cache_close();
+#endif
 
-static kvm_t *kvmd;
-char *nlistf = NULL, *memf = NULL;
+int    Aflag;          /* show addresses of protocol control block */
+int    aflag;          /* show all sockets (including servers) */
+int    bflag;          /* show i/f total bytes in/out */
+int    cflag;          /* show specific classq */
+int    dflag;          /* show i/f dropped packets */
+int    Fflag;          /* show i/f forwarded packets */
+#if defined(__APPLE__)
+int    gflag;          /* show group (multicast) routing or stats */
+#endif
+int    iflag;          /* show interfaces */
+int    lflag;          /* show routing table with use and ref */
+int    Lflag;          /* show size of listen queues */
+int    mflag;          /* show memory stats */
+int    nflag;          /* show addresses numerically */
+static int pflag;      /* show given protocol */
+int    prioflag = -1;  /* show packet priority statistics */
+int    Rflag;          /* show reachability information */
+int    rflag;          /* show routing tables (or routing stats) */
+int    sflag;          /* show protocol statistics */
+int    Sflag;          /* show additional i/f link status */
+int    tflag;          /* show i/f watchdog timers */
+int    vflag;          /* more verbose */
+int    Wflag;          /* wide display */
+int    qflag;          /* classq stats display */
+int    Qflag;          /* opportunistic polling stats display */
+int    xflag;          /* show extended link-layer reachability information */
+
+int    cq = -1;        /* send classq index (-1 for all) */
+int    interval;       /* repeat interval for i/f stats */
+
+char   *interface;     /* desired i/f for stats, or NULL for all i/fs */
+int    unit;           /* unit number for above */
+
+int    af;             /* address family */
 
 int
 main(argc, argv)
        int argc;
        char *argv[];
 {
-       register struct protoent *p;
-       register struct protox *tp;     /* for printing cblocks & stats */
+       register struct protox *tp = NULL;  /* for printing cblocks & stats */
        int ch;
 
        af = AF_UNSPEC;
 
-       while ((ch = getopt(argc, argv, "Aabdf:ghI:iM:mN:np:rstuw:")) != -1)
+       while ((ch = getopt(argc, argv, "Aabc:dFf:gI:ikLlmnP:p:qQrRsStuvWw:x")) != -1)
                switch(ch) {
                case 'A':
                        Aflag = 1;
@@ -288,36 +245,42 @@ main(argc, argv)
                case 'b':
                        bflag = 1;
                        break;
+               case 'c':
+                       cflag = 1;
+                       cq = atoi(optarg);
+                       break;
                case 'd':
                        dflag = 1;
                        break;
+               case 'F':
+                       Fflag = 1;
+                       break;
                case 'f':
-#ifdef NS
-                       if (strcmp(optarg, "ns") == 0)
-                               af = AF_NS;
-                       else
-#endif
                        if (strcmp(optarg, "ipx") == 0)
                                af = AF_IPX;
                        else if (strcmp(optarg, "inet") == 0)
                                af = AF_INET;
+#ifdef INET6
+                       else if (strcmp(optarg, "inet6") == 0)
+                               af = AF_INET6;
+#endif /*INET6*/
+#ifdef INET6
+                       else if (strcmp(optarg, "pfkey") == 0)
+                               af = PF_KEY;
+#endif /*INET6*/
                        else if (strcmp(optarg, "unix") == 0)
                                af = AF_UNIX;
-                       else if (strcmp(optarg, "local") == 0)
-                               af = AF_LOCAL;
-                       else if (strcmp(optarg, "atalk") == 0)
-                               af = AF_APPLETALK;
-#ifdef ISO
-                       else if (strcmp(optarg, "iso") == 0)
-                               af = AF_ISO;
-#endif
+                       else if (strcmp(optarg, "systm") == 0)
+                               af = AF_SYSTEM;
                        else {
                                errx(1, "%s: unknown address family", optarg);
                        }
                        break;
+#if defined(__APPLE__)
                case 'g':
                        gflag = 1;
                        break;
+#endif
                case 'I': {
                        char *cp;
 
@@ -330,18 +293,21 @@ main(argc, argv)
                case 'i':
                        iflag = 1;
                        break;
-               case 'M':
-                       memf = optarg;
+               case 'l':
+                       lflag = 1;
                        break;
-               case 'm':
-                       mflag = 1;
+               case 'L':
+                       Lflag = 1;
                        break;
-               case 'N':
-                       nlistf = optarg;
+               case 'm':
+                       mflag++;
                        break;
                case 'n':
                        nflag = 1;
                        break;
+               case 'P':
+                       prioflag = atoi(optarg);
+                       break;
                case 'p':
                        if ((tp = name2protox(optarg)) == NULL) {
                                errx(1, 
@@ -350,22 +316,44 @@ main(argc, argv)
                        }
                        pflag = 1;
                        break;
+               case 'q':
+                       qflag++;
+                       break;
+               case 'Q':
+                       Qflag++;
+                       break;
+               case 'R':
+                       Rflag = 1;
+                       break;
                case 'r':
                        rflag = 1;
                        break;
                case 's':
                        ++sflag;
                        break;
+               case 'S':
+                       Sflag = 1;
+                       break;
                case 't':
                        tflag = 1;
                        break;
                case 'u':
                        af = AF_UNIX;
                        break;
+               case 'v':
+                       vflag++;
+                       break;
+               case 'W':
+                       Wflag = 1;
+                       break;
                case 'w':
                        interval = atoi(optarg);
                        iflag = 1;
                        break;
+               case 'x':
+                       xflag = 1;
+                       Rflag = 1;
+                       break;
                case '?':
                default:
                        usage();
@@ -383,115 +371,92 @@ main(argc, argv)
                        ++argv;
                        iflag = 1;
                }
-               if (*argv) {
-                       nlistf = *argv;
-                       if (*++argv)
-                               memf = *argv;
-               }
        }
 #endif
 
-       /*
-        * Discard setgid privileges if not the running kernel so that bad
-        * guys can't print interesting stuff from kernel memory.
-        */
-       if (nlistf != NULL || memf != NULL)
-               setgid(getgid());
-
        if (mflag) {
-               kread(0,0,0);
-               mbpr(nl[N_MBSTAT].n_value);
+               mbpr();
                exit(0);
        }
-       if (pflag) {
-               if (!tp->pr_stats) {
-                       printf("%s: no stats routine\n", tp->pr_name);
-                       exit(0);
-               }
-               if (tp->pr_usesysctl) {
-                       (*tp->pr_stats)(tp->pr_usesysctl, tp->pr_name);
-               } else {
-                       kread(0, 0, 0);
-                       (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
-                                       tp->pr_name);
-               }
-               exit(0);
-       }
-#if 0
-       /*
-        * Keep file descriptors open to avoid overhead
-        * of open/close on each call to get* routines.
-        */
-       sethostent(1);
-       setnetent(1);
-#else
-       /*
-        * This does not make sense any more with DNS being default over
-        * the files.  Doing a setXXXXent(1) causes a tcp connection to be
-        * used for the queries, which is slower.
-        */
-#endif
-       if (iflag) {
-               kread(0, 0, 0);
-               intpr(interval, nl[N_IFNET].n_value);
+       if (iflag && !sflag && !Sflag && !gflag && !qflag && !Qflag) {
+               if (Rflag)
+                       intpr_ri(NULL);
+               else
+                       intpr(NULL);
                exit(0);
        }
        if (rflag) {
-               kread(0, 0, 0);
                if (sflag)
-                       rt_stats(nl[N_RTSTAT].n_value);
+                       rt_stats();
                else
-                       routepr(nl[N_RTREE].n_value);
+                       routepr();
                exit(0);
        }
-       if (gflag) {
-               kread(0, 0, 0);
-               if (sflag)
-                       mrt_stats(nl[N_MRTSTAT].n_value);
-               else
-                       mroutepr(nl[N_MFCTABLE].n_value,
-                           nl[N_VIFTABLE].n_value);
+       if (qflag || Qflag) {
+               if (interface == NULL) {
+                       fprintf(stderr, "%s statistics option "
+                           "requires interface name\n", qflag ? "Queue" :
+                           "Polling");
+               } else if (qflag) {
+                       aqstatpr();
+               } else {
+                       rxpollstatpr();
+               }
                exit(0);
        }
-       if (af == AF_INET || af == AF_UNSPEC) {
-               setprotoent(1);
-               setservent(1);
-               /* ugh, this is O(MN) ... why do we do this? */
-               while ((p = getprotoent())) {
-                       for (tp = protox; tp->pr_name; tp++)
-                               if (strcmp(tp->pr_name, p->p_name) == 0)
-                                       break;
-                       if (tp->pr_name == 0 || tp->pr_wanted == 0)
-                               continue;
-                       printproto(tp, p->p_name);
+       if (Sflag) {
+               if (interface == NULL) {
+                       fprintf(stderr, "additional link status option"
+                               " requires interface name\n");
+               } else {
+                       print_link_status(interface);
                }
-               endprotoent();
+               exit(0);
        }
 
-#ifdef IPX
-       if (af == AF_IPX || af == AF_UNSPEC) {
-               kread(0, 0, 0);
-               for (tp = ipxprotox; tp->pr_name; tp++)
-                       printproto(tp, tp->pr_name);
+#if defined(__APPLE__)
+       if (gflag) {
+               ifmalist_dump();
+               exit(0);
        }
 #endif
-#ifdef UNIX_ATALK
-       if (af == AF_APPLETALK || af == AF_UNSPEC)
-               for (tp = atalkprotox; tp->pr_name; tp++)
+
+       if (tp) {
+               printproto(tp, tp->pr_name);
+               exit(0);
+       }
+       if (af == AF_INET || af == AF_UNSPEC)
+               for (tp = protox; tp->pr_name; tp++)
                        printproto(tp, tp->pr_name);
-#endif
-#ifdef NS
-       if (af == AF_NS || af == AF_UNSPEC)
-               for (tp = nsprotox; tp->pr_name; tp++)
+#ifdef INET6
+       if (af == AF_INET6 || af == AF_UNSPEC)
+               for (tp = ip6protox; tp->pr_name; tp++)
                        printproto(tp, tp->pr_name);
-#endif
-#ifdef ISO
-       if (af == AF_ISO || af == AF_UNSPEC)
-               for (tp = isoprotox; tp->pr_name; tp++)
+#endif /*INET6*/
+#ifdef IPSEC
+       if (af == PF_KEY || af == AF_UNSPEC)
+               for (tp = pfkeyprotox; tp->pr_name; tp++)
                        printproto(tp, tp->pr_name);
-#endif
-       if ((af == AF_UNIX || af == AF_LOCAL || af == AF_UNSPEC) && !sflag)
+#endif /*IPSEC*/
+       if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
                unixpr();
+               
+       if ((af == AF_SYSTEM || af == AF_UNSPEC) && !Lflag)
+               for (tp = systmprotox; tp->pr_name; tp++)
+                       printproto(tp, tp->pr_name);
+#if TARGET_OS_IPHONE
+       if (af == AF_UNSPEC && !Lflag)
+               for (tp = nstatprotox; tp->pr_name; tp++)
+                       printproto(tp, tp->pr_name);
+#endif /* TARGET_OS_IPHONE */
+
+       if (af == AF_UNSPEC && !Lflag)
+               for (tp = ipcprotox; tp->pr_name; tp++)
+                       printproto(tp, tp->pr_name);
+
+#ifdef SRVCACHE
+       _serv_cache_close();
+#endif
        exit(0);
 }
 
@@ -505,85 +470,70 @@ printproto(tp, name)
        register struct protox *tp;
        char *name;
 {
-       void (*pr)();
-       u_long off;
+       void (*pr)(uint32_t, char *, int);
+       uint32_t off;
 
        if (sflag) {
-               pr = tp->pr_stats;
-               off = tp->pr_usesysctl ? tp->pr_usesysctl 
-                       : nl[tp->pr_sindex].n_value;
+               if (iflag && !pflag) {
+                       if (tp->pr_istats)
+                               intpr(tp->pr_istats);
+                       else if (vflag)
+                               printf("%s: no per-interface stats routine\n",
+                                   tp->pr_name);
+                       return;
+               }
+               else {
+                       pr = tp->pr_stats;
+                       if (!pr) {
+                               if (pflag && vflag)
+                                       printf("%s: no stats routine\n",
+                                           tp->pr_name);
+                               return;
+                       }
+                       off = tp->pr_protocol;
+               }
        } else {
                pr = tp->pr_cblocks;
-               off = tp->pr_usesysctl ? tp->pr_usesysctl
-                       : nl[tp->pr_index].n_value;
+               if (!pr) {
+                       if (pflag && vflag)
+                               printf("%s: no PCB routine\n", tp->pr_name);
+                       return;
+               }
+               off = tp->pr_protocol;
+       }
+       if (pr != NULL) {
+               if (sflag && iflag && pflag)
+                       intervalpr(pr, off, name, af);
+               else
+                       (*pr)(off, name, af);
+       } else {
+               printf("### no stats for %s\n", name);
        }
-       if (pr != NULL && (off || af != AF_UNSPEC))
-               (*pr)(off, name);
 }
 
-/*
- * Read kernel memory, return 0 on success.
- */
-int
-kread(addr, buf, size)
-       u_long addr;
-       char *buf;
-       int size;
+char *
+plural(int n)
 {
-       if (kvmd == 0) {
-               /*
-                * XXX.
-                */
-               kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
-               if (kvmd != NULL) {
-                       if (kvm_nlist(kvmd, nl) < 0) {
-                               if(nlistf)
-                                       errx(1, "%s: kvm_nlist: %s", nlistf,
-                                            kvm_geterr(kvmd));
-                               else
-                                       errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
-                       }
-
-                       if (nl[0].n_type == 0) {
-                               if(nlistf)
-                                       errx(1, "%s: no namelist", nlistf);
-                               else
-                                       errx(1, "no namelist");
-                       }
-               } else {
-                       warnx("kvm not available");
-                       return(-1);
-               }
-       }
-       if (!buf)
-               return (0);
-       if (kvm_read(kvmd, addr, buf, size) != size) {
-               warnx("%s", kvm_geterr(kvmd));
-               return (-1);
-       }
-       return (0);
+       return (n > 1 ? "s" : "");
 }
 
 char *
-plural(n)
-       int n;
+plurales(int n)
 {
-       return (n != 1 ? "s" : "");
+       return (n > 1 ? "es" : "");
 }
 
 char *
-plurales(n)
-       int n;
+pluralies(int n)
 {
-       return (n != 1 ? "es" : "");
+       return (n > 1 ? "ies" : "y");
 }
 
 /*
  * Find the protox for the given "well-known" name.
  */
 static struct protox *
-knownname(name)
-       char *name;
+knownname(char *name)
 {
        struct protox **tpp, *tp;
 
@@ -598,8 +548,7 @@ knownname(name)
  * Find the protox corresponding to name.
  */
 static struct protox *
-name2protox(name)
-       char *name;
+name2protox(char *name)
 {
        struct protox *tp;
        char **alias;                   /* alias from p->aliases */
@@ -609,11 +558,11 @@ name2protox(name)
         * Try to find the name in the list of "well-known" names. If that
         * fails, check if name is an alias for an Internet protocol.
         */
-       if ((tp = knownname(name)))
+       if ((tp = knownname(name)) != NULL)
                return (tp);
 
        setprotoent(1);                 /* make protocol lookup cheaper */
-       while ((p = getprotoent())) {
+       while ((p = getprotoent()) != NULL) {
                /* assert: name not same as p->name */
                for (alias = p->p_aliases; *alias; alias++)
                        if (strcmp(name, *alias) == 0) {
@@ -625,43 +574,36 @@ name2protox(name)
        return (NULL);
 }
 
+#define        NETSTAT_USAGE "\
+Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\
+       netstat [-gilns] [-f address_family]\n\
+       netstat -i | -I interface [-w wait] [-abdgRtS]\n\
+       netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\
+       netstat -i | -I interface -s [-f address_family | -p protocol]\n\
+       netstat -m [-m]\n\
+       netstat -r [-Aaln] [-f address_family]\n\
+       netstat -rs [-s]\n\
+"
+
 static void
-usage()
+usage(void)
 {
-       (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
-"usage: netstat [-Aan] [-f address_family] [-M core] [-N system]",
-"       netstat [-bdghimnrs] [-f address_family] [-M core] [-N system]",
-"       netstat [-bdn] [-I interface] [-M core] [-N system] [-w wait]",
-"       netstat [-M core] [-N system] [-p protocol]");
+       (void) fprintf(stderr, "%s\n", NETSTAT_USAGE);
        exit(1);
 }
 
-void
-trimdomain(cp)
-       char *cp;
+int
+print_time(void)
 {
-       static char domain[MAXHOSTNAMELEN + 1];
-       static int first = 1;
-       char *s;
-
-       if (first) {
-               first = 0;
-               if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
-                   (s = strchr(domain, '.')))
-                       (void) strcpy(domain, s + 1);
-               else
-                       domain[0] = 0;
-       }
-
-       if (domain[0]) {
-               while ((cp = strchr(cp, '.'))) {
-                       if (!strcasecmp(cp + 1, domain)) {
-                               *cp = 0;        /* hit it */
-                               break;
-                       } else {
-                               cp++;
-                       }
-               }
-       }
+    time_t now;
+    struct tm tm;
+    int num_written = 0;
+    
+    (void) time(&now);
+    (void) localtime_r(&now, &tm);
+    
+    num_written += printf("%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec);
+    
+    return (num_written);
 }