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