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