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