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