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