inet6.c revision 1.69.6.1 1 /* $NetBSD: inet6.c,v 1.69.6.1 2022/09/12 14:29:19 martin Exp $ */
2 /* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
3
4 /*
5 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 1983, 1988, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62 #include <sys/cdefs.h>
63 #ifndef lint
64 #if 0
65 static char sccsid[] = "@(#)inet.c 8.4 (Berkeley) 4/20/94";
66 #else
67 __RCSID("$NetBSD: inet6.c,v 1.69.6.1 2022/09/12 14:29:19 martin Exp $");
68 #endif
69 #endif /* not lint */
70
71 #define _CALLOUT_PRIVATE
72
73 #include <sys/param.h>
74 #include <sys/socket.h>
75 #include <sys/socketvar.h>
76 #include <sys/ioctl.h>
77 #include <sys/mbuf.h>
78 #include <sys/protosw.h>
79 #include <sys/sysctl.h>
80
81 #include <net/route.h>
82 #include <net/if.h>
83 #include <netinet/in.h>
84 #include <netinet/ip6.h>
85 #include <netinet/icmp6.h>
86 #include <netinet/in_systm.h>
87 #ifndef TCP6
88 #include <netinet/ip.h>
89 #include <netinet/ip_var.h>
90 #endif
91 #include <netinet6/ip6_var.h>
92 #include <netinet6/in6_pcb.h>
93 #include <netinet6/in6_var.h>
94 #ifdef TCP6
95 #include <netinet/tcp6.h>
96 #include <netinet/tcp6_seq.h>
97 #define TCP6STATES
98 #include <netinet/tcp6_fsm.h>
99 #define TCP6TIMERS
100 #include <netinet/tcp6_timer.h>
101 #include <netinet/tcp6_var.h>
102 #include <netinet/tcp6_debug.h>
103 #else
104 #define TCP6T_NTIMERS TCPT_NTIMERS
105 #define tcp6timers tcptimers
106 #define tcp6states tcpstates
107 #define TCP6_NSTATES TCP_NSTATES
108 #define tcp6cb tcpcb
109 #include <netinet/tcp.h>
110 #include <netinet/tcpip.h>
111 #include <netinet/tcp_seq.h>
112 #include <netinet/tcp_fsm.h>
113 extern const char * const tcpstates[];
114 extern const char * const tcptimers[];
115 #include <netinet/tcp_timer.h>
116 #include <netinet/tcp_var.h>
117 #include <netinet/tcp_debug.h>
118 #endif /*TCP6*/
119 #include <netinet6/udp6.h>
120 #include <netinet6/udp6_var.h>
121 #include <netinet6/pim6_var.h>
122 #include <netinet6/raw_ip6.h>
123 #include <netinet/tcp_vtw.h>
124
125 #include <arpa/inet.h>
126 #if 0
127 #include "gethostbyname2.h"
128 #endif
129 #include <netdb.h>
130
131 #include <err.h>
132 #include <errno.h>
133 #include <kvm.h>
134 #include <stdio.h>
135 #include <stdlib.h>
136 #include <string.h>
137 #include <unistd.h>
138 #include <util.h>
139 #include "netstat.h"
140 #include "vtw.h"
141 #include "prog_ops.h"
142
143 #ifdef INET6
144
145 struct in6pcb in6pcb;
146 #ifdef TCP6
147 struct tcp6cb tcp6cb;
148 #else
149 struct tcpcb tcpcb;
150 #endif
151
152 char *inet6name(const struct in6_addr *);
153 void inet6print(const struct in6_addr *, int, const char *);
154 void print_vtw_v6(const vtw_t *);
155
156 /*
157 * Print a summary of connections related to an Internet
158 * protocol. For TCP, also give state of connection.
159 * Listening processes (aflag) are suppressed unless the
160 * -a (all) flag is specified.
161 */
162 static int width;
163 static int compact;
164
165 /* VTW-related variables. */
166 static struct timeval now;
167
168 static void
169 ip6protoprhdr(void)
170 {
171
172 printf("Active Internet6 connections");
173
174 if (aflag)
175 printf(" (including servers)");
176 putchar('\n');
177
178 if (Aflag) {
179 printf("%-8.8s ", "PCB");
180 width = 18;
181 }
182 printf(
183 Vflag ? "%-5.5s %-6.6s %-6.6s %*.*s %*.*s %-13.13s Expires\n"
184 : "%-5.5s %-6.6s %-6.6s %*.*s %*.*s %s\n",
185 "Proto", "Recv-Q", "Send-Q",
186 -width, width, "Local Address",
187 -width, width, "Foreign Address", "(state)");
188 }
189
190 static void
191 ip6protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc,
192 const struct in6_addr *laddr, uint16_t lport,
193 const struct in6_addr *faddr, uint16_t fport,
194 short t_state, const char *name, const struct timeval *expires)
195 {
196 static const char *shorttcpstates[] = {
197 "CLOSED", "LISTEN", "SYNSEN", "SYSRCV",
198 "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG",
199 "LASTAK", "FWAIT2", "TMWAIT"
200 };
201 int istcp;
202
203 istcp = strcmp(name, "tcp6") == 0;
204 if (Aflag)
205 printf("%8" PRIxPTR " ", ppcb);
206
207 printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc,
208 compact ? "" : " ");
209
210 inet6print(laddr, (int)lport, name);
211 inet6print(faddr, (int)fport, name);
212 if (istcp) {
213 #ifdef TCP6
214 if (t_state < 0 || t_state >= TCP6_NSTATES)
215 printf(" %d", t_state);
216 else
217 printf(" %s", tcp6states[t_state]);
218 #else
219 if (t_state < 0 || t_state >= TCP_NSTATES)
220 printf(" %d", t_state);
221 else
222 printf(" %s", compact ? shorttcpstates[t_state] :
223 tcpstates[t_state]);
224 #endif
225 }
226 if (Vflag && expires != NULL) {
227 if (expires->tv_sec == 0 && expires->tv_usec == -1)
228 printf(" reclaimed");
229 else {
230 struct timeval delta;
231
232 timersub(expires, &now, &delta);
233 printf(" %.3fms",
234 delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0);
235 }
236 }
237 putchar('\n');
238 }
239
240 static void
241 dbg_printf(const char *fmt, ...)
242 {
243
244 return;
245 }
246
247 void
248 print_vtw_v6(const vtw_t *vtw)
249 {
250 const vtw_v6_t *v6 = (const vtw_v6_t *)vtw;
251 struct timeval delta;
252 char buf[2][128];
253 static const struct timeval zero = {.tv_sec = 0, .tv_usec = 0};
254
255 inet_ntop(AF_INET6, &v6->laddr, buf[0], sizeof(buf[0]));
256 inet_ntop(AF_INET6, &v6->faddr, buf[1], sizeof(buf[1]));
257
258 timersub(&vtw->expire, &now, &delta);
259
260 if (vtw->expire.tv_sec == 0 && vtw->expire.tv_usec == -1) {
261 dbg_printf("%15.15s:%d %15.15s:%d reclaimed\n",
262 buf[0], ntohs(v6->lport),
263 buf[1], ntohs(v6->fport));
264 if (!(Vflag && vflag))
265 return;
266 } else if (vtw->expire.tv_sec == 0)
267 return;
268 else if (timercmp(&delta, &zero, <) && !(Vflag && vflag)) {
269 dbg_printf("%15.15s:%d %15.15s:%d expired\n",
270 buf[0], ntohs(v6->lport),
271 buf[1], ntohs(v6->fport));
272 return;
273 } else {
274 dbg_printf("%15.15s:%d %15.15s:%d expires in %.3fms\n",
275 buf[0], ntohs(v6->lport),
276 buf[1], ntohs(v6->fport),
277 delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0);
278 }
279 ip6protopr0(0, 0, 0,
280 &v6->laddr, v6->lport,
281 &v6->faddr, v6->fport,
282 TCPS_TIME_WAIT, "tcp6", &vtw->expire);
283 }
284
285
286 static struct kinfo_pcb *
287 getpcblist_kmem(u_long off, const char *name, size_t *len)
288 {
289 struct socket sockb;
290 struct inpcbtable table;
291 struct inpcb_hdr *next, *prev;
292 int istcp = strcmp(name, "tcp6") == 0;
293 struct kinfo_pcb *pcblist;
294 size_t size = 100, i;
295 struct sockaddr_in6 sin6;
296 struct inpcbqueue *head;
297
298 if (off == 0) {
299 *len = 0;
300 return NULL;
301 }
302 kread(off, (char *)&table, sizeof (table));
303 head = &table.inpt_queue;
304 next = TAILQ_FIRST(head);
305 prev = TAILQ_END(head);
306
307 if ((pcblist = malloc(size * sizeof(*pcblist))) == NULL)
308 err(1, "malloc");
309
310 i = 0;
311 while (next != TAILQ_END(head)) {
312 kread((u_long)next, (char *)&in6pcb, sizeof in6pcb);
313 next = TAILQ_NEXT(&in6pcb, in6p_queue);
314 prev = next;
315
316 if (in6pcb.in6p_af != AF_INET6)
317 continue;
318
319 kread((u_long)in6pcb.in6p_socket, (char *)&sockb,
320 sizeof (sockb));
321 if (istcp) {
322 #ifdef TCP6
323 kread((u_long)in6pcb.in6p_ppcb,
324 (char *)&tcp6cb, sizeof (tcp6cb));
325 #else
326 kread((u_long)in6pcb.in6p_ppcb,
327 (char *)&tcpcb, sizeof (tcpcb));
328 #endif
329 }
330 pcblist[i].ki_ppcbaddr =
331 istcp ? (uintptr_t) in6pcb.in6p_ppcb : (uintptr_t) prev;
332 pcblist[i].ki_rcvq = (uint64_t)sockb.so_rcv.sb_cc;
333 pcblist[i].ki_sndq = (uint64_t)sockb.so_snd.sb_cc;
334 sin6.sin6_addr = in6pcb.in6p_laddr;
335 sin6.sin6_port = in6pcb.in6p_lport;
336 memcpy(&pcblist[i].ki_s, &sin6, sizeof(sin6));
337 sin6.sin6_addr = in6pcb.in6p_faddr;
338 sin6.sin6_port = in6pcb.in6p_fport;
339 memcpy(&pcblist[i].ki_d, &sin6, sizeof(sin6));
340 pcblist[i].ki_tstate = tcpcb.t_state;
341 if (i++ == size) {
342 size += 100;
343 struct kinfo_pcb *n = realloc(pcblist,
344 size * sizeof(*pcblist));
345 if (n == NULL)
346 err(1, "realloc");
347 pcblist = n;
348 }
349 }
350 *len = i;
351 return pcblist;
352 }
353
354 void
355 ip6protopr(u_long off, const char *name)
356 {
357 struct kinfo_pcb *pcblist;
358 size_t i, len;
359 static int first = 1;
360
361 compact = 0;
362 if (Aflag) {
363 if (!numeric_addr)
364 width = 18;
365 else {
366 width = 21;
367 compact = 1;
368 }
369 } else
370 width = 22;
371
372 if (use_sysctl)
373 pcblist = getpcblist_sysctl(name, &len);
374 else
375 pcblist = getpcblist_kmem(off, name, &len);
376
377 for (i = 0; i < len; i++) {
378 struct sockaddr_in6 src, dst;
379
380 memcpy(&src, &pcblist[i].ki_s, sizeof(src));
381 memcpy(&dst, &pcblist[i].ki_d, sizeof(dst));
382
383 if (!aflag && IN6_IS_ADDR_UNSPECIFIED(&dst.sin6_addr))
384 continue;
385
386 if (first) {
387 ip6protoprhdr();
388 first = 0;
389 }
390
391 ip6protopr0((intptr_t) pcblist[i].ki_ppcbaddr,
392 pcblist[i].ki_rcvq, pcblist[i].ki_sndq,
393 &src.sin6_addr, src.sin6_port,
394 &dst.sin6_addr, dst.sin6_port,
395 pcblist[i].ki_tstate, name, NULL);
396 }
397
398 free(pcblist);
399
400 if (strcmp(name, "tcp6") == 0) {
401 struct timeval t;
402 timebase(&t);
403 gettimeofday(&now, NULL);
404 timersub(&now, &t, &now);
405 show_vtw_v6(print_vtw_v6);
406 }
407 }
408
409 #ifdef TCP6
410 /*
411 * Dump TCP6 statistics structure.
412 */
413 void
414 tcp6_stats(u_long off, const char *name)
415 {
416 struct tcp6stat tcp6stat;
417
418 if (use_sysctl) {
419 size_t size = sizeof(tcp6stat);
420
421 if (sysctlbyname("net.inet6.tcp6.stats", &tcp6stat, &size,
422 NULL, 0) == -1)
423 return;
424 } else {
425 warnx("%s stats not available via KVM.", name);
426 return;
427 }
428
429 printf ("%s:\n", name);
430
431 #define p(f, m) if (tcp6stat.f || sflag <= 1) \
432 printf(m, tcp6stat.f, plural(tcp6stat.f))
433 #define p2(f1, f2, m) if (tcp6stat.f1 || tcp6stat.f2 || sflag <= 1) \
434 printf(m, tcp6stat.f1, plural(tcp6stat.f1), tcp6stat.f2, \
435 plural(tcp6stat.f2))
436 #define p3(f, m) if (tcp6stat.f || sflag <= 1) \
437 printf(m, tcp6stat.f, plurales(tcp6stat.f))
438
439 p(tcp6s_sndtotal, "\t%ld packet%s sent\n");
440 p2(tcp6s_sndpack,tcp6s_sndbyte,
441 "\t\t%ld data packet%s (%ld byte%s)\n");
442 p2(tcp6s_sndrexmitpack, tcp6s_sndrexmitbyte,
443 "\t\t%ld data packet%s (%ld byte%s) retransmitted\n");
444 p2(tcp6s_sndacks, tcp6s_delack,
445 "\t\t%ld ack-only packet%s (%ld packet%s delayed)\n");
446 p(tcp6s_sndurg, "\t\t%ld URG only packet%s\n");
447 p(tcp6s_sndprobe, "\t\t%ld window probe packet%s\n");
448 p(tcp6s_sndwinup, "\t\t%ld window update packet%s\n");
449 p(tcp6s_sndctrl, "\t\t%ld control packet%s\n");
450 p(tcp6s_rcvtotal, "\t%ld packet%s received\n");
451 p2(tcp6s_rcvackpack, tcp6s_rcvackbyte,
452 "\t\t%ld ack%s (for %ld byte%s)\n");
453 p(tcp6s_rcvdupack, "\t\t%ld duplicate ack%s\n");
454 p(tcp6s_rcvacktoomuch, "\t\t%ld ack%s for unsent data\n");
455 p2(tcp6s_rcvpack, tcp6s_rcvbyte,
456 "\t\t%ld packet%s (%ld byte%s) received in-sequence\n");
457 p2(tcp6s_rcvduppack, tcp6s_rcvdupbyte,
458 "\t\t%ld completely duplicate packet%s (%ld byte%s)\n");
459 p(tcp6s_pawsdrop, "\t\t%ld old duplicate packet%s\n");
460 p2(tcp6s_rcvpartduppack, tcp6s_rcvpartdupbyte,
461 "\t\t%ld packet%s with some dup. data (%ld byte%s duped)\n");
462 p2(tcp6s_rcvoopack, tcp6s_rcvoobyte,
463 "\t\t%ld out-of-order packet%s (%ld byte%s)\n");
464 p2(tcp6s_rcvpackafterwin, tcp6s_rcvbyteafterwin,
465 "\t\t%ld packet%s (%ld byte%s) of data after window\n");
466 p(tcp6s_rcvwinprobe, "\t\t%ld window probe%s\n");
467 p(tcp6s_rcvwinupd, "\t\t%ld window update packet%s\n");
468 p(tcp6s_rcvafterclose, "\t\t%ld packet%s received after close\n");
469 p(tcp6s_rcvbadsum, "\t\t%ld discarded for bad checksum%s\n");
470 p(tcp6s_rcvbadoff,
471 "\t\t%ld discarded for bad header offset field%s\n");
472 p(tcp6s_rcvshort, "\t\t%ld discarded because packet%s too short\n");
473 p(tcp6s_connattempt, "\t%ld connection request%s\n");
474 p(tcp6s_accepts, "\t%ld connection accept%s\n");
475 p(tcp6s_badsyn, "\t%ld bad connection attempt%s\n");
476 p(tcp6s_connects,
477 "\t%ld connection%s established (including accepts)\n");
478 p2(tcp6s_closed, tcp6s_drops,
479 "\t%ld connection%s closed (including %ld drop%s)\n");
480 p(tcp6s_conndrops, "\t%ld embryonic connection%s dropped\n");
481 p2(tcp6s_rttupdated, tcp6s_segstimed,
482 "\t%ld segment%s updated rtt (of %ld attempt%s)\n");
483 p(tcp6s_rexmttimeo, "\t%ld retransmit timeout%s\n");
484 p(tcp6s_timeoutdrop,
485 "\t\t%ld connection%s dropped by rexmit timeout\n");
486 p(tcp6s_persisttimeo, "\t%ld persist timeout%s\n");
487 p(tcp6s_persistdrop, "\t%ld connection%s timed out in persist\n");
488 p(tcp6s_keeptimeo, "\t%ld keepalive timeout%s\n");
489 p(tcp6s_keepprobe, "\t\t%ld keepalive probe%s sent\n");
490 p(tcp6s_keepdrops, "\t\t%ld connection%s dropped by keepalive\n");
491 p(tcp6s_predack, "\t%ld correct ACK header prediction%s\n");
492 p(tcp6s_preddat, "\t%ld correct data packet header prediction%s\n");
493 p3(tcp6s_pcbcachemiss, "\t%ld PCB cache miss%s\n");
494 #undef p
495 #undef p2
496 #undef p3
497 }
498 #endif
499
500 /*
501 * Dump UDP6 statistics structure.
502 */
503 void
504 udp6_stats(u_long off, const char *name)
505 {
506 uint64_t udp6stat[UDP6_NSTATS];
507 u_quad_t delivered;
508
509 if (use_sysctl) {
510 size_t size = sizeof(udp6stat);
511
512 if (sysctlbyname("net.inet6.udp6.stats", udp6stat, &size,
513 NULL, 0) == -1)
514 return;
515 } else {
516 warnx("%s stats not available via KVM.", name);
517 return;
518 }
519 printf("%s:\n", name);
520 #define p(f, m) if (udp6stat[f] || sflag <= 1) \
521 printf(m, (unsigned long long)udp6stat[f], plural(udp6stat[f]))
522 #define p1(f, m) if (udp6stat[f] || sflag <= 1) \
523 printf(m, (unsigned long long)udp6stat[f])
524 p(UDP6_STAT_IPACKETS, "\t%llu datagram%s received\n");
525 p1(UDP6_STAT_HDROPS, "\t%llu with incomplete header\n");
526 p1(UDP6_STAT_BADLEN, "\t%llu with bad data length field\n");
527 p1(UDP6_STAT_BADSUM, "\t%llu with bad checksum\n");
528 p1(UDP6_STAT_NOSUM, "\t%llu with no checksum\n");
529 p1(UDP6_STAT_NOPORT, "\t%llu dropped due to no socket\n");
530 p(UDP6_STAT_NOPORTMCAST,
531 "\t%llu multicast datagram%s dropped due to no socket\n");
532 p1(UDP6_STAT_FULLSOCK, "\t%llu dropped due to full socket buffers\n");
533 delivered = udp6stat[UDP6_STAT_IPACKETS] -
534 udp6stat[UDP6_STAT_HDROPS] -
535 udp6stat[UDP6_STAT_BADLEN] -
536 udp6stat[UDP6_STAT_BADSUM] -
537 udp6stat[UDP6_STAT_NOPORT] -
538 udp6stat[UDP6_STAT_NOPORTMCAST] -
539 udp6stat[UDP6_STAT_FULLSOCK];
540 if (delivered || sflag <= 1)
541 printf("\t%llu delivered\n", (unsigned long long)delivered);
542 p(UDP6_STAT_OPACKETS, "\t%llu datagram%s output\n");
543 #undef p
544 #undef p1
545 }
546
547 static const char *ip6nh[] = {
548 /*0*/ "hop by hop",
549 "ICMP",
550 "IGMP",
551 NULL,
552 "IP",
553 /*5*/ NULL,
554 "TCP",
555 NULL,
556 NULL,
557 NULL,
558 /*10*/ NULL, NULL, NULL, NULL, NULL,
559 /*15*/ NULL,
560 NULL,
561 "UDP",
562 NULL,
563 NULL,
564 /*20*/ NULL,
565 NULL,
566 "IDP",
567 NULL,
568 NULL,
569 /*25*/ NULL,
570 NULL,
571 NULL,
572 NULL,
573 NULL,
574 /*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
575 /*40*/ NULL,
576 "IP6",
577 NULL,
578 "routing",
579 "fragment",
580 /*45*/ NULL, NULL, NULL, NULL, NULL,
581 /*50*/ "ESP",
582 "AH",
583 NULL,
584 NULL,
585 NULL,
586 /*55*/ NULL,
587 NULL,
588 NULL,
589 "ICMP6",
590 "no next header",
591 /*60*/ "destination option",
592 NULL,
593 NULL,
594 NULL,
595 NULL,
596 /*65*/ NULL, NULL, NULL, NULL, NULL,
597 /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
598 /*80*/ NULL,
599 NULL,
600 NULL,
601 NULL,
602 NULL,
603 NULL,
604 NULL,
605 NULL,
606 NULL,
607 "OSPF",
608 /*90*/ NULL, NULL, NULL, NULL, NULL,
609 /*95*/ NULL,
610 NULL,
611 "Ethernet",
612 NULL,
613 NULL,
614 /*100*/ NULL,
615 NULL,
616 NULL,
617 "PIM",
618 NULL,
619 /*105*/ NULL, NULL, NULL, NULL, NULL,
620 /*110*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
621 /*120*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
622 /*130*/ NULL,
623 NULL,
624 "SCTP",
625 NULL,
626 NULL,
627 /*135*/ NULL, NULL, NULL, NULL, NULL,
628 /*140*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
629 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
630 /*160*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
631 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
632 /*180*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
633 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
634 /*200*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
635 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
636 /*220*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
637 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
638 /*240*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
639 NULL, NULL, NULL, NULL, NULL, NULL
640 };
641
642 /*
643 * Dump IP6 statistics structure.
644 */
645 void
646 ip6_stats(u_long off, const char *name)
647 {
648 uint64_t ip6stat[IP6_NSTATS];
649 int first, i;
650 struct protoent *ep;
651 const char *n;
652
653 if (use_sysctl) {
654 size_t size = sizeof(ip6stat);
655
656 if (sysctlbyname("net.inet6.ip6.stats", ip6stat, &size,
657 NULL, 0) == -1)
658 return;
659 } else {
660 warnx("%s stats not available via KVM.", name);
661 return;
662 }
663 printf("%s:\n", name);
664
665 #define p(f, m) if (ip6stat[f] || sflag <= 1) \
666 printf(m, (unsigned long long)ip6stat[f], plural(ip6stat[f]))
667 #define p1(f, m) if (ip6stat[f] || sflag <= 1) \
668 printf(m, (unsigned long long)ip6stat[f])
669
670 p(IP6_STAT_TOTAL, "\t%llu total packet%s received\n");
671 p1(IP6_STAT_TOOSMALL, "\t%llu with size smaller than minimum\n");
672 p1(IP6_STAT_TOOSHORT, "\t%llu with data size < data length\n");
673 p1(IP6_STAT_BADOPTIONS, "\t%llu with bad options\n");
674 p1(IP6_STAT_BADVERS, "\t%llu with incorrect version number\n");
675 p(IP6_STAT_FRAGMENTS, "\t%llu fragment%s received\n");
676 p(IP6_STAT_FRAGDROPPED,
677 "\t%llu fragment%s dropped (dup or out of space)\n");
678 p(IP6_STAT_FRAGTIMEOUT, "\t%llu fragment%s dropped after timeout\n");
679 p(IP6_STAT_FRAGOVERFLOW, "\t%llu fragment%s that exceeded limit\n");
680 p(IP6_STAT_REASSEMBLED, "\t%llu packet%s reassembled ok\n");
681 p(IP6_STAT_DELIVERED, "\t%llu packet%s for this host\n");
682 p(IP6_STAT_FORWARD, "\t%llu packet%s forwarded\n");
683 p(IP6_STAT_FASTFORWARD, "\t%llu packet%s fast forwarded\n");
684 p1(IP6_STAT_FASTFORWARDFLOWS, "\t%llu fast forward flows\n");
685 p(IP6_STAT_CANTFORWARD, "\t%llu packet%s not forwardable\n");
686 p(IP6_STAT_REDIRECTSENT, "\t%llu redirect%s sent\n");
687 p(IP6_STAT_LOCALOUT, "\t%llu packet%s sent from this host\n");
688 p(IP6_STAT_RAWOUT, "\t%llu packet%s sent with fabricated ip header\n");
689 p(IP6_STAT_ODROPPED,
690 "\t%llu output packet%s dropped due to no bufs, etc.\n");
691 p(IP6_STAT_NOROUTE,
692 "\t%llu output packet%s discarded due to no route\n");
693 p(IP6_STAT_FRAGMENTED, "\t%llu output datagram%s fragmented\n");
694 p(IP6_STAT_OFRAGMENTS, "\t%llu fragment%s created\n");
695 p(IP6_STAT_CANTFRAG, "\t%llu datagram%s that can't be fragmented\n");
696 p(IP6_STAT_BADSCOPE, "\t%llu packet%s that violated scope rules\n");
697 p(IP6_STAT_NOTMEMBER, "\t%llu multicast packet%s which we don't join\n");
698 for (first = 1, i = 0; i < 256; i++)
699 if (ip6stat[IP6_STAT_NXTHIST + i] != 0) {
700 if (first) {
701 printf("\tInput packet histogram:\n");
702 first = 0;
703 }
704 n = NULL;
705 if (ip6nh[i])
706 n = ip6nh[i];
707 else if ((ep = getprotobynumber(i)) != NULL)
708 n = ep->p_name;
709 if (n)
710 printf("\t\t%s: %llu\n", n,
711 (unsigned long long)ip6stat[IP6_STAT_NXTHIST + i]);
712 else
713 printf("\t\t#%d: %llu\n", i,
714 (unsigned long long)ip6stat[IP6_STAT_NXTHIST + i]);
715 }
716 printf("\tMbuf statistics:\n");
717 p(IP6_STAT_M1, "\t\t%llu one mbuf%s\n");
718 for (first = 1, i = 0; i < 32; i++) {
719 char ifbuf[IFNAMSIZ];
720 if (ip6stat[IP6_STAT_M2M + i] != 0) {
721 if (first) {
722 printf("\t\ttwo or more mbuf:\n");
723 first = 0;
724 }
725 printf("\t\t\t%s = %llu\n",
726 if_indextoname(i, ifbuf),
727 (unsigned long long)ip6stat[IP6_STAT_M2M + i]);
728 }
729 }
730 p(IP6_STAT_MEXT1, "\t\t%llu one ext mbuf%s\n");
731 p(IP6_STAT_MEXT2M, "\t\t%llu two or more ext mbuf%s\n");
732 p(IP6_STAT_EXTHDRTOOLONG,
733 "\t%llu packet%s whose headers are not continuous\n");
734 p(IP6_STAT_NOGIF, "\t%llu tunneling packet%s that can't find gif\n");
735 p(IP6_STAT_NOIPSEC,
736 "\t%llu tunneling packet%s that can't find ipsecif\n");
737 p(IP6_STAT_TOOMANYHDR,
738 "\t%llu packet%s discarded due to too many headers\n");
739
740 /* for debugging source address selection */
741 #define PRINT_SCOPESTAT(s, i) do { \
742 switch (i) { /* XXX hardcoding in each case */ \
743 case 1: \
744 p(s, "\t\t%llu node-local%s\n"); \
745 break; \
746 case 2: \
747 p(s, "\t\t%llu link-local%s\n"); \
748 break; \
749 case 5: \
750 p(s, "\t\t%llu site-local%s\n"); \
751 break; \
752 case 14: \
753 p(s, "\t\t%llu global%s\n"); \
754 break; \
755 default: \
756 printf("\t\t%llu addresses scope=%x\n", \
757 (unsigned long long)ip6stat[s], i); \
758 } \
759 } while(/*CONSTCOND*/0);
760
761 p(IP6_STAT_SOURCES_NONE,
762 "\t%llu failure%s of source address selection\n");
763 for (first = 1, i = 0; i < 16; i++) {
764 if (ip6stat[IP6_STAT_SOURCES_SAMEIF + i]) {
765 if (first) {
766 printf("\tsource addresses on an outgoing I/F\n");
767 first = 0;
768 }
769 PRINT_SCOPESTAT(IP6_STAT_SOURCES_SAMEIF + i, i);
770 }
771 }
772 for (first = 1, i = 0; i < 16; i++) {
773 if (ip6stat[IP6_STAT_SOURCES_OTHERIF + i]) {
774 if (first) {
775 printf("\tsource addresses on a non-outgoing I/F\n");
776 first = 0;
777 }
778 PRINT_SCOPESTAT(IP6_STAT_SOURCES_OTHERIF + i, i);
779 }
780 }
781 for (first = 1, i = 0; i < 16; i++) {
782 if (ip6stat[IP6_STAT_SOURCES_SAMESCOPE + i]) {
783 if (first) {
784 printf("\tsource addresses of same scope\n");
785 first = 0;
786 }
787 PRINT_SCOPESTAT(IP6_STAT_SOURCES_SAMESCOPE + i, i);
788 }
789 }
790 for (first = 1, i = 0; i < 16; i++) {
791 if (ip6stat[IP6_STAT_SOURCES_OTHERSCOPE + i]) {
792 if (first) {
793 printf("\tsource addresses of a different scope\n");
794 first = 0;
795 }
796 PRINT_SCOPESTAT(IP6_STAT_SOURCES_OTHERSCOPE + i, i);
797 }
798 }
799 for (first = 1, i = 0; i < 16; i++) {
800 if (ip6stat[IP6_STAT_SOURCES_DEPRECATED + i]) {
801 if (first) {
802 printf("\tdeprecated source addresses\n");
803 first = 0;
804 }
805 PRINT_SCOPESTAT(IP6_STAT_SOURCES_DEPRECATED + i, i);
806 }
807 }
808
809 p1(IP6_STAT_FORWARD_CACHEHIT, "\t%llu forward cache hit\n");
810 p1(IP6_STAT_FORWARD_CACHEMISS, "\t%llu forward cache miss\n");
811 #undef p
812 #undef p1
813 }
814
815 /*
816 * Dump IPv6 per-interface statistics based on RFC 2465.
817 */
818 void
819 ip6_ifstats(const char *ifname)
820 {
821 struct in6_ifreq ifr;
822 int s;
823 #define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
824 printf(m, (unsigned long long)ifr.ifr_ifru.ifru_stat.f, \
825 plural(ifr.ifr_ifru.ifru_stat.f))
826 #define p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
827 printf(m, (unsigned long long)ip6stat.f)
828
829 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
830 perror("Warning: socket(AF_INET6)");
831 return;
832 }
833
834 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
835 printf("ip6 on %s:\n", ifname);
836
837 if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
838 perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
839 goto end;
840 }
841
842 p(ifs6_in_receive, "\t%llu total input datagram%s\n");
843 p(ifs6_in_hdrerr, "\t%llu datagram%s with invalid header received\n");
844 p(ifs6_in_toobig, "\t%llu datagram%s exceeded MTU received\n");
845 p(ifs6_in_noroute, "\t%llu datagram%s with no route received\n");
846 p(ifs6_in_addrerr, "\t%llu datagram%s with invalid dst received\n");
847 p(ifs6_in_truncated, "\t%llu truncated datagram%s received\n");
848 p(ifs6_in_protounknown,
849 "\t%llu datagram%s with unknown proto received\n");
850 p(ifs6_in_discard, "\t%llu input datagram%s discarded\n");
851 p(ifs6_in_deliver,
852 "\t%llu datagram%s delivered to an upper layer protocol\n");
853 p(ifs6_out_forward, "\t%llu datagram%s forwarded to this interface\n");
854 p(ifs6_out_request,
855 "\t%llu datagram%s sent from an upper layer protocol\n");
856 p(ifs6_out_discard, "\t%llu total discarded output datagram%s\n");
857 p(ifs6_out_fragok, "\t%llu output datagram%s fragmented\n");
858 p(ifs6_out_fragfail, "\t%llu output datagram%s failed on fragment\n");
859 p(ifs6_out_fragcreat,
860 "\t%llu output datagram%s succeeded on fragment\n");
861 p(ifs6_reass_reqd, "\t%llu incoming datagram%s fragmented\n");
862 p(ifs6_reass_ok, "\t%llu datagram%s reassembled\n");
863 p(ifs6_reass_fail, "\t%llu datagram%s failed on reassembling\n");
864 p(ifs6_in_mcast, "\t%llu multicast datagram%s received\n");
865 p(ifs6_out_mcast, "\t%llu multicast datagram%s sent\n");
866
867 end:
868 close(s);
869
870 #undef p
871 #undef p_5
872 }
873
874 static const char *icmp6names[256] = {
875 "#0",
876 "unreach",
877 "packet too big",
878 "time exceed",
879 "parameter problem",
880 "#5",
881 "#6",
882 "#7",
883 "#8",
884 "#9",
885 "#10",
886 "#11",
887 "#12",
888 "#13",
889 "#14",
890 "#15",
891 "#16",
892 "#17",
893 "#18",
894 "#19",
895 "#20",
896 "#21",
897 "#22",
898 "#23",
899 "#24",
900 "#25",
901 "#26",
902 "#27",
903 "#28",
904 "#29",
905 "#30",
906 "#31",
907 "#32",
908 "#33",
909 "#34",
910 "#35",
911 "#36",
912 "#37",
913 "#38",
914 "#39",
915 "#40",
916 "#41",
917 "#42",
918 "#43",
919 "#44",
920 "#45",
921 "#46",
922 "#47",
923 "#48",
924 "#49",
925 "#50",
926 "#51",
927 "#52",
928 "#53",
929 "#54",
930 "#55",
931 "#56",
932 "#57",
933 "#58",
934 "#59",
935 "#60",
936 "#61",
937 "#62",
938 "#63",
939 "#64",
940 "#65",
941 "#66",
942 "#67",
943 "#68",
944 "#69",
945 "#70",
946 "#71",
947 "#72",
948 "#73",
949 "#74",
950 "#75",
951 "#76",
952 "#77",
953 "#78",
954 "#79",
955 "#80",
956 "#81",
957 "#82",
958 "#83",
959 "#84",
960 "#85",
961 "#86",
962 "#87",
963 "#88",
964 "#89",
965 "#80",
966 "#91",
967 "#92",
968 "#93",
969 "#94",
970 "#95",
971 "#96",
972 "#97",
973 "#98",
974 "#99",
975 "#100",
976 "#101",
977 "#102",
978 "#103",
979 "#104",
980 "#105",
981 "#106",
982 "#107",
983 "#108",
984 "#109",
985 "#110",
986 "#111",
987 "#112",
988 "#113",
989 "#114",
990 "#115",
991 "#116",
992 "#117",
993 "#118",
994 "#119",
995 "#120",
996 "#121",
997 "#122",
998 "#123",
999 "#124",
1000 "#125",
1001 "#126",
1002 "#127",
1003 "echo",
1004 "echo reply",
1005 "multicast listener query",
1006 "multicast listener report",
1007 "multicast listener done",
1008 "router solicitation",
1009 "router advertisement",
1010 "neighbor solicitation",
1011 "neighbor advertisement",
1012 "redirect",
1013 "router renumbering",
1014 "node information request",
1015 "node information reply",
1016 "#141",
1017 "#142",
1018 "multicast listener report (v2)",
1019 "home agent discovery request",
1020 "home agent discovery reply",
1021 "mobile prefix solicitation",
1022 "mobile prefix advertisement",
1023 "#148",
1024 "#149",
1025 "#150",
1026 "multicast router advertisement",
1027 "multicast router solicitation",
1028 "multicast router termination",
1029 "#154",
1030 "#155",
1031 "#156",
1032 "#157",
1033 "#158",
1034 "#159",
1035 "#160",
1036 "#161",
1037 "#162",
1038 "#163",
1039 "#164",
1040 "#165",
1041 "#166",
1042 "#167",
1043 "#168",
1044 "#169",
1045 "#170",
1046 "#171",
1047 "#172",
1048 "#173",
1049 "#174",
1050 "#175",
1051 "#176",
1052 "#177",
1053 "#178",
1054 "#179",
1055 "#180",
1056 "#181",
1057 "#182",
1058 "#183",
1059 "#184",
1060 "#185",
1061 "#186",
1062 "#187",
1063 "#188",
1064 "#189",
1065 "#180",
1066 "#191",
1067 "#192",
1068 "#193",
1069 "#194",
1070 "#195",
1071 "#196",
1072 "#197",
1073 "#198",
1074 "#199",
1075 "#200",
1076 "#201",
1077 "#202",
1078 "#203",
1079 "#204",
1080 "#205",
1081 "#206",
1082 "#207",
1083 "#208",
1084 "#209",
1085 "#210",
1086 "#211",
1087 "#212",
1088 "#213",
1089 "#214",
1090 "#215",
1091 "#216",
1092 "#217",
1093 "#218",
1094 "#219",
1095 "#220",
1096 "#221",
1097 "#222",
1098 "#223",
1099 "#224",
1100 "#225",
1101 "#226",
1102 "#227",
1103 "#228",
1104 "#229",
1105 "#230",
1106 "#231",
1107 "#232",
1108 "#233",
1109 "#234",
1110 "#235",
1111 "#236",
1112 "#237",
1113 "#238",
1114 "#239",
1115 "#240",
1116 "#241",
1117 "#242",
1118 "#243",
1119 "#244",
1120 "#245",
1121 "#246",
1122 "#247",
1123 "#248",
1124 "#249",
1125 "#250",
1126 "#251",
1127 "#252",
1128 "#253",
1129 "#254",
1130 "#255"
1131 };
1132
1133 /*
1134 * Dump ICMPv6 statistics.
1135 */
1136 void
1137 icmp6_stats(u_long off, const char *name)
1138 {
1139 uint64_t icmp6stat[ICMP6_NSTATS];
1140 int i, first;
1141
1142 if (use_sysctl) {
1143 size_t size = sizeof(icmp6stat);
1144
1145 if (sysctlbyname("net.inet6.icmp6.stats", icmp6stat, &size,
1146 NULL, 0) == -1)
1147 return;
1148 } else {
1149 warnx("%s stats not available via KVM.", name);
1150 return;
1151 }
1152
1153 printf("%s:\n", name);
1154
1155 #define p(f, m) if (icmp6stat[f] || sflag <= 1) \
1156 printf(m, (unsigned long long)icmp6stat[f], \
1157 plural(icmp6stat[f]))
1158 #define p_oerr(f, m) if (icmp6stat[ICMP6_STAT_OUTERRHIST + f] || sflag <= 1) \
1159 printf(m, \
1160 (unsigned long long)icmp6stat[ICMP6_STAT_OUTERRHIST + f])
1161
1162 p(ICMP6_STAT_ERROR, "\t%llu call%s to icmp6_error\n");
1163 p(ICMP6_STAT_CANTERROR,
1164 "\t%llu error%s not generated because old message was icmp6 or so\n");
1165 p(ICMP6_STAT_TOOFREQ,
1166 "\t%llu error%s not generated because of rate limitation\n");
1167 for (first = 1, i = 0; i < 256; i++)
1168 if (icmp6stat[ICMP6_STAT_OUTHIST + i] != 0) {
1169 if (first) {
1170 printf("\tOutput packet histogram:\n");
1171 first = 0;
1172 }
1173 printf("\t\t%s: %llu\n", icmp6names[i],
1174 (unsigned long long)icmp6stat[ICMP6_STAT_OUTHIST + i]);
1175 }
1176 p(ICMP6_STAT_BADCODE, "\t%llu message%s with bad code fields\n");
1177 p(ICMP6_STAT_TOOSHORT, "\t%llu message%s < minimum length\n");
1178 p(ICMP6_STAT_CHECKSUM, "\t%llu bad checksum%s\n");
1179 p(ICMP6_STAT_BADLEN, "\t%llu message%s with bad length\n");
1180 for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++)
1181 if (icmp6stat[ICMP6_STAT_INHIST + i] != 0) {
1182 if (first) {
1183 printf("\tInput packet histogram:\n");
1184 first = 0;
1185 }
1186 printf("\t\t%s: %llu\n", icmp6names[i],
1187 (unsigned long long)icmp6stat[ICMP6_STAT_INHIST + i]);
1188 }
1189 printf("\tHistogram of error messages to be generated:\n");
1190 p_oerr(ICMP6_ERRSTAT_DST_UNREACH_NOROUTE, "\t\t%llu no route\n");
1191 p_oerr(ICMP6_ERRSTAT_DST_UNREACH_ADMIN,
1192 "\t\t%llu administratively prohibited\n");
1193 p_oerr(ICMP6_ERRSTAT_DST_UNREACH_BEYONDSCOPE,
1194 "\t\t%llu beyond scope\n");
1195 p_oerr(ICMP6_ERRSTAT_DST_UNREACH_ADDR,
1196 "\t\t%llu address unreachable\n");
1197 p_oerr(ICMP6_ERRSTAT_DST_UNREACH_NOPORT,
1198 "\t\t%llu port unreachable\n");
1199 p_oerr(ICMP6_ERRSTAT_PACKET_TOO_BIG, "\t\t%llu packet too big\n");
1200 p_oerr(ICMP6_ERRSTAT_TIME_EXCEED_TRANSIT,
1201 "\t\t%llu time exceed transit\n");
1202 p_oerr(ICMP6_ERRSTAT_TIME_EXCEED_REASSEMBLY,
1203 "\t\t%llu time exceed reassembly\n");
1204 p_oerr(ICMP6_ERRSTAT_PARAMPROB_HEADER,
1205 "\t\t%llu erroneous header field\n");
1206 p_oerr(ICMP6_ERRSTAT_PARAMPROB_NEXTHEADER,
1207 "\t\t%llu unrecognized next header\n");
1208 p_oerr(ICMP6_ERRSTAT_PARAMPROB_OPTION,
1209 "\t\t%llu unrecognized option\n");
1210 p_oerr(ICMP6_ERRSTAT_REDIRECT, "\t\t%llu redirect\n");
1211 p_oerr(ICMP6_ERRSTAT_UNKNOWN, "\t\t%llu unknown\n");
1212
1213 p(ICMP6_STAT_REFLECT, "\t%llu message response%s generated\n");
1214 p(ICMP6_STAT_ND_TOOMANYOPT,
1215 "\t%llu message%s with too many ND options\n");
1216 p(ICMP6_STAT_ND_BADOPT, "\t%llu message%s with bad ND options\n");
1217 p(ICMP6_STAT_BADNS, "\t%llu bad neighbor solicitation message%s\n");
1218 p(ICMP6_STAT_BADNA, "\t%llu bad neighbor advertisement message%s\n");
1219 p(ICMP6_STAT_BADRS, "\t%llu bad router solicitation message%s\n");
1220 p(ICMP6_STAT_BADRA, "\t%llu bad router advertisement message%s\n");
1221 p(ICMP6_STAT_DROPPED_RAROUTE,
1222 "\t%llu router advertisement route%s dropped\n");
1223 p(ICMP6_STAT_BADREDIRECT, "\t%llu bad redirect message%s\n");
1224 p(ICMP6_STAT_PMTUCHG, "\t%llu path MTU change%s\n");
1225 #undef p
1226 #undef p_oerr
1227 }
1228
1229 /*
1230 * Dump ICMPv6 per-interface statistics based on RFC 2466.
1231 */
1232 void
1233 icmp6_ifstats(const char *ifname)
1234 {
1235 struct in6_ifreq ifr;
1236 int s;
1237 #define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1238 printf(m, (unsigned long long)ifr.ifr_ifru.ifru_icmp6stat.f, \
1239 plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1240
1241 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1242 perror("Warning: socket(AF_INET6)");
1243 return;
1244 }
1245
1246 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1247 printf("icmp6 on %s:\n", ifname);
1248
1249 if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1250 perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
1251 goto end;
1252 }
1253
1254 p(ifs6_in_msg, "\t%llu total input message%s\n");
1255 p(ifs6_in_error, "\t%llu total input error message%s\n");
1256 p(ifs6_in_dstunreach,
1257 "\t%llu input destination unreachable error%s\n");
1258 p(ifs6_in_adminprohib,
1259 "\t%llu input administratively prohibited error%s\n");
1260 p(ifs6_in_timeexceed, "\t%llu input time exceeded error%s\n");
1261 p(ifs6_in_paramprob, "\t%llu input parameter problem error%s\n");
1262 p(ifs6_in_pkttoobig, "\t%llu input packet too big error%s\n");
1263 p(ifs6_in_echo, "\t%llu input echo request%s\n");
1264 p(ifs6_in_echoreply, "\t%llu input echo reply%s\n");
1265 p(ifs6_in_routersolicit, "\t%llu input router solicitation%s\n");
1266 p(ifs6_in_routeradvert, "\t%llu input router advertisement%s\n");
1267 p(ifs6_in_neighborsolicit, "\t%llu input neighbor solicitation%s\n");
1268 p(ifs6_in_neighboradvert, "\t%llu input neighbor advertisement%s\n");
1269 p(ifs6_in_redirect, "\t%llu input redirect%s\n");
1270 p(ifs6_in_mldquery, "\t%llu input MLD query%s\n");
1271 p(ifs6_in_mldreport, "\t%llu input MLD report%s\n");
1272 p(ifs6_in_mlddone, "\t%llu input MLD done%s\n");
1273
1274 p(ifs6_out_msg, "\t%llu total output message%s\n");
1275 p(ifs6_out_error, "\t%llu total output error message%s\n");
1276 p(ifs6_out_dstunreach,
1277 "\t%llu output destination unreachable error%s\n");
1278 p(ifs6_out_adminprohib,
1279 "\t%llu output administratively prohibited error%s\n");
1280 p(ifs6_out_timeexceed, "\t%llu output time exceeded error%s\n");
1281 p(ifs6_out_paramprob, "\t%llu output parameter problem error%s\n");
1282 p(ifs6_out_pkttoobig, "\t%llu output packet too big error%s\n");
1283 p(ifs6_out_echo, "\t%llu output echo request%s\n");
1284 p(ifs6_out_echoreply, "\t%llu output echo reply%s\n");
1285 p(ifs6_out_routersolicit, "\t%llu output router solicitation%s\n");
1286 p(ifs6_out_routeradvert, "\t%llu output router advertisement%s\n");
1287 p(ifs6_out_neighborsolicit, "\t%llu output neighbor solicitation%s\n");
1288 p(ifs6_out_neighboradvert, "\t%llu output neighbor advertisement%s\n");
1289 p(ifs6_out_redirect, "\t%llu output redirect%s\n");
1290 p(ifs6_out_mldquery, "\t%llu output MLD query%s\n");
1291 p(ifs6_out_mldreport, "\t%llu output MLD report%s\n");
1292 p(ifs6_out_mlddone, "\t%llu output MLD done%s\n");
1293
1294 end:
1295 close(s);
1296 #undef p
1297 }
1298
1299 /*
1300 * Dump PIM statistics structure.
1301 */
1302 void
1303 pim6_stats(u_long off, const char *name)
1304 {
1305 uint64_t pim6stat[PIM6_NSTATS];
1306
1307 if (use_sysctl) {
1308 size_t size = sizeof(pim6stat);
1309
1310 if (sysctlbyname("net.inet6.pim6.stats", pim6stat, &size,
1311 NULL, 0) == -1)
1312 return;
1313 } else {
1314 warnx("%s stats not available via KVM.", name);
1315 return;
1316 }
1317 printf("%s:\n", name);
1318
1319 #define p(f, m) if (pim6stat[f] || sflag <= 1) \
1320 printf(m, (unsigned long long)pim6stat[f], plural(pim6stat[f]))
1321
1322 p(PIM6_STAT_RCV_TOTAL, "\t%llu message%s received\n");
1323 p(PIM6_STAT_RCV_TOOSHORT,
1324 "\t%llu message%s received with too few bytes\n");
1325 p(PIM6_STAT_RCV_BADSUM,
1326 "\t%llu message%s received with bad checksum\n");
1327 p(PIM6_STAT_RCV_BADVERSION,
1328 "\t%llu message%s received with bad version\n");
1329 p(PIM6_STAT_RCV_REGISTERS, "\t%llu register%s received\n");
1330 p(PIM6_STAT_RCV_BADREGISTERS, "\t%llu bad register%s received\n");
1331 p(PIM6_STAT_SND_REGISTERS, "\t%llu register%s sent\n");
1332 #undef p
1333 }
1334
1335 /*
1336 * Dump raw ip6 statistics structure.
1337 */
1338 void
1339 rip6_stats(u_long off, const char *name)
1340 {
1341 uint64_t rip6stat[RIP6_NSTATS];
1342 u_quad_t delivered;
1343
1344 if (use_sysctl) {
1345 size_t size = sizeof(rip6stat);
1346
1347 if (sysctlbyname("net.inet6.raw6.stats", rip6stat, &size,
1348 NULL, 0) == -1)
1349 return;
1350 } else {
1351 warnx("%s stats not available via KVM.", name);
1352 return;
1353 }
1354 printf("%s:\n", name);
1355
1356 #define p(f, m) if (rip6stat[f] || sflag <= 1) \
1357 printf(m, (unsigned long long)rip6stat[f], plural(rip6stat[f]))
1358 p(RIP6_STAT_IPACKETS, "\t%llu message%s received\n");
1359 p(RIP6_STAT_ISUM, "\t%llu checksum calculation%s on inbound\n");
1360 p(RIP6_STAT_BADSUM, "\t%llu message%s with bad checksum\n");
1361 p(RIP6_STAT_NOSOCK, "\t%llu message%s dropped due to no socket\n");
1362 p(RIP6_STAT_NOSOCKMCAST,
1363 "\t%llu multicast message%s dropped due to no socket\n");
1364 p(RIP6_STAT_FULLSOCK,
1365 "\t%llu message%s dropped due to full socket buffers\n");
1366 delivered = rip6stat[RIP6_STAT_IPACKETS] -
1367 rip6stat[RIP6_STAT_BADSUM] -
1368 rip6stat[RIP6_STAT_NOSOCK] -
1369 rip6stat[RIP6_STAT_NOSOCKMCAST] -
1370 rip6stat[RIP6_STAT_FULLSOCK];
1371 if (delivered || sflag <= 1)
1372 printf("\t%llu delivered\n", (unsigned long long)delivered);
1373 p(RIP6_STAT_OPACKETS, "\t%llu datagram%s output\n");
1374 #undef p
1375 }
1376
1377 /*
1378 * Pretty print an Internet address (net address + port).
1379 * Take numeric_addr and numeric_port into consideration.
1380 */
1381 void
1382 inet6print(const struct in6_addr *in6, int port, const char *proto)
1383 {
1384 #define GETSERVBYPORT6(port, proto, ret) \
1385 do { \
1386 if (strcmp((proto), "tcp6") == 0) \
1387 (ret) = getservbyport((int)(port), "tcp"); \
1388 else if (strcmp((proto), "udp6") == 0) \
1389 (ret) = getservbyport((int)(port), "udp"); \
1390 else \
1391 (ret) = getservbyport((int)(port), (proto)); \
1392 } while (0)
1393
1394 struct servent *sp = 0;
1395 char line[80], *cp;
1396 int lwidth;
1397
1398 lwidth = Aflag ? 12 : 16;
1399 if (vflag && lwidth < (int)strlen(inet6name(in6)))
1400 lwidth = strlen(inet6name(in6));
1401 snprintf(line, sizeof(line), "%.*s.", lwidth, inet6name(in6));
1402 cp = strchr(line, '\0');
1403 if (!numeric_port && port)
1404 GETSERVBYPORT6(port, proto, sp);
1405 if (sp || port == 0)
1406 snprintf(cp, sizeof(line) - (cp - line),
1407 "%s", sp ? sp->s_name : "*");
1408 else
1409 snprintf(cp, sizeof(line) - (cp - line),
1410 "%d", ntohs((u_short)port));
1411 lwidth = Aflag ? 18 : 22;
1412 if (vflag && lwidth < (int)strlen(line))
1413 lwidth = strlen(line);
1414 printf(" %-*.*s", lwidth, lwidth, line);
1415 }
1416
1417 /*
1418 * Construct an Internet address representation.
1419 * If the numeric_addr has been supplied, give
1420 * numeric value, otherwise try for symbolic name.
1421 */
1422
1423 char *
1424 inet6name(const struct in6_addr *in6p)
1425 {
1426 char *cp;
1427 static char line[NI_MAXHOST];
1428 struct hostent *hp;
1429 static char domain[MAXHOSTNAMELEN + 1];
1430 static int first = 1;
1431 char hbuf[NI_MAXHOST];
1432 struct sockaddr_in6 sin6;
1433 const int niflag = NI_NUMERICHOST;
1434
1435 if (first && !numeric_addr) {
1436 first = 0;
1437 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1438 (cp = strchr(domain, '.')))
1439 (void) strlcpy(domain, cp + 1, sizeof(domain));
1440 else
1441 domain[0] = 0;
1442 }
1443 cp = 0;
1444 if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1445 hp = gethostbyaddr((const char *)in6p, sizeof(*in6p), AF_INET6);
1446 if (hp) {
1447 if ((cp = strchr(hp->h_name, '.')) &&
1448 !strcmp(cp + 1, domain))
1449 *cp = 0;
1450 cp = hp->h_name;
1451 }
1452 }
1453 if (IN6_IS_ADDR_UNSPECIFIED(in6p))
1454 strlcpy(line, "*", sizeof(line));
1455 else if (cp)
1456 strlcpy(line, cp, sizeof(line));
1457 else {
1458 memset(&sin6, 0, sizeof(sin6));
1459 sin6.sin6_len = sizeof(sin6);
1460 sin6.sin6_family = AF_INET6;
1461 sin6.sin6_addr = *in6p;
1462 inet6_getscopeid(&sin6,
1463 INET6_IS_ADDR_LINKLOCAL | INET6_IS_ADDR_MC_LINKLOCAL);
1464 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
1465 hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
1466 strlcpy(hbuf, "?", sizeof(hbuf));
1467 strlcpy(line, hbuf, sizeof(line));
1468 }
1469 return line;
1470 }
1471
1472 /*
1473 * Dump the contents of a TCP6 PCB.
1474 */
1475 void
1476 tcp6_dump(u_long off, const char *name, u_long pcbaddr)
1477 {
1478 callout_impl_t *ci;
1479 int i, hardticks;
1480 struct kinfo_pcb *pcblist;
1481 #ifdef TCP6
1482 #define mypcb tcp6cb
1483 #else
1484 #define mypcb tcpcb
1485 #endif
1486 size_t j, len;
1487
1488 if (use_sysctl)
1489 pcblist = getpcblist_sysctl(name, &len);
1490 else
1491 pcblist = getpcblist_kmem(off, name, &len);
1492
1493 for (j = 0; j < len; j++)
1494 if (pcblist[j].ki_ppcbaddr == pcbaddr)
1495 break;
1496 free(pcblist);
1497
1498 if (j == len)
1499 errx(1, "0x%lx is not a valid pcb address", pcbaddr);
1500
1501 kread(pcbaddr, (char *)&mypcb, sizeof(mypcb));
1502 hardticks = get_hardticks();
1503
1504 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
1505 printf("Timers:\n");
1506 for (i = 0; i < TCP6T_NTIMERS; i++) {
1507 char buf[128];
1508 ci = (callout_impl_t *)&tcpcb.t_timer[i];
1509 snprintb(buf, sizeof(buf), CALLOUT_FMT, ci->c_flags);
1510 printf("\t%s\t%s", tcptimers[i], buf);
1511 if (ci->c_flags & CALLOUT_PENDING)
1512 printf("\t%d\n", ci->c_time - hardticks);
1513 else
1514 printf("\n");
1515 }
1516 printf("\n\n");
1517
1518 if (mypcb.t_state < 0 || mypcb.t_state >= TCP6_NSTATES)
1519 printf("State: %d", mypcb.t_state);
1520 else
1521 printf("State: %s", tcp6states[mypcb.t_state]);
1522 printf(", flags 0x%x, in6pcb 0x%lx\n\n", mypcb.t_flags,
1523 (u_long)mypcb.t_in6pcb);
1524
1525 printf("rxtshift %d, rxtcur %d, dupacks %d\n", mypcb.t_rxtshift,
1526 mypcb.t_rxtcur, mypcb.t_dupacks);
1527 #ifdef TCP6
1528 printf("peermaxseg %u, maxseg %u, force %d\n\n", mypcb.t_peermaxseg,
1529 mypcb.t_maxseg, mypcb.t_force);
1530 #else
1531 printf("peermss %u, ourmss %u, segsz %u, segqlen %u\n\n",
1532 tcpcb.t_peermss, tcpcb.t_ourmss, tcpcb.t_segsz, tcpcb.t_segqlen);
1533 #endif
1534
1535 printf("snd_una %u, snd_nxt %u, snd_up %u\n",
1536 mypcb.snd_una, mypcb.snd_nxt, mypcb.snd_up);
1537 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %llu\n\n",
1538 mypcb.snd_wl1, mypcb.snd_wl2, mypcb.iss,
1539 (unsigned long long)mypcb.snd_wnd);
1540
1541 printf("rcv_wnd %llu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
1542 (unsigned long long)mypcb.rcv_wnd, mypcb.rcv_nxt,
1543 mypcb.rcv_up, mypcb.irs);
1544
1545 printf("rcv_adv %u, snd_max %u, snd_cwnd %llu, snd_ssthresh %llu\n",
1546 mypcb.rcv_adv, mypcb.snd_max, (unsigned long long)mypcb.snd_cwnd,
1547 (unsigned long long)mypcb.snd_ssthresh);
1548
1549 #ifdef TCP6
1550 printf("idle %d, rtt %d, " mypcb.t_idle, mypcb.t_rtt);
1551 #else
1552 printf("rcvtime %u, rtttime %u, ", tcpcb.t_rcvtime, tcpcb.t_rtttime);
1553 #endif
1554
1555 printf("rtseq %u, srtt %d, rttvar %d, rttmin %d, "
1556 "max_sndwnd %llu\n\n", mypcb.t_rtseq,
1557 mypcb.t_srtt, mypcb.t_rttvar, mypcb.t_rttmin,
1558 (unsigned long long)mypcb.max_sndwnd);
1559
1560 printf("oobflags %d, iobc %d, softerror %d\n\n", mypcb.t_oobflags,
1561 mypcb.t_iobc, mypcb.t_softerror);
1562
1563 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
1564 mypcb.snd_scale, mypcb.rcv_scale, mypcb.request_r_scale,
1565 mypcb.requested_s_scale);
1566 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
1567 mypcb.ts_recent, mypcb.ts_recent_age, mypcb.last_ack_sent);
1568 }
1569
1570 #endif /*INET6*/
1571