changes from donn@utah-cs for common header file for pcc
[unix-history] / usr / src / usr.bin / netstat / inet.c
CommitLineData
c7fc5288 1#ifndef lint
f36bd7cf 2static char sccsid[] = "@(#)inet.c 4.18 (Berkeley) 84/10/31";
c7fc5288
SL
3#endif
4
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <sys/socketvar.h>
8#include <sys/mbuf.h>
9#include <sys/protosw.h>
44906619 10
c7fc5288 11#include <net/route.h>
44906619
SL
12#include <netinet/in.h>
13#include <netinet/in_systm.h>
14#include <netinet/in_pcb.h>
15#include <netinet/ip.h>
16#include <netinet/ip_icmp.h>
7333c75b 17#include <netinet/icmp_var.h>
44906619
SL
18#include <netinet/ip_var.h>
19#include <netinet/tcp.h>
20#include <netinet/tcpip.h>
21#include <netinet/tcp_seq.h>
c7fc5288 22#define TCPSTATES
44906619
SL
23#include <netinet/tcp_fsm.h>
24#include <netinet/tcp_timer.h>
25#include <netinet/tcp_var.h>
26#include <netinet/tcp_debug.h>
27#include <netinet/udp.h>
28#include <netinet/udp_var.h>
29
c7fc5288
SL
30#include <netdb.h>
31
32struct inpcb inpcb;
33struct tcpcb tcpcb;
34struct socket socket;
35struct protosw proto;
36extern int kmem;
37extern int Aflag;
38extern int aflag;
39extern int nflag;
40
41static int first = 1;
42char *inetname();
43
44/*
45 * Print a summary of connections related to an Internet
46 * protocol. For TCP, also give state of connection.
47 * Listening processes (aflag) are suppressed unless the
48 * -a (all) flag is specified.
49 */
50protopr(off, name)
51 off_t off;
52 char *name;
53{
54 struct inpcb cb;
55 register struct inpcb *prev, *next;
56 int istcp;
57
58 if (off == 0) {
59 printf("%s control block: symbol not in namelist\n", name);
60 return;
61 }
62 istcp = strcmp(name, "tcp") == 0;
63 klseek(kmem, off, 0);
64 read(kmem, &cb, sizeof (struct inpcb));
65 inpcb = cb;
66 prev = (struct inpcb *)off;
67 if (first) {
68 printf("Active connections");
69 if (aflag)
70 printf(" (including servers)");
71 putchar('\n');
72 if (Aflag)
73 printf("%-8.8s ", "PCB");
f36bd7cf
MK
74 printf(Aflag ? "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
75 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
c7fc5288
SL
76 "Proto", "Recv-Q", "Send-Q",
77 "Local Address", "Foreign Address", "(state)");
78 first = 0;
79 }
80 while (inpcb.inp_next != (struct inpcb *)off) {
81 char *cp;
82
83 next = inpcb.inp_next;
84 klseek(kmem, (off_t)next, 0);
85 read(kmem, &inpcb, sizeof (inpcb));
86 if (inpcb.inp_prev != prev) {
87 printf("???\n");
88 break;
89 }
90 if (!aflag &&
444a708d 91 inet_lnaof(inpcb.inp_laddr.s_addr) == INADDR_ANY) {
c7fc5288
SL
92 prev = next;
93 continue;
94 }
95 klseek(kmem, (off_t)inpcb.inp_socket, 0);
96 read(kmem, &socket, sizeof (socket));
97 if (istcp) {
98 klseek(kmem, (off_t)inpcb.inp_ppcb, 0);
99 read(kmem, &tcpcb, sizeof (tcpcb));
100 }
101 if (Aflag)
102 printf("%8x ", inpcb.inp_ppcb);
103 printf("%-5.5s %6d %6d ", name, socket.so_rcv.sb_cc,
104 socket.so_snd.sb_cc);
105 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name);
106 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name);
107 if (istcp) {
108 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
109 printf(" %d", tcpcb.t_state);
110 else
111 printf(" %s", tcpstates[tcpcb.t_state]);
112 }
113 putchar('\n');
114 prev = next;
115 }
116}
117
6df0a927
SL
118/*
119 * Dump TCP statistics structure.
120 */
121tcp_stats(off, name)
122 off_t off;
123 char *name;
124{
125 struct tcpstat tcpstat;
126
127 if (off == 0) {
128 printf("%sstat: symbol not in namelist\n", name);
129 return;
130 }
131 klseek(kmem, off, 0);
132 read(kmem, (char *)&tcpstat, sizeof (tcpstat));
d69a747c
SL
133 printf("%s:\n\t%d bad header checksum%s\n", name,
134 tcpstat.tcps_badsum, plural(tcpstat.tcps_badsum));
135 printf("\t%d bad header offset field%s\n",
136 tcpstat.tcps_badoff, plural(tcpstat.tcps_badoff));
137 printf("\t%d incomplete header%s\n",
138 tcpstat.tcps_hdrops, plural(tcpstat.tcps_hdrops));
6df0a927 139#ifdef notdef
d69a747c
SL
140 printf("\t%d bad segment%s\n",
141 tcpstat.tcps_badsegs, plural(tcpstat.badsegs));
142 printf("\t%d unacknowledged packet%s\n",
143 tcpstat.tcps_unack, plural(tcpstat.tcps_unack));
6df0a927
SL
144#endif
145}
146
147/*
148 * Dump UDP statistics structure.
149 */
150udp_stats(off, name)
151 off_t off;
152 char *name;
153{
154 struct udpstat udpstat;
155
156 if (off == 0) {
157 printf("%sstat: symbol not in namelist\n", name);
158 return;
159 }
160 klseek(kmem, off, 0);
161 read(kmem, (char *)&udpstat, sizeof (udpstat));
d69a747c
SL
162 printf("%s:\n\t%d bad header checksum%s\n", name,
163 udpstat.udps_badsum, plural(udpstat.udps_badsum));
164 printf("\t%d incomplete header%s\n",
165 udpstat.udps_hdrops, plural(udpstat.udps_hdrops));
166 printf("\t%d bad data length field%s\n",
167 udpstat.udps_badlen, plural(udpstat.udps_badlen));
6df0a927
SL
168}
169
170/*
171 * Dump IP statistics structure.
172 */
173ip_stats(off, name)
174 off_t off;
175 char *name;
176{
177 struct ipstat ipstat;
178
179 if (off == 0) {
180 printf("%sstat: symbol not in namelist\n", name);
181 return;
182 }
183 klseek(kmem, off, 0);
184 read(kmem, (char *)&ipstat, sizeof (ipstat));
d69a747c
SL
185 printf("%s:\n\t%d bad header checksum%s\n", name,
186 ipstat.ips_badsum, plural(ipstat.ips_badsum));
187 printf("\t%d with size smaller than minimum\n", ipstat.ips_tooshort);
188 printf("\t%d with data size < data length\n", ipstat.ips_toosmall);
189 printf("\t%d with header length < data size\n", ipstat.ips_badhlen);
190 printf("\t%d with data length < header length\n", ipstat.ips_badlen);
6df0a927
SL
191}
192
7333c75b
SL
193static char *icmpnames[] = {
194 "echo reply",
195 "#1",
196 "#2",
197 "destination unreachable",
198 "source quench",
199 "routing redirect",
200 "#6",
201 "#7",
202 "echo",
203 "#9",
204 "#10",
205 "time exceeded",
206 "parameter problem",
207 "time stamp",
208 "time stamp reply",
209 "information request",
210 "information request reply"
211};
212
213/*
214 * Dump ICMP statistics.
215 */
216icmp_stats(off, name)
217 off_t off;
218 char *name;
219{
220 struct icmpstat icmpstat;
221 register int i, first;
222
223 if (off == 0) {
224 printf("%sstat: symbol not in namelist\n", name);
225 return;
226 }
227 klseek(kmem, off, 0);
228 read(kmem, (char *)&icmpstat, sizeof (icmpstat));
d69a747c
SL
229 printf("%s:\n\t%d call%s to icmp_error\n", name,
230 icmpstat.icps_error, plural(icmpstat.icps_error));
231 printf("\t%d error%s not generated 'cuz old message too short\n",
232 icmpstat.icps_oldshort, plural(icmpstat.icps_oldshort));
233 printf("\t%d error%s not generated 'cuz old message was icmp\n",
234 icmpstat.icps_oldicmp, plural(icmpstat.icps_oldicmp));
94ff35a7 235 for (first = 1, i = 0; i < ICMP_IREQREPLY + 1; i++)
7333c75b
SL
236 if (icmpstat.icps_outhist[i] != 0) {
237 if (first) {
238 printf("\tOutput histogram:\n");
239 first = 0;
240 }
241 printf("\t\t%s: %d\n", icmpnames[i],
242 icmpstat.icps_outhist[i]);
243 }
bdf25b53
SL
244 printf("\t%d message%s with bad code fields\n",
245 icmpstat.icps_badcode, plural(icmpstat.icps_badcode));
d69a747c
SL
246 printf("\t%d message%s < minimum length\n",
247 icmpstat.icps_tooshort, plural(icmpstat.icps_tooshort));
4fbbc6d9
SL
248 printf("\t%d bad checksum%s\n",
249 icmpstat.icps_checksum, plural(icmpstat.icps_checksum));
d69a747c
SL
250 printf("\t%d message%s with bad length\n",
251 icmpstat.icps_badlen, plural(icmpstat.icps_badlen));
252 printf("\t%d message response%s generated\n",
253 icmpstat.icps_reflect, plural(icmpstat.icps_reflect));
94ff35a7 254 for (first = 1, i = 0; i < ICMP_IREQREPLY + 1; i++)
7333c75b
SL
255 if (icmpstat.icps_inhist[i] != 0) {
256 if (first) {
257 printf("\tInput histogram:\n");
258 first = 0;
259 }
260 printf("\t\t%s: %d\n", icmpnames[i],
261 icmpstat.icps_inhist[i]);
262 }
263}
264
c7fc5288
SL
265/*
266 * Pretty print an Internet address (net address + port).
267 * If the nflag was specified, use numbers instead of names.
268 */
269inetprint(in, port, proto)
270 register struct in_addr *in;
271 int port;
272 char *proto;
273{
274 struct servent *sp = 0;
275 char line[80], *cp, *index();
f36bd7cf 276 int width;
c7fc5288 277
f36bd7cf 278 sprintf(line, "%.*s.", Aflag ? 10 : 16, inetname(*in));
c7fc5288 279 cp = index(line, '\0');
c7fc5288 280 if (!nflag && port)
9bce7b73 281 sp = getservbyport(port, proto);
c7fc5288
SL
282 if (sp || port == 0)
283 sprintf(cp, "%.8s", sp ? sp->s_name : "*");
284 else
1f34f70d 285 sprintf(cp, "%d", ntohs((u_short)port));
f36bd7cf
MK
286 width = Aflag ? 18 : 22;
287 printf(" %-*.*s", width, width, line);
c7fc5288
SL
288}
289
c7fc5288
SL
290/*
291 * Construct an Internet address representation.
292 * If the nflag has been supplied, give
293 * numeric value, otherwise try for symbolic name.
294 */
295char *
296inetname(in)
297 struct in_addr in;
298{
299 char *cp = 0;
300 static char line[50];
f6d7bbb7
MK
301 struct hostent *hp;
302 struct netent *np;
c7fc5288 303
227faf58 304 if (!nflag && in.s_addr != INADDR_ANY) {
40f48772 305 int net = inet_netof(in), subnet = inet_subnetof(in);
f6d7bbb7 306 int lna = inet_lnaof(in);
227faf58 307
f6d7bbb7 308 if (lna == INADDR_ANY) {
40f48772 309 np = getnetbyaddr(net, AF_INET);
c7fc5288
SL
310 if (np)
311 cp = np->n_name;
227faf58 312 } else if (subnet != net && (lna & 0xff) == 0 &&
f6d7bbb7
MK
313 (np = getnetbyaddr(subnet, AF_INET))) {
314 struct in_addr subnaddr, inet_makeaddr();
227faf58 315
f6d7bbb7 316 subnaddr = inet_makeaddr(subnet, INADDR_ANY);
227faf58 317 if (bcmp(&in, &subnaddr, sizeof (in)) == 0)
f6d7bbb7
MK
318 cp = np->n_name;
319 else
320 goto host;
c7fc5288 321 } else {
f6d7bbb7 322host:
227faf58 323 hp = gethostbyaddr(&in, sizeof (in), AF_INET);
c7fc5288
SL
324 if (hp)
325 cp = hp->h_name;
326 }
327 }
328 if (in.s_addr == INADDR_ANY)
329 strcpy(line, "*");
330 else if (cp)
331 strcpy(line, cp);
332 else {
333 u_char *ucp = (u_char *)&in;
227faf58 334
c7fc5288
SL
335 sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1], ucp[2], ucp[3]);
336 }
337 return (line);
338}