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