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