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