inet.c revision 1.70 1 /* $NetBSD: inet.c,v 1.70 2006/05/18 17:19:22 riz Exp $ */
2
3 /*
4 * Copyright (c) 1983, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
36 #else
37 __RCSID("$NetBSD: inet.c,v 1.70 2006/05/18 17:19:22 riz Exp $");
38 #endif
39 #endif /* not lint */
40
41 #include <sys/param.h>
42 #include <sys/queue.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/mbuf.h>
46 #include <sys/protosw.h>
47 #include <sys/sysctl.h>
48
49 #include <net/if_arp.h>
50 #include <net/route.h>
51 #include <netinet/in.h>
52 #include <netinet/in_systm.h>
53 #include <netinet/ip.h>
54 #include <netinet/in_pcb.h>
55 #include <netinet/ip_icmp.h>
56
57 #ifdef INET6
58 #include <netinet/ip6.h>
59 #endif
60
61 #include <netinet/icmp_var.h>
62 #include <netinet/igmp_var.h>
63 #include <netinet/ip_var.h>
64 #include <netinet/pim_var.h>
65 #include <netinet/tcp.h>
66 #include <netinet/tcpip.h>
67 #include <netinet/tcp_seq.h>
68 #define TCPSTATES
69 #include <netinet/tcp_fsm.h>
70 #define TCPTIMERS
71 #include <netinet/tcp_timer.h>
72 #include <netinet/tcp_var.h>
73 #include <netinet/tcp_debug.h>
74 #include <netinet/udp.h>
75 #include <netinet/ip_carp.h>
76 #include <netinet/udp_var.h>
77
78 #include <arpa/inet.h>
79 #include <kvm.h>
80 #include <netdb.h>
81 #include <stdio.h>
82 #include <string.h>
83 #include <unistd.h>
84 #include <stdlib.h>
85 #include <err.h>
86 #include "netstat.h"
87
88 struct inpcb inpcb;
89 struct tcpcb tcpcb;
90 struct socket sockb;
91
92 char *inetname __P((struct in_addr *));
93 void inetprint __P((struct in_addr *, u_int16_t, const char *, int));
94
95 /*
96 * Print a summary of connections related to an Internet
97 * protocol. For TCP, also give state of connection.
98 * Listening processes (aflag) are suppressed unless the
99 * -a (all) flag is specified.
100 */
101 static int width;
102 static int compact;
103
104 static void
105 protoprhdr(void)
106 {
107 printf("Active Internet connections");
108 if (aflag)
109 printf(" (including servers)");
110 putchar('\n');
111 if (Aflag)
112 printf("%-8.8s ", "PCB");
113 printf("%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n",
114 "Proto", "Recv-Q", "Send-Q", compact ? "" : " ",
115 width, width, "Local Address",
116 width, width, "Foreign Address",
117 "State");
118 }
119
120 static void
121 protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc,
122 struct in_addr *laddr, u_int16_t lport,
123 struct in_addr *faddr, u_int16_t fport,
124 short t_state, char *name)
125 {
126 static char *shorttcpstates[] = {
127 "CLOSED", "LISTEN", "SYNSEN", "SYSRCV",
128 "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG",
129 "LASTAK", "FWAIT2", "TMWAIT",
130 };
131 int istcp;
132
133 istcp = strcmp(name, "tcp") == 0;
134
135 if (Aflag) {
136 printf("%8" PRIxPTR " ", ppcb);
137 }
138 printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc,
139 compact ? "" : " ");
140 if (numeric_port) {
141 inetprint(laddr, lport, name, 1);
142 inetprint(faddr, fport, name, 1);
143 } else if (inpcb.inp_flags & INP_ANONPORT) {
144 inetprint(laddr, lport, name, 1);
145 inetprint(faddr, fport, name, 0);
146 } else {
147 inetprint(laddr, lport, name, 0);
148 inetprint(faddr, fport, name, 0);
149 }
150 if (istcp) {
151 if (t_state < 0 || t_state >= TCP_NSTATES)
152 printf(" %d", t_state);
153 else
154 printf(" %s", compact ? shorttcpstates[t_state] :
155 tcpstates[t_state]);
156 }
157 putchar('\n');
158 }
159
160 void
161 protopr(off, name)
162 u_long off;
163 char *name;
164 {
165 struct inpcbtable table;
166 struct inpcb *head, *next, *prev;
167 struct inpcb inpcb;
168 int istcp;
169 static int first = 1;
170
171 if (off == 0)
172 return;
173 istcp = strcmp(name, "tcp") == 0;
174 kread(off, (char *)&table, sizeof table);
175 prev = head =
176 (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
177 next = (struct inpcb *)table.inpt_queue.cqh_first;
178
179 compact = 0;
180 if (Aflag) {
181 if (!numeric_addr)
182 width = 18;
183 else {
184 width = 21;
185 compact = 1;
186 }
187 } else
188 width = 22;
189
190 if (use_sysctl) {
191 struct kinfo_pcb *pcblist;
192 int mib[8];
193 size_t namelen = 0, size = 0, i;
194 char *mibname = NULL;
195
196 memset(mib, 0, sizeof(mib));
197
198 if (asprintf(&mibname, "net.inet.%s.pcblist", name) == -1)
199 err(1, "asprintf");
200
201 /* get dynamic pcblist node */
202 if (sysctlnametomib(mibname, mib, &namelen) == -1)
203 err(1, "sysctlnametomib");
204
205 if (sysctl(mib, sizeof(mib) / sizeof(*mib), NULL, &size,
206 NULL, 0) == -1)
207 err(1, "sysctl (query)");
208
209 pcblist = malloc(size);
210 memset(pcblist, 0, size);
211
212 mib[6] = sizeof(*pcblist);
213 mib[7] = size / sizeof(*pcblist);
214
215 if (sysctl(mib, sizeof(mib) / sizeof(*mib), pcblist,
216 &size, NULL, 0) == -1)
217 err(1, "sysctl (copy)");
218
219 for (i = 0; i < size / sizeof(*pcblist); i++) {
220 struct sockaddr_in src, dst;
221
222 memcpy(&src, &pcblist[i].ki_s, sizeof(src));
223 memcpy(&dst, &pcblist[i].ki_d, sizeof(dst));
224
225 if (first) {
226 protoprhdr();
227 first = 0;
228 }
229
230 protopr0((intptr_t) pcblist[i].ki_ppcbaddr,
231 pcblist[i].ki_rcvq, pcblist[i].ki_sndq,
232 &src.sin_addr, src.sin_port,
233 &dst.sin_addr, dst.sin_port,
234 pcblist[i].ki_tstate, name);
235 }
236
237 free(pcblist);
238 return;
239 }
240
241 while (next != head) {
242 kread((u_long)next, (char *)&inpcb, sizeof inpcb);
243 if ((struct inpcb *)inpcb.inp_queue.cqe_prev != prev) {
244 printf("???\n");
245 break;
246 }
247 prev = next;
248 next = (struct inpcb *)inpcb.inp_queue.cqe_next;
249
250 if (inpcb.inp_af != AF_INET)
251 continue;
252
253 if (!aflag &&
254 inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
255 continue;
256 kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
257 if (istcp) {
258 kread((u_long)inpcb.inp_ppcb,
259 (char *)&tcpcb, sizeof (tcpcb));
260 }
261
262 if (first) {
263 protoprhdr();
264 first = 0;
265 }
266
267 protopr0(istcp ? (intptr_t) inpcb.inp_ppcb : (intptr_t) prev,
268 sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc,
269 &inpcb.inp_laddr, inpcb.inp_lport,
270 &inpcb.inp_faddr, inpcb.inp_fport,
271 tcpcb.t_state, name);
272 }
273 }
274
275 /*
276 * Dump TCP statistics structure.
277 */
278 void
279 tcp_stats(off, name)
280 u_long off;
281 char *name;
282 {
283 struct tcpstat tcpstat;
284
285 if (use_sysctl) {
286 size_t size = sizeof(tcpstat);
287
288 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &size,
289 NULL, 0) == -1)
290 err(1, "net.inet.tcp.stats");
291 } else {
292 if (off == 0)
293 return;
294 kread(off, (char *)&tcpstat, sizeof (tcpstat));
295 }
296
297 printf ("%s:\n", name);
298
299 #define ps(f, m) if (tcpstat.f || sflag <= 1) \
300 printf(m, (unsigned long long)tcpstat.f)
301 #define p(f, m) if (tcpstat.f || sflag <= 1) \
302 printf(m, (unsigned long long)tcpstat.f, plural(tcpstat.f))
303 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
304 printf(m, (unsigned long long)tcpstat.f1, plural(tcpstat.f1), \
305 (unsigned long long)tcpstat.f2, plural(tcpstat.f2))
306 #define p2s(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
307 printf(m, (unsigned long long)tcpstat.f1, plural(tcpstat.f1), \
308 (unsigned long long)tcpstat.f2)
309 #define p3(f, m) if (tcpstat.f || sflag <= 1) \
310 printf(m, (unsigned long long)tcpstat.f, plurales(tcpstat.f))
311
312 p(tcps_sndtotal, "\t%llu packet%s sent\n");
313 p2(tcps_sndpack,tcps_sndbyte,
314 "\t\t%llu data packet%s (%llu byte%s)\n");
315 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
316 "\t\t%llu data packet%s (%llu byte%s) retransmitted\n");
317 p2s(tcps_sndacks, tcps_delack,
318 "\t\t%llu ack-only packet%s (%llu delayed)\n");
319 p(tcps_sndurg, "\t\t%llu URG only packet%s\n");
320 p(tcps_sndprobe, "\t\t%llu window probe packet%s\n");
321 p(tcps_sndwinup, "\t\t%llu window update packet%s\n");
322 p(tcps_sndctrl, "\t\t%llu control packet%s\n");
323 p(tcps_selfquench,
324 "\t\t%llu send attempt%s resulted in self-quench\n");
325 p(tcps_rcvtotal, "\t%llu packet%s received\n");
326 p2(tcps_rcvackpack, tcps_rcvackbyte,
327 "\t\t%llu ack%s (for %llu byte%s)\n");
328 p(tcps_rcvdupack, "\t\t%llu duplicate ack%s\n");
329 p(tcps_rcvacktoomuch, "\t\t%llu ack%s for unsent data\n");
330 p2(tcps_rcvpack, tcps_rcvbyte,
331 "\t\t%llu packet%s (%llu byte%s) received in-sequence\n");
332 p2(tcps_rcvduppack, tcps_rcvdupbyte,
333 "\t\t%llu completely duplicate packet%s (%llu byte%s)\n");
334 p(tcps_pawsdrop, "\t\t%llu old duplicate packet%s\n");
335 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
336 "\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n");
337 p2(tcps_rcvoopack, tcps_rcvoobyte,
338 "\t\t%llu out-of-order packet%s (%llu byte%s)\n");
339 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
340 "\t\t%llu packet%s (%llu byte%s) of data after window\n");
341 p(tcps_rcvwinprobe, "\t\t%llu window probe%s\n");
342 p(tcps_rcvwinupd, "\t\t%llu window update packet%s\n");
343 p(tcps_rcvafterclose, "\t\t%llu packet%s received after close\n");
344 p(tcps_rcvbadsum, "\t\t%llu discarded for bad checksum%s\n");
345 p(tcps_rcvbadoff, "\t\t%llu discarded for bad header offset field%s\n");
346 ps(tcps_rcvshort, "\t\t%llu discarded because packet too short\n");
347 p(tcps_connattempt, "\t%llu connection request%s\n");
348 p(tcps_accepts, "\t%llu connection accept%s\n");
349 p(tcps_connects,
350 "\t%llu connection%s established (including accepts)\n");
351 p2(tcps_closed, tcps_drops,
352 "\t%llu connection%s closed (including %llu drop%s)\n");
353 p(tcps_conndrops, "\t%llu embryonic connection%s dropped\n");
354 p(tcps_delayed_free, "\t%llu delayed free%s of tcpcb\n");
355 p2(tcps_rttupdated, tcps_segstimed,
356 "\t%llu segment%s updated rtt (of %llu attempt%s)\n");
357 p(tcps_rexmttimeo, "\t%llu retransmit timeout%s\n");
358 p(tcps_timeoutdrop,
359 "\t\t%llu connection%s dropped by rexmit timeout\n");
360 p2(tcps_persisttimeo, tcps_persistdrops,
361 "\t%llu persist timeout%s (resulting in %llu dropped "
362 "connection%s)\n");
363 p(tcps_keeptimeo, "\t%llu keepalive timeout%s\n");
364 p(tcps_keepprobe, "\t\t%llu keepalive probe%s sent\n");
365 p(tcps_keepdrops, "\t\t%llu connection%s dropped by keepalive\n");
366 p(tcps_predack, "\t%llu correct ACK header prediction%s\n");
367 p(tcps_preddat, "\t%llu correct data packet header prediction%s\n");
368 p3(tcps_pcbhashmiss, "\t%llu PCB hash miss%s\n");
369 ps(tcps_noport, "\t%llu dropped due to no socket\n");
370 p(tcps_connsdrained, "\t%llu connection%s drained due to memory "
371 "shortage\n");
372 p(tcps_pmtublackhole, "\t%llu PMTUD blackhole%s detected\n");
373
374 p(tcps_badsyn, "\t%llu bad connection attempt%s\n");
375 ps(tcps_sc_added, "\t%llu SYN cache entries added\n");
376 p(tcps_sc_collisions, "\t\t%llu hash collision%s\n");
377 ps(tcps_sc_completed, "\t\t%llu completed\n");
378 ps(tcps_sc_aborted, "\t\t%llu aborted (no space to build PCB)\n");
379 ps(tcps_sc_timed_out, "\t\t%llu timed out\n");
380 ps(tcps_sc_overflowed, "\t\t%llu dropped due to overflow\n");
381 ps(tcps_sc_bucketoverflow, "\t\t%llu dropped due to bucket overflow\n");
382 ps(tcps_sc_reset, "\t\t%llu dropped due to RST\n");
383 ps(tcps_sc_unreach, "\t\t%llu dropped due to ICMP unreachable\n");
384 ps(tcps_sc_delayed_free, "\t\t%llu delayed free of SYN cache "
385 "entries\n");
386 p(tcps_sc_retransmitted, "\t%llu SYN,ACK%s retransmitted\n");
387 p(tcps_sc_dupesyn, "\t%llu duplicate SYN%s received for entries "
388 "already in the cache\n");
389 p(tcps_sc_dropped, "\t%llu SYN%s dropped (no route or no space)\n");
390 p(tcps_badsig, "\t%llu packet%s with bad signature\n");
391 p(tcps_goodsig, "\t%llu packet%s with good signature\n");
392
393 #undef p
394 #undef ps
395 #undef p2
396 #undef p2s
397 #undef p3
398 }
399
400 /*
401 * Dump UDP statistics structure.
402 */
403 void
404 udp_stats(off, name)
405 u_long off;
406 char *name;
407 {
408 struct udpstat udpstat;
409 u_quad_t delivered;
410
411 if (use_sysctl) {
412 size_t size = sizeof(udpstat);
413
414 if (sysctlbyname("net.inet.udp.stats", &udpstat, &size,
415 NULL, 0) == -1)
416 err(1, "net.inet.udp.stats");
417 } else {
418 if (off == 0)
419 return;
420 kread(off, (char *)&udpstat, sizeof (udpstat));
421 }
422
423 printf ("%s:\n", name);
424
425 #define ps(f, m) if (udpstat.f || sflag <= 1) \
426 printf(m, (unsigned long long)udpstat.f)
427 #define p(f, m) if (udpstat.f || sflag <= 1) \
428 printf(m, (unsigned long long)udpstat.f, plural(udpstat.f))
429 #define p3(f, m) if (udpstat.f || sflag <= 1) \
430 printf(m, (unsigned long long)udpstat.f, plurales(udpstat.f))
431
432 p(udps_ipackets, "\t%llu datagram%s received\n");
433 ps(udps_hdrops, "\t%llu with incomplete header\n");
434 ps(udps_badlen, "\t%llu with bad data length field\n");
435 ps(udps_badsum, "\t%llu with bad checksum\n");
436 ps(udps_noport, "\t%llu dropped due to no socket\n");
437 p(udps_noportbcast, "\t%llu broadcast/multicast datagram%s dropped due to no socket\n");
438 ps(udps_fullsock, "\t%llu dropped due to full socket buffers\n");
439 delivered = udpstat.udps_ipackets -
440 udpstat.udps_hdrops -
441 udpstat.udps_badlen -
442 udpstat.udps_badsum -
443 udpstat.udps_noport -
444 udpstat.udps_noportbcast -
445 udpstat.udps_fullsock;
446 if (delivered || sflag <= 1)
447 printf("\t%llu delivered\n", (unsigned long long)delivered);
448 p3(udps_pcbhashmiss, "\t%llu PCB hash miss%s\n");
449 p(udps_opackets, "\t%llu datagram%s output\n");
450
451 #undef ps
452 #undef p
453 #undef p3
454 }
455
456 /*
457 * Dump IP statistics structure.
458 */
459 void
460 ip_stats(off, name)
461 u_long off;
462 char *name;
463 {
464 struct ipstat ipstat;
465
466 if (use_sysctl) {
467 size_t size = sizeof(ipstat);
468
469 if (sysctlbyname("net.inet.ip.stats", &ipstat, &size,
470 NULL, 0) == -1)
471 err(1, "net.inet.ip.stats");
472 } else {
473 if (off == 0)
474 return;
475 kread(off, (char *)&ipstat, sizeof (ipstat));
476 }
477
478 printf("%s:\n", name);
479
480 #define ps(f, m) if (ipstat.f || sflag <= 1) \
481 printf(m, (unsigned long long)ipstat.f)
482 #define p(f, m) if (ipstat.f || sflag <= 1) \
483 printf(m, (unsigned long long)ipstat.f, plural(ipstat.f))
484
485 p(ips_total, "\t%llu total packet%s received\n");
486 p(ips_badsum, "\t%llu bad header checksum%s\n");
487 ps(ips_toosmall, "\t%llu with size smaller than minimum\n");
488 ps(ips_tooshort, "\t%llu with data size < data length\n");
489 ps(ips_toolong, "\t%llu with length > max ip packet size\n");
490 ps(ips_badhlen, "\t%llu with header length < data size\n");
491 ps(ips_badlen, "\t%llu with data length < header length\n");
492 ps(ips_badoptions, "\t%llu with bad options\n");
493 ps(ips_badvers, "\t%llu with incorrect version number\n");
494 p(ips_fragments, "\t%llu fragment%s received\n");
495 p(ips_fragdropped, "\t%llu fragment%s dropped (dup or out of space)\n");
496 p(ips_rcvmemdrop, "\t%llu fragment%s dropped (out of ipqent)\n");
497 p(ips_badfrags, "\t%llu malformed fragment%s dropped\n");
498 p(ips_fragtimeout, "\t%llu fragment%s dropped after timeout\n");
499 p(ips_reassembled, "\t%llu packet%s reassembled ok\n");
500 p(ips_delivered, "\t%llu packet%s for this host\n");
501 p(ips_noproto, "\t%llu packet%s for unknown/unsupported protocol\n");
502 p(ips_forward, "\t%llu packet%s forwarded");
503 p(ips_fastforward, " (%llu packet%s fast forwarded)");
504 if (ipstat.ips_forward || sflag <= 1)
505 putchar('\n');
506 p(ips_cantforward, "\t%llu packet%s not forwardable\n");
507 p(ips_redirectsent, "\t%llu redirect%s sent\n");
508 p(ips_nogif, "\t%llu packet%s no matching gif found\n");
509 p(ips_localout, "\t%llu packet%s sent from this host\n");
510 p(ips_rawout, "\t%llu packet%s sent with fabricated ip header\n");
511 p(ips_odropped, "\t%llu output packet%s dropped due to no bufs, etc.\n");
512 p(ips_noroute, "\t%llu output packet%s discarded due to no route\n");
513 p(ips_fragmented, "\t%llu output datagram%s fragmented\n");
514 p(ips_ofragments, "\t%llu fragment%s created\n");
515 p(ips_cantfrag, "\t%llu datagram%s that can't be fragmented\n");
516 p(ips_badaddr, "\t%llu datagram%s with bad address in header\n");
517 #undef ps
518 #undef p
519 }
520
521 static char *icmpnames[] = {
522 "echo reply",
523 "#1",
524 "#2",
525 "destination unreachable",
526 "source quench",
527 "routing redirect",
528 "alternate host address",
529 "#7",
530 "echo",
531 "router advertisement",
532 "router solicitation",
533 "time exceeded",
534 "parameter problem",
535 "time stamp",
536 "time stamp reply",
537 "information request",
538 "information request reply",
539 "address mask request",
540 "address mask reply",
541 };
542
543 /*
544 * Dump ICMP statistics.
545 */
546 void
547 icmp_stats(off, name)
548 u_long off;
549 char *name;
550 {
551 struct icmpstat icmpstat;
552 int i, first;
553
554 if (use_sysctl) {
555 size_t size = sizeof(icmpstat);
556
557 if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &size,
558 NULL, 0) == -1)
559 err(1, "net.inet.icmp.stats");
560 } else {
561 if (off == 0)
562 return;
563 kread(off, (char *)&icmpstat, sizeof (icmpstat));
564 }
565
566 printf("%s:\n", name);
567
568 #define p(f, m) if (icmpstat.f || sflag <= 1) \
569 printf(m, (unsigned long long)icmpstat.f, plural(icmpstat.f))
570
571 p(icps_error, "\t%llu call%s to icmp_error\n");
572 p(icps_oldicmp,
573 "\t%llu error%s not generated because old message was icmp\n");
574 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
575 if (icmpstat.icps_outhist[i] != 0) {
576 if (first) {
577 printf("\tOutput histogram:\n");
578 first = 0;
579 }
580 printf("\t\t%s: %llu\n", icmpnames[i],
581 (unsigned long long)icmpstat.icps_outhist[i]);
582 }
583 p(icps_badcode, "\t%llu message%s with bad code fields\n");
584 p(icps_tooshort, "\t%llu message%s < minimum length\n");
585 p(icps_checksum, "\t%llu bad checksum%s\n");
586 p(icps_badlen, "\t%llu message%s with bad length\n");
587 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
588 if (icmpstat.icps_inhist[i] != 0) {
589 if (first) {
590 printf("\tInput histogram:\n");
591 first = 0;
592 }
593 printf("\t\t%s: %llu\n", icmpnames[i],
594 (unsigned long long)icmpstat.icps_inhist[i]);
595 }
596 p(icps_reflect, "\t%llu message response%s generated\n");
597 p(icps_pmtuchg, "\t%llu path MTU change%s\n");
598 #undef p
599 }
600
601 /*
602 * Dump IGMP statistics structure.
603 */
604 void
605 igmp_stats(off, name)
606 u_long off;
607 char *name;
608 {
609 struct igmpstat igmpstat;
610
611 if (off == 0)
612 return;
613 kread(off, (char *)&igmpstat, sizeof (igmpstat));
614 printf("%s:\n", name);
615
616 #define p(f, m) if (igmpstat.f || sflag <= 1) \
617 printf(m, (unsigned long long)igmpstat.f, plural(igmpstat.f))
618 #define py(f, m) if (igmpstat.f || sflag <= 1) \
619 printf(m, (unsigned long long)igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
620 p(igps_rcv_total, "\t%llu message%s received\n");
621 p(igps_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
622 p(igps_rcv_badsum, "\t%llu message%s received with bad checksum\n");
623 py(igps_rcv_queries, "\t%llu membership quer%s received\n");
624 py(igps_rcv_badqueries, "\t%llu membership quer%s received with invalid field(s)\n");
625 p(igps_rcv_reports, "\t%llu membership report%s received\n");
626 p(igps_rcv_badreports, "\t%llu membership report%s received with invalid field(s)\n");
627 p(igps_rcv_ourreports, "\t%llu membership report%s received for groups to which we belong\n");
628 p(igps_snd_reports, "\t%llu membership report%s sent\n");
629 #undef p
630 #undef py
631 }
632
633 /*
634 * Dump CARP statistics structure.
635 */
636 void
637 carp_stats(u_long off, char *name)
638 {
639 struct carpstats carpstat;
640
641 if (use_sysctl) {
642 size_t size = sizeof(carpstat);
643
644 if (sysctlbyname("net.inet.carp.stats", &carpstat, &size,
645 NULL, 0) == -1)
646 err(1, "net.inet.carp.stats");
647 } else {
648 if (off == 0)
649 return;
650 kread(off, (char *)&carpstat, sizeof(carpstat));
651 }
652
653 printf("%s:\n", name);
654
655 #define p(f, m) if (carpstat.f || sflag <= 1) \
656 printf(m, carpstat.f, plural(carpstat.f))
657 #define p2(f, m) if (carpstat.f || sflag <= 1) \
658 printf(m, carpstat.f)
659
660 p(carps_ipackets, "\t%" PRIu64 " packet%s received (IPv4)\n");
661 p(carps_ipackets6, "\t%" PRIu64 " packet%s received (IPv6)\n");
662 p(carps_badif,
663 "\t\t%" PRIu64 " packet%s discarded for bad interface\n");
664 p(carps_badttl,
665 "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n");
666 p(carps_hdrops, "\t\t%" PRIu64 " packet%s shorter than header\n");
667 p(carps_badsum, "\t\t%" PRIu64
668 " packet%s discarded for bad checksum\n");
669 p(carps_badver,
670 "\t\t%" PRIu64 " packet%s discarded with a bad version\n");
671 p2(carps_badlen,
672 "\t\t%" PRIu64 " discarded because packet was too short\n");
673 p(carps_badauth,
674 "\t\t%" PRIu64 " packet%s discarded for bad authentication\n");
675 p(carps_badvhid, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n");
676 p(carps_badaddrs, "\t\t%" PRIu64
677 " packet%s discarded because of a bad address list\n");
678 p(carps_opackets, "\t%" PRIu64 " packet%s sent (IPv4)\n");
679 p(carps_opackets6, "\t%" PRIu64 " packet%s sent (IPv6)\n");
680 p2(carps_onomem,
681 "\t\t%" PRIu64 " send failed due to mbuf memory error\n");
682 #undef p
683 #undef p2
684 }
685
686 /*
687 * Dump PIM statistics structure.
688 */
689 void
690 pim_stats(off, name)
691 u_long off;
692 char *name;
693 {
694 struct pimstat pimstat;
695
696 if (off == 0)
697 return;
698 if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) {
699 /* XXX: PIM is probably not enabled in the kernel */
700 return;
701 }
702
703 printf("%s:\n", name);
704
705 #define p(f, m) if (pimstat.f || sflag <= 1) \
706 printf(m, (unsigned long long)pimstat.f, plural(pimstat.f))
707
708 p(pims_rcv_total_msgs, "\t%llu message%s received\n");
709 p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
710 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
711 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
712 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
713 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
714 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
715 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
716 p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
717 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
718 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
719 #undef p
720 }
721
722 /*
723 * Dump the ARP statistics structure.
724 */
725 void
726 arp_stats(off, name)
727 u_long off;
728 char *name;
729 {
730 struct arpstat arpstat;
731
732 if (off == 0)
733 return;
734 kread(off, (char *)&arpstat, sizeof (arpstat));
735 printf("%s:\n", name);
736
737 #define ps(f, m) if (arpstat.f || sflag <= 1) \
738 printf(m, (unsigned long long)arpstat.f)
739 #define p(f, m) if (arpstat.f || sflag <= 1) \
740 printf(m, (unsigned long long)arpstat.f, plural(arpstat.f))
741
742 p(as_sndtotal, "\t%llu packet%s sent\n");
743 p(as_sndreply, "\t\t%llu reply packet%s\n");
744 p(as_sndrequest, "\t\t%llu request packet%s\n");
745
746 p(as_rcvtotal, "\t%llu packet%s received\n");
747 p(as_rcvreply, "\t\t%llu reply packet%s\n");
748 p(as_rcvrequest, "\t\t%llu valid request packet%s\n");
749 p(as_rcvmcast, "\t\t%llu broadcast/multicast packet%s\n");
750 p(as_rcvbadproto, "\t\t%llu packet%s with unknown protocol type\n");
751 p(as_rcvbadlen, "\t\t%llu packet%s with bad (short) length\n");
752 p(as_rcvzerotpa, "\t\t%llu packet%s with null target IP address\n");
753 p(as_rcvzerospa, "\t\t%llu packet%s with null source IP address\n");
754 ps(as_rcvnoint, "\t\t%llu could not be mapped to an interface\n");
755 p(as_rcvlocalsha, "\t\t%llu packet%s sourced from a local hardware "
756 "address\n");
757 p(as_rcvbcastsha, "\t\t%llu packet%s with a broadcast "
758 "source hardware address\n");
759 p(as_rcvlocalspa, "\t\t%llu duplicate%s for a local IP address\n");
760 p(as_rcvoverperm, "\t\t%llu attempt%s to overwrite a static entry\n");
761 p(as_rcvoverint, "\t\t%llu packet%s received on wrong interface\n");
762 p(as_rcvover, "\t\t%llu entry%s overwritten\n");
763 p(as_rcvlenchg, "\t\t%llu change%s in hardware address length\n");
764
765 p(as_dfrtotal, "\t%llu packet%s deferred pending ARP resolution\n");
766 ps(as_dfrsent, "\t\t%llu sent\n");
767 ps(as_dfrdropped, "\t\t%llu dropped\n");
768
769 p(as_allocfail, "\t%llu failure%s to allocate llinfo\n");
770
771 #undef ps
772 #undef p
773 }
774
775 /*
776 * Pretty print an Internet address (net address + port).
777 * Take numeric_addr and numeric_port into consideration.
778 */
779 void
780 inetprint(in, port, proto, numeric_port)
781 struct in_addr *in;
782 u_int16_t port;
783 const char *proto;
784 int numeric_port;
785 {
786 struct servent *sp = 0;
787 char line[80], *cp;
788 size_t space;
789
790 (void)snprintf(line, sizeof line, "%.*s.",
791 (Aflag && !numeric_addr) ? 12 : 16, inetname(in));
792 cp = strchr(line, '\0');
793 if (!numeric_port && port)
794 sp = getservbyport((int)port, proto);
795 space = sizeof line - (cp-line);
796 if (sp || port == 0)
797 (void)snprintf(cp, space, "%s", sp ? sp->s_name : "*");
798 else
799 (void)snprintf(cp, space, "%u", ntohs(port));
800 (void)printf(" %-*.*s", width, width, line);
801 }
802
803 /*
804 * Construct an Internet address representation.
805 * If numeric_addr has been supplied, give
806 * numeric value, otherwise try for symbolic name.
807 */
808 char *
809 inetname(inp)
810 struct in_addr *inp;
811 {
812 char *cp;
813 static char line[50];
814 struct hostent *hp;
815 struct netent *np;
816 static char domain[MAXHOSTNAMELEN + 1];
817 static int first = 1;
818
819 if (first && !numeric_addr) {
820 first = 0;
821 if (gethostname(domain, sizeof domain) == 0) {
822 domain[sizeof(domain) - 1] = '\0';
823 if ((cp = strchr(domain, '.')))
824 (void) strlcpy(domain, cp + 1, sizeof(domain));
825 else
826 domain[0] = 0;
827 } else
828 domain[0] = 0;
829 }
830 cp = 0;
831 if (!numeric_addr && inp->s_addr != INADDR_ANY) {
832 int net = inet_netof(*inp);
833 int lna = inet_lnaof(*inp);
834
835 if (lna == INADDR_ANY) {
836 np = getnetbyaddr(net, AF_INET);
837 if (np)
838 cp = np->n_name;
839 }
840 if (cp == 0) {
841 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
842 if (hp) {
843 if ((cp = strchr(hp->h_name, '.')) &&
844 !strcmp(cp + 1, domain))
845 *cp = 0;
846 cp = hp->h_name;
847 }
848 }
849 }
850 if (inp->s_addr == INADDR_ANY)
851 strlcpy(line, "*", sizeof line);
852 else if (cp)
853 strlcpy(line, cp, sizeof line);
854 else {
855 inp->s_addr = ntohl(inp->s_addr);
856 #define C(x) ((x) & 0xff)
857 (void)snprintf(line, sizeof line, "%u.%u.%u.%u",
858 C(inp->s_addr >> 24), C(inp->s_addr >> 16),
859 C(inp->s_addr >> 8), C(inp->s_addr));
860 #undef C
861 }
862 return (line);
863 }
864
865 /*
866 * Dump the contents of a TCP PCB.
867 */
868 void
869 tcp_dump(pcbaddr)
870 u_long pcbaddr;
871 {
872 struct tcpcb tcpcb;
873 int i, hardticks;
874
875 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
876 hardticks = get_hardticks();
877
878 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
879
880 printf("Timers:\n");
881 for (i = 0; i < TCPT_NTIMERS; i++) {
882 printf("\t%s: %d", tcptimers[i],
883 (tcpcb.t_timer[i].c_flags & CALLOUT_PENDING) ?
884 tcpcb.t_timer[i].c_time - hardticks : 0);
885 }
886 printf("\n\n");
887
888 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
889 printf("State: %d", tcpcb.t_state);
890 else
891 printf("State: %s", tcpstates[tcpcb.t_state]);
892 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags,
893 (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb);
894
895 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
896 tcpcb.t_rxtcur, tcpcb.t_dupacks);
897 printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss,
898 tcpcb.t_ourmss, tcpcb.t_segsz);
899
900 printf("snd_una %u, snd_nxt %u, snd_up %u\n",
901 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
902 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
903 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
904
905 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
906 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
907
908 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
909 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
910
911 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
912 "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime,
913 tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin,
914 tcpcb.max_sndwnd);
915
916 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
917 tcpcb.t_iobc, tcpcb.t_softerror);
918
919 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
920 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
921 tcpcb.requested_s_scale);
922 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
923 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
924 }
925