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