bc(1): Raise WARNS to 3 and fix a warning.
[dragonfly.git] / usr.bin / netstat / inet.c
1 /*
2  * Copyright (c) 1983, 1988, 1993, 1995
3  *      The 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  * @(#)inet.c   8.5 (Berkeley) 5/24/95
34  * $FreeBSD: src/usr.bin/netstat/inet.c,v 1.37.2.11 2003/11/27 14:46:49 ru Exp $
35  */
36
37 #include <sys/param.h>
38 #include <sys/queue.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
41 #include <sys/sysctl.h>
42 #include <sys/protosw.h>
43 #include <sys/time.h>
44
45 #include <net/route.h>
46 #include <netinet/in.h>
47 #include <netinet/in_systm.h>
48 #include <netinet/ip.h>
49 #include <netinet/ip_carp.h>
50 #ifdef INET6
51 #include <netinet/ip6.h>
52 #endif /* INET6 */
53 #include <netinet/in_pcb.h>
54 #include <netinet/ip_icmp.h>
55 #include <netinet/icmp_var.h>
56 #include <netinet/igmp_var.h>
57 #include <netinet/ip_var.h>
58 #include <netinet/pim_var.h>
59 #include <netinet/tcp.h>
60 #include <netinet/tcpip.h>
61 #include <netinet/tcp_seq.h>
62 #define TCPSTATES
63 #include <netinet/tcp_fsm.h>
64 #include <netinet/tcp_timer.h>
65 #include <netinet/tcp_var.h>
66 #include <netinet/tcp_debug.h>
67 #include <netinet/udp.h>
68 #include <netinet/udp_var.h>
69
70 #include <arpa/inet.h>
71 #include <err.h>
72 #include <errno.h>
73 #include <libutil.h>
74 #include <netdb.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include <unistd.h>
79 #include "netstat.h"
80
81 char    *inetname (struct in_addr *);
82 void    inetprint (struct in_addr *, int, const char *, int);
83 #ifdef INET6
84 extern void     inet6print (struct in6_addr *, int, const char *, int);
85 static int udp_done, tcp_done;
86 #endif /* INET6 */
87
88 /*
89  * Print a summary of connections related to an Internet
90  * protocol.  For TCP, also give state of connection.
91  * Listening processes (aflag) are suppressed unless the
92  * -a (all) flag is specified.
93  */
94
95 static int ppr_first = 1;
96 static void outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp);
97
98 void
99 protopr(u_long proto, const char *name, int af1 __unused)
100 {
101         int istcp;
102         void *buf;
103         const char *mibvar;
104         size_t i, len;
105
106         istcp = 0;
107         switch (proto) {
108         case IPPROTO_TCP:
109 #ifdef INET6
110                 if (tcp_done != 0)
111                         return;
112                 else
113                         tcp_done = 1;
114 #endif
115                 istcp = 1;
116                 mibvar = "net.inet.tcp.pcblist";
117                 break;
118         case IPPROTO_UDP:
119 #ifdef INET6
120                 if (udp_done != 0)
121                         return;
122                 else
123                         udp_done = 1;
124 #endif
125                 mibvar = "net.inet.udp.pcblist";
126                 break;
127         case IPPROTO_DIVERT:
128                 mibvar = "net.inet.divert.pcblist";
129                 break;
130         default:
131                 mibvar = "net.inet.raw.pcblist";
132                 break;
133         }
134         len = 0;
135         if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
136                 if (errno != ENOENT)
137                         warn("sysctl: %s", mibvar);
138                 return;
139         }
140         if (len == 0)
141                 return;
142         if ((buf = malloc(len)) == NULL) {
143                 warn("malloc %lu bytes", (u_long)len);
144                 return;
145         }
146         if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
147                 warn("sysctl: %s", mibvar);
148                 free(buf);
149                 return;
150         }
151
152         if (istcp) {
153                 struct xtcpcb *tcp = buf;
154                 len /= sizeof(*tcp);
155                 for (i = 0; i < len; i++) {
156                         if (tcp[i].xt_len != sizeof(*tcp))
157                                 break;
158                         outputpcb(proto, name, &tcp[i].xt_inp,
159                                   &tcp[i].xt_socket, &tcp[i].xt_tp);
160                 }
161         } else {
162                 struct xinpcb *in = buf;
163                 len /= sizeof(*in);
164                 for (i = 0; i < len; i++) {
165                         if (in[i].xi_len != sizeof(*in))
166                                 break;
167                         outputpcb(proto, name, &in[i].xi_inp,
168                                   &in[i].xi_socket, NULL);
169                 }
170         }
171         free(buf);
172 }
173
174 static void
175 outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp)
176 {
177         const char *vchar;
178         static struct clockinfo clockinfo;
179
180         if (clockinfo.hz == 0) {
181                 size_t size = sizeof(clockinfo);
182                 sysctlbyname("kern.clockrate", &clockinfo, &size, NULL, 0);
183                 if (clockinfo.hz == 0)
184                         clockinfo.hz = 100;
185         }
186
187         /* Ignore sockets for protocols other than the desired one. */
188         if (so->xso_protocol != (int)proto)
189                 return;
190
191         if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
192 #ifdef INET6
193             || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
194 #endif /* INET6 */
195             || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
196 #ifdef INET6
197                 && (inp->inp_vflag & INP_IPV6) == 0
198 #endif /* INET6 */
199                 ))
200             ) {
201                 return;
202         }
203         if (!aflag && ( 
204                 (proto == IPPROTO_TCP && tp->t_state == TCPS_LISTEN) ||
205                 (af == AF_INET && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
206 #ifdef INET6
207             || (af == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
208 #endif /* INET6 */
209             || (af == AF_UNSPEC && (((inp->inp_vflag & INP_IPV4) != 0 &&
210                 inet_lnaof(inp->inp_laddr) == INADDR_ANY)
211 #ifdef INET6
212             || ((inp->inp_vflag & INP_IPV6) != 0 &&
213                 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
214 #endif
215                   ))
216              )) {
217                 return;
218         }
219
220         if (ppr_first) {
221                 if (!Lflag) {
222                         printf("Active Internet connections");
223                         if (aflag)
224                                 printf(" (including servers)");
225                 } else {
226                         printf("Current listen queue sizes "
227                                 "(qlen/incqlen/maxqlen)");
228                 }
229                 putchar('\n');
230                 if (Aflag)
231                         printf("%-8.8s ", "Socket");
232                 if (Pflag)
233                         printf("%8.8s %8.8s %8.8s ", "TxWin", "Unacked", "RTT/ms");
234                 if (Lflag) {
235                         printf("%-5.5s %-14.14s %-22.22s\n",
236                                 "Proto", "Listen", "Local Address");
237                 } else {
238                         printf((Aflag && !Wflag) ?
239                             "%-5.5s %-6.6s %-6.6s %-17.17s %-17.17s %s\n" :
240                             "%-5.5s %-6.6s %-6.6s %-21.21s %-21.21s %s\n",
241                             "Proto", "Recv-Q", "Send-Q",
242                             "Local Address", "Foreign Address",
243                             "(state)");
244                 }
245                 ppr_first = 0;
246         }
247         if (Lflag && so->so_qlimit == 0)
248                 return;
249         if (Aflag) {
250                 if (tp)
251                         printf("%8lx ", (u_long)inp->inp_ppcb);
252                 else
253                         printf("%8lx ", (u_long)so->so_pcb);
254         }
255         if (Pflag) {
256                 if (tp) {
257                         int window = MIN(tp->snd_cwnd, tp->snd_bwnd);
258                         if (window == 1073725440)
259                                 printf("%8s ", "max");
260                         else
261                                 printf("%8d ", (int)MIN(tp->snd_cwnd, tp->snd_bwnd));
262                         printf("%8d ", (int)(tp->snd_max - tp->snd_una));
263                         if (tp->t_srtt == 0)
264                             printf("%8s ", "-");
265                         else
266                             printf("%8.3f ", (double)tp->t_srtt * 1000.0 / TCP_RTT_SCALE / clockinfo.hz);
267                 } else {
268                         printf("%8s %8s %8s ", "-", "-", "-");
269                 }
270         }
271 #ifdef INET6
272         if ((inp->inp_vflag & INP_IPV6) != 0)
273                 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "46" : "6 ";
274         else
275 #endif
276                 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4 " : "  ";
277
278         printf("%-3.3s%-2.2s ", name, vchar);
279         if (Lflag) {
280                 char buf[15];
281
282                 snprintf(buf, sizeof(buf), "%d/%d/%d", so->so_qlen,
283                          so->so_incqlen, so->so_qlimit);
284                 printf("%-13.13s ", buf);
285         } else if (Bflag) {
286                 printf("%6ld %6ld ",
287                        so->so_rcv.sb_hiwat,
288                        so->so_snd.sb_hiwat);
289         } else {
290                 printf("%6ld %6ld ",
291                        so->so_rcv.sb_cc,
292                        so->so_snd.sb_cc);
293         }
294         if (numeric_port) {
295                 if (inp->inp_vflag & INP_IPV4) {
296                         inetprint(&inp->inp_laddr, (int)inp->inp_lport,
297                                   name, 1);
298                         if (!Lflag)
299                                 inetprint(&inp->inp_faddr,
300                                           (int)inp->inp_fport, name, 1);
301                 }
302 #ifdef INET6
303                 else if (inp->inp_vflag & INP_IPV6) {
304                         inet6print(&inp->in6p_laddr,
305                                    (int)inp->inp_lport, name, 1);
306                         if (!Lflag)
307                                 inet6print(&inp->in6p_faddr,
308                                            (int)inp->inp_fport, name, 1);
309                 } /* else nothing printed now */
310 #endif /* INET6 */
311         } else if (inp->inp_flags & INP_ANONPORT) {
312                 if (inp->inp_vflag & INP_IPV4) {
313                         inetprint(&inp->inp_laddr, (int)inp->inp_lport,
314                                   name, 1);
315                         if (!Lflag)
316                                 inetprint(&inp->inp_faddr,
317                                           (int)inp->inp_fport, name, 0);
318                 }
319 #ifdef INET6
320                 else if (inp->inp_vflag & INP_IPV6) {
321                         inet6print(&inp->in6p_laddr,
322                                    (int)inp->inp_lport, name, 1);
323                         if (!Lflag)
324                                 inet6print(&inp->in6p_faddr,
325                                            (int)inp->inp_fport, name, 0);
326                 } /* else nothing printed now */
327 #endif /* INET6 */
328         } else {
329                 if (inp->inp_vflag & INP_IPV4) {
330                         inetprint(&inp->inp_laddr, (int)inp->inp_lport,
331                                   name, 0);
332                         if (!Lflag)
333                                 inetprint(&inp->inp_faddr,
334                                           (int)inp->inp_fport, name,
335                                           inp->inp_lport !=
336                                                 inp->inp_fport);
337                 }
338 #ifdef INET6
339                 else if (inp->inp_vflag & INP_IPV6) {
340                         inet6print(&inp->in6p_laddr,
341                                    (int)inp->inp_lport, name, 0);
342                         if (!Lflag)
343                                 inet6print(&inp->in6p_faddr,
344                                            (int)inp->inp_fport, name,
345                                            inp->inp_lport !=
346                                                 inp->inp_fport);
347                 } /* else nothing printed now */
348 #endif /* INET6 */
349         }
350         if (tp && !Lflag) {
351                 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
352                         printf("%d", tp->t_state);
353               else {
354                         printf("%s", tcpstates[tp->t_state]);
355 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
356                       /* Show T/TCP `hidden state' */
357                       if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
358                               putchar('*');
359 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
360               }
361         }
362         putchar('\n');
363 }
364
365
366
367 #define CPU_STATS_FUNC(proto,type)                            \
368 static void                                                   \
369 proto ##_stats_agg(type *ary, type *ttl, int cpucnt)          \
370 {                                                             \
371     int i, off, siz;                                          \
372     siz = sizeof(type);                                       \
373                                                               \
374     if (!ary && !ttl)                                         \
375         return;                                               \
376                                                               \
377     bzero(ttl, siz);                                          \
378     if (cpucnt == 1) {                                        \
379         *ttl = ary[0];                                        \
380     } else {                                                  \
381         for (i = 0; i < cpucnt; ++i) {                        \
382             for (off = 0; off < siz; off += sizeof(u_long)) { \
383                 *(u_long *)((char *)(*(&ttl)) + off) +=       \
384                 *(u_long *)((char *)&ary[i] + off);           \
385             }                                                 \
386         }                                                     \
387     }                                                         \
388 }
389 CPU_STATS_FUNC(tcp, struct tcp_stats);
390 CPU_STATS_FUNC(ip, struct ip_stats);
391
392 /*
393  * Dump TCP statistics structure.
394  */
395 void
396 tcp_stats(u_long off __unused, const char *name, int af1 __unused)
397 {
398         struct tcp_stats tcpstat, *stattmp;
399         struct tcp_stats zerostat[SMP_MAXCPU];
400         size_t len = sizeof(struct tcp_stats) * SMP_MAXCPU;
401         int cpucnt;
402         
403         if (zflag)
404                 memset(zerostat, 0, len);
405
406         if ((stattmp = malloc(len)) == NULL) {
407                 return;
408         } else {
409                 if (sysctlbyname("net.inet.tcp.stats", stattmp, &len,
410                         zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
411                         warn("sysctl: net.inet.tcp.stats");
412                         free(stattmp);
413                         return;
414                 } else {
415                         if ((stattmp = realloc(stattmp, len)) == NULL) {
416                                 warn("tcp_stats");
417                                 return;
418                         }
419                 }
420         }
421         cpucnt = len / sizeof(struct tcp_stats);
422         tcp_stats_agg(stattmp, &tcpstat, cpucnt);
423
424 #ifdef INET6
425         if (tcp_done != 0)
426                 return;
427         else
428                 tcp_done = 1;
429 #endif
430
431         printf ("%s:\n", name);
432
433 #define p(f, m) if (tcpstat.f || sflag <= 1) \
434     printf(m, tcpstat.f, plural(tcpstat.f))
435 #define p1a(f, m) if (tcpstat.f || sflag <= 1) \
436     printf(m, tcpstat.f)
437 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
438     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
439 #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
440     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
441 #define p3(f, m) if (tcpstat.f || sflag <= 1) \
442     printf(m, tcpstat.f, plurales(tcpstat.f))
443
444         p(tcps_sndtotal, "\t%lu packet%s sent\n");
445         p2(tcps_sndpack,tcps_sndbyte,
446                 "\t\t%lu data packet%s (%lu byte%s)\n");
447         p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
448                 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
449         p2(tcps_sndsackrtopack, tcps_sndsackrtobyte,
450                 "\t\t%lu data packet%s (%lu byte%s) retransmitted by SACK\n");
451         p2(tcps_sndsackpack, tcps_sndsackbyte,
452                 "\t\t%lu data packet%s (%lu byte%s) sent by SACK recovery\n");
453         p2(tcps_sackrescue, tcps_sackrescue_try,
454                 "\t\t%lu SACK rescue packet%s sent (of %lu attempt%s)\n");
455         p2a(tcps_sndfastrexmit, tcps_sndearlyrexmit,
456                 "\t\t%lu Fast Retransmit%s (%lu early)\n");
457         p(tcps_sndlimited, "\t\t%lu packet%s sent by Limited Transmit\n");
458         p2(tcps_sndrtobad, tcps_eifelresponse,
459                 "\t\t%lu spurious RTO retransmit%s (%lu Eifel-response%s)\n");
460         p2a(tcps_sndfastrexmitbad, tcps_sndearlyrexmitbad,
461                 "\t\t%lu spurious Fast Retransmit%s (%lu early)\n");
462         p2a(tcps_eifeldetected, tcps_rttcantdetect,
463                 "\t\t%lu Eifel-detected spurious retransmit%s (%lu non-RTT)\n");
464         p(tcps_rttdetected, "\t\t%lu RTT-detected spurious retransmit%s\n");
465         p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
466         p(tcps_sndsackopt, "\t\t%lu SACK option%s sent\n");
467         p(tcps_snddsackopt, "\t\t%lu D-SACK option%s sent\n");
468         p2a(tcps_sndacks, tcps_delack,
469                 "\t\t%lu ack-only packet%s (%lu delayed)\n");
470         p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
471         p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
472         p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
473         p(tcps_sndctrl, "\t\t%lu control packet%s\n");
474         p(tcps_rcvtotal, "\t%lu packet%s received\n");
475         p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
476         p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
477         p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
478         p2(tcps_rcvpack, tcps_rcvbyte,
479                 "\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
480         p2(tcps_rcvduppack, tcps_rcvdupbyte,
481                 "\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
482         p2(tcps_pawsdrop, tcps_pawsaccept,
483                 "\t\t%lu old duplicate packet%s (%lu packet%s accepted)\n");
484         p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
485                 "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
486         p2(tcps_rcvoopack, tcps_rcvoobyte,
487                 "\t\t%lu out-of-order packet%s (%lu byte%s)\n");
488         p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
489                 "\t\t%lu packet%s (%lu byte%s) of data after window\n");
490         p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
491         p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
492         p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
493         p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
494         p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
495         p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
496         p(tcps_rcvbadsackopt, "\t\t%lu bad SACK option%s\n");
497         p1a(tcps_sackrenege, "\t\t%lu other side reneged\n");
498         p(tcps_connattempt, "\t%lu connection request%s\n");
499         p(tcps_accepts, "\t%lu connection accept%s\n");
500         p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
501         p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
502         p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
503         p2(tcps_closed, tcps_drops,
504                 "\t%lu connection%s closed (including %lu drop%s)\n");
505         p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
506         p(tcps_cachedrttvar, 
507           "\t\t%lu connection%s updated cached RTT variance on close\n");
508         p(tcps_cachedssthresh,
509           "\t\t%lu connection%s updated cached ssthresh on close\n");
510         p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
511         p2(tcps_rttupdated, tcps_segstimed,
512                 "\t%lu segment%s updated rtt (of %lu attempt%s)\n");
513         p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
514         p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
515         p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
516         p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
517         p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
518         p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
519         p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
520         p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
521         p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
522         p(tcps_sndidle, "\t%lu send idle%s\n");
523
524         p1a(tcps_sc_added, "\t%lu syncache entries added\n"); 
525         p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n"); 
526         p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n"); 
527         p1a(tcps_sc_dropped, "\t\t%lu dropped\n"); 
528         p1a(tcps_sc_completed, "\t\t%lu completed\n"); 
529         p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n"); 
530         p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n"); 
531         p1a(tcps_sc_reset, "\t\t%lu reset\n"); 
532         p1a(tcps_sc_stale, "\t\t%lu stale\n"); 
533         p1a(tcps_sc_aborted, "\t\t%lu aborted\n"); 
534         p1a(tcps_sc_badack, "\t\t%lu badack\n"); 
535         p1a(tcps_sc_unreach, "\t\t%lu unreach\n"); 
536         p1a(tcps_sc_zonefail, "\t\t%lu zone failures\n"); 
537         p1a(tcps_sc_sendcookie, "\t\t%lu cookies sent\n"); 
538         p1a(tcps_sc_recvcookie, "\t\t%lu cookies received\n"); 
539
540         p(tcps_sacksbupdate, "\t%lu SACK scoreboard update%s\n");
541         p(tcps_sacksboverflow, "\t\t%lu overflow%s\n");
542         p(tcps_sacksbfailed, "\t\t%lu failure%s\n");
543         p(tcps_sacksbreused, "\t\t%lu record%s reused\n");
544         p(tcps_sacksbfast, "\t\t%lu record%s fast allocated\n");
545
546         free(stattmp);
547 #undef p
548 #undef p1a
549 #undef p2
550 #undef p2a
551 #undef p3
552 }
553
554 /*
555  * Dump UDP statistics structure.
556  */
557 void
558 udp_stats(u_long off __unused, const char *name, int af1 __unused)
559 {
560         struct udpstat udpstat, zerostat;
561         size_t len = sizeof udpstat;
562         u_long delivered;
563
564         if (zflag)
565                 memset(&zerostat, 0, len);
566         if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
567             zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
568                 warn("sysctl: net.inet.udp.stats");
569                 return;
570         }
571
572 #ifdef INET6
573         if (udp_done != 0)
574                 return;
575         else
576                 udp_done = 1;
577 #endif
578
579         printf("%s:\n", name);
580 #define p(f, m) if (udpstat.f || sflag <= 1) \
581     printf(m, udpstat.f, plural(udpstat.f))
582 #define p1a(f, m) if (udpstat.f || sflag <= 1) \
583     printf(m, udpstat.f)
584         p(udps_ipackets, "\t%lu datagram%s received\n");
585         p1a(udps_hdrops, "\t%lu with incomplete header\n");
586         p1a(udps_badlen, "\t%lu with bad data length field\n");
587         p1a(udps_badsum, "\t%lu with bad checksum\n");
588         p1a(udps_nosum, "\t%lu with no checksum\n");
589         p1a(udps_noport, "\t%lu dropped due to no socket\n");
590         p(udps_noportbcast,
591             "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
592         p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
593         p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
594         delivered = udpstat.udps_ipackets -
595                     udpstat.udps_hdrops -
596                     udpstat.udps_badlen -
597                     udpstat.udps_badsum -
598                     udpstat.udps_noport -
599                     udpstat.udps_noportbcast -
600                     udpstat.udps_fullsock;
601         if (delivered || sflag <= 1)
602                 printf("\t%lu delivered\n", delivered);
603         p(udps_opackets, "\t%lu datagram%s output\n");
604 #undef p
605 #undef p1a
606 }
607
608 /* 
609  * Dump CARP statistics structure.
610  */
611 void
612 carp_stats(u_long off __unused, const char *name, int af1 __unused)
613 {
614        struct carpstats carpstat, zerostat;
615        size_t len = sizeof(struct carpstats);
616
617        if (zflag)
618                memset(&zerostat, 0, len);
619        if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
620            zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
621                warn("sysctl: net.inet.carp.stats");
622                return;
623        }
624
625        printf("%s:\n", name);
626
627 #define p(f, m) if (carpstat.f || sflag <= 1) \
628        printf(m, (uintmax_t)carpstat.f, plural((int)carpstat.f))
629 #define p2(f, m) if (carpstat.f || sflag <= 1) \
630        printf(m, (uintmax_t)carpstat.f)
631
632        p(carps_ipackets, "\t%ju packet%s received (IPv4)\n");
633        p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n");
634        p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n");
635        p(carps_hdrops, "\t\t%ju packet%s shorter than header\n");
636        p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n");
637        p(carps_badver, "\t\t%ju discarded packet%s with a bad version\n");
638        p2(carps_badlen, "\t\t%ju discarded because packet too short\n");
639        p2(carps_badauth, "\t\t%ju discarded for bad authentication\n");
640        p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n");
641        p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n");
642        p(carps_opackets, "\t%ju packet%s sent (IPv4)\n");
643        p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n");
644        p2(carps_onomem, "\t\t%ju send failed due to mbuf memory error\n");
645 #if notyet
646        p(carps_ostates, "\t\t%s state update%s sent\n");
647 #endif
648 #undef p
649 #undef p2
650 }
651
652 /*
653  * Dump IP statistics structure.
654  */
655 void
656 ip_stats(u_long off __unused, const char *name, int af1 __unused)
657 {
658         struct ip_stats ipstat, *stattmp;
659         struct ip_stats zerostat[SMP_MAXCPU];
660         size_t len = sizeof(struct ip_stats) * SMP_MAXCPU;
661         int cpucnt;
662
663         if (zflag)
664                 memset(zerostat, 0, len);
665         if ((stattmp = malloc(len)) == NULL) {
666                 return;
667         } else {
668                 if (sysctlbyname("net.inet.ip.stats", stattmp, &len,
669                         zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
670                                 warn("sysctl: net.inet.ip.stats");
671                                 free(stattmp);
672                                 return;
673                 } else {
674                         if ((stattmp = realloc(stattmp, len)) == NULL) {
675                                 warn("ip_stats");
676                                 return;
677                         }
678                 }
679         }
680         cpucnt = len / sizeof(struct ip_stats);
681         ip_stats_agg(stattmp, &ipstat, cpucnt);
682
683         printf("%s:\n", name);
684
685 #define p(f, m) if (ipstat.f || sflag <= 1) \
686     printf(m, ipstat.f, plural(ipstat.f))
687 #define p1a(f, m) if (ipstat.f || sflag <= 1) \
688     printf(m, ipstat.f)
689
690         p(ips_total, "\t%lu total packet%s received\n");
691         p(ips_badsum, "\t%lu bad header checksum%s\n");
692         p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
693         p1a(ips_tooshort, "\t%lu with data size < data length\n");
694         p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n");
695         p1a(ips_badhlen, "\t%lu with header length < data size\n");
696         p1a(ips_badlen, "\t%lu with data length < header length\n");
697         p1a(ips_badoptions, "\t%lu with bad options\n");
698         p1a(ips_badvers, "\t%lu with incorrect version number\n");
699         p(ips_fragments, "\t%lu fragment%s received\n");
700         p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
701         p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
702         p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
703         p(ips_delivered, "\t%lu packet%s for this host\n");
704         p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
705         p(ips_forward, "\t%lu packet%s forwarded");
706         p(ips_fastforward, " (%lu packet%s fast forwarded)");
707         if (ipstat.ips_forward || sflag <= 1) 
708                 putchar('\n');
709         p(ips_cantforward, "\t%lu packet%s not forwardable\n");
710         p(ips_notmember,
711           "\t%lu packet%s received for unknown multicast group\n");
712         p(ips_redirectsent, "\t%lu redirect%s sent\n");
713         p(ips_localout, "\t%lu packet%s sent from this host\n");
714         p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
715         p(ips_odropped,
716           "\t%lu output packet%s dropped due to no bufs, etc.\n");
717         p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
718         p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
719         p(ips_ofragments, "\t%lu fragment%s created\n");
720         p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
721         p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
722         p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
723         free(stattmp);
724 #undef p
725 #undef p1a
726 }
727
728 static  const char *icmpnames[] = {
729         "echo reply",
730         "#1",
731         "#2",
732         "destination unreachable",
733         "source quench",
734         "routing redirect",
735         "#6",
736         "#7",
737         "echo",
738         "router advertisement",
739         "router solicitation",
740         "time exceeded",
741         "parameter problem",
742         "time stamp",
743         "time stamp reply",
744         "information request",
745         "information request reply",
746         "address mask request",
747         "address mask reply",
748 };
749
750 /*
751  * Dump ICMP statistics.
752  */
753 void
754 icmp_stats(u_long off __unused, const char *name, int af1 __unused)
755 {
756         struct icmpstat icmpstat, zerostat;
757         int i, first;
758         int mib[4];             /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
759         size_t len;
760
761         mib[0] = CTL_NET;
762         mib[1] = PF_INET;
763         mib[2] = IPPROTO_ICMP;
764         mib[3] = ICMPCTL_STATS;
765
766         len = sizeof icmpstat;
767         if (zflag)
768                 memset(&zerostat, 0, len);
769         if (sysctl(mib, 4, &icmpstat, &len,
770             zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
771                 warn("sysctl: net.inet.icmp.stats");
772                 return;
773         }
774
775         printf("%s:\n", name);
776
777 #define p(f, m) if (icmpstat.f || sflag <= 1) \
778     printf(m, icmpstat.f, plural(icmpstat.f))
779 #define p1a(f, m) if (icmpstat.f || sflag <= 1) \
780     printf(m, icmpstat.f)
781 #define p2(f, m) if (icmpstat.f || sflag <= 1) \
782     printf(m, icmpstat.f, plurales(icmpstat.f))
783
784         p(icps_error, "\t%lu call%s to icmp_error\n");
785         p(icps_oldicmp,
786             "\t%lu error%s not generated 'cuz old message was icmp\n");
787         for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
788                 if (icmpstat.icps_outhist[i] != 0) {
789                         if (first) {
790                                 printf("\tOutput histogram:\n");
791                                 first = 0;
792                         }
793                         printf("\t\t%s: %lu\n", icmpnames[i],
794                                 icmpstat.icps_outhist[i]);
795                 }
796         p(icps_badcode, "\t%lu message%s with bad code fields\n");
797         p(icps_tooshort, "\t%lu message%s < minimum length\n");
798         p(icps_checksum, "\t%lu bad checksum%s\n");
799         p(icps_badlen, "\t%lu message%s with bad length\n");
800         p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
801         p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
802         for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
803                 if (icmpstat.icps_inhist[i] != 0) {
804                         if (first) {
805                                 printf("\tInput histogram:\n");
806                                 first = 0;
807                         }
808                         printf("\t\t%s: %lu\n", icmpnames[i],
809                                 icmpstat.icps_inhist[i]);
810                 }
811         p(icps_reflect, "\t%lu message response%s generated\n");
812         p2(icps_badaddr, "\t%lu invalid return address%s\n");
813         p(icps_noroute, "\t%lu no return route%s\n");
814 #undef p
815 #undef p1a
816 #undef p2
817         mib[3] = ICMPCTL_MASKREPL;
818         len = sizeof i;
819         if (sysctl(mib, 4, &i, &len, NULL, 0) < 0)
820                 return;
821         printf("\tICMP address mask responses are %sabled\n", 
822                i ? "en" : "dis");
823 }
824
825 /*
826  * Dump IGMP statistics structure.
827  */
828 void
829 igmp_stats(u_long off __unused, const char *name, int af1 __unused)
830 {
831         struct igmpstat igmpstat, zerostat;
832         size_t len = sizeof igmpstat;
833
834         if (zflag)
835                 memset(&zerostat, 0, len);
836         if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
837             zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
838                 warn("sysctl: net.inet.igmp.stats");
839                 return;
840         }
841
842         printf("%s:\n", name);
843
844 #define p(f, m) if (igmpstat.f || sflag <= 1) \
845     printf(m, igmpstat.f, plural(igmpstat.f))
846 #define py(f, m) if (igmpstat.f || sflag <= 1) \
847     printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
848         p(igps_rcv_total, "\t%u message%s received\n");
849         p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
850         p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
851         py(igps_rcv_queries, "\t%u membership quer%s received\n");
852         py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
853         p(igps_rcv_reports, "\t%u membership report%s received\n");
854         p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
855         p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
856         p(igps_snd_reports, "\t%u membership report%s sent\n");
857 #undef p
858 #undef py
859 }
860
861 /*
862  * Dump PIM statistics structure.
863  */
864 void
865 pim_stats(u_long off __unused, const char *name, int af1 __unused)
866 {
867         struct pimstat pimstat, zerostat;
868         size_t len = sizeof pimstat;
869
870         if (zflag)
871                 memset(&zerostat, 0, len);
872         if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
873             zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
874                 if (errno != ENOENT)
875                         warn("sysctl: net.inet.pim.stats");
876                 return;
877         }
878
879         printf("%s:\n", name);
880
881 #define p(f, m) if (pimstat.f || sflag <= 1) \
882     printf(m, (uintmax_t)pimstat.f, plural(pimstat.f))
883 #define py(f, m) if (pimstat.f || sflag <= 1) \
884     printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y")
885         p(pims_rcv_total_msgs, "\t%ju message%s received\n");
886         p(pims_rcv_total_bytes, "\t%ju byte%s received\n");
887         p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
888         p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n");
889         p(pims_rcv_badversion, "\t%ju message%s received with bad version\n");
890         p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n");
891         p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n");
892         p(pims_rcv_registers_wrongiif, "\t%ju data register message%s received on wrong iif\n");
893         p(pims_rcv_badregisters, "\t%ju bad register%s received\n");
894         p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n");
895         p(pims_snd_registers_bytes, "\t%ju data register byte%s sent\n");
896 #undef p
897 #undef py
898 }
899
900 /*
901  * Pretty print an Internet address (net address + port).
902  */
903 void
904 inetprint(struct in_addr *in, int port, const char *proto, int num_port)
905 {
906         struct servent *sp = NULL;
907         char line[80], *cp;
908         int width;
909
910         if (Wflag)
911             sprintf(line, "%s.", inetname(in));
912         else
913             sprintf(line, "%.*s.", (Aflag && !num_port) ? 12 : 16, inetname(in));
914         cp = strchr(line, '\0');
915         if (!num_port && port)
916                 sp = getservbyport((int)port, proto);
917         if (sp || port == 0)
918                 sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
919         else
920                 sprintf(cp, "%d ", ntohs((u_short)port));
921         width = (Aflag && !Wflag) ? 17 : 21;
922         if (Wflag)
923             printf("%-*s ", width, line);
924         else
925             printf("%-*.*s ", width, width, line);
926 }
927
928 /*
929  * Construct an Internet address representation.
930  * If numeric_addr has been supplied, give
931  * numeric value, otherwise try for symbolic name.
932  */
933 char *
934 inetname(struct in_addr *inp)
935 {
936         char *cp;
937         static char line[MAXHOSTNAMELEN];
938         struct hostent *hp;
939         struct netent *np;
940
941         cp = NULL;
942         if (!numeric_addr && inp->s_addr != INADDR_ANY) {
943                 int net = inet_netof(*inp);
944                 int lna = inet_lnaof(*inp);
945
946                 if (lna == INADDR_ANY) {
947                         np = getnetbyaddr(net, AF_INET);
948                         if (np)
949                                 cp = np->n_name;
950                 }
951                 if (cp == NULL) {
952                         hp = gethostbyaddr(inp, sizeof (*inp), AF_INET);
953                         if (hp) {
954                                 cp = hp->h_name;
955                                 trimdomain(cp, strlen(cp));
956                         }
957                 }
958         }
959         if (inp->s_addr == INADDR_ANY)
960                 strcpy(line, "*");
961         else if (cp) {
962                 strncpy(line, cp, sizeof(line) - 1);
963                 line[sizeof(line) - 1] = '\0';
964         } else {
965                 inp->s_addr = ntohl(inp->s_addr);
966 #define C(x)    ((u_int)((x) & 0xff))
967                 sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
968                     C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
969         }
970         return (line);
971 }