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