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