poor grammar
[unix-history] / usr / src / usr.bin / netstat / inet.c
CommitLineData
c7fc5288 1#ifndef lint
68634afa 2static char sccsid[] = "@(#)inet.c 4.11 83/03/12";
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");
74 printf("%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n",
75 "Proto", "Recv-Q", "Send-Q",
76 "Local Address", "Foreign Address", "(state)");
77 first = 0;
78 }
79 while (inpcb.inp_next != (struct inpcb *)off) {
80 char *cp;
81
82 next = inpcb.inp_next;
83 klseek(kmem, (off_t)next, 0);
84 read(kmem, &inpcb, sizeof (inpcb));
85 if (inpcb.inp_prev != prev) {
86 printf("???\n");
87 break;
88 }
89 if (!aflag &&
444a708d 90 inet_lnaof(inpcb.inp_laddr.s_addr) == INADDR_ANY) {
c7fc5288
SL
91 prev = next;
92 continue;
93 }
94 klseek(kmem, (off_t)inpcb.inp_socket, 0);
95 read(kmem, &socket, sizeof (socket));
96 if (istcp) {
97 klseek(kmem, (off_t)inpcb.inp_ppcb, 0);
98 read(kmem, &tcpcb, sizeof (tcpcb));
99 }
100 if (Aflag)
101 printf("%8x ", inpcb.inp_ppcb);
102 printf("%-5.5s %6d %6d ", name, socket.so_rcv.sb_cc,
103 socket.so_snd.sb_cc);
104 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name);
105 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name);
106 if (istcp) {
107 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
108 printf(" %d", tcpcb.t_state);
109 else
110 printf(" %s", tcpstates[tcpcb.t_state]);
111 }
112 putchar('\n');
113 prev = next;
114 }
115}
116
6df0a927
SL
117/*
118 * Dump TCP statistics structure.
119 */
120tcp_stats(off, name)
121 off_t off;
122 char *name;
123{
124 struct tcpstat tcpstat;
125
126 if (off == 0) {
127 printf("%sstat: symbol not in namelist\n", name);
128 return;
129 }
130 klseek(kmem, off, 0);
131 read(kmem, (char *)&tcpstat, sizeof (tcpstat));
132 printf("%s:\n\t%d bad header checksums\n", name, tcpstat.tcps_badsum);
133 printf("\t%d bad header offset fields\n", tcpstat.tcps_badoff);
134 printf("\t%d incomplete headers\n", tcpstat.tcps_hdrops);
135#ifdef notdef
136 printf("\t%d bad segments\n", tcpstat.tcps_badsegs);
137 printf("\t%d unacknowledged packets\n", tcpstat.tcps_unack);
138#endif
139}
140
141/*
142 * Dump UDP statistics structure.
143 */
144udp_stats(off, name)
145 off_t off;
146 char *name;
147{
148 struct udpstat udpstat;
149
150 if (off == 0) {
151 printf("%sstat: symbol not in namelist\n", name);
152 return;
153 }
154 klseek(kmem, off, 0);
155 read(kmem, (char *)&udpstat, sizeof (udpstat));
156 printf("%s:\n\t%d bad header checksums\n", name, udpstat.udps_badsum);
157 printf("\t%d incomplete headers\n", udpstat.udps_hdrops);
158 printf("\t%d bad data length fields\n", udpstat.udps_badlen);
159}
160
161/*
162 * Dump IP statistics structure.
163 */
164ip_stats(off, name)
165 off_t off;
166 char *name;
167{
168 struct ipstat ipstat;
169
170 if (off == 0) {
171 printf("%sstat: symbol not in namelist\n", name);
172 return;
173 }
174 klseek(kmem, off, 0);
175 read(kmem, (char *)&ipstat, sizeof (ipstat));
176 printf("%s:\n\t%d bad header checksums\n", name, ipstat.ips_badsum);
f48ec3b3
SL
177 printf("\t%d packet size smaller than minimum\n",
178 ipstat.ips_tooshort);
179 printf("\t%d data size < data length\n", ipstat.ips_toosmall);
180 printf("\t%d header length < data size\n", ipstat.ips_badhlen);
181 printf("\t%d data length < header length\n", ipstat.ips_badlen);
6df0a927
SL
182}
183
7333c75b
SL
184static char *icmpnames[] = {
185 "echo reply",
186 "#1",
187 "#2",
188 "destination unreachable",
189 "source quench",
190 "routing redirect",
191 "#6",
192 "#7",
193 "echo",
194 "#9",
195 "#10",
196 "time exceeded",
197 "parameter problem",
198 "time stamp",
199 "time stamp reply",
200 "information request",
201 "information request reply"
202};
203
204/*
205 * Dump ICMP statistics.
206 */
207icmp_stats(off, name)
208 off_t off;
209 char *name;
210{
211 struct icmpstat icmpstat;
212 register int i, first;
213
214 if (off == 0) {
215 printf("%sstat: symbol not in namelist\n", name);
216 return;
217 }
218 klseek(kmem, off, 0);
219 read(kmem, (char *)&icmpstat, sizeof (icmpstat));
220 printf("%s:\n\t%d calls to icmp_error\n", name, icmpstat.icps_error);
221 printf("\t%d errors not generated 'cuz old message too short\n",
222 icmpstat.icps_oldshort);
223 printf("\t%d errors not generated 'cuz old message was icmp\n",
224 icmpstat.icps_oldicmp);
94ff35a7 225 for (first = 1, i = 0; i < ICMP_IREQREPLY + 1; i++)
7333c75b
SL
226 if (icmpstat.icps_outhist[i] != 0) {
227 if (first) {
228 printf("\tOutput histogram:\n");
229 first = 0;
230 }
231 printf("\t\t%s: %d\n", icmpnames[i],
232 icmpstat.icps_outhist[i]);
233 }
234 printf("\t%d messages < minimum length\n", icmpstat.icps_tooshort);
235 printf("\t%d bad checksums\n", icmpstat.icps_checksum);
236 printf("\t%d messages with bad length\n", icmpstat.icps_badlen);
68634afa 237 printf("\t%d message responses generated\n", icmpstat.icps_reflect);
94ff35a7 238 for (first = 1, i = 0; i < ICMP_IREQREPLY + 1; i++)
7333c75b
SL
239 if (icmpstat.icps_inhist[i] != 0) {
240 if (first) {
241 printf("\tInput histogram:\n");
242 first = 0;
243 }
244 printf("\t\t%s: %d\n", icmpnames[i],
245 icmpstat.icps_inhist[i]);
246 }
247}
248
c7fc5288
SL
249/*
250 * Pretty print an Internet address (net address + port).
251 * If the nflag was specified, use numbers instead of names.
252 */
253inetprint(in, port, proto)
254 register struct in_addr *in;
255 int port;
256 char *proto;
257{
258 struct servent *sp = 0;
259 char line[80], *cp, *index();
260
261 sprintf(line, "%.10s.", inetname(*in));
262 cp = index(line, '\0');
c7fc5288 263 if (!nflag && port)
9bce7b73 264 sp = getservbyport(port, proto);
c7fc5288
SL
265 if (sp || port == 0)
266 sprintf(cp, "%.8s", sp ? sp->s_name : "*");
267 else
1f34f70d 268 sprintf(cp, "%d", ntohs((u_short)port));
c7fc5288
SL
269 printf(" %-18.18s", line);
270}
271
c7fc5288
SL
272/*
273 * Construct an Internet address representation.
274 * If the nflag has been supplied, give
275 * numeric value, otherwise try for symbolic name.
276 */
277char *
278inetname(in)
279 struct in_addr in;
280{
281 char *cp = 0;
282 static char line[50];
283
284 if (!nflag) {
444a708d
SL
285 if (inet_lnaof(in) == INADDR_ANY) {
286 struct netent *np;
c7fc5288 287
444a708d 288 np = getnetbyaddr(inet_netof(in), AF_INET);
c7fc5288
SL
289 if (np)
290 cp = np->n_name;
291 } else {
9bce7b73 292 struct hostent *hp;
c7fc5288 293
3394f0b5
SL
294 hp = gethostbyaddr(&in, sizeof (struct in_addr),
295 AF_INET);
c7fc5288
SL
296 if (hp)
297 cp = hp->h_name;
298 }
299 }
300 if (in.s_addr == INADDR_ANY)
301 strcpy(line, "*");
302 else if (cp)
303 strcpy(line, cp);
304 else {
305 u_char *ucp = (u_char *)&in;
306 sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1], ucp[2], ucp[3]);
307 }
308 return (line);
309}