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