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