inet.c revision 1.65 1 /* $NetBSD: inet.c,v 1.65 2005/08/06 17:58:13 elad 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.65 2005/08/06 17:58:13 elad 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/udp_var.h>
76
77 #include <arpa/inet.h>
78 #include <kvm.h>
79 #include <netdb.h>
80 #include <stdio.h>
81 #include <string.h>
82 #include <unistd.h>
83 #include <err.h>
84 #include "netstat.h"
85
86 struct inpcb inpcb;
87 struct tcpcb tcpcb;
88 struct socket sockb;
89
90 char *inetname __P((struct in_addr *));
91 void inetprint __P((struct in_addr *, u_int16_t, const char *, int));
92
93 /*
94 * Print a summary of connections related to an Internet
95 * protocol. For TCP, also give state of connection.
96 * Listening processes (aflag) are suppressed unless the
97 * -a (all) flag is specified.
98 */
99 static int width;
100
101 void
102 protopr(off, name)
103 u_long off;
104 char *name;
105 {
106 struct inpcbtable table;
107 struct inpcb *head, *next, *prev;
108 struct inpcb inpcb;
109 int istcp, compact;
110 static int first = 1;
111 static char *shorttcpstates[] = {
112 "CLOSED", "LISTEN", "SYNSEN", "SYSRCV",
113 "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG",
114 "LASTAK", "FWAIT2", "TMWAIT",
115 };
116
117 if (off == 0)
118 return;
119 istcp = strcmp(name, "tcp") == 0;
120 kread(off, (char *)&table, sizeof table);
121 prev = head =
122 (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
123 next = (struct inpcb *)table.inpt_queue.cqh_first;
124
125 compact = 0;
126 if (Aflag) {
127 if (!numeric_addr)
128 width = 18;
129 else {
130 width = 21;
131 compact = 1;
132 }
133 } else
134 width = 22;
135 while (next != head) {
136 kread((u_long)next, (char *)&inpcb, sizeof inpcb);
137 if ((struct inpcb *)inpcb.inp_queue.cqe_prev != prev) {
138 printf("???\n");
139 break;
140 }
141 prev = next;
142 next = (struct inpcb *)inpcb.inp_queue.cqe_next;
143
144 if (inpcb.inp_af != AF_INET)
145 continue;
146
147 if (!aflag &&
148 inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
149 continue;
150 kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
151 if (istcp) {
152 kread((u_long)inpcb.inp_ppcb,
153 (char *)&tcpcb, sizeof (tcpcb));
154 }
155 if (first) {
156 printf("Active Internet connections");
157 if (aflag)
158 printf(" (including servers)");
159 putchar('\n');
160 if (Aflag)
161 printf("%-8.8s ", "PCB");
162 printf("%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n",
163 "Proto", "Recv-Q", "Send-Q",
164 compact ? "" : " ",
165 width, width, "Local Address",
166 width, width, "Foreign Address", "State");
167 first = 0;
168 }
169 if (Aflag) {
170 if (istcp)
171 printf("%8lx ", (u_long) inpcb.inp_ppcb);
172 else
173 printf("%8lx ", (u_long) prev);
174 }
175 printf("%-5.5s %6ld %6ld%s", name, sockb.so_rcv.sb_cc,
176 sockb.so_snd.sb_cc, compact ? "" : " ");
177 if (numeric_port) {
178 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name, 1);
179 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name, 1);
180 } else if (inpcb.inp_flags & INP_ANONPORT) {
181 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name, 1);
182 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name, 0);
183 } else {
184 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name, 0);
185 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name, 0);
186 }
187 if (istcp) {
188 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
189 printf(" %d", tcpcb.t_state);
190 else
191 printf(" %s", compact ?
192 shorttcpstates[tcpcb.t_state] :
193 tcpstates[tcpcb.t_state]);
194 }
195 putchar('\n');
196 }
197 }
198
199 /*
200 * Dump TCP statistics structure.
201 */
202 void
203 tcp_stats(off, name)
204 u_long off;
205 char *name;
206 {
207 struct tcpstat tcpstat;
208
209 if (use_sysctl) {
210 size_t size = sizeof(tcpstat);
211
212 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &size,
213 NULL, 0) == -1)
214 err(1, "net.inet.tcp.stats");
215 } else {
216 if (off == 0)
217 return;
218 kread(off, (char *)&tcpstat, sizeof (tcpstat));
219 }
220
221 printf ("%s:\n", name);
222
223 #define ps(f, m) if (tcpstat.f || sflag <= 1) \
224 printf(m, (unsigned long long)tcpstat.f)
225 #define p(f, m) if (tcpstat.f || sflag <= 1) \
226 printf(m, (unsigned long long)tcpstat.f, plural(tcpstat.f))
227 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
228 printf(m, (unsigned long long)tcpstat.f1, plural(tcpstat.f1), \
229 (unsigned long long)tcpstat.f2, plural(tcpstat.f2))
230 #define p2s(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
231 printf(m, (unsigned long long)tcpstat.f1, plural(tcpstat.f1), \
232 (unsigned long long)tcpstat.f2)
233 #define p3(f, m) if (tcpstat.f || sflag <= 1) \
234 printf(m, (unsigned long long)tcpstat.f, plurales(tcpstat.f))
235
236 p(tcps_sndtotal, "\t%llu packet%s sent\n");
237 p2(tcps_sndpack,tcps_sndbyte,
238 "\t\t%llu data packet%s (%llu byte%s)\n");
239 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
240 "\t\t%llu data packet%s (%llu byte%s) retransmitted\n");
241 p2s(tcps_sndacks, tcps_delack,
242 "\t\t%llu ack-only packet%s (%llu delayed)\n");
243 p(tcps_sndurg, "\t\t%llu URG only packet%s\n");
244 p(tcps_sndprobe, "\t\t%llu window probe packet%s\n");
245 p(tcps_sndwinup, "\t\t%llu window update packet%s\n");
246 p(tcps_sndctrl, "\t\t%llu control packet%s\n");
247 p(tcps_selfquench,
248 "\t\t%llu send attempt%s resulted in self-quench\n");
249 p(tcps_rcvtotal, "\t%llu packet%s received\n");
250 p2(tcps_rcvackpack, tcps_rcvackbyte,
251 "\t\t%llu ack%s (for %llu byte%s)\n");
252 p(tcps_rcvdupack, "\t\t%llu duplicate ack%s\n");
253 p(tcps_rcvacktoomuch, "\t\t%llu ack%s for unsent data\n");
254 p2(tcps_rcvpack, tcps_rcvbyte,
255 "\t\t%llu packet%s (%llu byte%s) received in-sequence\n");
256 p2(tcps_rcvduppack, tcps_rcvdupbyte,
257 "\t\t%llu completely duplicate packet%s (%llu byte%s)\n");
258 p(tcps_pawsdrop, "\t\t%llu old duplicate packet%s\n");
259 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
260 "\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n");
261 p2(tcps_rcvoopack, tcps_rcvoobyte,
262 "\t\t%llu out-of-order packet%s (%llu byte%s)\n");
263 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
264 "\t\t%llu packet%s (%llu byte%s) of data after window\n");
265 p(tcps_rcvwinprobe, "\t\t%llu window probe%s\n");
266 p(tcps_rcvwinupd, "\t\t%llu window update packet%s\n");
267 p(tcps_rcvafterclose, "\t\t%llu packet%s received after close\n");
268 p(tcps_rcvbadsum, "\t\t%llu discarded for bad checksum%s\n");
269 p(tcps_rcvbadoff, "\t\t%llu discarded for bad header offset field%s\n");
270 ps(tcps_rcvshort, "\t\t%llu discarded because packet too short\n");
271 p(tcps_connattempt, "\t%llu connection request%s\n");
272 p(tcps_accepts, "\t%llu connection accept%s\n");
273 p(tcps_connects,
274 "\t%llu connection%s established (including accepts)\n");
275 p2(tcps_closed, tcps_drops,
276 "\t%llu connection%s closed (including %llu drop%s)\n");
277 p(tcps_conndrops, "\t%llu embryonic connection%s dropped\n");
278 p(tcps_delayed_free, "\t%llu delayed free%s of tcpcb\n");
279 p2(tcps_rttupdated, tcps_segstimed,
280 "\t%llu segment%s updated rtt (of %llu attempt%s)\n");
281 p(tcps_rexmttimeo, "\t%llu retransmit timeout%s\n");
282 p(tcps_timeoutdrop,
283 "\t\t%llu connection%s dropped by rexmit timeout\n");
284 p2(tcps_persisttimeo, tcps_persistdrops,
285 "\t%llu persist timeout%s (resulting in %llu dropped "
286 "connection%s)\n");
287 p(tcps_keeptimeo, "\t%llu keepalive timeout%s\n");
288 p(tcps_keepprobe, "\t\t%llu keepalive probe%s sent\n");
289 p(tcps_keepdrops, "\t\t%llu connection%s dropped by keepalive\n");
290 p(tcps_predack, "\t%llu correct ACK header prediction%s\n");
291 p(tcps_preddat, "\t%llu correct data packet header prediction%s\n");
292 p3(tcps_pcbhashmiss, "\t%llu PCB hash miss%s\n");
293 ps(tcps_noport, "\t%llu dropped due to no socket\n");
294 p(tcps_connsdrained, "\t%llu connection%s drained due to memory "
295 "shortage\n");
296 p(tcps_pmtublackhole, "\t%llu PMTUD blackhole%s detected\n");
297
298 p(tcps_badsyn, "\t%llu bad connection attempt%s\n");
299 ps(tcps_sc_added, "\t%llu SYN cache entries added\n");
300 p(tcps_sc_collisions, "\t\t%llu hash collision%s\n");
301 ps(tcps_sc_completed, "\t\t%llu completed\n");
302 ps(tcps_sc_aborted, "\t\t%llu aborted (no space to build PCB)\n");
303 ps(tcps_sc_timed_out, "\t\t%llu timed out\n");
304 ps(tcps_sc_overflowed, "\t\t%llu dropped due to overflow\n");
305 ps(tcps_sc_bucketoverflow, "\t\t%llu dropped due to bucket overflow\n");
306 ps(tcps_sc_reset, "\t\t%llu dropped due to RST\n");
307 ps(tcps_sc_unreach, "\t\t%llu dropped due to ICMP unreachable\n");
308 ps(tcps_sc_delayed_free, "\t\t%llu delayed free of SYN cache "
309 "entries\n");
310 p(tcps_sc_retransmitted, "\t%llu SYN,ACK%s retransmitted\n");
311 p(tcps_sc_dupesyn, "\t%llu duplicate SYN%s received for entries "
312 "already in the cache\n");
313 p(tcps_sc_dropped, "\t%llu SYN%s dropped (no route or no space)\n");
314 p(tcps_badsig, "\t%llu packet%s with bad signature\n");
315 p(tcps_goodsig, "\t%llu packet%s with good signature\n");
316
317 #undef p
318 #undef ps
319 #undef p2
320 #undef p2s
321 #undef p3
322 }
323
324 /*
325 * Dump UDP statistics structure.
326 */
327 void
328 udp_stats(off, name)
329 u_long off;
330 char *name;
331 {
332 struct udpstat udpstat;
333 u_quad_t delivered;
334
335 if (use_sysctl) {
336 size_t size = sizeof(udpstat);
337
338 if (sysctlbyname("net.inet.udp.stats", &udpstat, &size,
339 NULL, 0) == -1)
340 err(1, "net.inet.udp.stats");
341 } else {
342 if (off == 0)
343 return;
344 kread(off, (char *)&udpstat, sizeof (udpstat));
345 }
346
347 printf ("%s:\n", name);
348
349 #define ps(f, m) if (udpstat.f || sflag <= 1) \
350 printf(m, (unsigned long long)udpstat.f)
351 #define p(f, m) if (udpstat.f || sflag <= 1) \
352 printf(m, (unsigned long long)udpstat.f, plural(udpstat.f))
353 #define p3(f, m) if (udpstat.f || sflag <= 1) \
354 printf(m, (unsigned long long)udpstat.f, plurales(udpstat.f))
355
356 p(udps_ipackets, "\t%llu datagram%s received\n");
357 ps(udps_hdrops, "\t%llu with incomplete header\n");
358 ps(udps_badlen, "\t%llu with bad data length field\n");
359 ps(udps_badsum, "\t%llu with bad checksum\n");
360 ps(udps_noport, "\t%llu dropped due to no socket\n");
361 p(udps_noportbcast, "\t%llu broadcast/multicast datagram%s dropped due to no socket\n");
362 ps(udps_fullsock, "\t%llu dropped due to full socket buffers\n");
363 delivered = udpstat.udps_ipackets -
364 udpstat.udps_hdrops -
365 udpstat.udps_badlen -
366 udpstat.udps_badsum -
367 udpstat.udps_noport -
368 udpstat.udps_noportbcast -
369 udpstat.udps_fullsock;
370 if (delivered || sflag <= 1)
371 printf("\t%llu delivered\n", (unsigned long long)delivered);
372 p3(udps_pcbhashmiss, "\t%llu PCB hash miss%s\n");
373 p(udps_opackets, "\t%llu datagram%s output\n");
374
375 #undef ps
376 #undef p
377 #undef p3
378 }
379
380 /*
381 * Dump IP statistics structure.
382 */
383 void
384 ip_stats(off, name)
385 u_long off;
386 char *name;
387 {
388 struct ipstat ipstat;
389
390 if (use_sysctl) {
391 size_t size = sizeof(ipstat);
392
393 if (sysctlbyname("net.inet.ip.stats", &ipstat, &size,
394 NULL, 0) == -1)
395 err(1, "net.inet.ip.stats");
396 } else {
397 if (off == 0)
398 return;
399 kread(off, (char *)&ipstat, sizeof (ipstat));
400 }
401
402 printf("%s:\n", name);
403
404 #define ps(f, m) if (ipstat.f || sflag <= 1) \
405 printf(m, (unsigned long long)ipstat.f)
406 #define p(f, m) if (ipstat.f || sflag <= 1) \
407 printf(m, (unsigned long long)ipstat.f, plural(ipstat.f))
408
409 p(ips_total, "\t%llu total packet%s received\n");
410 p(ips_badsum, "\t%llu bad header checksum%s\n");
411 ps(ips_toosmall, "\t%llu with size smaller than minimum\n");
412 ps(ips_tooshort, "\t%llu with data size < data length\n");
413 ps(ips_toolong, "\t%llu with length > max ip packet size\n");
414 ps(ips_badhlen, "\t%llu with header length < data size\n");
415 ps(ips_badlen, "\t%llu with data length < header length\n");
416 ps(ips_badoptions, "\t%llu with bad options\n");
417 ps(ips_badvers, "\t%llu with incorrect version number\n");
418 p(ips_fragments, "\t%llu fragment%s received\n");
419 p(ips_fragdropped, "\t%llu fragment%s dropped (dup or out of space)\n");
420 p(ips_rcvmemdrop, "\t%llu fragment%s dropped (out of ipqent)\n");
421 p(ips_badfrags, "\t%llu malformed fragment%s dropped\n");
422 p(ips_fragtimeout, "\t%llu fragment%s dropped after timeout\n");
423 p(ips_reassembled, "\t%llu packet%s reassembled ok\n");
424 p(ips_delivered, "\t%llu packet%s for this host\n");
425 p(ips_noproto, "\t%llu packet%s for unknown/unsupported protocol\n");
426 p(ips_forward, "\t%llu packet%s forwarded");
427 p(ips_fastforward, " (%llu packet%s fast forwarded)");
428 if (ipstat.ips_forward || sflag <= 1)
429 putchar('\n');
430 p(ips_cantforward, "\t%llu packet%s not forwardable\n");
431 p(ips_redirectsent, "\t%llu redirect%s sent\n");
432 p(ips_nogif, "\t%llu packet%s no matching gif found\n");
433 p(ips_localout, "\t%llu packet%s sent from this host\n");
434 p(ips_rawout, "\t%llu packet%s sent with fabricated ip header\n");
435 p(ips_odropped, "\t%llu output packet%s dropped due to no bufs, etc.\n");
436 p(ips_noroute, "\t%llu output packet%s discarded due to no route\n");
437 p(ips_fragmented, "\t%llu output datagram%s fragmented\n");
438 p(ips_ofragments, "\t%llu fragment%s created\n");
439 p(ips_cantfrag, "\t%llu datagram%s that can't be fragmented\n");
440 p(ips_badaddr, "\t%llu datagram%s with bad address in header\n");
441 #undef ps
442 #undef p
443 }
444
445 static char *icmpnames[] = {
446 "echo reply",
447 "#1",
448 "#2",
449 "destination unreachable",
450 "source quench",
451 "routing redirect",
452 "alternate host address",
453 "#7",
454 "echo",
455 "router advertisement",
456 "router solicitation",
457 "time exceeded",
458 "parameter problem",
459 "time stamp",
460 "time stamp reply",
461 "information request",
462 "information request reply",
463 "address mask request",
464 "address mask reply",
465 };
466
467 /*
468 * Dump ICMP statistics.
469 */
470 void
471 icmp_stats(off, name)
472 u_long off;
473 char *name;
474 {
475 struct icmpstat icmpstat;
476 int i, first;
477
478 if (use_sysctl) {
479 size_t size = sizeof(icmpstat);
480
481 if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &size,
482 NULL, 0) == -1)
483 err(1, "net.inet.icmp.stats");
484 } else {
485 if (off == 0)
486 return;
487 kread(off, (char *)&icmpstat, sizeof (icmpstat));
488 }
489
490 printf("%s:\n", name);
491
492 #define p(f, m) if (icmpstat.f || sflag <= 1) \
493 printf(m, (unsigned long long)icmpstat.f, plural(icmpstat.f))
494
495 p(icps_error, "\t%llu call%s to icmp_error\n");
496 p(icps_oldicmp,
497 "\t%llu error%s not generated because old message was icmp\n");
498 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
499 if (icmpstat.icps_outhist[i] != 0) {
500 if (first) {
501 printf("\tOutput histogram:\n");
502 first = 0;
503 }
504 printf("\t\t%s: %llu\n", icmpnames[i],
505 (unsigned long long)icmpstat.icps_outhist[i]);
506 }
507 p(icps_badcode, "\t%llu message%s with bad code fields\n");
508 p(icps_tooshort, "\t%llu message%s < minimum length\n");
509 p(icps_checksum, "\t%llu bad checksum%s\n");
510 p(icps_badlen, "\t%llu message%s with bad length\n");
511 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
512 if (icmpstat.icps_inhist[i] != 0) {
513 if (first) {
514 printf("\tInput histogram:\n");
515 first = 0;
516 }
517 printf("\t\t%s: %llu\n", icmpnames[i],
518 (unsigned long long)icmpstat.icps_inhist[i]);
519 }
520 p(icps_reflect, "\t%llu message response%s generated\n");
521 p(icps_pmtuchg, "\t%llu path MTU change%s\n");
522 #undef p
523 }
524
525 /*
526 * Dump IGMP statistics structure.
527 */
528 void
529 igmp_stats(off, name)
530 u_long off;
531 char *name;
532 {
533 struct igmpstat igmpstat;
534
535 if (off == 0)
536 return;
537 kread(off, (char *)&igmpstat, sizeof (igmpstat));
538 printf("%s:\n", name);
539
540 #define p(f, m) if (igmpstat.f || sflag <= 1) \
541 printf(m, (unsigned long long)igmpstat.f, plural(igmpstat.f))
542 #define py(f, m) if (igmpstat.f || sflag <= 1) \
543 printf(m, (unsigned long long)igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
544 p(igps_rcv_total, "\t%llu message%s received\n");
545 p(igps_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
546 p(igps_rcv_badsum, "\t%llu message%s received with bad checksum\n");
547 py(igps_rcv_queries, "\t%llu membership quer%s received\n");
548 py(igps_rcv_badqueries, "\t%llu membership quer%s received with invalid field(s)\n");
549 p(igps_rcv_reports, "\t%llu membership report%s received\n");
550 p(igps_rcv_badreports, "\t%llu membership report%s received with invalid field(s)\n");
551 p(igps_rcv_ourreports, "\t%llu membership report%s received for groups to which we belong\n");
552 p(igps_snd_reports, "\t%llu membership report%s sent\n");
553 #undef p
554 #undef py
555 }
556
557 /*
558 * Dump PIM statistics structure.
559 */
560 void
561 pim_stats(off, name)
562 u_long off;
563 char *name;
564 {
565 struct pimstat pimstat;
566
567 if (off == 0)
568 return;
569 if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) {
570 /* XXX: PIM is probably not enabled in the kernel */
571 return;
572 }
573
574 printf("%s:\n", name);
575
576 #define p(f, m) if (pimstat.f || sflag <= 1) \
577 printf(m, (unsigned long long)pimstat.f, plural(pimstat.f))
578
579 p(pims_rcv_total_msgs, "\t%llu message%s received\n");
580 p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
581 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
582 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
583 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
584 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
585 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
586 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
587 p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
588 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
589 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
590 #undef p
591 }
592
593 /*
594 * Dump the ARP statistics structure.
595 */
596 void
597 arp_stats(off, name)
598 u_long off;
599 char *name;
600 {
601 struct arpstat arpstat;
602
603 if (off == 0)
604 return;
605 kread(off, (char *)&arpstat, sizeof (arpstat));
606 printf("%s:\n", name);
607
608 #define ps(f, m) if (arpstat.f || sflag <= 1) \
609 printf(m, (unsigned long long)arpstat.f)
610 #define p(f, m) if (arpstat.f || sflag <= 1) \
611 printf(m, (unsigned long long)arpstat.f, plural(arpstat.f))
612
613 p(as_sndtotal, "\t%llu packet%s sent\n");
614 p(as_sndreply, "\t\t%llu reply packet%s\n");
615 p(as_sndrequest, "\t\t%llu request packet%s\n");
616
617 p(as_rcvtotal, "\t%llu packet%s received\n");
618 p(as_rcvreply, "\t\t%llu reply packet%s\n");
619 p(as_rcvrequest, "\t\t%llu valid request packet%s\n");
620 p(as_rcvmcast, "\t\t%llu broadcast/multicast packet%s\n");
621 p(as_rcvbadproto, "\t\t%llu packet%s with unknown protocol type\n");
622 p(as_rcvbadlen, "\t\t%llu packet%s with bad (short) length\n");
623 p(as_rcvzerotpa, "\t\t%llu packet%s with null target IP address\n");
624 p(as_rcvzerospa, "\t\t%llu packet%s with null source IP address\n");
625 ps(as_rcvnoint, "\t\t%llu could not be mapped to an interface\n");
626 p(as_rcvlocalsha, "\t\t%llu packet%s sourced from a local hardware "
627 "address\n");
628 p(as_rcvbcastsha, "\t\t%llu packet%s with a broadcast "
629 "source hardware address\n");
630 p(as_rcvlocalspa, "\t\t%llu duplicate%s for a local IP address\n");
631 p(as_rcvoverperm, "\t\t%llu attempt%s to overwrite a static entry\n");
632 p(as_rcvoverint, "\t\t%llu packet%s received on wrong interface\n");
633 p(as_rcvover, "\t\t%llu entry%s overwritten\n");
634 p(as_rcvlenchg, "\t\t%llu change%s in hardware address length\n");
635
636 p(as_dfrtotal, "\t%llu packet%s deferred pending ARP resolution\n");
637 ps(as_dfrsent, "\t\t%llu sent\n");
638 ps(as_dfrdropped, "\t\t%llu dropped\n");
639
640 p(as_allocfail, "\t%llu failure%s to allocate llinfo\n");
641
642 #undef ps
643 #undef p
644 }
645
646 /*
647 * Pretty print an Internet address (net address + port).
648 * Take numeric_addr and numeric_port into consideration.
649 */
650 void
651 inetprint(in, port, proto, numeric_port)
652 struct in_addr *in;
653 u_int16_t port;
654 const char *proto;
655 int numeric_port;
656 {
657 struct servent *sp = 0;
658 char line[80], *cp;
659 size_t space;
660
661 (void)snprintf(line, sizeof line, "%.*s.",
662 (Aflag && !numeric_addr) ? 12 : 16, inetname(in));
663 cp = strchr(line, '\0');
664 if (!numeric_port && port)
665 sp = getservbyport((int)port, proto);
666 space = sizeof line - (cp-line);
667 if (sp || port == 0)
668 (void)snprintf(cp, space, "%s", sp ? sp->s_name : "*");
669 else
670 (void)snprintf(cp, space, "%u", ntohs(port));
671 (void)printf(" %-*.*s", width, width, line);
672 }
673
674 /*
675 * Construct an Internet address representation.
676 * If numeric_addr has been supplied, give
677 * numeric value, otherwise try for symbolic name.
678 */
679 char *
680 inetname(inp)
681 struct in_addr *inp;
682 {
683 char *cp;
684 static char line[50];
685 struct hostent *hp;
686 struct netent *np;
687 static char domain[MAXHOSTNAMELEN + 1];
688 static int first = 1;
689
690 if (first && !numeric_addr) {
691 first = 0;
692 if (gethostname(domain, sizeof domain) == 0) {
693 domain[sizeof(domain) - 1] = '\0';
694 if ((cp = strchr(domain, '.')))
695 (void) strlcpy(domain, cp + 1, sizeof(domain));
696 else
697 domain[0] = 0;
698 } else
699 domain[0] = 0;
700 }
701 cp = 0;
702 if (!numeric_addr && inp->s_addr != INADDR_ANY) {
703 int net = inet_netof(*inp);
704 int lna = inet_lnaof(*inp);
705
706 if (lna == INADDR_ANY) {
707 np = getnetbyaddr(net, AF_INET);
708 if (np)
709 cp = np->n_name;
710 }
711 if (cp == 0) {
712 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
713 if (hp) {
714 if ((cp = strchr(hp->h_name, '.')) &&
715 !strcmp(cp + 1, domain))
716 *cp = 0;
717 cp = hp->h_name;
718 }
719 }
720 }
721 if (inp->s_addr == INADDR_ANY)
722 strlcpy(line, "*", sizeof line);
723 else if (cp)
724 strlcpy(line, cp, sizeof line);
725 else {
726 inp->s_addr = ntohl(inp->s_addr);
727 #define C(x) ((x) & 0xff)
728 (void)snprintf(line, sizeof line, "%u.%u.%u.%u",
729 C(inp->s_addr >> 24), C(inp->s_addr >> 16),
730 C(inp->s_addr >> 8), C(inp->s_addr));
731 #undef C
732 }
733 return (line);
734 }
735
736 /*
737 * Dump the contents of a TCP PCB.
738 */
739 void
740 tcp_dump(pcbaddr)
741 u_long pcbaddr;
742 {
743 struct tcpcb tcpcb;
744 int i, hardticks;
745
746 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
747 hardticks = get_hardticks();
748
749 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
750
751 printf("Timers:\n");
752 for (i = 0; i < TCPT_NTIMERS; i++) {
753 printf("\t%s: %d", tcptimers[i],
754 (tcpcb.t_timer[i].c_flags & CALLOUT_PENDING) ?
755 tcpcb.t_timer[i].c_time - hardticks : 0);
756 }
757 printf("\n\n");
758
759 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
760 printf("State: %d", tcpcb.t_state);
761 else
762 printf("State: %s", tcpstates[tcpcb.t_state]);
763 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags,
764 (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb);
765
766 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
767 tcpcb.t_rxtcur, tcpcb.t_dupacks);
768 printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss,
769 tcpcb.t_ourmss, tcpcb.t_segsz);
770
771 printf("snd_una %u, snd_nxt %u, snd_up %u\n",
772 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
773 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
774 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
775
776 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
777 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
778
779 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
780 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
781
782 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
783 "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime,
784 tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin,
785 tcpcb.max_sndwnd);
786
787 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
788 tcpcb.t_iobc, tcpcb.t_softerror);
789
790 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
791 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
792 tcpcb.requested_s_scale);
793 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
794 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
795 }
796