inet.c revision 1.64 1 /* $NetBSD: inet.c,v 1.64 2005/08/04 19:41:28 rpaulo 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.64 2005/08/04 19:41:28 rpaulo Exp $");
38 #endif
39 #endif /* not lint */
40
41 #include <sys/param.h>
42 #include <sys/queue.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/mbuf.h>
46 #include <sys/protosw.h>
47
48 #include <net/if_arp.h>
49 #include <net/route.h>
50 #include <netinet/in.h>
51 #include <netinet/in_systm.h>
52 #include <netinet/ip.h>
53 #include <netinet/in_pcb.h>
54 #include <netinet/ip_icmp.h>
55
56 #ifdef INET6
57 #include <netinet/ip6.h>
58 #endif
59
60 #include <netinet/icmp_var.h>
61 #include <netinet/igmp_var.h>
62 #include <netinet/ip_var.h>
63 #include <netinet/pim_var.h>
64 #include <netinet/tcp.h>
65 #include <netinet/tcpip.h>
66 #include <netinet/tcp_seq.h>
67 #define TCPSTATES
68 #include <netinet/tcp_fsm.h>
69 #define TCPTIMERS
70 #include <netinet/tcp_timer.h>
71 #include <netinet/tcp_var.h>
72 #include <netinet/tcp_debug.h>
73 #include <netinet/udp.h>
74 #include <netinet/udp_var.h>
75
76 #include <arpa/inet.h>
77 #include <kvm.h>
78 #include <netdb.h>
79 #include <stdio.h>
80 #include <string.h>
81 #include <unistd.h>
82 #include "netstat.h"
83
84 struct inpcb inpcb;
85 struct tcpcb tcpcb;
86 struct socket sockb;
87
88 char *inetname __P((struct in_addr *));
89 void inetprint __P((struct in_addr *, u_int16_t, const char *, int));
90
91 /*
92 * Print a summary of connections related to an Internet
93 * protocol. For TCP, also give state of connection.
94 * Listening processes (aflag) are suppressed unless the
95 * -a (all) flag is specified.
96 */
97 static int width;
98
99 void
100 protopr(off, name)
101 u_long off;
102 char *name;
103 {
104 struct inpcbtable table;
105 struct inpcb *head, *next, *prev;
106 struct inpcb inpcb;
107 int istcp, compact;
108 static int first = 1;
109 static char *shorttcpstates[] = {
110 "CLOSED", "LISTEN", "SYNSEN", "SYSRCV",
111 "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG",
112 "LASTAK", "FWAIT2", "TMWAIT",
113 };
114
115 if (off == 0)
116 return;
117 istcp = strcmp(name, "tcp") == 0;
118 kread(off, (char *)&table, sizeof table);
119 prev = head =
120 (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
121 next = (struct inpcb *)table.inpt_queue.cqh_first;
122
123 compact = 0;
124 if (Aflag) {
125 if (!numeric_addr)
126 width = 18;
127 else {
128 width = 21;
129 compact = 1;
130 }
131 } else
132 width = 22;
133 while (next != head) {
134 kread((u_long)next, (char *)&inpcb, sizeof inpcb);
135 if ((struct inpcb *)inpcb.inp_queue.cqe_prev != prev) {
136 printf("???\n");
137 break;
138 }
139 prev = next;
140 next = (struct inpcb *)inpcb.inp_queue.cqe_next;
141
142 if (inpcb.inp_af != AF_INET)
143 continue;
144
145 if (!aflag &&
146 inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
147 continue;
148 kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
149 if (istcp) {
150 kread((u_long)inpcb.inp_ppcb,
151 (char *)&tcpcb, sizeof (tcpcb));
152 }
153 if (first) {
154 printf("Active Internet connections");
155 if (aflag)
156 printf(" (including servers)");
157 putchar('\n');
158 if (Aflag)
159 printf("%-8.8s ", "PCB");
160 printf("%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n",
161 "Proto", "Recv-Q", "Send-Q",
162 compact ? "" : " ",
163 width, width, "Local Address",
164 width, width, "Foreign Address", "State");
165 first = 0;
166 }
167 if (Aflag) {
168 if (istcp)
169 printf("%8lx ", (u_long) inpcb.inp_ppcb);
170 else
171 printf("%8lx ", (u_long) prev);
172 }
173 printf("%-5.5s %6ld %6ld%s", name, sockb.so_rcv.sb_cc,
174 sockb.so_snd.sb_cc, compact ? "" : " ");
175 if (numeric_port) {
176 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name, 1);
177 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name, 1);
178 } else if (inpcb.inp_flags & INP_ANONPORT) {
179 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name, 1);
180 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name, 0);
181 } else {
182 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name, 0);
183 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name, 0);
184 }
185 if (istcp) {
186 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
187 printf(" %d", tcpcb.t_state);
188 else
189 printf(" %s", compact ?
190 shorttcpstates[tcpcb.t_state] :
191 tcpstates[tcpcb.t_state]);
192 }
193 putchar('\n');
194 }
195 }
196
197 /*
198 * Dump TCP statistics structure.
199 */
200 void
201 tcp_stats(off, name)
202 u_long off;
203 char *name;
204 {
205 struct tcpstat tcpstat;
206
207 if (off == 0)
208 return;
209 printf ("%s:\n", name);
210 kread(off, (char *)&tcpstat, sizeof (tcpstat));
211
212 #define ps(f, m) if (tcpstat.f || sflag <= 1) \
213 printf(m, (unsigned long long)tcpstat.f)
214 #define p(f, m) if (tcpstat.f || sflag <= 1) \
215 printf(m, (unsigned long long)tcpstat.f, plural(tcpstat.f))
216 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
217 printf(m, (unsigned long long)tcpstat.f1, plural(tcpstat.f1), \
218 (unsigned long long)tcpstat.f2, plural(tcpstat.f2))
219 #define p2s(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
220 printf(m, (unsigned long long)tcpstat.f1, plural(tcpstat.f1), \
221 (unsigned long long)tcpstat.f2)
222 #define p3(f, m) if (tcpstat.f || sflag <= 1) \
223 printf(m, (unsigned long long)tcpstat.f, plurales(tcpstat.f))
224
225 p(tcps_sndtotal, "\t%llu packet%s sent\n");
226 p2(tcps_sndpack,tcps_sndbyte,
227 "\t\t%llu data packet%s (%llu byte%s)\n");
228 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
229 "\t\t%llu data packet%s (%llu byte%s) retransmitted\n");
230 p2s(tcps_sndacks, tcps_delack,
231 "\t\t%llu ack-only packet%s (%llu delayed)\n");
232 p(tcps_sndurg, "\t\t%llu URG only packet%s\n");
233 p(tcps_sndprobe, "\t\t%llu window probe packet%s\n");
234 p(tcps_sndwinup, "\t\t%llu window update packet%s\n");
235 p(tcps_sndctrl, "\t\t%llu control packet%s\n");
236 p(tcps_selfquench,
237 "\t\t%llu send attempt%s resulted in self-quench\n");
238 p(tcps_rcvtotal, "\t%llu packet%s received\n");
239 p2(tcps_rcvackpack, tcps_rcvackbyte,
240 "\t\t%llu ack%s (for %llu byte%s)\n");
241 p(tcps_rcvdupack, "\t\t%llu duplicate ack%s\n");
242 p(tcps_rcvacktoomuch, "\t\t%llu ack%s for unsent data\n");
243 p2(tcps_rcvpack, tcps_rcvbyte,
244 "\t\t%llu packet%s (%llu byte%s) received in-sequence\n");
245 p2(tcps_rcvduppack, tcps_rcvdupbyte,
246 "\t\t%llu completely duplicate packet%s (%llu byte%s)\n");
247 p(tcps_pawsdrop, "\t\t%llu old duplicate packet%s\n");
248 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
249 "\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n");
250 p2(tcps_rcvoopack, tcps_rcvoobyte,
251 "\t\t%llu out-of-order packet%s (%llu byte%s)\n");
252 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
253 "\t\t%llu packet%s (%llu byte%s) of data after window\n");
254 p(tcps_rcvwinprobe, "\t\t%llu window probe%s\n");
255 p(tcps_rcvwinupd, "\t\t%llu window update packet%s\n");
256 p(tcps_rcvafterclose, "\t\t%llu packet%s received after close\n");
257 p(tcps_rcvbadsum, "\t\t%llu discarded for bad checksum%s\n");
258 p(tcps_rcvbadoff, "\t\t%llu discarded for bad header offset field%s\n");
259 ps(tcps_rcvshort, "\t\t%llu discarded because packet too short\n");
260 p(tcps_connattempt, "\t%llu connection request%s\n");
261 p(tcps_accepts, "\t%llu connection accept%s\n");
262 p(tcps_connects,
263 "\t%llu connection%s established (including accepts)\n");
264 p2(tcps_closed, tcps_drops,
265 "\t%llu connection%s closed (including %llu drop%s)\n");
266 p(tcps_conndrops, "\t%llu embryonic connection%s dropped\n");
267 p(tcps_delayed_free, "\t%llu delayed free%s of tcpcb\n");
268 p2(tcps_rttupdated, tcps_segstimed,
269 "\t%llu segment%s updated rtt (of %llu attempt%s)\n");
270 p(tcps_rexmttimeo, "\t%llu retransmit timeout%s\n");
271 p(tcps_timeoutdrop,
272 "\t\t%llu connection%s dropped by rexmit timeout\n");
273 p2(tcps_persisttimeo, tcps_persistdrops,
274 "\t%llu persist timeout%s (resulting in %llu dropped "
275 "connection%s)\n");
276 p(tcps_keeptimeo, "\t%llu keepalive timeout%s\n");
277 p(tcps_keepprobe, "\t\t%llu keepalive probe%s sent\n");
278 p(tcps_keepdrops, "\t\t%llu connection%s dropped by keepalive\n");
279 p(tcps_predack, "\t%llu correct ACK header prediction%s\n");
280 p(tcps_preddat, "\t%llu correct data packet header prediction%s\n");
281 p3(tcps_pcbhashmiss, "\t%llu PCB hash miss%s\n");
282 ps(tcps_noport, "\t%llu dropped due to no socket\n");
283 p(tcps_connsdrained, "\t%llu connection%s drained due to memory "
284 "shortage\n");
285 p(tcps_pmtublackhole, "\t%llu PMTUD blackhole%s detected\n");
286
287 p(tcps_badsyn, "\t%llu bad connection attempt%s\n");
288 ps(tcps_sc_added, "\t%llu SYN cache entries added\n");
289 p(tcps_sc_collisions, "\t\t%llu hash collision%s\n");
290 ps(tcps_sc_completed, "\t\t%llu completed\n");
291 ps(tcps_sc_aborted, "\t\t%llu aborted (no space to build PCB)\n");
292 ps(tcps_sc_timed_out, "\t\t%llu timed out\n");
293 ps(tcps_sc_overflowed, "\t\t%llu dropped due to overflow\n");
294 ps(tcps_sc_bucketoverflow, "\t\t%llu dropped due to bucket overflow\n");
295 ps(tcps_sc_reset, "\t\t%llu dropped due to RST\n");
296 ps(tcps_sc_unreach, "\t\t%llu dropped due to ICMP unreachable\n");
297 ps(tcps_sc_delayed_free, "\t\t%llu delayed free of SYN cache "
298 "entries\n");
299 p(tcps_sc_retransmitted, "\t%llu SYN,ACK%s retransmitted\n");
300 p(tcps_sc_dupesyn, "\t%llu duplicate SYN%s received for entries "
301 "already in the cache\n");
302 p(tcps_sc_dropped, "\t%llu SYN%s dropped (no route or no space)\n");
303 p(tcps_badsig, "\t%llu packet%s with bad signature\n");
304 p(tcps_goodsig, "\t%llu packet%s with good signature\n");
305
306 #undef p
307 #undef ps
308 #undef p2
309 #undef p2s
310 #undef p3
311 }
312
313 /*
314 * Dump UDP statistics structure.
315 */
316 void
317 udp_stats(off, name)
318 u_long off;
319 char *name;
320 {
321 struct udpstat udpstat;
322 u_quad_t delivered;
323
324 if (off == 0)
325 return;
326 printf("%s:\n", name);
327 kread(off, (char *)&udpstat, sizeof (udpstat));
328
329 #define ps(f, m) if (udpstat.f || sflag <= 1) \
330 printf(m, (unsigned long long)udpstat.f)
331 #define p(f, m) if (udpstat.f || sflag <= 1) \
332 printf(m, (unsigned long long)udpstat.f, plural(udpstat.f))
333 #define p3(f, m) if (udpstat.f || sflag <= 1) \
334 printf(m, (unsigned long long)udpstat.f, plurales(udpstat.f))
335
336 p(udps_ipackets, "\t%llu datagram%s received\n");
337 ps(udps_hdrops, "\t%llu with incomplete header\n");
338 ps(udps_badlen, "\t%llu with bad data length field\n");
339 ps(udps_badsum, "\t%llu with bad checksum\n");
340 ps(udps_noport, "\t%llu dropped due to no socket\n");
341 p(udps_noportbcast, "\t%llu broadcast/multicast datagram%s dropped due to no socket\n");
342 ps(udps_fullsock, "\t%llu dropped due to full socket buffers\n");
343 delivered = udpstat.udps_ipackets -
344 udpstat.udps_hdrops -
345 udpstat.udps_badlen -
346 udpstat.udps_badsum -
347 udpstat.udps_noport -
348 udpstat.udps_noportbcast -
349 udpstat.udps_fullsock;
350 if (delivered || sflag <= 1)
351 printf("\t%llu delivered\n", (unsigned long long)delivered);
352 p3(udps_pcbhashmiss, "\t%llu PCB hash miss%s\n");
353 p(udps_opackets, "\t%llu datagram%s output\n");
354
355 #undef ps
356 #undef p
357 #undef p3
358 }
359
360 /*
361 * Dump IP statistics structure.
362 */
363 void
364 ip_stats(off, name)
365 u_long off;
366 char *name;
367 {
368 struct ipstat ipstat;
369
370 if (off == 0)
371 return;
372 kread(off, (char *)&ipstat, sizeof (ipstat));
373 printf("%s:\n", name);
374
375 #define ps(f, m) if (ipstat.f || sflag <= 1) \
376 printf(m, (unsigned long long)ipstat.f)
377 #define p(f, m) if (ipstat.f || sflag <= 1) \
378 printf(m, (unsigned long long)ipstat.f, plural(ipstat.f))
379
380 p(ips_total, "\t%llu total packet%s received\n");
381 p(ips_badsum, "\t%llu bad header checksum%s\n");
382 ps(ips_toosmall, "\t%llu with size smaller than minimum\n");
383 ps(ips_tooshort, "\t%llu with data size < data length\n");
384 ps(ips_toolong, "\t%llu with length > max ip packet size\n");
385 ps(ips_badhlen, "\t%llu with header length < data size\n");
386 ps(ips_badlen, "\t%llu with data length < header length\n");
387 ps(ips_badoptions, "\t%llu with bad options\n");
388 ps(ips_badvers, "\t%llu with incorrect version number\n");
389 p(ips_fragments, "\t%llu fragment%s received\n");
390 p(ips_fragdropped, "\t%llu fragment%s dropped (dup or out of space)\n");
391 p(ips_rcvmemdrop, "\t%llu fragment%s dropped (out of ipqent)\n");
392 p(ips_badfrags, "\t%llu malformed fragment%s dropped\n");
393 p(ips_fragtimeout, "\t%llu fragment%s dropped after timeout\n");
394 p(ips_reassembled, "\t%llu packet%s reassembled ok\n");
395 p(ips_delivered, "\t%llu packet%s for this host\n");
396 p(ips_noproto, "\t%llu packet%s for unknown/unsupported protocol\n");
397 p(ips_forward, "\t%llu packet%s forwarded");
398 p(ips_fastforward, " (%llu packet%s fast forwarded)");
399 if (ipstat.ips_forward || sflag <= 1)
400 putchar('\n');
401 p(ips_cantforward, "\t%llu packet%s not forwardable\n");
402 p(ips_redirectsent, "\t%llu redirect%s sent\n");
403 p(ips_nogif, "\t%llu packet%s no matching gif found\n");
404 p(ips_localout, "\t%llu packet%s sent from this host\n");
405 p(ips_rawout, "\t%llu packet%s sent with fabricated ip header\n");
406 p(ips_odropped, "\t%llu output packet%s dropped due to no bufs, etc.\n");
407 p(ips_noroute, "\t%llu output packet%s discarded due to no route\n");
408 p(ips_fragmented, "\t%llu output datagram%s fragmented\n");
409 p(ips_ofragments, "\t%llu fragment%s created\n");
410 p(ips_cantfrag, "\t%llu datagram%s that can't be fragmented\n");
411 p(ips_badaddr, "\t%llu datagram%s with bad address in header\n");
412 #undef ps
413 #undef p
414 }
415
416 static char *icmpnames[] = {
417 "echo reply",
418 "#1",
419 "#2",
420 "destination unreachable",
421 "source quench",
422 "routing redirect",
423 "alternate host address",
424 "#7",
425 "echo",
426 "router advertisement",
427 "router solicitation",
428 "time exceeded",
429 "parameter problem",
430 "time stamp",
431 "time stamp reply",
432 "information request",
433 "information request reply",
434 "address mask request",
435 "address mask reply",
436 };
437
438 /*
439 * Dump ICMP statistics.
440 */
441 void
442 icmp_stats(off, name)
443 u_long off;
444 char *name;
445 {
446 struct icmpstat icmpstat;
447 int i, first;
448
449 if (off == 0)
450 return;
451 kread(off, (char *)&icmpstat, sizeof (icmpstat));
452 printf("%s:\n", name);
453
454 #define p(f, m) if (icmpstat.f || sflag <= 1) \
455 printf(m, (unsigned long long)icmpstat.f, plural(icmpstat.f))
456
457 p(icps_error, "\t%llu call%s to icmp_error\n");
458 p(icps_oldicmp,
459 "\t%llu error%s not generated because old message was icmp\n");
460 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
461 if (icmpstat.icps_outhist[i] != 0) {
462 if (first) {
463 printf("\tOutput histogram:\n");
464 first = 0;
465 }
466 printf("\t\t%s: %llu\n", icmpnames[i],
467 (unsigned long long)icmpstat.icps_outhist[i]);
468 }
469 p(icps_badcode, "\t%llu message%s with bad code fields\n");
470 p(icps_tooshort, "\t%llu message%s < minimum length\n");
471 p(icps_checksum, "\t%llu bad checksum%s\n");
472 p(icps_badlen, "\t%llu message%s with bad length\n");
473 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
474 if (icmpstat.icps_inhist[i] != 0) {
475 if (first) {
476 printf("\tInput histogram:\n");
477 first = 0;
478 }
479 printf("\t\t%s: %llu\n", icmpnames[i],
480 (unsigned long long)icmpstat.icps_inhist[i]);
481 }
482 p(icps_reflect, "\t%llu message response%s generated\n");
483 p(icps_pmtuchg, "\t%llu path MTU change%s\n");
484 #undef p
485 }
486
487 /*
488 * Dump IGMP statistics structure.
489 */
490 void
491 igmp_stats(off, name)
492 u_long off;
493 char *name;
494 {
495 struct igmpstat igmpstat;
496
497 if (off == 0)
498 return;
499 kread(off, (char *)&igmpstat, sizeof (igmpstat));
500 printf("%s:\n", name);
501
502 #define p(f, m) if (igmpstat.f || sflag <= 1) \
503 printf(m, (unsigned long long)igmpstat.f, plural(igmpstat.f))
504 #define py(f, m) if (igmpstat.f || sflag <= 1) \
505 printf(m, (unsigned long long)igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
506 p(igps_rcv_total, "\t%llu message%s received\n");
507 p(igps_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
508 p(igps_rcv_badsum, "\t%llu message%s received with bad checksum\n");
509 py(igps_rcv_queries, "\t%llu membership quer%s received\n");
510 py(igps_rcv_badqueries, "\t%llu membership quer%s received with invalid field(s)\n");
511 p(igps_rcv_reports, "\t%llu membership report%s received\n");
512 p(igps_rcv_badreports, "\t%llu membership report%s received with invalid field(s)\n");
513 p(igps_rcv_ourreports, "\t%llu membership report%s received for groups to which we belong\n");
514 p(igps_snd_reports, "\t%llu membership report%s sent\n");
515 #undef p
516 #undef py
517 }
518
519 /*
520 * Dump PIM statistics structure.
521 */
522 void
523 pim_stats(off, name)
524 u_long off;
525 char *name;
526 {
527 struct pimstat pimstat;
528
529 if (off == 0)
530 return;
531 if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) {
532 /* XXX: PIM is probably not enabled in the kernel */
533 return;
534 }
535
536 printf("%s:\n", name);
537
538 #define p(f, m) if (pimstat.f || sflag <= 1) \
539 printf(m, (unsigned long long)pimstat.f, plural(pimstat.f))
540
541 p(pims_rcv_total_msgs, "\t%llu message%s received\n");
542 p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
543 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
544 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
545 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
546 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
547 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
548 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
549 p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
550 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
551 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
552 #undef p
553 }
554
555 /*
556 * Dump the ARP statistics structure.
557 */
558 void
559 arp_stats(off, name)
560 u_long off;
561 char *name;
562 {
563 struct arpstat arpstat;
564
565 if (off == 0)
566 return;
567 kread(off, (char *)&arpstat, sizeof (arpstat));
568 printf("%s:\n", name);
569
570 #define ps(f, m) if (arpstat.f || sflag <= 1) \
571 printf(m, (unsigned long long)arpstat.f)
572 #define p(f, m) if (arpstat.f || sflag <= 1) \
573 printf(m, (unsigned long long)arpstat.f, plural(arpstat.f))
574
575 p(as_sndtotal, "\t%llu packet%s sent\n");
576 p(as_sndreply, "\t\t%llu reply packet%s\n");
577 p(as_sndrequest, "\t\t%llu request packet%s\n");
578
579 p(as_rcvtotal, "\t%llu packet%s received\n");
580 p(as_rcvreply, "\t\t%llu reply packet%s\n");
581 p(as_rcvrequest, "\t\t%llu valid request packet%s\n");
582 p(as_rcvmcast, "\t\t%llu broadcast/multicast packet%s\n");
583 p(as_rcvbadproto, "\t\t%llu packet%s with unknown protocol type\n");
584 p(as_rcvbadlen, "\t\t%llu packet%s with bad (short) length\n");
585 p(as_rcvzerotpa, "\t\t%llu packet%s with null target IP address\n");
586 p(as_rcvzerospa, "\t\t%llu packet%s with null source IP address\n");
587 ps(as_rcvnoint, "\t\t%llu could not be mapped to an interface\n");
588 p(as_rcvlocalsha, "\t\t%llu packet%s sourced from a local hardware "
589 "address\n");
590 p(as_rcvbcastsha, "\t\t%llu packet%s with a broadcast "
591 "source hardware address\n");
592 p(as_rcvlocalspa, "\t\t%llu duplicate%s for a local IP address\n");
593 p(as_rcvoverperm, "\t\t%llu attempt%s to overwrite a static entry\n");
594 p(as_rcvoverint, "\t\t%llu packet%s received on wrong interface\n");
595 p(as_rcvover, "\t\t%llu entry%s overwritten\n");
596 p(as_rcvlenchg, "\t\t%llu change%s in hardware address length\n");
597
598 p(as_dfrtotal, "\t%llu packet%s deferred pending ARP resolution\n");
599 ps(as_dfrsent, "\t\t%llu sent\n");
600 ps(as_dfrdropped, "\t\t%llu dropped\n");
601
602 p(as_allocfail, "\t%llu failure%s to allocate llinfo\n");
603
604 #undef ps
605 #undef p
606 }
607
608 /*
609 * Pretty print an Internet address (net address + port).
610 * Take numeric_addr and numeric_port into consideration.
611 */
612 void
613 inetprint(in, port, proto, numeric_port)
614 struct in_addr *in;
615 u_int16_t port;
616 const char *proto;
617 int numeric_port;
618 {
619 struct servent *sp = 0;
620 char line[80], *cp;
621 size_t space;
622
623 (void)snprintf(line, sizeof line, "%.*s.",
624 (Aflag && !numeric_addr) ? 12 : 16, inetname(in));
625 cp = strchr(line, '\0');
626 if (!numeric_port && port)
627 sp = getservbyport((int)port, proto);
628 space = sizeof line - (cp-line);
629 if (sp || port == 0)
630 (void)snprintf(cp, space, "%s", sp ? sp->s_name : "*");
631 else
632 (void)snprintf(cp, space, "%u", ntohs(port));
633 (void)printf(" %-*.*s", width, width, line);
634 }
635
636 /*
637 * Construct an Internet address representation.
638 * If numeric_addr has been supplied, give
639 * numeric value, otherwise try for symbolic name.
640 */
641 char *
642 inetname(inp)
643 struct in_addr *inp;
644 {
645 char *cp;
646 static char line[50];
647 struct hostent *hp;
648 struct netent *np;
649 static char domain[MAXHOSTNAMELEN + 1];
650 static int first = 1;
651
652 if (first && !numeric_addr) {
653 first = 0;
654 if (gethostname(domain, sizeof domain) == 0) {
655 domain[sizeof(domain) - 1] = '\0';
656 if ((cp = strchr(domain, '.')))
657 (void) strlcpy(domain, cp + 1, sizeof(domain));
658 else
659 domain[0] = 0;
660 } else
661 domain[0] = 0;
662 }
663 cp = 0;
664 if (!numeric_addr && inp->s_addr != INADDR_ANY) {
665 int net = inet_netof(*inp);
666 int lna = inet_lnaof(*inp);
667
668 if (lna == INADDR_ANY) {
669 np = getnetbyaddr(net, AF_INET);
670 if (np)
671 cp = np->n_name;
672 }
673 if (cp == 0) {
674 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
675 if (hp) {
676 if ((cp = strchr(hp->h_name, '.')) &&
677 !strcmp(cp + 1, domain))
678 *cp = 0;
679 cp = hp->h_name;
680 }
681 }
682 }
683 if (inp->s_addr == INADDR_ANY)
684 strlcpy(line, "*", sizeof line);
685 else if (cp)
686 strlcpy(line, cp, sizeof line);
687 else {
688 inp->s_addr = ntohl(inp->s_addr);
689 #define C(x) ((x) & 0xff)
690 (void)snprintf(line, sizeof line, "%u.%u.%u.%u",
691 C(inp->s_addr >> 24), C(inp->s_addr >> 16),
692 C(inp->s_addr >> 8), C(inp->s_addr));
693 #undef C
694 }
695 return (line);
696 }
697
698 /*
699 * Dump the contents of a TCP PCB.
700 */
701 void
702 tcp_dump(pcbaddr)
703 u_long pcbaddr;
704 {
705 struct tcpcb tcpcb;
706 int i, hardticks;
707
708 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
709 hardticks = get_hardticks();
710
711 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
712
713 printf("Timers:\n");
714 for (i = 0; i < TCPT_NTIMERS; i++) {
715 printf("\t%s: %d", tcptimers[i],
716 (tcpcb.t_timer[i].c_flags & CALLOUT_PENDING) ?
717 tcpcb.t_timer[i].c_time - hardticks : 0);
718 }
719 printf("\n\n");
720
721 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
722 printf("State: %d", tcpcb.t_state);
723 else
724 printf("State: %s", tcpstates[tcpcb.t_state]);
725 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags,
726 (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb);
727
728 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
729 tcpcb.t_rxtcur, tcpcb.t_dupacks);
730 printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss,
731 tcpcb.t_ourmss, tcpcb.t_segsz);
732
733 printf("snd_una %u, snd_nxt %u, snd_up %u\n",
734 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
735 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
736 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
737
738 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
739 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
740
741 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
742 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
743
744 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
745 "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime,
746 tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin,
747 tcpcb.max_sndwnd);
748
749 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
750 tcpcb.t_iobc, tcpcb.t_softerror);
751
752 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
753 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
754 tcpcb.requested_s_scale);
755 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
756 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
757 }
758