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