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