]> 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 9d686078ff13464b95fc0f7aafa3647ac6a9de34..6830b67d810ca127a72a775e7fc930b483434fcd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2015 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -67,6 +67,7 @@ char const copyright[] =
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/socket.h>
+#include <sys/sys_domain.h>
 
 #include <netinet/in.h>
 #include <net/pfkeyv2.h>
@@ -102,166 +103,83 @@ char const copyright[] =
  *
  */
 
-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_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_NGSOCKS      27
-       { "_ngsocklist"},
-#define N_IP6STAT      28
-       { "_ip6stat" },
-#define N_ICMP6STAT    29
-       { "_icmp6stat" },
-#define N_IPSECSTAT    30
-       { "_ipsecstat" },
-#define N_IPSEC6STAT   31
-       { "_ipsec6stat" },
-#define N_PIM6STAT     32
-       { "_pim6stat" },
-#define N_MRT6PROTO    33
-       { "_ip6_mrtproto" },
-#define N_MRT6STAT     34
-       { "_mrt6stat" },
-#define N_MF6CTABLE    35
-       { "_mf6ctable" },
-#define N_MIF6TABLE    36
-       { "_mif6table" },
-#define N_PFKEYSTAT    37
-       { "_pfkeystat" },
-#define N_MBSTAT       38
-       { "_mbstat" },
-#define N_MBTYPES      39
-       { "_mbtypes" },
-#define N_NMBCLUSTERS  40
-       { "_nmbclusters" },
-#define N_NMBUFS       41
-       { "_nmbufs" },
-#define        N_RTTRASH       42
-       { "_rttrash" },
-       { "" },
-};
-
-
 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)(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,    NULL,           "tcp",  IPPROTO_TCP },
-       { -1,           -1,             1,      protopr,
-         udp_stats,    NULL,           "udp",  IPPROTO_UDP },
-       { -1,           -1,             1,      protopr,
-         NULL,         NULL,           "divert",IPPROTO_DIVERT },
-       { -1,           -1,             1,      protopr,
-         ip_stats,     NULL,           "ip",   IPPROTO_RAW },
-       { -1,           -1,             1,      protopr,
-         icmp_stats,   NULL,           "icmp", IPPROTO_ICMP },
-       { -1,           -1,             1,      protopr,
-         igmp_stats,   NULL,           "igmp", IPPROTO_IGMP },
+       { 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
-       { -1,           -1,     1,      0,
-         ipsec_stats,  NULL,           "ipsec",        IPPROTO_ESP},
+       { NULL,         ipsec_stats,    NULL,   "ipsec", IPPROTO_ESP},
 #endif
-       { -1,           -1,             0,      0,
-         0,            NULL,           0 }
+       { NULL,         arp_stats,      NULL,   "arp",  0 },
+       { mptcppr,      mptcp_stats,    NULL,   "mptcp", IPPROTO_TCP },
+       { NULL,         NULL,           NULL,   NULL,   0 }
 };
 
 #ifdef INET6
 struct protox ip6protox[] = {
-       { -1,           -1,             1,      protopr,
-         tcp_stats,    NULL,           "tcp",  IPPROTO_TCP },
-       { -1,           -1,             1,      protopr,
-         udp_stats,    NULL,           "udp",  IPPROTO_UDP },
-       { -1,           N_IP6STAT,      1,      protopr,
-         ip6_stats,    ip6_ifstats,    "ip6",  IPPROTO_RAW },
-       { -1,           N_ICMP6STAT,    1,      protopr,
-         icmp6_stats,  icmp6_ifstats,  "icmp6",IPPROTO_ICMPV6 },
+       { 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
-       { -1,           N_IPSEC6STAT,   1,      0,
-         ipsec_stats,  NULL,           "ipsec6",IPPROTO_ESP },
-#endif
-#ifdef notyet
-       { -1,           N_PIM6STAT,     1,      0,
-         pim6_stats,   NULL,           "pim6", 0 },
+       { NULL,         ipsec_stats,    NULL,   "ipsec6", IPPROTO_ESP },
 #endif
-       { -1,           -1,             1,      0,
-         rip6_stats,   NULL,           "rip6", IPPROTO_RAW },
-       { -1,           -1,             0,      0,
-         0,            NULL,           0,      0 }
+       { NULL,         rip6_stats,     NULL,   "rip6", IPPROTO_RAW },
+       { mptcppr,      mptcp_stats,    NULL,   "mptcp", IPPROTO_TCP },
+       { NULL,         NULL,           NULL,   NULL,   0 }
 };
 #endif /*INET6*/
 
 #ifdef IPSEC
 struct protox pfkeyprotox[] = {
-       { -1,           N_PFKEYSTAT,    1,      0,
-         pfkey_stats,  NULL,           "pfkey", PF_KEY_V2 },
-       { -1,           -1,             0,      0,
-         0,            NULL,           0,      0 }
+       { NULL,         pfkey_stats,    NULL,   "pfkey", PF_KEY_V2 },
+       { NULL,         NULL,           NULL,   NULL,   0 }
 };
 #endif
 
+
+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 }
+};
+
+struct protox nstatprotox[] = {
+       { NULL,         print_nstat_stats,      NULL,   "nstat", 0 },
+       { NULL,         NULL,           NULL,   NULL,   0 }
+};
+
+struct protox ipcprotox[] = {
+       { NULL,         print_extbkidle_stats,  NULL,   "xbkidle", 0 },
+       { NULL,         NULL,           NULL,   NULL,   0 }
+};
+
+
 struct protox *protoprotox[] = {
-                                        protox,
+       protox,
 #ifdef INET6
-                                        ip6protox,
+       ip6protox,
 #endif
 #ifdef IPSEC
-                                        pfkeyprotox,
+       pfkeyprotox,
 #endif
-                                        NULL };
+       systmprotox,
+       nstatprotox,
+       ipcprotox,
+       NULL
+};
 
 static void printproto (struct protox *, char *);
 static void usage (void);
@@ -274,8 +192,10 @@ extern void _serv_cache_close();
 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 */
-#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
+int    Fflag;          /* show i/f forwarded packets */
+#if defined(__APPLE__)
 int    gflag;          /* show group (multicast) routing or stats */
 #endif
 int    iflag;          /* show interfaces */
@@ -284,11 +204,19 @@ 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 */
@@ -306,7 +234,7 @@ main(argc, argv)
 
        af = AF_UNSPEC;
 
-       while ((ch = getopt(argc, argv, "Aabdf:gI:iLlmnp:rRstuWw:")) != -1)
+       while ((ch = getopt(argc, argv, "Aabc:dFf:gI:ikLlmnP:p:qQrRsStuvWw:x")) != -1)
                switch(ch) {
                case 'A':
                        Aflag = 1;
@@ -317,9 +245,16 @@ 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':
                        if (strcmp(optarg, "ipx") == 0)
                                af = AF_IPX;
@@ -335,11 +270,13 @@ main(argc, argv)
 #endif /*INET6*/
                        else if (strcmp(optarg, "unix") == 0)
                                af = AF_UNIX;
+                       else if (strcmp(optarg, "systm") == 0)
+                               af = AF_SYSTEM;
                        else {
                                errx(1, "%s: unknown address family", optarg);
                        }
                        break;
-#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
+#if defined(__APPLE__)
                case 'g':
                        gflag = 1;
                        break;
@@ -368,6 +305,9 @@ main(argc, argv)
                case 'n':
                        nflag = 1;
                        break;
+               case 'P':
+                       prioflag = atoi(optarg);
+                       break;
                case 'p':
                        if ((tp = name2protox(optarg)) == NULL) {
                                errx(1, 
@@ -376,18 +316,33 @@ 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;
@@ -395,6 +350,10 @@ main(argc, argv)
                        interval = atoi(optarg);
                        iflag = 1;
                        break;
+               case 'x':
+                       xflag = 1;
+                       Rflag = 1;
+                       break;
                case '?':
                default:
                        usage();
@@ -419,34 +378,44 @@ main(argc, argv)
                mbpr();
                exit(0);
        }
-       if (iflag && !sflag) {
-               intpr(NULL);
+       if (iflag && !sflag && !Sflag && !gflag && !qflag && !Qflag) {
+               if (Rflag)
+                       intpr_ri(NULL);
+               else
+                       intpr(NULL);
                exit(0);
        }
        if (rflag) {
                if (sflag)
                        rt_stats();
                else
-                       routepr(nl[N_RTREE].n_value);
+                       routepr();
                exit(0);
        }
-#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
-       if (gflag) {
-               if (sflag) {
-                       if (af == AF_INET || af == AF_UNSPEC)
-                               mrt_stats();
-#ifdef INET6
-                       if (af == AF_INET6 || af == AF_UNSPEC)
-                               mrt6_stats();
-#endif
+       if (qflag || Qflag) {
+               if (interface == NULL) {
+                       fprintf(stderr, "%s statistics option "
+                           "requires interface name\n", qflag ? "Queue" :
+                           "Polling");
+               } else if (qflag) {
+                       aqstatpr();
                } else {
-                       if (af == AF_INET || af == AF_UNSPEC)
-                               mroutepr();
-#ifdef INET6
-                       if (af == AF_INET6 || af == AF_UNSPEC)
-                               mroute6pr();
-#endif
+                       rxpollstatpr();
+               }
+               exit(0);
+       }
+       if (Sflag) {
+               if (interface == NULL) {
+                       fprintf(stderr, "additional link status option"
+                               " requires interface name\n");
+               } else {
+                       print_link_status(interface);
                }
+               exit(0);
+       }
+
+#if defined(__APPLE__)
+       if (gflag) {
                ifmalist_dump();
                exit(0);
        }
@@ -471,6 +440,20 @@ main(argc, argv)
 #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
@@ -494,7 +477,7 @@ printproto(tp, name)
                if (iflag && !pflag) {
                        if (tp->pr_istats)
                                intpr(tp->pr_istats);
-                       else
+                       else if (vflag)
                                printf("%s: no per-interface stats routine\n",
                                    tp->pr_name);
                        return;
@@ -502,25 +485,23 @@ printproto(tp, name)
                else {
                        pr = tp->pr_stats;
                        if (!pr) {
-                               if (pflag)
+                               if (pflag && vflag)
                                        printf("%s: no stats routine\n",
                                            tp->pr_name);
                                return;
                        }
-                       off = tp->pr_usesysctl ? tp->pr_usesysctl 
-                               : nl[tp->pr_sindex].n_value;
+                       off = tp->pr_protocol;
                }
        } else {
                pr = tp->pr_cblocks;
                if (!pr) {
-                       if (pflag)
+                       if (pflag && vflag)
                                printf("%s: no PCB routine\n", tp->pr_name);
                        return;
                }
-               off = tp->pr_usesysctl ? tp->pr_usesysctl
-                       : nl[tp->pr_index].n_value;
+               off = tp->pr_protocol;
        }
-       if (pr != NULL && (off || af != AF_UNSPEC)) {
+       if (pr != NULL) {
                if (sflag && iflag && pflag)
                        intervalpr(pr, off, name, af);
                else
@@ -533,13 +514,19 @@ printproto(tp, name)
 char *
 plural(int n)
 {
-       return (n != 1 ? "s" : "");
+       return (n > 1 ? "s" : "");
 }
 
 char *
 plurales(int n)
 {
-       return (n != 1 ? "es" : "");
+       return (n > 1 ? "es" : "");
+}
+
+char *
+pluralies(int n)
+{
+       return (n > 1 ? "ies" : "y");
 }
 
 /*
@@ -590,7 +577,7 @@ name2protox(char *name)
 #define        NETSTAT_USAGE "\
 Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\
        netstat [-gilns] [-f address_family]\n\
-       netstat -i | -I interface [-w wait] [-abdgt]\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\
@@ -604,3 +591,19 @@ usage(void)
        (void) fprintf(stderr, "%s\n", NETSTAT_USAGE);
        exit(1);
 }
+
+int
+print_time(void)
+{
+    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);
+}
+