inet.c revision 1.45 1 /* $NetBSD: inet.c,v 1.45 2001/04/06 05:10:28 itojun 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.45 2001/04/06 05:10:28 itojun 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 (!nflag)
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 (nflag) {
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,
183 inpcb.inp_lport != inpcb.inp_fport);
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_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 p2(tcps_rttupdated, tcps_segstimed,
266 "\t%llu segment%s updated rtt (of %llu attempt%s)\n");
267 p(tcps_rexmttimeo, "\t%llu retransmit timeout%s\n");
268 p(tcps_timeoutdrop,
269 "\t\t%llu connection%s dropped by rexmit timeout\n");
270 p2(tcps_persisttimeo, tcps_persistdrops,
271 "\t%llu persist timeout%s (resulting in %llu dropped "
272 "connection%s)\n");
273 p(tcps_keeptimeo, "\t%llu keepalive timeout%s\n");
274 p(tcps_keepprobe, "\t\t%llu keepalive probe%s sent\n");
275 p(tcps_keepdrops, "\t\t%llu connection%s dropped by keepalive\n");
276 p(tcps_predack, "\t%llu correct ACK header prediction%s\n");
277 p(tcps_preddat, "\t%llu correct data packet header prediction%s\n");
278 p3(tcps_pcbhashmiss, "\t%llu PCB hash miss%s\n");
279 ps(tcps_noport, "\t%llu dropped due to no socket\n");
280 p(tcps_connsdrained, "\t%llu connection%s drained due to memory "
281 "shortage\n");
282
283 p(tcps_badsyn, "\t%llu bad connection attempt%s\n");
284 ps(tcps_sc_added, "\t%llu SYN cache entries added\n");
285 p(tcps_sc_collisions, "\t\t%llu hash collision%s\n");
286 ps(tcps_sc_completed, "\t\t%llu completed\n");
287 ps(tcps_sc_aborted, "\t\t%llu aborted (no space to build PCB)\n");
288 ps(tcps_sc_timed_out, "\t\t%llu timed out\n");
289 ps(tcps_sc_overflowed, "\t\t%llu dropped due to overflow\n");
290 ps(tcps_sc_bucketoverflow, "\t\t%llu dropped due to bucket overflow\n");
291 ps(tcps_sc_reset, "\t\t%llu dropped due to RST\n");
292 ps(tcps_sc_unreach, "\t\t%llu dropped due to ICMP unreachable\n");
293 p(tcps_sc_retransmitted, "\t%llu SYN,ACK%s retransmitted\n");
294 p(tcps_sc_dupesyn, "\t%llu duplicate SYN%s received for entries "
295 "already in the cache\n");
296 p(tcps_sc_dropped, "\t%llu SYN%s dropped (no route or no space)\n");
297
298 #undef p
299 #undef ps
300 #undef p2
301 #undef p2s
302 #undef p3
303 }
304
305 /*
306 * Dump UDP statistics structure.
307 */
308 void
309 udp_stats(off, name)
310 u_long off;
311 char *name;
312 {
313 struct udpstat udpstat;
314 u_quad_t delivered;
315
316 if (off == 0)
317 return;
318 printf("%s:\n", name);
319 kread(off, (char *)&udpstat, sizeof (udpstat));
320
321 #define ps(f, m) if (udpstat.f || sflag <= 1) \
322 printf(m, (unsigned long long)udpstat.f)
323 #define p(f, m) if (udpstat.f || sflag <= 1) \
324 printf(m, (unsigned long long)udpstat.f, plural(udpstat.f))
325 #define p3(f, m) if (udpstat.f || sflag <= 1) \
326 printf(m, (unsigned long long)udpstat.f, plurales(udpstat.f))
327
328 p(udps_ipackets, "\t%llu datagram%s received\n");
329 ps(udps_hdrops, "\t%llu with incomplete header\n");
330 ps(udps_badlen, "\t%llu with bad data length field\n");
331 ps(udps_badsum, "\t%llu with bad checksum\n");
332 ps(udps_noport, "\t%llu dropped due to no socket\n");
333 p(udps_noportbcast, "\t%llu broadcast/multicast datagram%s dropped due to no socket\n");
334 ps(udps_fullsock, "\t%llu dropped due to full socket buffers\n");
335 delivered = udpstat.udps_ipackets -
336 udpstat.udps_hdrops -
337 udpstat.udps_badlen -
338 udpstat.udps_badsum -
339 udpstat.udps_noport -
340 udpstat.udps_noportbcast -
341 udpstat.udps_fullsock;
342 if (delivered || sflag <= 1)
343 printf("\t%llu delivered\n", (unsigned long long)delivered);
344 p3(udps_pcbhashmiss, "\t%llu PCB hash miss%s\n");
345 p(udps_opackets, "\t%llu datagram%s output\n");
346
347 #undef ps
348 #undef p
349 #undef p3
350 }
351
352 /*
353 * Dump IP statistics structure.
354 */
355 void
356 ip_stats(off, name)
357 u_long off;
358 char *name;
359 {
360 struct ipstat ipstat;
361
362 if (off == 0)
363 return;
364 kread(off, (char *)&ipstat, sizeof (ipstat));
365 printf("%s:\n", name);
366
367 #define ps(f, m) if (ipstat.f || sflag <= 1) \
368 printf(m, (unsigned long long)ipstat.f)
369 #define p(f, m) if (ipstat.f || sflag <= 1) \
370 printf(m, (unsigned long long)ipstat.f, plural(ipstat.f))
371
372 p(ips_total, "\t%llu total packet%s received\n");
373 p(ips_badsum, "\t%llu bad header checksum%s\n");
374 ps(ips_toosmall, "\t%llu with size smaller than minimum\n");
375 ps(ips_tooshort, "\t%llu with data size < data length\n");
376 ps(ips_toolong, "\t%llu with length > max ip packet size\n");
377 ps(ips_badhlen, "\t%llu with header length < data size\n");
378 ps(ips_badlen, "\t%llu with data length < header length\n");
379 ps(ips_badoptions, "\t%llu with bad options\n");
380 ps(ips_badvers, "\t%llu with incorrect version number\n");
381 p(ips_fragments, "\t%llu fragment%s received\n");
382 p(ips_fragdropped, "\t%llu fragment%s dropped (dup or out of space)\n");
383 p(ips_badfrags, "\t%llu malformed fragment%s dropped\n");
384 p(ips_fragtimeout, "\t%llu fragment%s dropped after timeout\n");
385 p(ips_reassembled, "\t%llu packet%s reassembled ok\n");
386 p(ips_delivered, "\t%llu packet%s for this host\n");
387 p(ips_noproto, "\t%llu packet%s for unknown/unsupported protocol\n");
388 p(ips_forward, "\t%llu packet%s forwarded");
389 p(ips_fastforward, " (%llu packet%s fast forwarded)");
390 if (ipstat.ips_forward || sflag <= 1)
391 putchar('\n');
392 p(ips_cantforward, "\t%llu packet%s not forwardable\n");
393 p(ips_redirectsent, "\t%llu redirect%s sent\n");
394 p(ips_localout, "\t%llu packet%s sent from this host\n");
395 p(ips_rawout, "\t%llu packet%s sent with fabricated ip header\n");
396 p(ips_odropped, "\t%llu output packet%s dropped due to no bufs, etc.\n");
397 p(ips_noroute, "\t%llu output packet%s discarded due to no route\n");
398 p(ips_fragmented, "\t%llu output datagram%s fragmented\n");
399 p(ips_ofragments, "\t%llu fragment%s created\n");
400 p(ips_cantfrag, "\t%llu datagram%s that can't be fragmented\n");
401 p(ips_badaddr, "\t%llu datagram%s with bad address in header\n");
402 #undef ps
403 #undef p
404 }
405
406 static char *icmpnames[] = {
407 "echo reply",
408 "#1",
409 "#2",
410 "destination unreachable",
411 "source quench",
412 "routing redirect",
413 "alternate host address",
414 "#7",
415 "echo",
416 "router advertisement",
417 "router solicitation",
418 "time exceeded",
419 "parameter problem",
420 "time stamp",
421 "time stamp reply",
422 "information request",
423 "information request reply",
424 "address mask request",
425 "address mask reply",
426 };
427
428 /*
429 * Dump ICMP statistics.
430 */
431 void
432 icmp_stats(off, name)
433 u_long off;
434 char *name;
435 {
436 struct icmpstat icmpstat;
437 int i, first;
438
439 if (off == 0)
440 return;
441 kread(off, (char *)&icmpstat, sizeof (icmpstat));
442 printf("%s:\n", name);
443
444 #define p(f, m) if (icmpstat.f || sflag <= 1) \
445 printf(m, (unsigned long long)icmpstat.f, plural(icmpstat.f))
446
447 p(icps_error, "\t%llu call%s to icmp_error\n");
448 p(icps_oldicmp,
449 "\t%llu error%s not generated because old message was icmp\n");
450 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
451 if (icmpstat.icps_outhist[i] != 0) {
452 if (first) {
453 printf("\tOutput histogram:\n");
454 first = 0;
455 }
456 printf("\t\t%s: %llu\n", icmpnames[i],
457 (unsigned long long)icmpstat.icps_outhist[i]);
458 }
459 p(icps_badcode, "\t%llu message%s with bad code fields\n");
460 p(icps_tooshort, "\t%llu message%s < minimum length\n");
461 p(icps_checksum, "\t%llu bad checksum%s\n");
462 p(icps_badlen, "\t%llu message%s with bad length\n");
463 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
464 if (icmpstat.icps_inhist[i] != 0) {
465 if (first) {
466 printf("\tInput histogram:\n");
467 first = 0;
468 }
469 printf("\t\t%s: %llu\n", icmpnames[i],
470 (unsigned long long)icmpstat.icps_inhist[i]);
471 }
472 p(icps_reflect, "\t%llu message response%s generated\n");
473 p(icps_pmtuchg, "\t%llu path MTU change%s\n");
474 #undef p
475 }
476
477 /*
478 * Dump IGMP statistics structure.
479 */
480 void
481 igmp_stats(off, name)
482 u_long off;
483 char *name;
484 {
485 struct igmpstat igmpstat;
486
487 if (off == 0)
488 return;
489 kread(off, (char *)&igmpstat, sizeof (igmpstat));
490 printf("%s:\n", name);
491
492 #define p(f, m) if (igmpstat.f || sflag <= 1) \
493 printf(m, (unsigned long long)igmpstat.f, plural(igmpstat.f))
494 #define py(f, m) if (igmpstat.f || sflag <= 1) \
495 printf(m, (unsigned long long)igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
496 p(igps_rcv_total, "\t%llu message%s received\n");
497 p(igps_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
498 p(igps_rcv_badsum, "\t%llu message%s received with bad checksum\n");
499 py(igps_rcv_queries, "\t%llu membership quer%s received\n");
500 py(igps_rcv_badqueries, "\t%llu membership quer%s received with invalid field(s)\n");
501 p(igps_rcv_reports, "\t%llu membership report%s received\n");
502 p(igps_rcv_badreports, "\t%llu membership report%s received with invalid field(s)\n");
503 p(igps_rcv_ourreports, "\t%llu membership report%s received for groups to which we belong\n");
504 p(igps_snd_reports, "\t%llu membership report%s sent\n");
505 #undef p
506 #undef py
507 }
508
509 /*
510 * Dump the ARP statistics structure.
511 */
512 void
513 arp_stats(off, name)
514 u_long off;
515 char *name;
516 {
517 struct arpstat arpstat;
518
519 if (off == 0)
520 return;
521 kread(off, (char *)&arpstat, sizeof (arpstat));
522 printf("%s:\n", name);
523
524 #define ps(f, m) if (arpstat.f || sflag <= 1) \
525 printf(m, (unsigned long long)arpstat.f)
526 #define p(f, m) if (arpstat.f || sflag <= 1) \
527 printf(m, (unsigned long long)arpstat.f, plural(arpstat.f))
528
529 p(as_sndtotal, "\t%llu packet%s sent\n");
530 p(as_sndreply, "\t\t%llu reply packet%s\n");
531 p(as_sndrequest, "\t\t%llu request packet%s\n");
532
533 p(as_rcvtotal, "\t%llu packet%s received\n");
534 p(as_rcvreply, "\t\t%llu reply packet%s\n");
535 p(as_rcvrequest, "\t\t%llu valid request packet%s\n");
536 p(as_rcvmcast, "\t\t%llu broadcast/multicast packet%s\n");
537 p(as_rcvbadproto, "\t\t%llu packet%s with unknown protocol type\n");
538 p(as_rcvbadlen, "\t\t%llu packet%s with bad (short) length\n");
539 p(as_rcvzerotpa, "\t\t%llu packet%s with null target IP address\n");
540 p(as_rcvzerospa, "\t\t%llu packet%s with null source IP address\n");
541 ps(as_rcvnoint, "\t\t%llu could not be mapped to an interface\n");
542 p(as_rcvlocalsha, "\t\t%llu packet%s sourced from a local hardware "
543 "address\n");
544 p(as_rcvbcastsha, "\t\t%llu packet%s with a broadcast "
545 "source hardware address\n");
546 p(as_rcvlocalspa, "\t\t%llu duplicate%s for a local IP address\n");
547 p(as_rcvoverperm, "\t\t%llu attempt%s to overwrite a static entry\n");
548 p(as_rcvoverint, "\t\t%llu packet%s received on wrong interface\n");
549 p(as_rcvover, "\t\t%llu entry%s overwritten\n");
550 p(as_rcvlenchg, "\t\t%llu change%s in hardware address length\n");
551
552 p(as_dfrtotal, "\t%llu packet%s deferred pending ARP resolution\n");
553 ps(as_dfrsent, "\t\t%llu sent\n");
554 ps(as_dfrdropped, "\t\t%llu dropped\n");
555
556 p(as_allocfail, "\t%llu failure%s to allocate llinfo\n");
557
558 #undef ps
559 #undef p
560 }
561
562 /*
563 * Pretty print an Internet address (net address + port).
564 * If the nflag was specified, use numbers instead of names.
565 */
566 void
567 inetprint(in, port, proto, numeric)
568 struct in_addr *in;
569 u_int16_t port;
570 const char *proto;
571 int numeric;
572 {
573 struct servent *sp = 0;
574 char line[80], *cp;
575 size_t space;
576
577 (void)snprintf(line, sizeof line, "%.*s.",
578 (Aflag && !nflag) ? 12 : 16, inetname(in));
579 cp = strchr(line, '\0');
580 if (!numeric && port)
581 sp = getservbyport((int)port, proto);
582 space = sizeof line - (cp-line);
583 if (sp || port == 0)
584 (void)snprintf(cp, space, "%.8s", sp ? sp->s_name : "*");
585 else
586 (void)snprintf(cp, space, "%u", ntohs(port));
587 (void)printf(" %-*.*s", width, width, line);
588 }
589
590 /*
591 * Construct an Internet address representation.
592 * If the nflag has been supplied, give
593 * numeric value, otherwise try for symbolic name.
594 */
595 char *
596 inetname(inp)
597 struct in_addr *inp;
598 {
599 char *cp;
600 static char line[50];
601 struct hostent *hp;
602 struct netent *np;
603 static char domain[MAXHOSTNAMELEN + 1];
604 static int first = 1;
605
606 if (first && !nflag) {
607 first = 0;
608 if (gethostname(domain, sizeof domain) == 0) {
609 domain[sizeof(domain) - 1] = '\0';
610 if ((cp = strchr(domain, '.')))
611 (void) strlcpy(domain, cp + 1, sizeof(domain));
612 else
613 domain[0] = 0;
614 } else
615 domain[0] = 0;
616 }
617 cp = 0;
618 if (!nflag && inp->s_addr != INADDR_ANY) {
619 int net = inet_netof(*inp);
620 int lna = inet_lnaof(*inp);
621
622 if (lna == INADDR_ANY) {
623 np = getnetbyaddr(net, AF_INET);
624 if (np)
625 cp = np->n_name;
626 }
627 if (cp == 0) {
628 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
629 if (hp) {
630 if ((cp = strchr(hp->h_name, '.')) &&
631 !strcmp(cp + 1, domain))
632 *cp = 0;
633 cp = hp->h_name;
634 }
635 }
636 }
637 if (inp->s_addr == INADDR_ANY)
638 strncpy(line, "*", sizeof line);
639 else if (cp)
640 strncpy(line, cp, sizeof line);
641 else {
642 inp->s_addr = ntohl(inp->s_addr);
643 #define C(x) ((x) & 0xff)
644 (void)snprintf(line, sizeof line, "%u.%u.%u.%u",
645 C(inp->s_addr >> 24), C(inp->s_addr >> 16),
646 C(inp->s_addr >> 8), C(inp->s_addr));
647 #undef C
648 }
649 line[sizeof(line) - 1] = '\0';
650 return (line);
651 }
652
653 /*
654 * Dump the contents of a TCP PCB.
655 */
656 void
657 tcp_dump(pcbaddr)
658 u_long pcbaddr;
659 {
660 struct tcpcb tcpcb;
661 int i;
662
663 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
664
665 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
666
667 printf("Timers:\n");
668 for (i = 0; i < TCPT_NTIMERS; i++)
669 printf("\t%s: %u", tcptimers[i], tcpcb.t_timer[i]);
670 printf("\n\n");
671
672 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
673 printf("State: %d", tcpcb.t_state);
674 else
675 printf("State: %s", tcpstates[tcpcb.t_state]);
676 printf(", flags 0x%x, inpcb 0x%lx\n\n", tcpcb.t_flags,
677 (u_long)tcpcb.t_inpcb);
678
679 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
680 tcpcb.t_rxtcur, tcpcb.t_dupacks);
681 printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss,
682 tcpcb.t_ourmss, tcpcb.t_segsz);
683
684 printf("snd_una %u, snd_nxt %u, snd_up %u\n",
685 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
686 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
687 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
688
689 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
690 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
691
692 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
693 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
694
695 printf("idle %d, rtt %d, rtseq %u, srtt %d, rttvar %d, rttmin %d, "
696 "max_sndwnd %lu\n\n", tcpcb.t_idle, tcpcb.t_rtt, tcpcb.t_rtseq,
697 tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin, tcpcb.max_sndwnd);
698
699 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
700 tcpcb.t_iobc, tcpcb.t_softerror);
701
702 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
703 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
704 tcpcb.requested_s_scale);
705 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
706 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
707 }
708