temp files should be protected; bug report 4.3BSD/usr.bin/186
[unix-history] / usr / src / usr.bin / netstat / inet.c
CommitLineData
5ff67f98 1/*
b36fc510 2 * Copyright (c) 1983, 1988 Regents of the University of California.
ee3f90a5
MK
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
b36fc510
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
5ff67f98
DF
16 */
17
c7fc5288 18#ifndef lint
b36fc510
KB
19static char sccsid[] = "@(#)inet.c 5.11 (Berkeley) %G%";
20#endif /* not lint */
c7fc5288 21
f7c99b06
MK
22#include <strings.h>
23#include <stdio.h>
24
6c5bed6c 25#include <sys/param.h>
c7fc5288
SL
26#include <sys/socket.h>
27#include <sys/socketvar.h>
28#include <sys/mbuf.h>
29#include <sys/protosw.h>
44906619 30
c7fc5288 31#include <net/route.h>
44906619
SL
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/in_pcb.h>
35#include <netinet/ip.h>
36#include <netinet/ip_icmp.h>
7333c75b 37#include <netinet/icmp_var.h>
44906619
SL
38#include <netinet/ip_var.h>
39#include <netinet/tcp.h>
40#include <netinet/tcpip.h>
41#include <netinet/tcp_seq.h>
c7fc5288 42#define TCPSTATES
44906619
SL
43#include <netinet/tcp_fsm.h>
44#include <netinet/tcp_timer.h>
45#include <netinet/tcp_var.h>
46#include <netinet/tcp_debug.h>
47#include <netinet/udp.h>
48#include <netinet/udp_var.h>
49
c7fc5288
SL
50#include <netdb.h>
51
52struct inpcb inpcb;
53struct tcpcb tcpcb;
cab3a575 54struct socket sockb;
c7fc5288
SL
55extern int kmem;
56extern int Aflag;
57extern int aflag;
58extern int nflag;
f7c99b06 59extern char *plural();
c7fc5288 60
c7fc5288
SL
61char *inetname();
62
63/*
64 * Print a summary of connections related to an Internet
65 * protocol. For TCP, also give state of connection.
66 * Listening processes (aflag) are suppressed unless the
67 * -a (all) flag is specified.
68 */
69protopr(off, name)
70 off_t off;
71 char *name;
72{
73 struct inpcb cb;
74 register struct inpcb *prev, *next;
75 int istcp;
f7c99b06 76 static int first = 1;
c7fc5288 77
a960d94f 78 if (off == 0)
c7fc5288 79 return;
c7fc5288
SL
80 istcp = strcmp(name, "tcp") == 0;
81 klseek(kmem, off, 0);
f7c99b06 82 read(kmem, (char *)&cb, sizeof (struct inpcb));
c7fc5288
SL
83 inpcb = cb;
84 prev = (struct inpcb *)off;
a960d94f
MK
85 if (inpcb.inp_next == (struct inpcb *)off)
86 return;
c7fc5288 87 while (inpcb.inp_next != (struct inpcb *)off) {
c7fc5288
SL
88
89 next = inpcb.inp_next;
90 klseek(kmem, (off_t)next, 0);
f7c99b06 91 read(kmem, (char *)&inpcb, sizeof (inpcb));
c7fc5288
SL
92 if (inpcb.inp_prev != prev) {
93 printf("???\n");
94 break;
95 }
96 if (!aflag &&
f7c99b06 97 inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) {
c7fc5288
SL
98 prev = next;
99 continue;
100 }
101 klseek(kmem, (off_t)inpcb.inp_socket, 0);
f7c99b06 102 read(kmem, (char *)&sockb, sizeof (sockb));
c7fc5288
SL
103 if (istcp) {
104 klseek(kmem, (off_t)inpcb.inp_ppcb, 0);
f7c99b06 105 read(kmem, (char *)&tcpcb, sizeof (tcpcb));
c7fc5288 106 }
a960d94f
MK
107 if (first) {
108 printf("Active Internet connections");
109 if (aflag)
110 printf(" (including servers)");
111 putchar('\n');
112 if (Aflag)
113 printf("%-8.8s ", "PCB");
114 printf(Aflag ?
115 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
116 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
117 "Proto", "Recv-Q", "Send-Q",
118 "Local Address", "Foreign Address", "(state)");
119 first = 0;
120 }
c7fc5288 121 if (Aflag)
a960d94f
MK
122 if (istcp)
123 printf("%8x ", inpcb.inp_ppcb);
124 else
125 printf("%8x ", next);
cab3a575
MK
126 printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc,
127 sockb.so_snd.sb_cc);
c7fc5288
SL
128 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name);
129 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name);
130 if (istcp) {
131 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
132 printf(" %d", tcpcb.t_state);
133 else
134 printf(" %s", tcpstates[tcpcb.t_state]);
135 }
136 putchar('\n');
137 prev = next;
138 }
139}
140
6df0a927
SL
141/*
142 * Dump TCP statistics structure.
143 */
144tcp_stats(off, name)
145 off_t off;
146 char *name;
147{
148 struct tcpstat tcpstat;
149
a960d94f 150 if (off == 0)
6df0a927 151 return;
49a4dfd4 152 printf ("%s:\n", name);
6df0a927
SL
153 klseek(kmem, off, 0);
154 read(kmem, (char *)&tcpstat, sizeof (tcpstat));
49a4dfd4 155
01052009
KB
156#define p(f, m) printf(m, tcpstat.f, plural(tcpstat.f))
157#define p2(f1, f2, m) printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
158
159 p(tcps_sndtotal, "\t%d packet%s sent\n");
160 p2(tcps_sndpack,tcps_sndbyte,
161 "\t\t%d data packet%s (%d byte%s)\n");
162 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
163 "\t\t%d data packet%s (%d byte%s) retransmitted\n");
164 p2(tcps_sndacks, tcps_delack,
165 "\t\t%d ack-only packet%s (%d delayed)\n");
166 p(tcps_sndurg, "\t\t%d URG only packet%s\n");
167 p(tcps_sndprobe, "\t\t%d window probe packet%s\n");
168 p(tcps_sndwinup, "\t\t%d window update packet%s\n");
169 p(tcps_sndctrl, "\t\t%d control packet%s\n");
170 p(tcps_rcvtotal, "\t%d packet%s received\n");
171 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%d ack%s (for %d byte%s)\n");
172 p(tcps_rcvdupack, "\t\t%d duplicate ack%s\n");
173 p(tcps_rcvacktoomuch, "\t\t%d ack%s for unsent data\n");
174 p2(tcps_rcvpack, tcps_rcvbyte,
175 "\t\t%d packet%s (%d byte%s) received in-sequence\n");
176 p2(tcps_rcvduppack, tcps_rcvdupbyte,
177 "\t\t%d completely duplicate packet%s (%d byte%s)\n");
178 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
179 "\t\t%d packet%s with some dup. data (%d byte%s duped)\n");
180 p2(tcps_rcvoopack, tcps_rcvoobyte,
181 "\t\t%d out-of-order packet%s (%d byte%s)\n");
182 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
183 "\t\t%d packet%s (%d byte%s) of data after window\n");
184 p(tcps_rcvwinprobe, "\t\t%d window probe%s\n");
185 p(tcps_rcvwinupd, "\t\t%d window update packet%s\n");
186 p(tcps_rcvafterclose, "\t\t%d packet%s received after close\n");
187 p(tcps_rcvbadsum, "\t\t%d discarded for bad checksum%s\n");
188 p(tcps_rcvbadoff, "\t\t%d discarded for bad header offset field%s\n");
189 p(tcps_rcvshort, "\t\t%d discarded because packet too short\n");
190 p(tcps_connattempt, "\t%d connection request%s\n");
191 p(tcps_accepts, "\t%d connection accept%s\n");
192 p(tcps_connects, "\t%d connection%s established (including accepts)\n");
193 p2(tcps_closed, tcps_drops,
194 "\t%d connection%s closed (including %d drop%s)\n");
195 p(tcps_conndrops, "\t%d embryonic connection%s dropped\n");
196 p2(tcps_rttupdated, tcps_segstimed,
197 "\t%d segment%s updated rtt (of %d attempt%s)\n");
198 p(tcps_rexmttimeo, "\t%d retransmit timeout%s\n");
199 p(tcps_timeoutdrop, "\t\t%d connection%s dropped by rexmit timeout\n");
200 p(tcps_persisttimeo, "\t%d persist timeout%s\n");
201 p(tcps_keeptimeo, "\t%d keepalive timeout%s\n");
202 p(tcps_keepprobe, "\t\t%d keepalive probe%s sent\n");
203 p(tcps_keepdrops, "\t\t%d connection%s dropped by keepalive\n");
49a4dfd4
MK
204#undef p
205#undef p2
6df0a927
SL
206}
207
208/*
209 * Dump UDP statistics structure.
210 */
211udp_stats(off, name)
212 off_t off;
213 char *name;
214{
215 struct udpstat udpstat;
216
a960d94f 217 if (off == 0)
6df0a927 218 return;
6df0a927
SL
219 klseek(kmem, off, 0);
220 read(kmem, (char *)&udpstat, sizeof (udpstat));
bd91d3f9 221 printf("%s:\n\t%u incomplete header%s\n", name,
d69a747c 222 udpstat.udps_hdrops, plural(udpstat.udps_hdrops));
bd91d3f9 223 printf("\t%u bad data length field%s\n",
d69a747c 224 udpstat.udps_badlen, plural(udpstat.udps_badlen));
bd91d3f9 225 printf("\t%u bad checksum%s\n",
a960d94f 226 udpstat.udps_badsum, plural(udpstat.udps_badsum));
37c1b971
MK
227#ifdef sun
228 printf("\t%d socket overflow%s\n",
229 udpstat.udps_fullsock, plural(udpstat.udps_fullsock));
230#endif
6df0a927
SL
231}
232
233/*
234 * Dump IP statistics structure.
235 */
236ip_stats(off, name)
237 off_t off;
238 char *name;
239{
240 struct ipstat ipstat;
241
a960d94f 242 if (off == 0)
6df0a927 243 return;
6df0a927
SL
244 klseek(kmem, off, 0);
245 read(kmem, (char *)&ipstat, sizeof (ipstat));
37c1b971 246#if BSD>=43
bd91d3f9 247 printf("%s:\n\t%u total packets received\n", name,
a960d94f 248 ipstat.ips_total);
37c1b971 249#endif
bd91d3f9 250 printf("\t%u bad header checksum%s\n",
d69a747c 251 ipstat.ips_badsum, plural(ipstat.ips_badsum));
bd91d3f9
SL
252 printf("\t%u with size smaller than minimum\n", ipstat.ips_tooshort);
253 printf("\t%u with data size < data length\n", ipstat.ips_toosmall);
254 printf("\t%u with header length < data size\n", ipstat.ips_badhlen);
255 printf("\t%u with data length < header length\n", ipstat.ips_badlen);
37c1b971 256#if BSD>=43
bd91d3f9 257 printf("\t%u fragment%s received\n",
a960d94f 258 ipstat.ips_fragments, plural(ipstat.ips_fragments));
bd91d3f9 259 printf("\t%u fragment%s dropped (dup or out of space)\n",
a960d94f 260 ipstat.ips_fragdropped, plural(ipstat.ips_fragdropped));
bd91d3f9 261 printf("\t%u fragment%s dropped after timeout\n",
a960d94f 262 ipstat.ips_fragtimeout, plural(ipstat.ips_fragtimeout));
bd91d3f9 263 printf("\t%u packet%s forwarded\n",
a960d94f 264 ipstat.ips_forward, plural(ipstat.ips_forward));
bd91d3f9 265 printf("\t%u packet%s not forwardable\n",
a960d94f 266 ipstat.ips_cantforward, plural(ipstat.ips_cantforward));
bd91d3f9 267 printf("\t%u redirect%s sent\n",
a960d94f 268 ipstat.ips_redirectsent, plural(ipstat.ips_redirectsent));
37c1b971 269#endif
6df0a927
SL
270}
271
7333c75b
SL
272static char *icmpnames[] = {
273 "echo reply",
274 "#1",
275 "#2",
276 "destination unreachable",
277 "source quench",
278 "routing redirect",
279 "#6",
280 "#7",
281 "echo",
282 "#9",
283 "#10",
284 "time exceeded",
285 "parameter problem",
286 "time stamp",
287 "time stamp reply",
288 "information request",
a960d94f
MK
289 "information request reply",
290 "address mask request",
291 "address mask reply",
7333c75b
SL
292};
293
294/*
295 * Dump ICMP statistics.
296 */
297icmp_stats(off, name)
298 off_t off;
299 char *name;
300{
301 struct icmpstat icmpstat;
302 register int i, first;
303
a960d94f 304 if (off == 0)
7333c75b 305 return;
7333c75b
SL
306 klseek(kmem, off, 0);
307 read(kmem, (char *)&icmpstat, sizeof (icmpstat));
bd91d3f9 308 printf("%s:\n\t%u call%s to icmp_error\n", name,
d69a747c 309 icmpstat.icps_error, plural(icmpstat.icps_error));
bd91d3f9 310 printf("\t%u error%s not generated 'cuz old message was icmp\n",
d69a747c 311 icmpstat.icps_oldicmp, plural(icmpstat.icps_oldicmp));
7dbb09e5 312 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
7333c75b
SL
313 if (icmpstat.icps_outhist[i] != 0) {
314 if (first) {
315 printf("\tOutput histogram:\n");
316 first = 0;
317 }
bd91d3f9 318 printf("\t\t%s: %u\n", icmpnames[i],
7333c75b
SL
319 icmpstat.icps_outhist[i]);
320 }
bd91d3f9 321 printf("\t%u message%s with bad code fields\n",
bdf25b53 322 icmpstat.icps_badcode, plural(icmpstat.icps_badcode));
bd91d3f9 323 printf("\t%u message%s < minimum length\n",
d69a747c 324 icmpstat.icps_tooshort, plural(icmpstat.icps_tooshort));
bd91d3f9 325 printf("\t%u bad checksum%s\n",
4fbbc6d9 326 icmpstat.icps_checksum, plural(icmpstat.icps_checksum));
bd91d3f9 327 printf("\t%u message%s with bad length\n",
d69a747c 328 icmpstat.icps_badlen, plural(icmpstat.icps_badlen));
7dbb09e5 329 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
7333c75b
SL
330 if (icmpstat.icps_inhist[i] != 0) {
331 if (first) {
332 printf("\tInput histogram:\n");
333 first = 0;
334 }
bd91d3f9 335 printf("\t\t%s: %u\n", icmpnames[i],
7333c75b
SL
336 icmpstat.icps_inhist[i]);
337 }
bd91d3f9 338 printf("\t%u message response%s generated\n",
a960d94f 339 icmpstat.icps_reflect, plural(icmpstat.icps_reflect));
7333c75b
SL
340}
341
c7fc5288
SL
342/*
343 * Pretty print an Internet address (net address + port).
344 * If the nflag was specified, use numbers instead of names.
345 */
346inetprint(in, port, proto)
347 register struct in_addr *in;
f7c99b06 348 u_short port;
c7fc5288
SL
349 char *proto;
350{
351 struct servent *sp = 0;
352 char line[80], *cp, *index();
f36bd7cf 353 int width;
c7fc5288 354
8e7710ba 355 sprintf(line, "%.*s.", (Aflag && !nflag) ? 12 : 16, inetname(*in));
c7fc5288 356 cp = index(line, '\0');
c7fc5288 357 if (!nflag && port)
f7c99b06 358 sp = getservbyport((int)port, proto);
c7fc5288
SL
359 if (sp || port == 0)
360 sprintf(cp, "%.8s", sp ? sp->s_name : "*");
361 else
1f34f70d 362 sprintf(cp, "%d", ntohs((u_short)port));
f36bd7cf
MK
363 width = Aflag ? 18 : 22;
364 printf(" %-*.*s", width, width, line);
c7fc5288
SL
365}
366
c7fc5288
SL
367/*
368 * Construct an Internet address representation.
369 * If the nflag has been supplied, give
370 * numeric value, otherwise try for symbolic name.
371 */
372char *
373inetname(in)
374 struct in_addr in;
375{
6c5bed6c 376 register char *cp;
c7fc5288 377 static char line[50];
f6d7bbb7
MK
378 struct hostent *hp;
379 struct netent *np;
6c5bed6c
MK
380 static char domain[MAXHOSTNAMELEN + 1];
381 static int first = 1;
c7fc5288 382
6c5bed6c
MK
383 if (first && !nflag) {
384 first = 0;
385 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
386 (cp = index(domain, '.')))
387 (void) strcpy(domain, cp + 1);
388 else
389 domain[0] = 0;
390 }
391 cp = 0;
227faf58 392 if (!nflag && in.s_addr != INADDR_ANY) {
cab3a575 393 int net = inet_netof(in);
f6d7bbb7 394 int lna = inet_lnaof(in);
227faf58 395
f6d7bbb7 396 if (lna == INADDR_ANY) {
40f48772 397 np = getnetbyaddr(net, AF_INET);
c7fc5288
SL
398 if (np)
399 cp = np->n_name;
cab3a575
MK
400 }
401 if (cp == 0) {
f7c99b06 402 hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
6c5bed6c
MK
403 if (hp) {
404 if ((cp = index(hp->h_name, '.')) &&
405 !strcmp(cp + 1, domain))
406 *cp = 0;
c7fc5288 407 cp = hp->h_name;
6c5bed6c 408 }
c7fc5288
SL
409 }
410 }
411 if (in.s_addr == INADDR_ANY)
412 strcpy(line, "*");
413 else if (cp)
414 strcpy(line, cp);
415 else {
cab3a575
MK
416 in.s_addr = ntohl(in.s_addr);
417#define C(x) ((x) & 0xff)
418 sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
419 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
c7fc5288
SL
420 }
421 return (line);
422}