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