1 /* $NetBSD: inet.c,v 1.106 2015/02/08 15:09:45 christos Exp $ */
4 * Copyright (c) 1983, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
37 __RCSID("$NetBSD: inet.c,v 1.106 2015/02/08 15:09:45 christos Exp $");
41 #define _CALLOUT_PRIVATE /* for defs in sys/callout.h */
43 #include <sys/param.h>
44 #include <sys/queue.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
48 #include <sys/protosw.h>
49 #include <sys/sysctl.h>
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>
58 #include <netinet/ip_icmp.h>
61 #include <netinet/ip6.h>
64 #include <netinet/icmp_var.h>
65 #include <netinet/igmp_var.h>
66 #include <netinet/ip_var.h>
67 #include <netinet/pim_var.h>
68 #include <netinet/tcp.h>
69 #include <netinet/tcpip.h>
70 #include <netinet/tcp_seq.h>
72 #include <netinet/tcp_fsm.h>
74 #include <netinet/tcp_timer.h>
75 #include <netinet/tcp_var.h>
76 #include <netinet/tcp_debug.h>
77 #include <netinet/udp.h>
78 #include <netinet/ip_carp.h>
79 #include <netinet/udp_var.h>
80 #include <netinet/tcp_vtw.h>
82 #include <arpa/inet.h>
95 char *inetname(struct in_addr
*);
96 void inetprint(struct in_addr
*, u_int16_t
, const char *, int);
98 void print_vtw_v4(const vtw_t
*);
101 * Print a summary of connections related to an Internet
102 * protocol. For TCP, also give state of connection.
103 * Listening processes (aflag) are suppressed unless the
104 * -a (all) flag is specified.
109 /* VTW-related variables. */
110 static struct timeval now
;
115 printf("Active Internet connections");
117 printf(" (including servers)");
120 printf("%-8.8s ", "PCB");
122 Vflag
? "%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %-13.13s Expires\n"
123 : "%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n",
124 "Proto", "Recv-Q", "Send-Q", compact
? "" : " ",
125 width
, width
, "Local Address",
126 width
, width
, "Foreign Address",
131 protopr0(intptr_t ppcb
, u_long rcv_sb_cc
, u_long snd_sb_cc
,
132 struct in_addr
*laddr
, u_int16_t lport
,
133 struct in_addr
*faddr
, u_int16_t fport
,
134 short t_state
, const char *name
, int inp_flags
,
135 const struct timeval
*expires
)
137 static const char *shorttcpstates
[] = {
138 "CLOSED", "LISTEN", "SYNSEN", "SYSRCV",
139 "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG",
140 "LASTAK", "FWAIT2", "TMWAIT",
144 istcp
= strcmp(name
, "tcp") == 0;
147 printf("%8" PRIxPTR
" ", ppcb
);
149 printf("%-5.5s %6ld %6ld%s", name
, rcv_sb_cc
, snd_sb_cc
,
152 inetprint(laddr
, lport
, name
, 1);
153 inetprint(faddr
, fport
, name
, 1);
154 } else if (inp_flags
& INP_ANONPORT
) {
155 inetprint(laddr
, lport
, name
, 1);
156 inetprint(faddr
, fport
, name
, 0);
158 inetprint(laddr
, lport
, name
, 0);
159 inetprint(faddr
, fport
, name
, 0);
162 if (t_state
< 0 || t_state
>= TCP_NSTATES
)
163 printf(" %d", t_state
);
165 printf(" %s", compact
? shorttcpstates
[t_state
] :
168 if (Vflag
&& expires
!= NULL
) {
169 if (expires
->tv_sec
== 0 && expires
->tv_usec
== -1)
170 printf(" reclaimed");
172 struct timeval delta
;
174 timersub(expires
, &now
, &delta
);
176 delta
.tv_sec
* 1000.0 + delta
.tv_usec
/ 1000.0);
183 dbg_printf(const char *fmt
, ...)
189 print_vtw_v4(const vtw_t
*vtw
)
191 const vtw_v4_t
*v4
= (const vtw_v4_t
*)vtw
;
192 struct timeval delta
;
193 struct in_addr la
, fa
;
195 static const struct timeval zero
= {.tv_sec
= 0, .tv_usec
= 0};
197 la
.s_addr
= v4
->laddr
;
198 fa
.s_addr
= v4
->faddr
;
200 snprintf(&buf
[0][0], 32, "%s", inet_ntoa(la
));
201 snprintf(&buf
[1][0], 32, "%s", inet_ntoa(fa
));
203 timersub(&vtw
->expire
, &now
, &delta
);
205 if (vtw
->expire
.tv_sec
== 0 && vtw
->expire
.tv_usec
== -1) {
206 dbg_printf("%15.15s:%d %15.15s:%d reclaimed\n"
207 ,buf
[0], ntohs(v4
->lport
)
208 ,buf
[1], ntohs(v4
->fport
));
209 if (!(Vflag
&& vflag
))
211 } else if (vtw
->expire
.tv_sec
== 0)
213 else if (timercmp(&delta
, &zero
, <) && !(Vflag
&& vflag
)) {
214 dbg_printf("%15.15s:%d %15.15s:%d expired\n"
215 ,buf
[0], ntohs(v4
->lport
)
216 ,buf
[1], ntohs(v4
->fport
));
219 dbg_printf("%15.15s:%d %15.15s:%d expires in %.3fms\n"
220 ,buf
[0], ntohs(v4
->lport
)
221 ,buf
[1], ntohs(v4
->fport
)
222 ,delta
.tv_sec
* 1000.0 + delta
.tv_usec
/ 1000.0);
227 TCPS_TIME_WAIT
, "tcp", 0, &vtw
->expire
);
231 getpcblist_sysctl(const char *name
, size_t *len
) {
233 size_t namelen
= 0, size
= 0;
234 char *mibname
= NULL
;
235 struct kinfo_pcb
*pcblist
;
237 memset(mib
, 0, sizeof(mib
));
239 if (asprintf(&mibname
, "net.inet%s.%s.pcblist", name
+ 3, name
) == -1)
242 /* get dynamic pcblist node */
243 if (sysctlnametomib(mibname
, mib
, &namelen
) == -1)
244 err(1, "sysctlnametomib: %s", mibname
);
248 if (prog_sysctl(mib
, __arraycount(mib
), NULL
, &size
, NULL
, 0) == -1)
249 err(1, "sysctl (query)");
251 if ((pcblist
= malloc(size
)) == NULL
)
253 memset(pcblist
, 0, size
);
255 mib
[6] = sizeof(*pcblist
);
256 mib
[7] = size
/ sizeof(*pcblist
);
258 if (prog_sysctl(mib
, __arraycount(mib
), pcblist
, &size
, NULL
, 0) == -1)
259 err(1, "sysctl (copy)");
261 *len
= size
/ sizeof(*pcblist
);
266 static struct kinfo_pcb
*
267 getpcblist_kmem(u_long off
, const char *name
, size_t *len
) {
268 struct inpcbtable table
;
269 struct inpcb_hdr
*next
, *prev
;
273 int istcp
= strcmp(name
, "tcp") == 0;
274 struct kinfo_pcb
*pcblist
;
275 size_t size
= 100, i
;
276 struct sockaddr_in sin
;
277 struct inpcbqueue
*head
;
284 kread(off
, (char *)&table
, sizeof table
);
285 head
= &table
.inpt_queue
;
286 next
= TAILQ_FIRST(head
);
287 prev
= TAILQ_END(head
);
289 if ((pcblist
= malloc(size
* sizeof(*pcblist
))) == NULL
)
293 while (next
!= TAILQ_END(head
)) {
294 kread((u_long
)next
, (char *)&inpcb
, sizeof inpcb
);
296 next
= TAILQ_NEXT(&inpcb
, inp_queue
);
298 if (inpcb
.inp_af
!= AF_INET
)
301 kread((u_long
)inpcb
.inp_socket
, (char *)&sockb
, sizeof(sockb
));
303 kread((u_long
)inpcb
.inp_ppcb
,
304 (char *)&tcpcb
, sizeof (tcpcb
));
306 pcblist
[i
].ki_ppcbaddr
=
307 istcp
? (uintptr_t) inpcb
.inp_ppcb
: (uintptr_t) prev
;
308 pcblist
[i
].ki_rcvq
= (uint64_t)sockb
.so_rcv
.sb_cc
;
309 pcblist
[i
].ki_sndq
= (uint64_t)sockb
.so_snd
.sb_cc
;
311 sin
.sin_addr
= inpcb
.inp_laddr
;
312 sin
.sin_port
= inpcb
.inp_lport
;
313 memcpy(&pcblist
[i
].ki_s
, &sin
, sizeof(sin
));
314 sin
.sin_addr
= inpcb
.inp_faddr
;
315 sin
.sin_port
= inpcb
.inp_fport
;
316 memcpy(&pcblist
[i
].ki_d
, &sin
, sizeof(sin
));
317 pcblist
[i
].ki_tstate
= tcpcb
.t_state
;
318 pcblist
[i
].ki_pflags
= inpcb
.inp_flags
;
321 struct kinfo_pcb
*n
= realloc(pcblist
,
322 size
* sizeof(*pcblist
));
333 protopr(u_long off
, const char *name
)
335 static int first
= 1;
336 struct kinfo_pcb
*pcblist
;
351 pcblist
= getpcblist_sysctl(name
, &len
);
353 pcblist
= getpcblist_kmem(off
, name
, &len
);
355 for (i
= 0; i
< len
; i
++) {
356 struct sockaddr_in src
, dst
;
358 memcpy(&src
, &pcblist
[i
].ki_s
, sizeof(src
));
359 memcpy(&dst
, &pcblist
[i
].ki_d
, sizeof(dst
));
362 inet_lnaof(dst
.sin_addr
) == INADDR_ANY
)
369 protopr0((intptr_t) pcblist
[i
].ki_ppcbaddr
,
370 pcblist
[i
].ki_rcvq
, pcblist
[i
].ki_sndq
,
371 &src
.sin_addr
, src
.sin_port
,
372 &dst
.sin_addr
, dst
.sin_port
,
373 pcblist
[i
].ki_tstate
, name
,
374 pcblist
[i
].ki_pflags
, NULL
);
380 if (strcmp(name
, "tcp") == 0) {
383 gettimeofday(&now
, NULL
);
384 timersub(&now
, &t
, &now
);
385 show_vtw_v4(print_vtw_v4
);
387 #endif /* !__minix */
391 * Dump TCP statistics structure.
394 tcp_stats(u_long off
, const char *name
)
396 uint64_t tcpstat
[TCP_NSTATS
];
399 size_t size
= sizeof(tcpstat
);
401 if (sysctlbyname("net.inet.tcp.stats", tcpstat
, &size
,
405 warnx("%s stats not available via KVM.", name
);
409 printf ("%s:\n", name
);
411 #define ps(f, m) if (tcpstat[f] || sflag <= 1) \
412 printf(m, tcpstat[f])
413 #define p(f, m) if (tcpstat[f] || sflag <= 1) \
414 printf(m, tcpstat[f], plural(tcpstat[f]))
415 #define p2(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
416 printf(m, tcpstat[f1], plural(tcpstat[f1]), \
417 tcpstat[f2], plural(tcpstat[f2]))
418 #define p2s(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
419 printf(m, tcpstat[f1], plural(tcpstat[f1]), \
421 #define p3(f, m) if (tcpstat[f] || sflag <= 1) \
422 printf(m, tcpstat[f], plurales(tcpstat[f]))
424 p(TCP_STAT_SNDTOTAL
, "\t%" PRIu64
" packet%s sent\n");
425 p2(TCP_STAT_SNDPACK
,TCP_STAT_SNDBYTE
,
426 "\t\t%" PRIu64
" data packet%s (%" PRIu64
" byte%s)\n");
427 p2(TCP_STAT_SNDREXMITPACK
, TCP_STAT_SNDREXMITBYTE
,
428 "\t\t%" PRIu64
" data packet%s (%" PRIu64
" byte%s) retransmitted\n");
429 p2s(TCP_STAT_SNDACKS
, TCP_STAT_DELACK
,
430 "\t\t%" PRIu64
" ack-only packet%s (%" PRIu64
" delayed)\n");
431 p(TCP_STAT_SNDURG
, "\t\t%" PRIu64
" URG only packet%s\n");
432 p(TCP_STAT_SNDPROBE
, "\t\t%" PRIu64
" window probe packet%s\n");
433 p(TCP_STAT_SNDWINUP
, "\t\t%" PRIu64
" window update packet%s\n");
434 p(TCP_STAT_SNDCTRL
, "\t\t%" PRIu64
" control packet%s\n");
435 p(TCP_STAT_SELFQUENCH
,
436 "\t\t%" PRIu64
" send attempt%s resulted in self-quench\n");
437 p(TCP_STAT_RCVTOTAL
, "\t%" PRIu64
" packet%s received\n");
438 p2(TCP_STAT_RCVACKPACK
, TCP_STAT_RCVACKBYTE
,
439 "\t\t%" PRIu64
" ack%s (for %" PRIu64
" byte%s)\n");
440 p(TCP_STAT_RCVDUPACK
, "\t\t%" PRIu64
" duplicate ack%s\n");
441 p(TCP_STAT_RCVACKTOOMUCH
, "\t\t%" PRIu64
" ack%s for unsent data\n");
442 p2(TCP_STAT_RCVPACK
, TCP_STAT_RCVBYTE
,
443 "\t\t%" PRIu64
" packet%s (%" PRIu64
" byte%s) received in-sequence\n");
444 p2(TCP_STAT_RCVDUPPACK
, TCP_STAT_RCVDUPBYTE
,
445 "\t\t%" PRIu64
" completely duplicate packet%s (%" PRIu64
" byte%s)\n");
446 p(TCP_STAT_PAWSDROP
, "\t\t%" PRIu64
" old duplicate packet%s\n");
447 p2(TCP_STAT_RCVPARTDUPPACK
, TCP_STAT_RCVPARTDUPBYTE
,
448 "\t\t%" PRIu64
" packet%s with some dup. data (%" PRIu64
" byte%s duped)\n");
449 p2(TCP_STAT_RCVOOPACK
, TCP_STAT_RCVOOBYTE
,
450 "\t\t%" PRIu64
" out-of-order packet%s (%" PRIu64
" byte%s)\n");
451 p2(TCP_STAT_RCVPACKAFTERWIN
, TCP_STAT_RCVBYTEAFTERWIN
,
452 "\t\t%" PRIu64
" packet%s (%" PRIu64
" byte%s) of data after window\n");
453 p(TCP_STAT_RCVWINPROBE
, "\t\t%" PRIu64
" window probe%s\n");
454 p(TCP_STAT_RCVWINUPD
, "\t\t%" PRIu64
" window update packet%s\n");
455 p(TCP_STAT_RCVAFTERCLOSE
, "\t\t%" PRIu64
" packet%s received after close\n");
456 p(TCP_STAT_RCVBADSUM
, "\t\t%" PRIu64
" discarded for bad checksum%s\n");
457 p(TCP_STAT_RCVBADOFF
, "\t\t%" PRIu64
" discarded for bad header offset field%s\n");
458 ps(TCP_STAT_RCVSHORT
, "\t\t%" PRIu64
" discarded because packet too short\n");
459 p(TCP_STAT_CONNATTEMPT
, "\t%" PRIu64
" connection request%s\n");
460 p(TCP_STAT_ACCEPTS
, "\t%" PRIu64
" connection accept%s\n");
462 "\t%" PRIu64
" connection%s established (including accepts)\n");
463 p2(TCP_STAT_CLOSED
, TCP_STAT_DROPS
,
464 "\t%" PRIu64
" connection%s closed (including %" PRIu64
" drop%s)\n");
465 p(TCP_STAT_CONNDROPS
, "\t%" PRIu64
" embryonic connection%s dropped\n");
466 p(TCP_STAT_DELAYED_FREE
, "\t%" PRIu64
" delayed free%s of tcpcb\n");
467 p2(TCP_STAT_RTTUPDATED
, TCP_STAT_SEGSTIMED
,
468 "\t%" PRIu64
" segment%s updated rtt (of %" PRIu64
" attempt%s)\n");
469 p(TCP_STAT_REXMTTIMEO
, "\t%" PRIu64
" retransmit timeout%s\n");
470 p(TCP_STAT_TIMEOUTDROP
,
471 "\t\t%" PRIu64
" connection%s dropped by rexmit timeout\n");
472 p2(TCP_STAT_PERSISTTIMEO
, TCP_STAT_PERSISTDROPS
,
473 "\t%" PRIu64
" persist timeout%s (resulting in %" PRIu64
" dropped "
475 p(TCP_STAT_KEEPTIMEO
, "\t%" PRIu64
" keepalive timeout%s\n");
476 p(TCP_STAT_KEEPPROBE
, "\t\t%" PRIu64
" keepalive probe%s sent\n");
477 p(TCP_STAT_KEEPDROPS
, "\t\t%" PRIu64
" connection%s dropped by keepalive\n");
478 p(TCP_STAT_PREDACK
, "\t%" PRIu64
" correct ACK header prediction%s\n");
479 p(TCP_STAT_PREDDAT
, "\t%" PRIu64
" correct data packet header prediction%s\n");
480 p3(TCP_STAT_PCBHASHMISS
, "\t%" PRIu64
" PCB hash miss%s\n");
481 ps(TCP_STAT_NOPORT
, "\t%" PRIu64
" dropped due to no socket\n");
482 p(TCP_STAT_CONNSDRAINED
, "\t%" PRIu64
" connection%s drained due to memory "
484 p(TCP_STAT_PMTUBLACKHOLE
, "\t%" PRIu64
" PMTUD blackhole%s detected\n");
486 p(TCP_STAT_BADSYN
, "\t%" PRIu64
" bad connection attempt%s\n");
487 ps(TCP_STAT_SC_ADDED
, "\t%" PRIu64
" SYN cache entries added\n");
488 p(TCP_STAT_SC_COLLISIONS
, "\t\t%" PRIu64
" hash collision%s\n");
489 ps(TCP_STAT_SC_COMPLETED
, "\t\t%" PRIu64
" completed\n");
490 ps(TCP_STAT_SC_ABORTED
, "\t\t%" PRIu64
" aborted (no space to build PCB)\n");
491 ps(TCP_STAT_SC_TIMED_OUT
, "\t\t%" PRIu64
" timed out\n");
492 ps(TCP_STAT_SC_OVERFLOWED
, "\t\t%" PRIu64
" dropped due to overflow\n");
493 ps(TCP_STAT_SC_BUCKETOVERFLOW
, "\t\t%" PRIu64
" dropped due to bucket overflow\n");
494 ps(TCP_STAT_SC_RESET
, "\t\t%" PRIu64
" dropped due to RST\n");
495 ps(TCP_STAT_SC_UNREACH
, "\t\t%" PRIu64
" dropped due to ICMP unreachable\n");
496 ps(TCP_STAT_SC_DELAYED_FREE
, "\t\t%" PRIu64
" delayed free of SYN cache "
498 p(TCP_STAT_SC_RETRANSMITTED
, "\t%" PRIu64
" SYN,ACK%s retransmitted\n");
499 p(TCP_STAT_SC_DUPESYN
, "\t%" PRIu64
" duplicate SYN%s received for entries "
500 "already in the cache\n");
501 p(TCP_STAT_SC_DROPPED
, "\t%" PRIu64
" SYN%s dropped (no route or no space)\n");
502 p(TCP_STAT_BADSIG
, "\t%" PRIu64
" packet%s with bad signature\n");
503 p(TCP_STAT_GOODSIG
, "\t%" PRIu64
" packet%s with good signature\n");
505 p(TCP_STAT_ECN_SHS
, "\t%" PRIu64
" successful ECN handshake%s\n");
506 p(TCP_STAT_ECN_CE
, "\t%" PRIu64
" packet%s with ECN CE bit\n");
507 p(TCP_STAT_ECN_ECT
, "\t%" PRIu64
" packet%s ECN ECT(0) bit\n");
517 * Dump UDP statistics structure.
520 udp_stats(u_long off
, const char *name
)
522 uint64_t udpstat
[UDP_NSTATS
];
526 size_t size
= sizeof(udpstat
);
528 if (sysctlbyname("net.inet.udp.stats", udpstat
, &size
,
532 warnx("%s stats not available via KVM.", name
);
536 printf ("%s:\n", name
);
538 #define ps(f, m) if (udpstat[f] || sflag <= 1) \
539 printf(m, udpstat[f])
540 #define p(f, m) if (udpstat[f] || sflag <= 1) \
541 printf(m, udpstat[f], plural(udpstat[f]))
542 #define p3(f, m) if (udpstat[f] || sflag <= 1) \
543 printf(m, udpstat[f], plurales(udpstat[f]))
545 p(UDP_STAT_IPACKETS
, "\t%" PRIu64
" datagram%s received\n");
546 ps(UDP_STAT_HDROPS
, "\t%" PRIu64
" with incomplete header\n");
547 ps(UDP_STAT_BADLEN
, "\t%" PRIu64
" with bad data length field\n");
548 ps(UDP_STAT_BADSUM
, "\t%" PRIu64
" with bad checksum\n");
549 ps(UDP_STAT_NOPORT
, "\t%" PRIu64
" dropped due to no socket\n");
550 p(UDP_STAT_NOPORTBCAST
,
551 "\t%" PRIu64
" broadcast/multicast datagram%s dropped due to no socket\n");
552 ps(UDP_STAT_FULLSOCK
, "\t%" PRIu64
" dropped due to full socket buffers\n");
553 delivered
= udpstat
[UDP_STAT_IPACKETS
] -
554 udpstat
[UDP_STAT_HDROPS
] -
555 udpstat
[UDP_STAT_BADLEN
] -
556 udpstat
[UDP_STAT_BADSUM
] -
557 udpstat
[UDP_STAT_NOPORT
] -
558 udpstat
[UDP_STAT_NOPORTBCAST
] -
559 udpstat
[UDP_STAT_FULLSOCK
];
560 if (delivered
|| sflag
<= 1)
561 printf("\t%" PRIu64
" delivered\n", delivered
);
562 p3(UDP_STAT_PCBHASHMISS
, "\t%" PRIu64
" PCB hash miss%s\n");
563 p(UDP_STAT_OPACKETS
, "\t%" PRIu64
" datagram%s output\n");
571 * Dump IP statistics structure.
574 ip_stats(u_long off
, const char *name
)
576 uint64_t ipstat
[IP_NSTATS
];
579 size_t size
= sizeof(ipstat
);
581 if (sysctlbyname("net.inet.ip.stats", ipstat
, &size
,
585 warnx("%s stats not available via KVM.", name
);
589 printf("%s:\n", name
);
591 #define ps(f, m) if (ipstat[f] || sflag <= 1) \
593 #define p(f, m) if (ipstat[f] || sflag <= 1) \
594 printf(m, ipstat[f], plural(ipstat[f]))
596 p(IP_STAT_TOTAL
, "\t%" PRIu64
" total packet%s received\n");
597 p(IP_STAT_BADSUM
, "\t%" PRIu64
" bad header checksum%s\n");
598 ps(IP_STAT_TOOSMALL
, "\t%" PRIu64
" with size smaller than minimum\n");
599 ps(IP_STAT_TOOSHORT
, "\t%" PRIu64
" with data size < data length\n");
600 ps(IP_STAT_TOOLONG
, "\t%" PRIu64
" with length > max ip packet size\n");
601 ps(IP_STAT_BADHLEN
, "\t%" PRIu64
" with header length < data size\n");
602 ps(IP_STAT_BADLEN
, "\t%" PRIu64
" with data length < header length\n");
603 ps(IP_STAT_BADOPTIONS
, "\t%" PRIu64
" with bad options\n");
604 ps(IP_STAT_BADVERS
, "\t%" PRIu64
" with incorrect version number\n");
605 p(IP_STAT_FRAGMENTS
, "\t%" PRIu64
" fragment%s received\n");
606 p(IP_STAT_FRAGDROPPED
, "\t%" PRIu64
" fragment%s dropped (dup or out of space)\n");
607 p(IP_STAT_RCVMEMDROP
, "\t%" PRIu64
" fragment%s dropped (out of ipqent)\n");
608 p(IP_STAT_BADFRAGS
, "\t%" PRIu64
" malformed fragment%s dropped\n");
609 p(IP_STAT_FRAGTIMEOUT
, "\t%" PRIu64
" fragment%s dropped after timeout\n");
610 p(IP_STAT_REASSEMBLED
, "\t%" PRIu64
" packet%s reassembled ok\n");
611 p(IP_STAT_DELIVERED
, "\t%" PRIu64
" packet%s for this host\n");
612 p(IP_STAT_NOPROTO
, "\t%" PRIu64
" packet%s for unknown/unsupported protocol\n");
613 p(IP_STAT_FORWARD
, "\t%" PRIu64
" packet%s forwarded");
614 p(IP_STAT_FASTFORWARD
, " (%" PRIu64
" packet%s fast forwarded)");
615 if (ipstat
[IP_STAT_FORWARD
] || sflag
<= 1)
617 p(IP_STAT_CANTFORWARD
, "\t%" PRIu64
" packet%s not forwardable\n");
618 p(IP_STAT_REDIRECTSENT
, "\t%" PRIu64
" redirect%s sent\n");
619 p(IP_STAT_NOGIF
, "\t%" PRIu64
" packet%s no matching gif found\n");
620 p(IP_STAT_LOCALOUT
, "\t%" PRIu64
" packet%s sent from this host\n");
621 p(IP_STAT_RAWOUT
, "\t%" PRIu64
" packet%s sent with fabricated ip header\n");
622 p(IP_STAT_ODROPPED
, "\t%" PRIu64
" output packet%s dropped due to no bufs, etc.\n");
623 p(IP_STAT_NOROUTE
, "\t%" PRIu64
" output packet%s discarded due to no route\n");
624 p(IP_STAT_FRAGMENTED
, "\t%" PRIu64
" output datagram%s fragmented\n");
625 p(IP_STAT_OFRAGMENTS
, "\t%" PRIu64
" fragment%s created\n");
626 p(IP_STAT_CANTFRAG
, "\t%" PRIu64
" datagram%s that can't be fragmented\n");
627 p(IP_STAT_BADADDR
, "\t%" PRIu64
" datagram%s with bad address in header\n");
633 * Dump ICMP statistics.
636 icmp_stats(u_long off
, const char *name
)
638 uint64_t icmpstat
[ICMP_NSTATS
];
642 size_t size
= sizeof(icmpstat
);
644 if (sysctlbyname("net.inet.icmp.stats", icmpstat
, &size
,
648 warnx("%s stats not available via KVM.", name
);
652 printf("%s:\n", name
);
654 #define p(f, m) if (icmpstat[f] || sflag <= 1) \
655 printf(m, icmpstat[f], plural(icmpstat[f]))
657 p(ICMP_STAT_ERROR
, "\t%" PRIu64
" call%s to icmp_error\n");
659 "\t%" PRIu64
" error%s not generated because old message was icmp\n");
660 for (first
= 1, i
= 0; i
< ICMP_MAXTYPE
+ 1; i
++)
661 if (icmpstat
[ICMP_STAT_OUTHIST
+ i
] != 0) {
663 printf("\tOutput histogram:\n");
666 printf("\t\t%s: %" PRIu64
"\n", icmp_type
[i
],
667 icmpstat
[ICMP_STAT_OUTHIST
+ i
]);
669 p(ICMP_STAT_BADCODE
, "\t%" PRIu64
" message%s with bad code fields\n");
670 p(ICMP_STAT_TOOSHORT
, "\t%" PRIu64
" message%s < minimum length\n");
671 p(ICMP_STAT_CHECKSUM
, "\t%" PRIu64
" bad checksum%s\n");
672 p(ICMP_STAT_BADLEN
, "\t%" PRIu64
" message%s with bad length\n");
673 p(ICMP_STAT_BMCASTECHO
, "\t%" PRIu64
" multicast echo request%s ignored\n");
674 p(ICMP_STAT_BMCASTTSTAMP
, "\t%" PRIu64
" multicast timestamp request%s ignored\n");
675 for (first
= 1, i
= 0; i
< ICMP_MAXTYPE
+ 1; i
++)
676 if (icmpstat
[ICMP_STAT_INHIST
+ i
] != 0) {
678 printf("\tInput histogram:\n");
681 printf("\t\t%s: %" PRIu64
"\n", icmp_type
[i
],
682 icmpstat
[ICMP_STAT_INHIST
+ i
]);
684 p(ICMP_STAT_REFLECT
, "\t%" PRIu64
" message response%s generated\n");
685 p(ICMP_STAT_PMTUCHG
, "\t%" PRIu64
" path MTU change%s\n");
690 * Dump IGMP statistics structure.
693 igmp_stats(u_long off
, const char *name
)
695 uint64_t igmpstat
[IGMP_NSTATS
];
698 size_t size
= sizeof(igmpstat
);
700 if (sysctlbyname("net.inet.igmp.stats", igmpstat
, &size
,
704 warnx("%s stats not available via KVM.", name
);
708 printf("%s:\n", name
);
710 #define p(f, m) if (igmpstat[f] || sflag <= 1) \
711 printf(m, igmpstat[f], plural(igmpstat[f]))
712 #define py(f, m) if (igmpstat[f] || sflag <= 1) \
713 printf(m, igmpstat[f], igmpstat[f] != 1 ? "ies" : "y")
714 p(IGMP_STAT_RCV_TOTAL
, "\t%" PRIu64
" message%s received\n");
715 p(IGMP_STAT_RCV_TOOSHORT
, "\t%" PRIu64
" message%s received with too few bytes\n");
716 p(IGMP_STAT_RCV_BADSUM
, "\t%" PRIu64
" message%s received with bad checksum\n");
717 py(IGMP_STAT_RCV_QUERIES
, "\t%" PRIu64
" membership quer%s received\n");
718 py(IGMP_STAT_RCV_BADQUERIES
, "\t%" PRIu64
" membership quer%s received with invalid field(s)\n");
719 p(IGMP_STAT_RCV_REPORTS
, "\t%" PRIu64
" membership report%s received\n");
720 p(IGMP_STAT_RCV_BADREPORTS
, "\t%" PRIu64
" membership report%s received with invalid field(s)\n");
721 p(IGMP_STAT_RCV_OURREPORTS
, "\t%" PRIu64
" membership report%s received for groups to which we belong\n");
722 p(IGMP_STAT_SND_REPORTS
, "\t%" PRIu64
" membership report%s sent\n");
728 * Dump CARP statistics structure.
731 carp_stats(u_long off
, const char *name
)
733 uint64_t carpstat
[CARP_NSTATS
];
736 size_t size
= sizeof(carpstat
);
738 if (sysctlbyname("net.inet.carp.stats", carpstat
, &size
,
742 warnx("%s stats not available via KVM.", name
);
746 printf("%s:\n", name
);
748 #define p(f, m) if (carpstat[f] || sflag <= 1) \
749 printf(m, carpstat[f], plural(carpstat[f]))
750 #define p2(f, m) if (carpstat[f] || sflag <= 1) \
751 printf(m, carpstat[f])
753 p(CARP_STAT_IPACKETS
, "\t%" PRIu64
" packet%s received (IPv4)\n");
754 p(CARP_STAT_IPACKETS6
, "\t%" PRIu64
" packet%s received (IPv6)\n");
756 "\t\t%" PRIu64
" packet%s discarded for bad interface\n");
758 "\t\t%" PRIu64
" packet%s discarded for wrong TTL\n");
759 p(CARP_STAT_HDROPS
, "\t\t%" PRIu64
" packet%s shorter than header\n");
760 p(CARP_STAT_BADSUM
, "\t\t%" PRIu64
761 " packet%s discarded for bad checksum\n");
763 "\t\t%" PRIu64
" packet%s discarded with a bad version\n");
765 "\t\t%" PRIu64
" discarded because packet was too short\n");
767 "\t\t%" PRIu64
" packet%s discarded for bad authentication\n");
768 p(CARP_STAT_BADVHID
, "\t\t%" PRIu64
" packet%s discarded for bad vhid\n");
769 p(CARP_STAT_BADADDRS
, "\t\t%" PRIu64
770 " packet%s discarded because of a bad address list\n");
771 p(CARP_STAT_OPACKETS
, "\t%" PRIu64
" packet%s sent (IPv4)\n");
772 p(CARP_STAT_OPACKETS6
, "\t%" PRIu64
" packet%s sent (IPv6)\n");
774 "\t\t%" PRIu64
" send failed due to mbuf memory error\n");
780 * Dump PIM statistics structure.
783 pim_stats(u_long off
, const char *name
)
785 struct pimstat pimstat
;
789 if (kread(off
, (char *)&pimstat
, sizeof (pimstat
)) != 0) {
790 /* XXX: PIM is probably not enabled in the kernel */
794 printf("%s:\n", name
);
796 #define p(f, m) if (pimstat.f || sflag <= 1) \
797 printf(m, pimstat.f, plural(pimstat.f))
799 p(pims_rcv_total_msgs
, "\t%" PRIu64
" message%s received\n");
800 p(pims_rcv_total_bytes
, "\t%" PRIu64
" byte%s received\n");
801 p(pims_rcv_tooshort
, "\t%" PRIu64
" message%s received with too few bytes\n");
802 p(pims_rcv_badsum
, "\t%" PRIu64
" message%s received with bad checksum\n");
803 p(pims_rcv_badversion
, "\t%" PRIu64
" message%s received with bad version\n");
804 p(pims_rcv_registers_msgs
, "\t%" PRIu64
" data register message%s received\n");
805 p(pims_rcv_registers_bytes
, "\t%" PRIu64
" data register byte%s received\n");
806 p(pims_rcv_registers_wrongiif
, "\t%" PRIu64
" data register message%s received on wrong iif\n");
807 p(pims_rcv_badregisters
, "\t%" PRIu64
" bad register%s received\n");
808 p(pims_snd_registers_msgs
, "\t%" PRIu64
" data register message%s sent\n");
809 p(pims_snd_registers_bytes
, "\t%" PRIu64
" data register byte%s sent\n");
814 * Dump the ARP statistics structure.
817 arp_stats(u_long off
, const char *name
)
819 uint64_t arpstat
[ARP_NSTATS
];
822 size_t size
= sizeof(arpstat
);
824 if (sysctlbyname("net.inet.arp.stats", arpstat
, &size
,
828 warnx("%s stats not available via KVM.", name
);
832 printf("%s:\n", name
);
834 #define ps(f, m) if (arpstat[f] || sflag <= 1) \
835 printf(m, arpstat[f])
836 #define p(f, m) if (arpstat[f] || sflag <= 1) \
837 printf(m, arpstat[f], plural(arpstat[f]))
839 p(ARP_STAT_SNDTOTAL
, "\t%" PRIu64
" packet%s sent\n");
840 p(ARP_STAT_SNDREPLY
, "\t\t%" PRIu64
" reply packet%s\n");
841 p(ARP_STAT_SENDREQUEST
, "\t\t%" PRIu64
" request packet%s\n");
843 p(ARP_STAT_RCVTOTAL
, "\t%" PRIu64
" packet%s received\n");
844 p(ARP_STAT_RCVREPLY
, "\t\t%" PRIu64
" reply packet%s\n");
845 p(ARP_STAT_RCVREQUEST
, "\t\t%" PRIu64
" valid request packet%s\n");
846 p(ARP_STAT_RCVMCAST
, "\t\t%" PRIu64
" broadcast/multicast packet%s\n");
847 p(ARP_STAT_RCVBADPROTO
, "\t\t%" PRIu64
" packet%s with unknown protocol type\n");
848 p(ARP_STAT_RCVBADLEN
, "\t\t%" PRIu64
" packet%s with bad (short) length\n");
849 p(ARP_STAT_RCVZEROTPA
, "\t\t%" PRIu64
" packet%s with null target IP address\n");
850 p(ARP_STAT_RCVZEROSPA
, "\t\t%" PRIu64
" packet%s with null source IP address\n");
851 ps(ARP_STAT_RCVNOINT
, "\t\t%" PRIu64
" could not be mapped to an interface\n");
852 p(ARP_STAT_RCVLOCALSHA
, "\t\t%" PRIu64
" packet%s sourced from a local hardware "
854 p(ARP_STAT_RCVBCASTSHA
, "\t\t%" PRIu64
" packet%s with a broadcast "
855 "source hardware address\n");
856 p(ARP_STAT_RCVLOCALSPA
, "\t\t%" PRIu64
" duplicate%s for a local IP address\n");
857 p(ARP_STAT_RCVOVERPERM
, "\t\t%" PRIu64
" attempt%s to overwrite a static entry\n");
858 p(ARP_STAT_RCVOVERINT
, "\t\t%" PRIu64
" packet%s received on wrong interface\n");
859 p(ARP_STAT_RCVOVER
, "\t\t%" PRIu64
" entry%s overwritten\n");
860 p(ARP_STAT_RCVLENCHG
, "\t\t%" PRIu64
" change%s in hardware address length\n");
862 p(ARP_STAT_DFRTOTAL
, "\t%" PRIu64
" packet%s deferred pending ARP resolution\n");
863 ps(ARP_STAT_DFRSENT
, "\t\t%" PRIu64
" sent\n");
864 ps(ARP_STAT_DFRDROPPED
, "\t\t%" PRIu64
" dropped\n");
866 p(ARP_STAT_ALLOCFAIL
, "\t%" PRIu64
" failure%s to allocate llinfo\n");
873 * Pretty print an Internet address (net address + port).
874 * Take numeric_addr and numeric_port into consideration.
877 inetprint(struct in_addr
*in
, uint16_t port
, const char *proto
,
880 struct servent
*sp
= 0;
884 (void)snprintf(line
, sizeof line
, "%.*s.",
885 (Aflag
&& !numeric_addr
) ? 12 : 16, inetname(in
));
886 cp
= strchr(line
, '\0');
887 if (!port_numeric
&& port
)
888 sp
= getservbyport((int)port
, proto
);
889 space
= sizeof line
- (cp
-line
);
891 (void)snprintf(cp
, space
, "%s", sp
? sp
->s_name
: "*");
893 (void)snprintf(cp
, space
, "%u", ntohs(port
));
894 (void)printf(" %-*.*s", width
, width
, line
);
898 * Construct an Internet address representation.
899 * If numeric_addr has been supplied, give
900 * numeric value, otherwise try for symbolic name.
903 inetname(struct in_addr
*inp
)
906 static char line
[50];
909 static char domain
[MAXHOSTNAMELEN
+ 1];
910 static int first
= 1;
912 if (first
&& !numeric_addr
) {
914 if (gethostname(domain
, sizeof domain
) == 0) {
915 domain
[sizeof(domain
) - 1] = '\0';
916 if ((cp
= strchr(domain
, '.')))
917 (void) strlcpy(domain
, cp
+ 1, sizeof(domain
));
924 if (!numeric_addr
&& inp
->s_addr
!= INADDR_ANY
) {
925 int net
= inet_netof(*inp
);
926 int lna
= inet_lnaof(*inp
);
928 if (lna
== INADDR_ANY
) {
929 np
= getnetbyaddr(net
, AF_INET
);
934 hp
= gethostbyaddr((char *)inp
, sizeof (*inp
), AF_INET
);
936 if ((cp
= strchr(hp
->h_name
, '.')) &&
937 !strcmp(cp
+ 1, domain
))
943 if (inp
->s_addr
== INADDR_ANY
)
944 strlcpy(line
, "*", sizeof line
);
946 strlcpy(line
, cp
, sizeof line
);
948 inp
->s_addr
= ntohl(inp
->s_addr
);
949 #define C(x) ((x) & 0xff)
950 (void)snprintf(line
, sizeof line
, "%u.%u.%u.%u",
951 C(inp
->s_addr
>> 24), C(inp
->s_addr
>> 16),
952 C(inp
->s_addr
>> 8), C(inp
->s_addr
));
959 * Dump the contents of a TCP PCB.
962 tcp_dump(u_long off
, const char *name
, u_long pcbaddr
)
967 struct kinfo_pcb
*pcblist
;
971 pcblist
= getpcblist_sysctl(name
, &len
);
973 pcblist
= getpcblist_kmem(off
, name
, &len
);
975 for (j
= 0; j
< len
; j
++)
976 if (pcblist
[j
].ki_ppcbaddr
== pcbaddr
)
981 errx(1, "0x%lx is not a valid pcb address", pcbaddr
);
983 kread(pcbaddr
, (char *)&tcpcb
, sizeof(tcpcb
));
984 hardticks
= get_hardticks();
986 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr
);
989 for (i
= 0; i
< TCPT_NTIMERS
; i
++) {
991 ci
= (callout_impl_t
*)&tcpcb
.t_timer
[i
];
992 snprintb(buf
, sizeof(buf
), CALLOUT_FMT
, ci
->c_flags
);
993 printf("\t%s\t%s", tcptimers
[i
], buf
);
994 if (ci
->c_flags
& CALLOUT_PENDING
)
995 printf("\t%d\n", ci
->c_time
- hardticks
);
1001 if (tcpcb
.t_state
< 0 || tcpcb
.t_state
>= TCP_NSTATES
)
1002 printf("State: %d", tcpcb
.t_state
);
1004 printf("State: %s", tcpstates
[tcpcb
.t_state
]);
1005 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb
.t_flags
,
1006 (u_long
)tcpcb
.t_inpcb
, (u_long
)tcpcb
.t_in6pcb
);
1008 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb
.t_rxtshift
,
1009 tcpcb
.t_rxtcur
, tcpcb
.t_dupacks
);
1010 printf("peermss %u, ourmss %u, segsz %u, segqlen %u\n\n",
1011 tcpcb
.t_peermss
, tcpcb
.t_ourmss
, tcpcb
.t_segsz
, tcpcb
.t_segqlen
);
1013 printf("snd_una %u, snd_nxt %u, snd_up %u\n",
1014 tcpcb
.snd_una
, tcpcb
.snd_nxt
, tcpcb
.snd_up
);
1015 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
1016 tcpcb
.snd_wl1
, tcpcb
.snd_wl2
, tcpcb
.iss
, tcpcb
.snd_wnd
);
1018 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
1019 tcpcb
.rcv_wnd
, tcpcb
.rcv_nxt
, tcpcb
.rcv_up
, tcpcb
.irs
);
1021 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
1022 tcpcb
.rcv_adv
, tcpcb
.snd_max
, tcpcb
.snd_cwnd
, tcpcb
.snd_ssthresh
);
1024 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
1025 "rttmin %d, max_sndwnd %lu\n\n", tcpcb
.t_rcvtime
, tcpcb
.t_rtttime
,
1026 tcpcb
.t_rtseq
, tcpcb
.t_srtt
, tcpcb
.t_rttvar
, tcpcb
.t_rttmin
,
1029 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb
.t_oobflags
,
1030 tcpcb
.t_iobc
, tcpcb
.t_softerror
);
1032 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
1033 tcpcb
.snd_scale
, tcpcb
.rcv_scale
, tcpcb
.request_r_scale
,
1034 tcpcb
.requested_s_scale
);
1035 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
1036 tcpcb
.ts_recent
, tcpcb
.ts_recent_age
, tcpcb
.last_ack_sent
);