inet.c revision 1.88.8.1 1 /* $NetBSD: inet.c,v 1.88.8.1 2009/05/13 19:19:59 jym 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.88.8.1 2009/05/13 19:19:59 jym Exp $");
38 #endif
39 #endif /* not lint */
40
41 #define _CALLOUT_PRIVATE /* for defs in sys/callout.h */
42
43 #include <sys/param.h>
44 #include <sys/queue.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/mbuf.h>
48 #include <sys/protosw.h>
49 #include <sys/sysctl.h>
50
51 #include <net/if_arp.h>
52 #include <net/route.h>
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/ip.h>
56 #include <netinet/in_pcb.h>
57 #include <netinet/ip_icmp.h>
58
59 #ifdef INET6
60 #include <netinet/ip6.h>
61 #endif
62
63 #include <netinet/icmp_var.h>
64 #include <netinet/igmp_var.h>
65 #include <netinet/ip_var.h>
66 #include <netinet/pim_var.h>
67 #include <netinet/tcp.h>
68 #include <netinet/tcpip.h>
69 #include <netinet/tcp_seq.h>
70 #define TCPSTATES
71 #include <netinet/tcp_fsm.h>
72 #define TCPTIMERS
73 #include <netinet/tcp_timer.h>
74 #include <netinet/tcp_var.h>
75 #include <netinet/tcp_debug.h>
76 #include <netinet/udp.h>
77 #include <netinet/ip_carp.h>
78 #include <netinet/udp_var.h>
79
80 #include <arpa/inet.h>
81 #include <kvm.h>
82 #include <netdb.h>
83 #include <stdio.h>
84 #include <string.h>
85 #include <unistd.h>
86 #include <stdlib.h>
87 #include <err.h>
88 #include "netstat.h"
89
90 char *inetname(struct in_addr *);
91 void inetprint(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 static int compact;
101
102 static void
103 protoprhdr(void)
104 {
105 printf("Active Internet connections");
106 if (aflag)
107 printf(" (including servers)");
108 putchar('\n');
109 if (Aflag)
110 printf("%-8.8s ", "PCB");
111 printf("%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n",
112 "Proto", "Recv-Q", "Send-Q", compact ? "" : " ",
113 width, width, "Local Address",
114 width, width, "Foreign Address",
115 "State");
116 }
117
118 static void
119 protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc,
120 struct in_addr *laddr, u_int16_t lport,
121 struct in_addr *faddr, u_int16_t fport,
122 short t_state, const char *name, int inp_flags)
123 {
124 static const char *shorttcpstates[] = {
125 "CLOSED", "LISTEN", "SYNSEN", "SYSRCV",
126 "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG",
127 "LASTAK", "FWAIT2", "TMWAIT",
128 };
129 int istcp;
130
131 istcp = strcmp(name, "tcp") == 0;
132
133 if (Aflag) {
134 printf("%8" PRIxPTR " ", ppcb);
135 }
136 printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc,
137 compact ? "" : " ");
138 if (numeric_port) {
139 inetprint(laddr, lport, name, 1);
140 inetprint(faddr, fport, name, 1);
141 } else if (inp_flags & INP_ANONPORT) {
142 inetprint(laddr, lport, name, 1);
143 inetprint(faddr, fport, name, 0);
144 } else {
145 inetprint(laddr, lport, name, 0);
146 inetprint(faddr, fport, name, 0);
147 }
148 if (istcp) {
149 if (t_state < 0 || t_state >= TCP_NSTATES)
150 printf(" %d", t_state);
151 else
152 printf(" %s", compact ? shorttcpstates[t_state] :
153 tcpstates[t_state]);
154 }
155 putchar('\n');
156 }
157
158 void
159 protopr(u_long off, const char *name)
160 {
161 struct inpcbtable table;
162 struct inpcb *head, *next, *prev;
163 struct inpcb inpcb;
164 struct tcpcb tcpcb;
165 struct socket sockb;
166 int istcp;
167 static int first = 1;
168
169 compact = 0;
170 if (Aflag) {
171 if (!numeric_addr)
172 width = 18;
173 else {
174 width = 21;
175 compact = 1;
176 }
177 } else
178 width = 22;
179
180 if (use_sysctl) {
181 struct kinfo_pcb *pcblist;
182 int mib[8];
183 size_t namelen = 0, size = 0, i;
184 char *mibname = NULL;
185
186 memset(mib, 0, sizeof(mib));
187
188 if (asprintf(&mibname, "net.inet.%s.pcblist", name) == -1)
189 err(1, "asprintf");
190
191 /* get dynamic pcblist node */
192 if (sysctlnametomib(mibname, mib, &namelen) == -1)
193 err(1, "sysctlnametomib: %s", mibname);
194
195 if (sysctl(mib, sizeof(mib) / sizeof(*mib), NULL, &size,
196 NULL, 0) == -1)
197 err(1, "sysctl (query)");
198
199 if ((pcblist = malloc(size)) == NULL)
200 err(1, "malloc");
201 memset(pcblist, 0, size);
202
203 mib[6] = sizeof(*pcblist);
204 mib[7] = size / sizeof(*pcblist);
205
206 if (sysctl(mib, sizeof(mib) / sizeof(*mib), pcblist,
207 &size, NULL, 0) == -1)
208 err(1, "sysctl (copy)");
209
210 for (i = 0; i < size / sizeof(*pcblist); i++) {
211 struct sockaddr_in src, dst;
212
213 memcpy(&src, &pcblist[i].ki_s, sizeof(src));
214 memcpy(&dst, &pcblist[i].ki_d, sizeof(dst));
215
216 if (!aflag &&
217 inet_lnaof(dst.sin_addr) == INADDR_ANY)
218 continue;
219
220 if (first) {
221 protoprhdr();
222 first = 0;
223 }
224
225 protopr0((intptr_t) pcblist[i].ki_ppcbaddr,
226 pcblist[i].ki_rcvq, pcblist[i].ki_sndq,
227 &src.sin_addr, src.sin_port,
228 &dst.sin_addr, dst.sin_port,
229 pcblist[i].ki_tstate, name,
230 pcblist[i].ki_pflags);
231 }
232
233 free(pcblist);
234 return;
235 }
236
237 if (off == 0)
238 return;
239 istcp = strcmp(name, "tcp") == 0;
240 kread(off, (char *)&table, sizeof table);
241 prev = head =
242 (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
243 next = (struct inpcb *)table.inpt_queue.cqh_first;
244
245 while (next != head) {
246 kread((u_long)next, (char *)&inpcb, sizeof inpcb);
247 if ((struct inpcb *)inpcb.inp_queue.cqe_prev != prev) {
248 printf("???\n");
249 break;
250 }
251 prev = next;
252 next = (struct inpcb *)inpcb.inp_queue.cqe_next;
253
254 if (inpcb.inp_af != AF_INET)
255 continue;
256
257 if (!aflag &&
258 inet_lnaof(inpcb.inp_faddr) == INADDR_ANY)
259 continue;
260 kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
261 if (istcp) {
262 kread((u_long)inpcb.inp_ppcb,
263 (char *)&tcpcb, sizeof (tcpcb));
264 }
265
266 if (first) {
267 protoprhdr();
268 first = 0;
269 }
270
271 protopr0(istcp ? (intptr_t) inpcb.inp_ppcb : (intptr_t) prev,
272 sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc,
273 &inpcb.inp_laddr, inpcb.inp_lport,
274 &inpcb.inp_faddr, inpcb.inp_fport,
275 tcpcb.t_state, name, inpcb.inp_flags);
276 }
277 }
278
279 /*
280 * Dump TCP statistics structure.
281 */
282 void
283 tcp_stats(u_long off, const char *name)
284 {
285 uint64_t tcpstat[TCP_NSTATS];
286
287 if (use_sysctl) {
288 size_t size = sizeof(tcpstat);
289
290 if (sysctlbyname("net.inet.tcp.stats", tcpstat, &size,
291 NULL, 0) == -1)
292 return;
293 } else {
294 warnx("%s stats not available via KVM.", name);
295 return;
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(TCP_STAT_SNDTOTAL, "\t%llu packet%s sent\n");
314 p2(TCP_STAT_SNDPACK,TCP_STAT_SNDBYTE,
315 "\t\t%llu data packet%s (%llu byte%s)\n");
316 p2(TCP_STAT_SNDREXMITPACK, TCP_STAT_SNDREXMITBYTE,
317 "\t\t%llu data packet%s (%llu byte%s) retransmitted\n");
318 p2s(TCP_STAT_SNDACKS, TCP_STAT_DELACK,
319 "\t\t%llu ack-only packet%s (%llu delayed)\n");
320 p(TCP_STAT_SNDURG, "\t\t%llu URG only packet%s\n");
321 p(TCP_STAT_SNDPROBE, "\t\t%llu window probe packet%s\n");
322 p(TCP_STAT_SNDWINUP, "\t\t%llu window update packet%s\n");
323 p(TCP_STAT_SNDCTRL, "\t\t%llu control packet%s\n");
324 p(TCP_STAT_SELFQUENCH,
325 "\t\t%llu send attempt%s resulted in self-quench\n");
326 p(TCP_STAT_RCVTOTAL, "\t%llu packet%s received\n");
327 p2(TCP_STAT_RCVACKPACK, TCP_STAT_RCVACKBYTE,
328 "\t\t%llu ack%s (for %llu byte%s)\n");
329 p(TCP_STAT_RCVDUPACK, "\t\t%llu duplicate ack%s\n");
330 p(TCP_STAT_RCVACKTOOMUCH, "\t\t%llu ack%s for unsent data\n");
331 p2(TCP_STAT_RCVPACK, TCP_STAT_RCVBYTE,
332 "\t\t%llu packet%s (%llu byte%s) received in-sequence\n");
333 p2(TCP_STAT_RCVDUPPACK, TCP_STAT_RCVDUPBYTE,
334 "\t\t%llu completely duplicate packet%s (%llu byte%s)\n");
335 p(TCP_STAT_PAWSDROP, "\t\t%llu old duplicate packet%s\n");
336 p2(TCP_STAT_RCVPARTDUPPACK, TCP_STAT_RCVPARTDUPBYTE,
337 "\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n");
338 p2(TCP_STAT_RCVOOPACK, TCP_STAT_RCVOOBYTE,
339 "\t\t%llu out-of-order packet%s (%llu byte%s)\n");
340 p2(TCP_STAT_RCVPACKAFTERWIN, TCP_STAT_RCVBYTEAFTERWIN,
341 "\t\t%llu packet%s (%llu byte%s) of data after window\n");
342 p(TCP_STAT_RCVWINPROBE, "\t\t%llu window probe%s\n");
343 p(TCP_STAT_RCVWINUPD, "\t\t%llu window update packet%s\n");
344 p(TCP_STAT_RCVAFTERCLOSE, "\t\t%llu packet%s received after close\n");
345 p(TCP_STAT_RCVBADSUM, "\t\t%llu discarded for bad checksum%s\n");
346 p(TCP_STAT_RCVBADOFF, "\t\t%llu discarded for bad header offset field%s\n");
347 ps(TCP_STAT_RCVSHORT, "\t\t%llu discarded because packet too short\n");
348 p(TCP_STAT_CONNATTEMPT, "\t%llu connection request%s\n");
349 p(TCP_STAT_ACCEPTS, "\t%llu connection accept%s\n");
350 p(TCP_STAT_CONNECTS,
351 "\t%llu connection%s established (including accepts)\n");
352 p2(TCP_STAT_CLOSED, TCP_STAT_DROPS,
353 "\t%llu connection%s closed (including %llu drop%s)\n");
354 p(TCP_STAT_CONNDROPS, "\t%llu embryonic connection%s dropped\n");
355 p(TCP_STAT_DELAYED_FREE, "\t%llu delayed free%s of tcpcb\n");
356 p2(TCP_STAT_RTTUPDATED, TCP_STAT_SEGSTIMED,
357 "\t%llu segment%s updated rtt (of %llu attempt%s)\n");
358 p(TCP_STAT_REXMTTIMEO, "\t%llu retransmit timeout%s\n");
359 p(TCP_STAT_TIMEOUTDROP,
360 "\t\t%llu connection%s dropped by rexmit timeout\n");
361 p2(TCP_STAT_PERSISTTIMEO, TCP_STAT_PERSISTDROPS,
362 "\t%llu persist timeout%s (resulting in %llu dropped "
363 "connection%s)\n");
364 p(TCP_STAT_KEEPTIMEO, "\t%llu keepalive timeout%s\n");
365 p(TCP_STAT_KEEPPROBE, "\t\t%llu keepalive probe%s sent\n");
366 p(TCP_STAT_KEEPDROPS, "\t\t%llu connection%s dropped by keepalive\n");
367 p(TCP_STAT_PREDACK, "\t%llu correct ACK header prediction%s\n");
368 p(TCP_STAT_PREDDAT, "\t%llu correct data packet header prediction%s\n");
369 p3(TCP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n");
370 ps(TCP_STAT_NOPORT, "\t%llu dropped due to no socket\n");
371 p(TCP_STAT_CONNSDRAINED, "\t%llu connection%s drained due to memory "
372 "shortage\n");
373 p(TCP_STAT_PMTUBLACKHOLE, "\t%llu PMTUD blackhole%s detected\n");
374
375 p(TCP_STAT_BADSYN, "\t%llu bad connection attempt%s\n");
376 ps(TCP_STAT_SC_ADDED, "\t%llu SYN cache entries added\n");
377 p(TCP_STAT_SC_COLLISIONS, "\t\t%llu hash collision%s\n");
378 ps(TCP_STAT_SC_COMPLETED, "\t\t%llu completed\n");
379 ps(TCP_STAT_SC_ABORTED, "\t\t%llu aborted (no space to build PCB)\n");
380 ps(TCP_STAT_SC_TIMED_OUT, "\t\t%llu timed out\n");
381 ps(TCP_STAT_SC_OVERFLOWED, "\t\t%llu dropped due to overflow\n");
382 ps(TCP_STAT_SC_BUCKETOVERFLOW, "\t\t%llu dropped due to bucket overflow\n");
383 ps(TCP_STAT_SC_RESET, "\t\t%llu dropped due to RST\n");
384 ps(TCP_STAT_SC_UNREACH, "\t\t%llu dropped due to ICMP unreachable\n");
385 ps(TCP_STAT_SC_DELAYED_FREE, "\t\t%llu delayed free of SYN cache "
386 "entries\n");
387 p(TCP_STAT_SC_RETRANSMITTED, "\t%llu SYN,ACK%s retransmitted\n");
388 p(TCP_STAT_SC_DUPESYN, "\t%llu duplicate SYN%s received for entries "
389 "already in the cache\n");
390 p(TCP_STAT_SC_DROPPED, "\t%llu SYN%s dropped (no route or no space)\n");
391 p(TCP_STAT_BADSIG, "\t%llu packet%s with bad signature\n");
392 p(TCP_STAT_GOODSIG, "\t%llu packet%s with good signature\n");
393
394 p(TCP_STAT_ECN_SHS, "\t%llu sucessful ECN handshake%s\n");
395 p(TCP_STAT_ECN_CE, "\t%llu packet%s with ECN CE bit\n");
396 p(TCP_STAT_ECN_ECT, "\t%llu packet%s ECN ECT(0) bit\n");
397 #undef p
398 #undef ps
399 #undef p2
400 #undef p2s
401 #undef p3
402 }
403
404 /*
405 * Dump UDP statistics structure.
406 */
407 void
408 udp_stats(u_long off, const char *name)
409 {
410 uint64_t udpstat[UDP_NSTATS];
411 u_quad_t delivered;
412
413 if (use_sysctl) {
414 size_t size = sizeof(udpstat);
415
416 if (sysctlbyname("net.inet.udp.stats", udpstat, &size,
417 NULL, 0) == -1)
418 return;
419 } else {
420 warnx("%s stats not available via KVM.", name);
421 return;
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(UDP_STAT_IPACKETS, "\t%llu datagram%s received\n");
434 ps(UDP_STAT_HDROPS, "\t%llu with incomplete header\n");
435 ps(UDP_STAT_BADLEN, "\t%llu with bad data length field\n");
436 ps(UDP_STAT_BADSUM, "\t%llu with bad checksum\n");
437 ps(UDP_STAT_NOPORT, "\t%llu dropped due to no socket\n");
438 p(UDP_STAT_NOPORTBCAST,
439 "\t%llu broadcast/multicast datagram%s dropped due to no socket\n");
440 ps(UDP_STAT_FULLSOCK, "\t%llu dropped due to full socket buffers\n");
441 delivered = udpstat[UDP_STAT_IPACKETS] -
442 udpstat[UDP_STAT_HDROPS] -
443 udpstat[UDP_STAT_BADLEN] -
444 udpstat[UDP_STAT_BADSUM] -
445 udpstat[UDP_STAT_NOPORT] -
446 udpstat[UDP_STAT_NOPORTBCAST] -
447 udpstat[UDP_STAT_FULLSOCK];
448 if (delivered || sflag <= 1)
449 printf("\t%llu delivered\n", (unsigned long long)delivered);
450 p3(UDP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n");
451 p(UDP_STAT_OPACKETS, "\t%llu datagram%s output\n");
452
453 #undef ps
454 #undef p
455 #undef p3
456 }
457
458 /*
459 * Dump IP statistics structure.
460 */
461 void
462 ip_stats(u_long off, const char *name)
463 {
464 uint64_t ipstat[IP_NSTATS];
465
466 if (use_sysctl) {
467 size_t size = sizeof(ipstat);
468
469 if (sysctlbyname("net.inet.ip.stats", ipstat, &size,
470 NULL, 0) == -1)
471 return;
472 } else {
473 warnx("%s stats not available via KVM.", name);
474 return;
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(IP_STAT_TOTAL, "\t%llu total packet%s received\n");
485 p(IP_STAT_BADSUM, "\t%llu bad header checksum%s\n");
486 ps(IP_STAT_TOOSMALL, "\t%llu with size smaller than minimum\n");
487 ps(IP_STAT_TOOSHORT, "\t%llu with data size < data length\n");
488 ps(IP_STAT_TOOLONG, "\t%llu with length > max ip packet size\n");
489 ps(IP_STAT_BADHLEN, "\t%llu with header length < data size\n");
490 ps(IP_STAT_BADLEN, "\t%llu with data length < header length\n");
491 ps(IP_STAT_BADOPTIONS, "\t%llu with bad options\n");
492 ps(IP_STAT_BADVERS, "\t%llu with incorrect version number\n");
493 p(IP_STAT_FRAGMENTS, "\t%llu fragment%s received\n");
494 p(IP_STAT_FRAGDROPPED, "\t%llu fragment%s dropped (dup or out of space)\n");
495 p(IP_STAT_RCVMEMDROP, "\t%llu fragment%s dropped (out of ipqent)\n");
496 p(IP_STAT_BADFRAGS, "\t%llu malformed fragment%s dropped\n");
497 p(IP_STAT_FRAGTIMEOUT, "\t%llu fragment%s dropped after timeout\n");
498 p(IP_STAT_REASSEMBLED, "\t%llu packet%s reassembled ok\n");
499 p(IP_STAT_DELIVERED, "\t%llu packet%s for this host\n");
500 p(IP_STAT_NOPROTO, "\t%llu packet%s for unknown/unsupported protocol\n");
501 p(IP_STAT_FORWARD, "\t%llu packet%s forwarded");
502 p(IP_STAT_FASTFORWARD, " (%llu packet%s fast forwarded)");
503 if (ipstat[IP_STAT_FORWARD] || sflag <= 1)
504 putchar('\n');
505 p(IP_STAT_CANTFORWARD, "\t%llu packet%s not forwardable\n");
506 p(IP_STAT_REDIRECTSENT, "\t%llu redirect%s sent\n");
507 p(IP_STAT_NOGIF, "\t%llu packet%s no matching gif found\n");
508 p(IP_STAT_LOCALOUT, "\t%llu packet%s sent from this host\n");
509 p(IP_STAT_RAWOUT, "\t%llu packet%s sent with fabricated ip header\n");
510 p(IP_STAT_ODROPPED, "\t%llu output packet%s dropped due to no bufs, etc.\n");
511 p(IP_STAT_NOROUTE, "\t%llu output packet%s discarded due to no route\n");
512 p(IP_STAT_FRAGMENTED, "\t%llu output datagram%s fragmented\n");
513 p(IP_STAT_OFRAGMENTS, "\t%llu fragment%s created\n");
514 p(IP_STAT_CANTFRAG, "\t%llu datagram%s that can't be fragmented\n");
515 p(IP_STAT_BADADDR, "\t%llu datagram%s with bad address in header\n");
516 #undef ps
517 #undef p
518 }
519
520 static const 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(u_long off, const char *name)
547 {
548 uint64_t icmpstat[ICMP_NSTATS];
549 int i, first;
550
551 if (use_sysctl) {
552 size_t size = sizeof(icmpstat);
553
554 if (sysctlbyname("net.inet.icmp.stats", icmpstat, &size,
555 NULL, 0) == -1)
556 return;
557 } else {
558 warnx("%s stats not available via KVM.", name);
559 return;
560 }
561
562 printf("%s:\n", name);
563
564 #define p(f, m) if (icmpstat[f] || sflag <= 1) \
565 printf(m, (unsigned long long)icmpstat[f], plural(icmpstat[f]))
566
567 p(ICMP_STAT_ERROR, "\t%llu call%s to icmp_error\n");
568 p(ICMP_STAT_OLDICMP,
569 "\t%llu error%s not generated because old message was icmp\n");
570 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
571 if (icmpstat[ICMP_STAT_OUTHIST + i] != 0) {
572 if (first) {
573 printf("\tOutput histogram:\n");
574 first = 0;
575 }
576 printf("\t\t%s: %llu\n", icmpnames[i],
577 (unsigned long long)icmpstat[ICMP_STAT_OUTHIST + i]);
578 }
579 p(ICMP_STAT_BADCODE, "\t%llu message%s with bad code fields\n");
580 p(ICMP_STAT_TOOSHORT, "\t%llu message%s < minimum length\n");
581 p(ICMP_STAT_CHECKSUM, "\t%llu bad checksum%s\n");
582 p(ICMP_STAT_BADLEN, "\t%llu message%s with bad length\n");
583 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
584 if (icmpstat[ICMP_STAT_INHIST + i] != 0) {
585 if (first) {
586 printf("\tInput histogram:\n");
587 first = 0;
588 }
589 printf("\t\t%s: %llu\n", icmpnames[i],
590 (unsigned long long)icmpstat[ICMP_STAT_INHIST + i]);
591 }
592 p(ICMP_STAT_REFLECT, "\t%llu message response%s generated\n");
593 p(ICMP_STAT_PMTUCHG, "\t%llu path MTU change%s\n");
594 #undef p
595 }
596
597 /*
598 * Dump IGMP statistics structure.
599 */
600 void
601 igmp_stats(u_long off, const char *name)
602 {
603 uint64_t igmpstat[IGMP_NSTATS];
604
605 if (use_sysctl) {
606 size_t size = sizeof(igmpstat);
607
608 if (sysctlbyname("net.inet.igmp.stats", igmpstat, &size,
609 NULL, 0) == -1)
610 return;
611 } else {
612 warnx("%s stats not available via KVM.", name);
613 return;
614 }
615
616 printf("%s:\n", name);
617
618 #define p(f, m) if (igmpstat[f] || sflag <= 1) \
619 printf(m, (unsigned long long)igmpstat[f], plural(igmpstat[f]))
620 #define py(f, m) if (igmpstat[f] || sflag <= 1) \
621 printf(m, (unsigned long long)igmpstat[f], igmpstat[f] != 1 ? "ies" : "y")
622 p(IGMP_STAT_RCV_TOTAL, "\t%llu message%s received\n");
623 p(IGMP_STAT_RCV_TOOSHORT, "\t%llu message%s received with too few bytes\n");
624 p(IGMP_STAT_RCV_BADSUM, "\t%llu message%s received with bad checksum\n");
625 py(IGMP_STAT_RCV_QUERIES, "\t%llu membership quer%s received\n");
626 py(IGMP_STAT_RCV_BADQUERIES, "\t%llu membership quer%s received with invalid field(s)\n");
627 p(IGMP_STAT_RCV_REPORTS, "\t%llu membership report%s received\n");
628 p(IGMP_STAT_RCV_BADREPORTS, "\t%llu membership report%s received with invalid field(s)\n");
629 p(IGMP_STAT_RCV_OURREPORTS, "\t%llu membership report%s received for groups to which we belong\n");
630 p(IGMP_STAT_SND_REPORTS, "\t%llu membership report%s sent\n");
631 #undef p
632 #undef py
633 }
634
635 /*
636 * Dump CARP statistics structure.
637 */
638 void
639 carp_stats(u_long off, const char *name)
640 {
641 uint64_t carpstat[CARP_NSTATS];
642
643 if (use_sysctl) {
644 size_t size = sizeof(carpstat);
645
646 if (sysctlbyname("net.inet.carp.stats", carpstat, &size,
647 NULL, 0) == -1)
648 return;
649 } else {
650 warnx("%s stats not available via KVM.", name);
651 return;
652 }
653
654 printf("%s:\n", name);
655
656 #define p(f, m) if (carpstat[f] || sflag <= 1) \
657 printf(m, carpstat[f], plural(carpstat[f]))
658 #define p2(f, m) if (carpstat[f] || sflag <= 1) \
659 printf(m, carpstat[f])
660
661 p(CARP_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n");
662 p(CARP_STAT_IPACKETS6, "\t%" PRIu64 " packet%s received (IPv6)\n");
663 p(CARP_STAT_BADIF,
664 "\t\t%" PRIu64 " packet%s discarded for bad interface\n");
665 p(CARP_STAT_BADTTL,
666 "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n");
667 p(CARP_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n");
668 p(CARP_STAT_BADSUM, "\t\t%" PRIu64
669 " packet%s discarded for bad checksum\n");
670 p(CARP_STAT_BADVER,
671 "\t\t%" PRIu64 " packet%s discarded with a bad version\n");
672 p2(CARP_STAT_BADLEN,
673 "\t\t%" PRIu64 " discarded because packet was too short\n");
674 p(CARP_STAT_BADAUTH,
675 "\t\t%" PRIu64 " packet%s discarded for bad authentication\n");
676 p(CARP_STAT_BADVHID, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n");
677 p(CARP_STAT_BADADDRS, "\t\t%" PRIu64
678 " packet%s discarded because of a bad address list\n");
679 p(CARP_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n");
680 p(CARP_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n");
681 p2(CARP_STAT_ONOMEM,
682 "\t\t%" PRIu64 " send failed due to mbuf memory error\n");
683 #undef p
684 #undef p2
685 }
686
687 /*
688 * Dump PIM statistics structure.
689 */
690 void
691 pim_stats(u_long off, const char *name)
692 {
693 struct pimstat pimstat;
694
695 if (off == 0)
696 return;
697 if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) {
698 /* XXX: PIM is probably not enabled in the kernel */
699 return;
700 }
701
702 printf("%s:\n", name);
703
704 #define p(f, m) if (pimstat.f || sflag <= 1) \
705 printf(m, (unsigned long long)pimstat.f, plural(pimstat.f))
706
707 p(pims_rcv_total_msgs, "\t%llu message%s received\n");
708 p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
709 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
710 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
711 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
712 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
713 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
714 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
715 p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
716 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
717 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
718 #undef p
719 }
720
721 /*
722 * Dump the ARP statistics structure.
723 */
724 void
725 arp_stats(u_long off, const char *name)
726 {
727 uint64_t arpstat[ARP_NSTATS];
728
729 if (use_sysctl) {
730 size_t size = sizeof(arpstat);
731
732 if (sysctlbyname("net.inet.arp.stats", arpstat, &size,
733 NULL, 0) == -1)
734 return;
735 } else {
736 warnx("%s stats not available via KVM.", name);
737 return;
738 }
739
740 printf("%s:\n", name);
741
742 #define ps(f, m) if (arpstat[f] || sflag <= 1) \
743 printf(m, (unsigned long long)arpstat[f])
744 #define p(f, m) if (arpstat[f] || sflag <= 1) \
745 printf(m, (unsigned long long)arpstat[f], plural(arpstat[f]))
746
747 p(ARP_STAT_SNDTOTAL, "\t%llu packet%s sent\n");
748 p(ARP_STAT_SNDREPLY, "\t\t%llu reply packet%s\n");
749 p(ARP_STAT_SENDREQUEST, "\t\t%llu request packet%s\n");
750
751 p(ARP_STAT_RCVTOTAL, "\t%llu packet%s received\n");
752 p(ARP_STAT_RCVREPLY, "\t\t%llu reply packet%s\n");
753 p(ARP_STAT_RCVREQUEST, "\t\t%llu valid request packet%s\n");
754 p(ARP_STAT_RCVMCAST, "\t\t%llu broadcast/multicast packet%s\n");
755 p(ARP_STAT_RCVBADPROTO, "\t\t%llu packet%s with unknown protocol type\n");
756 p(ARP_STAT_RCVBADLEN, "\t\t%llu packet%s with bad (short) length\n");
757 p(ARP_STAT_RCVZEROTPA, "\t\t%llu packet%s with null target IP address\n");
758 p(ARP_STAT_RCVZEROSPA, "\t\t%llu packet%s with null source IP address\n");
759 ps(ARP_STAT_RCVNOINT, "\t\t%llu could not be mapped to an interface\n");
760 p(ARP_STAT_RCVLOCALSHA, "\t\t%llu packet%s sourced from a local hardware "
761 "address\n");
762 p(ARP_STAT_RCVBCASTSHA, "\t\t%llu packet%s with a broadcast "
763 "source hardware address\n");
764 p(ARP_STAT_RCVLOCALSPA, "\t\t%llu duplicate%s for a local IP address\n");
765 p(ARP_STAT_RCVOVERPERM, "\t\t%llu attempt%s to overwrite a static entry\n");
766 p(ARP_STAT_RCVOVERINT, "\t\t%llu packet%s received on wrong interface\n");
767 p(ARP_STAT_RCVOVER, "\t\t%llu entry%s overwritten\n");
768 p(ARP_STAT_RCVLENCHG, "\t\t%llu change%s in hardware address length\n");
769
770 p(ARP_STAT_DFRTOTAL, "\t%llu packet%s deferred pending ARP resolution\n");
771 ps(ARP_STAT_DFRSENT, "\t\t%llu sent\n");
772 ps(ARP_STAT_DFRDROPPED, "\t\t%llu dropped\n");
773
774 p(ARP_STAT_ALLOCFAIL, "\t%llu failure%s to allocate llinfo\n");
775
776 #undef ps
777 #undef p
778 }
779
780 /*
781 * Pretty print an Internet address (net address + port).
782 * Take numeric_addr and numeric_port into consideration.
783 */
784 void
785 inetprint(struct in_addr *in, uint16_t port, const char *proto,
786 int port_numeric)
787 {
788 struct servent *sp = 0;
789 char line[80], *cp;
790 size_t space;
791
792 (void)snprintf(line, sizeof line, "%.*s.",
793 (Aflag && !numeric_addr) ? 12 : 16, inetname(in));
794 cp = strchr(line, '\0');
795 if (!port_numeric && port)
796 sp = getservbyport((int)port, proto);
797 space = sizeof line - (cp-line);
798 if (sp || port == 0)
799 (void)snprintf(cp, space, "%s", sp ? sp->s_name : "*");
800 else
801 (void)snprintf(cp, space, "%u", ntohs(port));
802 (void)printf(" %-*.*s", width, width, line);
803 }
804
805 /*
806 * Construct an Internet address representation.
807 * If numeric_addr has been supplied, give
808 * numeric value, otherwise try for symbolic name.
809 */
810 char *
811 inetname(struct in_addr *inp)
812 {
813 char *cp;
814 static char line[50];
815 struct hostent *hp;
816 struct netent *np;
817 static char domain[MAXHOSTNAMELEN + 1];
818 static int first = 1;
819
820 if (first && !numeric_addr) {
821 first = 0;
822 if (gethostname(domain, sizeof domain) == 0) {
823 domain[sizeof(domain) - 1] = '\0';
824 if ((cp = strchr(domain, '.')))
825 (void) strlcpy(domain, cp + 1, sizeof(domain));
826 else
827 domain[0] = 0;
828 } else
829 domain[0] = 0;
830 }
831 cp = 0;
832 if (!numeric_addr && inp->s_addr != INADDR_ANY) {
833 int net = inet_netof(*inp);
834 int lna = inet_lnaof(*inp);
835
836 if (lna == INADDR_ANY) {
837 np = getnetbyaddr(net, AF_INET);
838 if (np)
839 cp = np->n_name;
840 }
841 if (cp == 0) {
842 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
843 if (hp) {
844 if ((cp = strchr(hp->h_name, '.')) &&
845 !strcmp(cp + 1, domain))
846 *cp = 0;
847 cp = hp->h_name;
848 }
849 }
850 }
851 if (inp->s_addr == INADDR_ANY)
852 strlcpy(line, "*", sizeof line);
853 else if (cp)
854 strlcpy(line, cp, sizeof line);
855 else {
856 inp->s_addr = ntohl(inp->s_addr);
857 #define C(x) ((x) & 0xff)
858 (void)snprintf(line, sizeof line, "%u.%u.%u.%u",
859 C(inp->s_addr >> 24), C(inp->s_addr >> 16),
860 C(inp->s_addr >> 8), C(inp->s_addr));
861 #undef C
862 }
863 return (line);
864 }
865
866 /*
867 * Dump the contents of a TCP PCB.
868 */
869 void
870 tcp_dump(u_long pcbaddr)
871 {
872 callout_impl_t *ci;
873 struct tcpcb tcpcb;
874 int i, hardticks;
875
876 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
877 hardticks = get_hardticks();
878
879 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
880
881 printf("Timers:\n");
882 for (i = 0; i < TCPT_NTIMERS; i++) {
883 ci = (callout_impl_t *)&tcpcb.t_timer[i];
884 printf("\t%s: %d", tcptimers[i],
885 (ci->c_flags & CALLOUT_PENDING) ?
886 ci->c_time - hardticks : 0);
887 }
888 printf("\n\n");
889
890 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
891 printf("State: %d", tcpcb.t_state);
892 else
893 printf("State: %s", tcpstates[tcpcb.t_state]);
894 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags,
895 (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb);
896
897 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
898 tcpcb.t_rxtcur, tcpcb.t_dupacks);
899 printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss,
900 tcpcb.t_ourmss, tcpcb.t_segsz);
901
902 printf("snd_una %u, snd_nxt %u, snd_up %u\n",
903 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
904 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
905 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
906
907 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
908 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
909
910 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
911 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
912
913 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
914 "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime,
915 tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin,
916 tcpcb.max_sndwnd);
917
918 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
919 tcpcb.t_iobc, tcpcb.t_softerror);
920
921 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
922 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
923 tcpcb.requested_s_scale);
924 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
925 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
926 }
927