]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/netstat/main.c
Output style: Get rid of an unnecessary newline.
[FreeBSD/FreeBSD.git] / usr.bin / netstat / main.c
1 /*
2  * Copyright (c) 1983, 1988, 1993
3  *      Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 char const copyright[] =
36 "@(#) Copyright (c) 1983, 1988, 1993\n\
37         Regents of the University of California.  All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)main.c      8.4 (Berkeley) 3/1/94";
43 #endif
44 static const char rcsid[] =
45   "$FreeBSD$";
46 #endif /* not lint */
47
48 #include <sys/param.h>
49 #include <sys/file.h>
50 #include <sys/protosw.h>
51 #include <sys/socket.h>
52
53 #include <netinet/in.h>
54
55 #include <netgraph/ng_socket.h>
56
57 #include <ctype.h>
58 #include <err.h>
59 #include <errno.h>
60 #include <kvm.h>
61 #include <limits.h>
62 #include <netdb.h>
63 #include <nlist.h>
64 #include <paths.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <unistd.h>
69 #include "netstat.h"
70
71 static struct nlist nl[] = {
72 #define N_IFNET         0
73         { "_ifnet" },
74 #define N_RTSTAT        1
75         { "_rtstat" },
76 #define N_RTREE         2
77         { "_rt_tables"},
78 #define N_MRTSTAT       3
79         { "_mrtstat" },
80 #define N_MFCTABLE      4
81         { "_mfctable" },
82 #define N_VIFTABLE      5
83         { "_viftable" },
84 #define N_IPX           6
85         { "_ipxpcb"},
86 #define N_IPXSTAT       7
87         { "_ipxstat"},
88 #define N_SPXSTAT       8
89         { "_spx_istat"},
90 #define N_DDPSTAT       9
91         { "_ddpstat"},
92 #define N_DDPCB         10
93         { "_ddpcb"},
94 #define N_NGSOCKS       11
95         { "_ngsocklist"},
96 #define N_IP6STAT       12
97         { "_ip6stat" },
98 #define N_ICMP6STAT     13
99         { "_icmp6stat" },
100 #define N_IPSECSTAT     14
101         { "_ipsecstat" },
102 #define N_IPSEC6STAT    15
103         { "_ipsec6stat" },
104 #define N_PIM6STAT      16
105         { "_pim6stat" },
106 #define N_MRT6STAT      17
107         { "_mrt6stat" },
108 #define N_MF6CTABLE     18
109         { "_mf6ctable" },
110 #define N_MIF6TABLE     19
111         { "_mif6table" },
112 #define N_PFKEYSTAT     20
113         { "_pfkeystat" },
114 #define N_MBSTAT        21
115         { "_mbstat" },
116 #define N_MBTYPES       22
117         { "_mbtypes" },
118 #define N_NMBCLUSTERS   23
119         { "_nmbclusters" },
120 #define N_NMBUFS        24
121         { "_nmbufs" },
122 #define N_MBHI          25
123         { "_mbuf_hiwm" },
124 #define N_CLHI          26
125         { "_clust_hiwm" },
126 #define N_NCPUS         27
127         { "_smp_cpus" },
128 #define N_PAGESZ        28
129         { "_pagesize" },
130 #define N_MBPSTAT       29
131         { "_mb_statpcpu" },
132 #define N_RTTRASH       30
133         { "_rttrash" },
134 #define N_MBLO          31
135         { "_mbuf_lowm" },
136 #define N_CLLO          32
137         { "_clust_lowm" },
138         { "" },
139 };
140
141 struct protox {
142         u_char  pr_index;               /* index into nlist of cb head */
143         u_char  pr_sindex;              /* index into nlist of stat block */
144         u_char  pr_wanted;              /* 1 if wanted, 0 otherwise */
145         void    (*pr_cblocks)(u_long, const char *, int);
146                                         /* control blocks printing routine */
147         void    (*pr_stats)(u_long, const char *, int);
148                                         /* statistics printing routine */
149         void    (*pr_istats)(char *);   /* per/if statistics printing routine */
150         const char      *pr_name;               /* well-known name */
151         u_long  pr_usesysctl;           /* non-zero if we use sysctl, not kvm */
152 } protox[] = {
153         { -1,           -1,             1,      protopr,
154           tcp_stats,    NULL,           "tcp",  IPPROTO_TCP },
155         { -1,           -1,             1,      protopr,
156           udp_stats,    NULL,           "udp",  IPPROTO_UDP },
157         { -1,           -1,             1,      protopr,
158           NULL,         NULL,           "divert",IPPROTO_DIVERT },
159         { -1,           -1,             1,      protopr,
160           ip_stats,     NULL,           "ip",   IPPROTO_RAW },
161         { -1,           -1,             1,      protopr,
162           icmp_stats,   NULL,           "icmp", IPPROTO_ICMP },
163         { -1,           -1,             1,      protopr,
164           igmp_stats,   NULL,           "igmp", IPPROTO_IGMP },
165 #ifdef IPSEC
166         { -1,           N_IPSECSTAT,    1,      NULL,
167           ipsec_stats,  NULL,           "ipsec",        0},
168 #endif
169         { -1,           -1,             1,      NULL,
170           bdg_stats,    NULL,           "bdg",  1 /* bridging... */ },
171         { -1,           -1,             1,      protopr,
172           pim_stats,    NULL,           "pim",  IPPROTO_PIM },
173         { -1,           -1,             0,      NULL,
174           NULL,         NULL,           NULL,   0 }
175 };
176
177 #ifdef INET6
178 struct protox ip6protox[] = {
179         { -1,           -1,             1,      protopr,
180           tcp_stats,    NULL,           "tcp",  IPPROTO_TCP },
181         { -1,           -1,             1,      protopr,
182           udp_stats,    NULL,           "udp",  IPPROTO_UDP },
183         { -1,           N_IP6STAT,      1,      protopr,
184           ip6_stats,    ip6_ifstats,    "ip6",  IPPROTO_RAW },
185         { -1,           N_ICMP6STAT,    1,      protopr,
186           icmp6_stats,  icmp6_ifstats,  "icmp6",IPPROTO_ICMPV6 },
187 #ifdef IPSEC
188         { -1,           N_IPSEC6STAT,   1,      NULL,
189           ipsec_stats,  NULL,           "ipsec6",0 },
190 #endif
191 #ifdef notyet
192         { -1,           N_PIM6STAT,     1,      NULL,
193           pim6_stats,   NULL,           "pim6", 0 },
194 #endif
195         { -1,           -1,             1,      NULL,
196           rip6_stats,   NULL,           "rip6", 0 },
197         { -1,           -1,             1,      NULL,
198           bdg_stats,    NULL,           "bdg",  1 /* bridging... */ },
199         { -1,           -1,             0,      NULL,
200           NULL,         NULL,           NULL,   0 }
201 };
202 #endif /*INET6*/
203
204 #ifdef IPSEC
205 struct protox pfkeyprotox[] = {
206         { -1,           N_PFKEYSTAT,    1,      NULL,
207           pfkey_stats,  NULL,           "pfkey", 0 },
208         { -1,           -1,             0,      NULL,
209           NULL,         NULL,           NULL,   0 }
210 };
211 #endif
212
213 struct protox atalkprotox[] = {
214         { N_DDPCB,      N_DDPSTAT,      1,      atalkprotopr,
215           ddp_stats,    NULL,           "ddp",  0 },
216         { -1,           -1,             0,      NULL,
217           NULL,         NULL,           NULL,   0 }
218 };
219
220 struct protox netgraphprotox[] = {
221         { N_NGSOCKS,    -1,             1,      netgraphprotopr,
222           NULL,         NULL,           "ctrl", 0 },
223         { N_NGSOCKS,    -1,             1,      netgraphprotopr,
224           NULL,         NULL,           "data", 0 },
225         { -1,           -1,             0,      NULL,
226           NULL,         NULL,           NULL,   0 }
227 };
228
229 struct protox ipxprotox[] = {
230         { N_IPX,        N_IPXSTAT,      1,      ipxprotopr,
231           ipx_stats,    NULL,           "ipx",  0 },
232         { N_IPX,        N_SPXSTAT,      1,      ipxprotopr,
233           spx_stats,    NULL,           "spx",  0 },
234         { -1,           -1,             0,      NULL,
235           NULL,         NULL,           0,      0 }
236 };
237
238 struct protox *protoprotox[] = {
239                                          protox,
240 #ifdef INET6
241                                          ip6protox,
242 #endif
243 #ifdef IPSEC
244                                          pfkeyprotox,
245 #endif
246                                          ipxprotox, atalkprotox, NULL };
247
248 static void printproto (struct protox *, const char *);
249 static void usage (void);
250 static struct protox *name2protox (char *);
251 static struct protox *knownname (char *);
252
253 static kvm_t *kvmd;
254 static char *nlistf = NULL, *memf = NULL;
255
256 int     Aflag;          /* show addresses of protocol control block */
257 int     aflag;          /* show all sockets (including servers) */
258 int     bflag;          /* show i/f total bytes in/out */
259 int     cflag;          /* show mbuf cache information */
260 int     dflag;          /* show i/f dropped packets */
261 int     gflag;          /* show group (multicast) routing or stats */
262 int     iflag;          /* show interfaces */
263 int     Lflag;          /* show size of listen queues */
264 int     mflag;          /* show memory stats */
265 int     numeric_addr;   /* show addresses numerically */
266 int     numeric_port;   /* show ports numerically */
267 static int pflag;       /* show given protocol */
268 int     rflag;          /* show routing tables (or routing stats) */
269 int     sflag;          /* show protocol statistics */
270 int     tflag;          /* show i/f watchdog timers */
271 int     Wflag;          /* wide display */
272 int     zflag;          /* zero stats */
273
274 int     interval;       /* repeat interval for i/f stats */
275
276 char    *interface;     /* desired i/f for stats, or NULL for all i/fs */
277 int     unit;           /* unit number for above */
278
279 int     af;             /* address family */
280
281 int
282 main(int argc, char *argv[])
283 {
284         struct protox *tp = NULL;  /* for printing cblocks & stats */
285         int ch;
286
287         af = AF_UNSPEC;
288
289         while ((ch = getopt(argc, argv, "Aabcdf:gI:iLlM:mN:np:rSstuWw:z")) != -1)
290                 switch(ch) {
291                 case 'A':
292                         Aflag = 1;
293                         break;
294                 case 'a':
295                         aflag = 1;
296                         break;
297                 case 'b':
298                         bflag = 1;
299                         break;
300                 case 'c':
301                         cflag = 1;
302                         break;
303                 case 'd':
304                         dflag = 1;
305                         break;
306                 case 'f':
307                         if (strcmp(optarg, "ipx") == 0)
308                                 af = AF_IPX;
309                         else if (strcmp(optarg, "inet") == 0)
310                                 af = AF_INET;
311 #ifdef INET6
312                         else if (strcmp(optarg, "inet6") == 0)
313                                 af = AF_INET6;
314 #endif /*INET6*/
315 #ifdef INET6
316                         else if (strcmp(optarg, "pfkey") == 0)
317                                 af = PF_KEY;
318 #endif /*INET6*/
319                         else if (strcmp(optarg, "unix") == 0)
320                                 af = AF_UNIX;
321                         else if (strcmp(optarg, "atalk") == 0)
322                                 af = AF_APPLETALK;
323                         else if (strcmp(optarg, "ng") == 0
324                             || strcmp(optarg, "netgraph") == 0)
325                                 af = AF_NETGRAPH;
326                         else if (strcmp(optarg, "link") == 0)
327                                 af = AF_LINK;
328                         else {
329                                 errx(1, "%s: unknown address family", optarg);
330                         }
331                         break;
332                 case 'g':
333                         gflag = 1;
334                         break;
335                 case 'I': {
336                         char *cp;
337
338                         iflag = 1;
339                         for (cp = interface = optarg; isalpha(*cp); cp++)
340                                 continue;
341                         unit = atoi(cp);
342                         break;
343                 }
344                 case 'i':
345                         iflag = 1;
346                         break;
347                 case 'L':
348                         Lflag = 1;
349                         break;
350                 case 'M':
351                         memf = optarg;
352                         break;
353                 case 'm':
354                         mflag = 1;
355                         break;
356                 case 'N':
357                         nlistf = optarg;
358                         break;
359                 case 'n':
360                         numeric_addr = numeric_port = 1;
361                         break;
362                 case 'p':
363                         if ((tp = name2protox(optarg)) == NULL) {
364                                 errx(1, 
365                                      "%s: unknown or uninstrumented protocol",
366                                      optarg);
367                         }
368                         pflag = 1;
369                         break;
370                 case 'r':
371                         rflag = 1;
372                         break;
373                 case 's':
374                         ++sflag;
375                         break;
376                 case 'S':
377                         numeric_addr = 1;
378                         break;
379                 case 't':
380                         tflag = 1;
381                         break;
382                 case 'u':
383                         af = AF_UNIX;
384                         break;
385                 case 'W':
386                 case 'l':
387                         Wflag = 1;
388                         break;
389                 case 'w':
390                         interval = atoi(optarg);
391                         iflag = 1;
392                         break;
393                 case 'z':
394                         zflag = 1;
395                         break;
396                 case '?':
397                 default:
398                         usage();
399                 }
400         argv += optind;
401         argc -= optind;
402
403 #define BACKWARD_COMPATIBILITY
404 #ifdef  BACKWARD_COMPATIBILITY
405         if (*argv) {
406                 if (isdigit(**argv)) {
407                         interval = atoi(*argv);
408                         if (interval <= 0)
409                                 usage();
410                         ++argv;
411                         iflag = 1;
412                 }
413                 if (*argv) {
414                         nlistf = *argv;
415                         if (*++argv)
416                                 memf = *argv;
417                 }
418         }
419 #endif
420
421         /*
422          * Discard setgid privileges if not the running kernel so that bad
423          * guys can't print interesting stuff from kernel memory.
424          */
425         if (nlistf != NULL || memf != NULL)
426                 setgid(getgid());
427
428         if (cflag && !mflag) {
429                 (void)fprintf(stderr, "-c only valid with -m\n");
430                 usage();
431         }
432         if (mflag) {
433                 if (memf != NULL) {
434                         if (kread(0, 0, 0) == 0)
435                                 mbpr(nl[N_MBSTAT].n_value,
436                                     nl[N_MBTYPES].n_value,
437                                     nl[N_NMBCLUSTERS].n_value,
438                                     nl[N_NMBUFS].n_value,
439                                     nl[N_MBHI].n_value,
440                                     nl[N_CLHI].n_value,
441                                     nl[N_MBLO].n_value,
442                                     nl[N_CLLO].n_value,
443                                     nl[N_NCPUS].n_value,
444                                     nl[N_PAGESZ].n_value,
445                                     nl[N_MBPSTAT].n_value);
446                 } else
447                         mbpr(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
448                 exit(0);
449         }
450 #if 0
451         /*
452          * Keep file descriptors open to avoid overhead
453          * of open/close on each call to get* routines.
454          */
455         sethostent(1);
456         setnetent(1);
457 #else
458         /*
459          * This does not make sense any more with DNS being default over
460          * the files.  Doing a setXXXXent(1) causes a tcp connection to be
461          * used for the queries, which is slower.
462          */
463 #endif
464         if (iflag && !sflag) {
465                 kread(0, 0, 0);
466                 intpr(interval, nl[N_IFNET].n_value, NULL);
467                 exit(0);
468         }
469         if (rflag) {
470                 kread(0, 0, 0);
471                 if (sflag)
472                         rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
473                 else
474                         routepr(nl[N_RTREE].n_value);
475                 exit(0);
476         }
477         if (gflag) {
478                 kread(0, 0, 0);
479                 if (sflag) {
480                         if (af == AF_INET || af == AF_UNSPEC)
481                                 mrt_stats(nl[N_MRTSTAT].n_value);
482 #ifdef INET6
483                         if (af == AF_INET6 || af == AF_UNSPEC)
484                                 mrt6_stats(nl[N_MRT6STAT].n_value);
485 #endif
486                 } else {
487                         if (af == AF_INET || af == AF_UNSPEC)
488                                 mroutepr(nl[N_MFCTABLE].n_value,
489                                          nl[N_VIFTABLE].n_value);
490 #ifdef INET6
491                         if (af == AF_INET6 || af == AF_UNSPEC)
492                                 mroute6pr(nl[N_MF6CTABLE].n_value,
493                                           nl[N_MIF6TABLE].n_value);
494 #endif
495                 }
496                 ifmalist_dump();
497                 exit(0);
498         }
499
500         kread(0, 0, 0);
501         if (tp) {
502                 printproto(tp, tp->pr_name);
503                 exit(0);
504         }
505         if (af == AF_INET || af == AF_UNSPEC)
506                 for (tp = protox; tp->pr_name; tp++)
507                         printproto(tp, tp->pr_name);
508 #ifdef INET6
509         if (af == AF_INET6 || af == AF_UNSPEC)
510                 for (tp = ip6protox; tp->pr_name; tp++)
511                         printproto(tp, tp->pr_name);
512 #endif /*INET6*/
513 #ifdef IPSEC
514         if (af == PF_KEY || af == AF_UNSPEC)
515                 for (tp = pfkeyprotox; tp->pr_name; tp++)
516                         printproto(tp, tp->pr_name);
517 #endif /*IPSEC*/
518         if (af == AF_IPX || af == AF_UNSPEC) {
519                 kread(0, 0, 0);
520                 for (tp = ipxprotox; tp->pr_name; tp++)
521                         printproto(tp, tp->pr_name);
522         }
523         if (af == AF_APPLETALK || af == AF_UNSPEC)
524                 for (tp = atalkprotox; tp->pr_name; tp++)
525                         printproto(tp, tp->pr_name);
526         if (af == AF_NETGRAPH || af == AF_UNSPEC)
527                 for (tp = netgraphprotox; tp->pr_name; tp++)
528                         printproto(tp, tp->pr_name);
529         if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
530                 unixpr();
531         exit(0);
532 }
533
534 /*
535  * Print out protocol statistics or control blocks (per sflag).
536  * If the interface was not specifically requested, and the symbol
537  * is not in the namelist, ignore this one.
538  */
539 static void
540 printproto(tp, name)
541         struct protox *tp;
542         const char *name;
543 {
544         void (*pr)(u_long, const char *, int);
545         u_long off;
546
547         if (sflag) {
548                 if (iflag) {
549                         if (tp->pr_istats)
550                                 intpr(interval, nl[N_IFNET].n_value,
551                                       tp->pr_istats);
552                         else if (pflag)
553                                 printf("%s: no per-interface stats routine\n",
554                                     tp->pr_name);
555                         return;
556                 }
557                 else {
558                         pr = tp->pr_stats;
559                         if (!pr) {
560                                 if (pflag)
561                                         printf("%s: no stats routine\n",
562                                             tp->pr_name);
563                                 return;
564                         }
565                         off = tp->pr_usesysctl ? tp->pr_usesysctl 
566                                 : nl[tp->pr_sindex].n_value;
567                 }
568         } else {
569                 pr = tp->pr_cblocks;
570                 if (!pr) {
571                         if (pflag)
572                                 printf("%s: no PCB routine\n", tp->pr_name);
573                         return;
574                 }
575                 off = tp->pr_usesysctl ? tp->pr_usesysctl
576                         : nl[tp->pr_index].n_value;
577         }
578         if (pr != NULL && (off || af != AF_UNSPEC))
579                 (*pr)(off, name, af);
580 }
581
582 /*
583  * Read kernel memory, return 0 on success.
584  */
585 int
586 kread(u_long addr, char *buf, int size)
587 {
588         if (kvmd == 0) {
589                 /*
590                  * XXX.
591                  */
592                 kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
593                 setgid(getgid());
594                 if (kvmd != NULL) {
595                         if (kvm_nlist(kvmd, nl) < 0) {
596                                 if(nlistf)
597                                         errx(1, "%s: kvm_nlist: %s", nlistf,
598                                              kvm_geterr(kvmd));
599                                 else
600                                         errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
601                         }
602
603                         if (nl[0].n_type == 0) {
604                                 if(nlistf)
605                                         errx(1, "%s: no namelist", nlistf);
606                                 else
607                                         errx(1, "no namelist");
608                         }
609                 } else {
610                         warnx("kvm not available");
611                         return(-1);
612                 }
613         }
614         if (!buf)
615                 return (0);
616         if (kvm_read(kvmd, addr, buf, size) != size) {
617                 warnx("%s", kvm_geterr(kvmd));
618                 return (-1);
619         }
620         return (0);
621 }
622
623 const char *
624 plural(int n)
625 {
626         return (n != 1 ? "s" : "");
627 }
628
629 const char *
630 plurales(int n)
631 {
632         return (n != 1 ? "es" : "");
633 }
634
635 const char *
636 pluralies(int n)
637 {
638         return (n != 1 ? "ies" : "y");
639 }
640
641 /*
642  * Find the protox for the given "well-known" name.
643  */
644 static struct protox *
645 knownname(char *name)
646 {
647         struct protox **tpp, *tp;
648
649         for (tpp = protoprotox; *tpp; tpp++)
650                 for (tp = *tpp; tp->pr_name; tp++)
651                         if (strcmp(tp->pr_name, name) == 0)
652                                 return (tp);
653         return (NULL);
654 }
655
656 /*
657  * Find the protox corresponding to name.
658  */
659 static struct protox *
660 name2protox(char *name)
661 {
662         struct protox *tp;
663         char **alias;                   /* alias from p->aliases */
664         struct protoent *p;
665
666         /*
667          * Try to find the name in the list of "well-known" names. If that
668          * fails, check if name is an alias for an Internet protocol.
669          */
670         if ((tp = knownname(name)) != NULL)
671                 return (tp);
672
673         setprotoent(1);                 /* make protocol lookup cheaper */
674         while ((p = getprotoent()) != NULL) {
675                 /* assert: name not same as p->name */
676                 for (alias = p->p_aliases; *alias; alias++)
677                         if (strcmp(name, *alias) == 0) {
678                                 endprotoent();
679                                 return (knownname(p->p_name));
680                         }
681         }
682         endprotoent();
683         return (NULL);
684 }
685
686 static void
687 usage(void)
688 {
689         (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
690 "usage: netstat [-AaLnSW] [-f protocol_family | -p protocol]\n"
691 "               [-M core] [-N system]",
692 "       netstat -i | -I interface [-abdnt] [-f address_family]\n"
693 "               [-M core] [-N system]",
694 "       netstat -w wait [-I interface] [-d] [-M core] [-N system]",
695 "       netstat -s [-s] [-z] [-f protocol_family | -p protocol] [-M core]",
696 "       netstat -i | -I interface -s [-f protocol_family | -p protocol]\n"
697 "               [-M core] [-N system]",
698 "       netstat -m [-c] [-M core] [-N system]",
699 "       netstat -r [-AenW] [-f address_family] [-M core] [-N system]",
700 "       netstat -rs [-s] [-M core] [-N system]",
701 "       netstat -g [-W] [-f address_family] [-M core] [-N system]",
702 "       netstat -gs [-s] [-f address_family] [-M core] [-N system]");
703         exit(1);
704 }