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