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