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