1300 lines
34 KiB
C
1300 lines
34 KiB
C
/*
|
|
* Copyright (c) 1983,1988 Regents of the University of California.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms are permitted
|
|
* provided that this notice is preserved and that due credit is given
|
|
* to the University of California at Berkeley. The name of the University
|
|
* may not be used to endorse or promote products derived from this
|
|
* software without specific prior written permission. This software
|
|
* is provided ``as is'' without express or implied warranty.
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char sccsid[] = "@(#)inet.c 5.10 (Berkeley) 2/7/88 plus MULTICAST 1.0";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include <bstring.h>
|
|
#define _KMEMUSER /* get definition of "struct socket" */
|
|
#include <strings.h>
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/socketvar.h>
|
|
#include <sys/mbuf.h>
|
|
#include <sys/protosw.h>
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/sysmp.h>
|
|
|
|
#include <net/route.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/in_systm.h>
|
|
#include <netinet/ip.h>
|
|
#include <netinet/in_pcb.h>
|
|
#include <netinet/ip_icmp.h>
|
|
#include <netinet/icmp_var.h>
|
|
#include <netinet/igmp_var.h>
|
|
#include <netinet/ip_var.h>
|
|
#include <netinet/tcp.h>
|
|
#include <netinet/tcpip.h>
|
|
#include <netinet/tcp_seq.h>
|
|
#define TCPSTATES
|
|
#include <netinet/tcp_fsm.h>
|
|
#include <netinet/tcp_timer.h>
|
|
#include <netinet/tcp_var.h>
|
|
#include <netinet/tcp_debug.h>
|
|
#include <netinet/udp.h>
|
|
#include <netinet/udp_var.h>
|
|
|
|
#include <sys/tcpipstats.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <mls.h>
|
|
#include <sys/so_dac.h>
|
|
#include <pwd.h>
|
|
#include <sys/types.h>
|
|
#include <malloc.h>
|
|
|
|
#define MAX_UID_LINE 9
|
|
#define MAX_SOACL_LINE 256
|
|
|
|
#include <curses.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "netstat.h"
|
|
#include "cdisplay.h"
|
|
|
|
|
|
struct printbuf {
|
|
struct printbuf *fwd;
|
|
struct inpcb *next;
|
|
struct inpcb inpcb;
|
|
struct socket sockb;
|
|
struct tcpcb tcpcb;
|
|
mac_label slabel;
|
|
struct soacl sacl;
|
|
};
|
|
struct inpcb inpcb;
|
|
struct tcpcb tcpcb;
|
|
struct socket sockb;
|
|
|
|
int ipforwarding = -1; /* let ipstats show state of flag */
|
|
|
|
|
|
extern int errno;
|
|
|
|
static void inetprint(struct in_addr*, u_short, char*);
|
|
|
|
#ifdef _SESMGR
|
|
extern mac_label plabel;
|
|
extern short havemac;
|
|
#endif
|
|
|
|
void
|
|
kread(int fd, void *buf, unsigned len)
|
|
{
|
|
if (read(fd, buf, len) < 0) {
|
|
perror("netstat: kread");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
#ifdef _SESMGR
|
|
mac_label *
|
|
fetchlabel(mac_label *lblp, ns_off_t off)
|
|
{
|
|
register int lblsize;
|
|
register int hdrsize = (caddr_t)lblp->ml_list - (caddr_t)&lblp;
|
|
|
|
klseek(kmem, off, 0);
|
|
kread(kmem, lblp, hdrsize);
|
|
lblsize = mac_size(lblp) - hdrsize;
|
|
if (lblsize > 0)
|
|
kread(kmem, (caddr_t)lblp + hdrsize, lblsize);
|
|
return lblp;
|
|
}
|
|
|
|
char *
|
|
uidtostr(int uid)
|
|
{
|
|
struct passwd *pwd;
|
|
char *uidstring;
|
|
|
|
uidstring = (char *)malloc(MAX_UID_LINE);
|
|
if (pwd = getpwuid(uid))
|
|
sprintf(uidstring, "%s", pwd->pw_name);
|
|
else
|
|
sprintf(uidstring, "%d", uid);
|
|
return(uidstring);
|
|
}
|
|
void
|
|
souidpr(uid_t uid)
|
|
{
|
|
register char *cp;
|
|
|
|
cp = uidtostr(uid);
|
|
printf("%-8.8s ", cp );
|
|
if (cp)
|
|
free(cp);
|
|
}
|
|
|
|
void
|
|
labelpr(mac_label *lblp)
|
|
{
|
|
register char *cp;
|
|
|
|
cp = mac_labeltostr(lblp, 1);
|
|
printf("%-8.8s ", cp ? cp : "INVALID" );
|
|
if (cp)
|
|
free(cp);
|
|
}
|
|
|
|
char *
|
|
soacltostr(struct soacl *sp)
|
|
{
|
|
char *buf;
|
|
register int count;
|
|
|
|
buf = (char *)malloc(MAX_SOACL_LINE);
|
|
if (sp->so_uidcount == WILDACL)
|
|
sprintf(buf, "wildacl");
|
|
else {
|
|
sprintf(buf, "%s", uidtostr(sp->so_uidlist[0]));
|
|
for (count = 1; count < sp->so_uidcount; count++) {
|
|
sprintf(buf, "%s,%s", buf,
|
|
uidtostr(sp->so_uidlist[count]));
|
|
}
|
|
}
|
|
return(buf);
|
|
}
|
|
|
|
void
|
|
soaclpr(struct soacl *soaclp)
|
|
{
|
|
register char *cp;
|
|
|
|
cp = soacltostr(soaclp);
|
|
printf("%s ", cp);
|
|
if (cp)
|
|
free(cp);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Print a summary of connections related to an Internet
|
|
* protocol. For TCP, also give state of connection.
|
|
* Listening processes (aflag) are suppressed unless the
|
|
* -a (all) flag is specified.
|
|
*/
|
|
void
|
|
protopr(ns_off_t off,
|
|
char *name)
|
|
{
|
|
struct inpcb cb;
|
|
register struct inpcb *prev, *next;
|
|
int istcp;
|
|
static int first = 1;
|
|
mac_label slabel;
|
|
struct soacl sacl;
|
|
int pass = 0;
|
|
struct printbuf *phead = 0;
|
|
struct printbuf **ptail = &phead;
|
|
struct printbuf *pnext;
|
|
struct in_pcbhead hcb;
|
|
ns_off_t hoff;
|
|
int h;
|
|
int tsize;
|
|
ns_off_t table;
|
|
struct inpcb *inp;
|
|
|
|
if (off == 0)
|
|
return;
|
|
|
|
istcp = strcmp(name, "tcp") == 0;
|
|
klseek(kmem, off, 0);
|
|
read(kmem, (char *)&cb, sizeof (struct inpcb));
|
|
inpcb = cb;
|
|
tsize = inpcb.inp_tablesz;
|
|
table = (ns_off_t)inpcb.inp_table;
|
|
for (h = 0; h < tsize; h++) {
|
|
hoff = table + (h * sizeof(hcb));
|
|
prev = (struct inpcb *)hoff;
|
|
klseek(kmem, hoff, 0);
|
|
read(kmem, (char *)&hcb, sizeof (struct in_pcbhead));
|
|
inp = (struct inpcb *)&hcb;
|
|
if (inp->inp_next == (struct inpcb *)hoff)
|
|
continue;
|
|
while (inp->inp_next != (struct inpcb *)hoff) {
|
|
|
|
next = inp->inp_next;
|
|
klseek(kmem, (ns_off_t)next, 0);
|
|
read(kmem, (char *)&inpcb, sizeof (inpcb));
|
|
inp = &inpcb;
|
|
if (inpcb.inp_prev != prev) {
|
|
printf("???\n");
|
|
break;
|
|
}
|
|
if (!aflag &&
|
|
inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) {
|
|
prev = next;
|
|
continue;
|
|
}
|
|
klseek(kmem, (ns_off_t)inpcb.inp_socket, 0);
|
|
read(kmem, (char *)&sockb, sizeof (sockb));
|
|
if (istcp) {
|
|
klseek(kmem, (ns_off_t)inpcb.inp_ppcb, 0);
|
|
read(kmem, (char *)&tcpcb, sizeof (tcpcb));
|
|
}
|
|
#ifdef _SESMGR
|
|
if (havemac) {
|
|
(void)fetchlabel(&slabel,
|
|
(ns_off_t)sockb.so_label);
|
|
if (!mac_dom(&plabel, &slabel)) {
|
|
prev = next;
|
|
continue;
|
|
}
|
|
klseek(kmem, (ns_off_t)sockb.so_acl, 0);
|
|
kread(kmem, &sacl, sizeof(struct soacl));
|
|
}
|
|
#endif
|
|
if (first) {
|
|
printf("Active Internet connections");
|
|
if (aflag)
|
|
printf(" (including servers)");
|
|
putchar('\n');
|
|
#ifdef _SESMGR
|
|
if (lflag) {
|
|
/* add label, uid, & acl headers */
|
|
printf("%-8.8s %-8.8s %-5.5s %-20.20s %-20.20s %-11.11s %-8.8s %s\n",
|
|
"Label", "SndLabel", "Proto",
|
|
"Local Address", "Foreign Address",
|
|
"(state)", "Souid", "Soacl");
|
|
} else {
|
|
#endif
|
|
#if _MIPS_SZLONG == 64
|
|
if (Aflag)
|
|
printf("%-16.16s ", "PCB");
|
|
#else
|
|
if (Aflag)
|
|
printf("%-8.8s ", "PCB");
|
|
#endif
|
|
printf(Aflag ?
|
|
"%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s" :
|
|
"%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s",
|
|
"Proto", "Recv-Q", "Send-Q",
|
|
"Local Address", "Foreign Address", "(state)");
|
|
#ifdef _SESMGR
|
|
}
|
|
#endif
|
|
if (qflag) {
|
|
printf(" Q0 Q Limit");
|
|
}
|
|
putchar('\n');
|
|
first = 0;
|
|
}
|
|
/* read everything into a linked list before printing
|
|
* anything, to avoid the Heisenburg effects of doing
|
|
* address-to-name resolution. That creates more PCBs.
|
|
*/
|
|
pnext = (struct printbuf*)malloc(sizeof(struct printbuf));
|
|
if (!pnext) {
|
|
(void)fprintf(stderr,"malloc(printbuf) failed\n");
|
|
exit(1);
|
|
}
|
|
*ptail = pnext;
|
|
ptail = &pnext->fwd;
|
|
pnext->fwd = 0;
|
|
pnext->inpcb = inpcb;
|
|
pnext->sockb = sockb;
|
|
pnext->tcpcb = tcpcb;
|
|
pnext->slabel = slabel;
|
|
pnext->sacl = sacl;
|
|
phead->next = next;
|
|
|
|
prev = next;
|
|
}
|
|
} /* for */
|
|
|
|
while (phead != 0) {
|
|
inpcb = phead->inpcb;
|
|
sockb = phead->sockb;
|
|
tcpcb = phead->tcpcb;
|
|
slabel = phead->slabel;
|
|
sacl = phead->sacl;
|
|
next = phead->next;
|
|
phead = phead->fwd;
|
|
|
|
#ifdef _SESMGR
|
|
if (lflag) {
|
|
labelpr(&slabel);
|
|
labelpr(fetchlabel(&slabel, (ns_off_t)sockb.so_sendlabel));
|
|
} else {
|
|
#endif
|
|
#if _MIPS_SZLONG == 64
|
|
if (Aflag)
|
|
if (istcp)
|
|
printf("%8llx ", inpcb.inp_ppcb);
|
|
else
|
|
printf("%8llx ", next);
|
|
#else
|
|
if (Aflag)
|
|
if (istcp)
|
|
printf("%8x ", inpcb.inp_ppcb);
|
|
else
|
|
printf("%8x ", next);
|
|
#endif
|
|
#ifdef _SESMGR
|
|
}
|
|
if (lflag)
|
|
printf("%-5.5s", name);
|
|
else
|
|
#endif
|
|
printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc,
|
|
sockb.so_snd.sb_cc);
|
|
inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name);
|
|
inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name);
|
|
if (istcp) {
|
|
if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
|
|
printf("%-12.12d", tcpcb.t_state);
|
|
else
|
|
printf(" %-12.12s", tcpstates[tcpcb.t_state]);
|
|
if (qflag) {
|
|
printf("%4d %4d %5d",
|
|
sockb.so_q0len, sockb.so_qlen,sockb.so_qlimit);
|
|
}
|
|
}
|
|
#ifdef _SESMGR
|
|
if (lflag) {
|
|
if (!istcp) {
|
|
printf("%12s", "");
|
|
if (qflag)
|
|
printf("%4s %4s %5s", "","","");
|
|
}
|
|
souidpr(sockb.so_uid);
|
|
soaclpr(&sacl);
|
|
}
|
|
#endif
|
|
putchar('\n');
|
|
prev = next;
|
|
}
|
|
}
|
|
|
|
static void
|
|
get_ipforwarding(void)
|
|
{
|
|
int name[4];
|
|
size_t len;
|
|
|
|
if (ipforwarding < 0) { /* only once */
|
|
ipforwarding = 0;
|
|
|
|
name[0] = CTL_NET;
|
|
name[1] = AF_INET;
|
|
name[2] = IPPROTO_IP;
|
|
name[3] = IPCTL_FORWARDING;
|
|
len = sizeof(ipforwarding);
|
|
if (sysctl(name, 4, &ipforwarding, &len, 0, 0) < 0) {
|
|
perror("netstat: cannot get ipforwarding");
|
|
ipforwarding = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Get the TCP/IP statistics structure from the kernel
|
|
* Currently we only support the option to obtain all the various TCP/IP
|
|
* related statistics on each CPU and return them summed for each category.
|
|
* Later additions could add support for obtaining individual CPU statistics.
|
|
*
|
|
* RETURNS:
|
|
* 0 => Success
|
|
* non-zero => Failure
|
|
*/
|
|
int
|
|
getkna(kna_p)
|
|
struct kna *kna_p;
|
|
{
|
|
int err;
|
|
|
|
err = sysmp(MP_SAGET, MPSA_TCPIPSTATS, kna_p, sizeof(struct kna));
|
|
return ((err < 0) ? errno : 0);
|
|
}
|
|
|
|
/*
|
|
* Dump TCP statistics structure.
|
|
*/
|
|
void
|
|
tcp_stats(char *name)
|
|
{
|
|
struct kna tcpipstats;
|
|
|
|
if (getkna(&tcpipstats)) { /* failed */
|
|
(void)fail("tcp_stats: failed sysmp MP_SAGET\n");
|
|
return;
|
|
}
|
|
|
|
printf ("%s:\n", name);
|
|
|
|
#define p(f, m) printf(m, tcpipstats.tcpstat.f, \
|
|
plural(tcpipstats.tcpstat.f))
|
|
#define p_nos(f, m) printf(m, tcpipstats.tcpstat.f)
|
|
#define p2(f1, f2, m) printf(m, tcpipstats.tcpstat.f1, \
|
|
plural(tcpipstats.tcpstat.f1), \
|
|
tcpipstats.tcpstat.f2, \
|
|
plural(tcpipstats.tcpstat.f2))
|
|
#define p2_nos(f1, f2, m) printf(m, tcpipstats.tcpstat.f1, \
|
|
plural(tcpipstats.tcpstat.f1), \
|
|
tcpipstats.tcpstat.f2)
|
|
|
|
p(tcps_sndtotal, "\t%llu packet%s sent\n");
|
|
p2(tcps_sndpack,tcps_sndbyte,
|
|
"\t\t%llu data packet%s (%llu byte%s)\n");
|
|
p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
|
|
"\t\t%llu data packet%s (%llu byte%s) retransmitted\n");
|
|
p2_nos(tcps_sndacks, tcps_delack,
|
|
"\t\t%llu ack-only packet%s (%llu delayed)\n");
|
|
p(tcps_sndurg, "\t\t%llu URG only packet%s\n");
|
|
p(tcps_sndprobe, "\t\t%llu window probe packet%s\n");
|
|
p(tcps_sndwinup, "\t\t%llu window update packet%s\n");
|
|
p(tcps_sndctrl, "\t\t%llu control packet%s\n");
|
|
p(tcps_rcvtotal, "\t%llu packet%s received\n");
|
|
p2(tcps_rcvackpack, tcps_rcvackbyte,
|
|
"\t\t%llu ack%s (for %llu byte%s)\n");
|
|
p(tcps_predack, "\t\t%llu ack prediction%s ok\n");
|
|
p(tcps_rcvdupack, "\t\t%llu duplicate ack%s\n");
|
|
p(tcps_rcvacktoomuch, "\t\t%llu ack%s for unsent data\n");
|
|
p2(tcps_rcvpack, tcps_rcvbyte,
|
|
"\t\t%llu packet%s (%llu byte%s) received in-sequence\n");
|
|
p(tcps_preddat, "\t\t%llu in-sequence prediction%s ok\n");
|
|
p2(tcps_rcvduppack, tcps_rcvdupbyte,
|
|
"\t\t%llu completely duplicate packet%s (%llu byte%s)\n");
|
|
p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
|
|
"\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n");
|
|
p2(tcps_rcvoopack, tcps_rcvoobyte,
|
|
"\t\t%llu out-of-order packet%s (%llu byte%s)\n");
|
|
p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
|
|
"\t\t%llu packet%s (%llu byte%s) of data after window\n");
|
|
p(tcps_rcvwinprobe, "\t\t%llu window probe%s\n");
|
|
p(tcps_rcvwinupd, "\t\t%llu window update packet%s\n");
|
|
p(tcps_rcvafterclose, "\t\t%llu packet%s received after close\n");
|
|
p(tcps_rcvbadsum, "\t\t%llu discarded for bad checksum%s\n");
|
|
p(tcps_rcvbadoff,
|
|
"\t\t%llu discarded for bad header offset field%s\n");
|
|
p_nos(tcps_rcvshort, "\t\t%llu discarded because packet too short\n");
|
|
p(tcps_pawsdrop, "\t\t%llu discarded because of old timestamp%s\n");
|
|
p(tcps_connattempt, "\t%llu connection request%s\n");
|
|
p(tcps_accepts, "\t%llu connection accept%s\n");
|
|
p(tcps_listendrop, "\t\t%llu listen queue overflow%s\n");
|
|
p(tcps_badsyn, "\t\t%llu bad connection attempt%s\n");
|
|
p(tcps_synpurge, "\t\t%llu drop%s from listen queue\n");
|
|
p(tcps_connects,
|
|
"\t%llu connection%s established (including accepts)\n");
|
|
p2(tcps_closed, tcps_drops,
|
|
"\t%llu connection%s closed (including %llu drop%s)\n");
|
|
p(tcps_conndrops, "\t%llu embryonic connection%s dropped\n");
|
|
p2(tcps_rttupdated, tcps_segstimed,
|
|
"\t%llu segment%s updated rtt (of %llu attempt%s)\n");
|
|
p(tcps_rexmttimeo, "\t%llu retransmit timeout%s\n");
|
|
p(tcps_timeoutdrop,
|
|
"\t\t%llu connection%s dropped by rexmit timeout\n");
|
|
p(tcps_persisttimeo, "\t%llu persist timeout%s\n");
|
|
p(tcps_persistdrop,
|
|
"\t\t%llu connection%s dropped by persist timeout\n");
|
|
p(tcps_keeptimeo, "\t%llu keepalive timeout%s\n");
|
|
p(tcps_keepprobe, "\t\t%llu keepalive probe%s sent\n");
|
|
p(tcps_keepdrops, "\t\t%llu connection%s dropped by keepalive\n");
|
|
#undef p
|
|
#undef p2
|
|
}
|
|
|
|
/*
|
|
* Dump UDP statistics structure.
|
|
*/
|
|
void
|
|
udp_stats(char *name)
|
|
{
|
|
u_long delivered;
|
|
struct kna tcpipstats;
|
|
|
|
if (getkna(&tcpipstats)) { /* failed */
|
|
(void)fail("und_stats: failed sysmp MP_SAGET\n");
|
|
return;
|
|
}
|
|
#define udpstat tcpipstats.udpstat
|
|
|
|
printf("%s:\n\t%llu total datagrams received\n", name,
|
|
udpstat.udps_ipackets);
|
|
printf("\t%llu with incomplete header\n", udpstat.udps_hdrops);
|
|
printf("\t%llu with bad data length field\n", udpstat.udps_badlen);
|
|
printf("\t%llu with bad checksum\n", udpstat.udps_badsum);
|
|
printf("\t%llu datagram%s dropped due to no socket\n",
|
|
udpstat.udps_noport, plural(udpstat.udps_noport));
|
|
printf("\t%llu broadcast/multicast datagram%s"
|
|
" dropped due to no socket\n",
|
|
udpstat.udps_noportbcast, plural(udpstat.udps_noportbcast));
|
|
printf("\t%llu datagram%s dropped due to full socket buffers\n",
|
|
udpstat.udps_fullsock, plural(udpstat.udps_fullsock));
|
|
delivered = udpstat.udps_ipackets -
|
|
udpstat.udps_hdrops -
|
|
udpstat.udps_badlen -
|
|
udpstat.udps_badsum -
|
|
udpstat.udps_noport -
|
|
udpstat.udps_noportbcast -
|
|
udpstat.udps_fullsock;
|
|
printf("\t%lu datagram%s delivered\n", delivered, plural(delivered));
|
|
printf("\t%llu datagram%s output\n",
|
|
udpstat.udps_opackets, plural(udpstat.udps_opackets));
|
|
|
|
#undef udpstat
|
|
}
|
|
|
|
/*
|
|
* Dump IP statistics structure.
|
|
*/
|
|
void
|
|
ip_stats(char *name)
|
|
{
|
|
struct kna tcpipstats;
|
|
|
|
if (getkna(&tcpipstats)) { /* failed */
|
|
(void)fail("ip_stats: failed sysmp MP_SAGET\n");
|
|
return;
|
|
}
|
|
get_ipforwarding();
|
|
#define ipstat tcpipstats.ipstat
|
|
|
|
printf("%s:\n\t%llu total packets received\n", name,
|
|
ipstat.ips_total);
|
|
printf("\t%llu bad header checksum%s\n",
|
|
ipstat.ips_badsum, plural(ipstat.ips_badsum));
|
|
printf("\t%llu with size smaller than minimum\n", ipstat.ips_toosmall);
|
|
printf("\t%llu with data size < data length\n", ipstat.ips_tooshort);
|
|
printf("\t%llu with header length < data size\n", ipstat.ips_badhlen);
|
|
printf("\t%llu with data length < header length\n", ipstat.ips_badlen);
|
|
printf("\t%llu with bad options\n", ipstat.ips_badoptions);
|
|
printf("\t%llu fragment%s received\n",
|
|
ipstat.ips_fragments, plural(ipstat.ips_fragments));
|
|
printf("\t%llu fragment%s dropped (dup or out of space)\n",
|
|
ipstat.ips_fragdropped, plural(ipstat.ips_fragdropped));
|
|
printf("\t%llu fragment%s dropped after timeout\n",
|
|
ipstat.ips_fragtimeout, plural(ipstat.ips_fragtimeout));
|
|
printf("\t%llu packet%s for this host\n",
|
|
ipstat.ips_delivered, plural(ipstat.ips_delivered));
|
|
printf("\t%llu packet%s recvd for unknown/unsupported protocol\n",
|
|
ipstat.ips_noproto, plural(ipstat.ips_noproto));
|
|
|
|
printf("\t%llu packet%s forwarded",
|
|
ipstat.ips_forward, plural(ipstat.ips_forward));
|
|
printf(" (forwarding %sabled)\n", ipforwarding ? "en" : "dis");
|
|
printf("\t%llu packet%s not forwardable\n",
|
|
ipstat.ips_cantforward, plural(ipstat.ips_cantforward));
|
|
printf("\t%llu redirect%s sent\n",
|
|
ipstat.ips_redirectsent, plural(ipstat.ips_redirectsent));
|
|
|
|
printf("\t%llu packet%s sent from this host\n",
|
|
ipstat.ips_localout, plural(ipstat.ips_localout));
|
|
printf("\t%llu output packet%s dropped due to no bufs, etc.\n",
|
|
ipstat.ips_odropped, plural(ipstat.ips_odropped));
|
|
printf("\t%llu output packet%s discarded due to no route\n",
|
|
ipstat.ips_noroute, plural(ipstat.ips_noroute));
|
|
printf("\t%llu datagram%s fragmented\n",
|
|
ipstat.ips_fragmented, plural(ipstat.ips_fragmented));
|
|
printf("\t%llu fragment%s created\n",
|
|
ipstat.ips_ofragments, plural(ipstat.ips_ofragments));
|
|
printf("\t%llu datagram%s that can't be fragmented\n",
|
|
ipstat.ips_cantfrag, plural(ipstat.ips_cantfrag));
|
|
#undef ipstat
|
|
}
|
|
|
|
static char *icmpnames[] = {
|
|
"echo reply\t",
|
|
"#1\t",
|
|
"#2\t",
|
|
"destination unreachable\t",
|
|
"source quench\t",
|
|
"routing redirect\t",
|
|
"#6\t",
|
|
"#7\t",
|
|
"echo\t",
|
|
"router advertisement\t",
|
|
"router solicitation\t",
|
|
"time exceeded\t",
|
|
"parameter problem\t",
|
|
"time stamp\t",
|
|
"time stamp reply\t",
|
|
"information request\t",
|
|
"information request reply\t",
|
|
"address mask request\t",
|
|
"address mask reply\t",
|
|
};
|
|
|
|
/*
|
|
* Dump ICMP statistics.
|
|
*/
|
|
void
|
|
icmp_stats(char *name)
|
|
{
|
|
register int i, first;
|
|
struct kna tcpipstats;
|
|
|
|
if (getkna(&tcpipstats)) { /* failed */
|
|
(void)fail("icmp_stats: failed sysmp MP_SAGET\n");
|
|
return;
|
|
}
|
|
#define icmpstat tcpipstats.icmpstat
|
|
|
|
printf("%s:\n\t%llu call%s to icmp_error\n", name,
|
|
icmpstat.icps_error, plural(icmpstat.icps_error));
|
|
printf("\t%llu error%s not generated 'cuz old message was icmp\n",
|
|
icmpstat.icps_oldicmp, plural(icmpstat.icps_oldicmp));
|
|
for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
|
|
if (icmpstat.icps_outhist[i] != 0) {
|
|
if (first) {
|
|
printf("\tOutput histogram:\n");
|
|
first = 0;
|
|
}
|
|
printf("\t\t%s: %llu\n", icmpnames[i],
|
|
icmpstat.icps_outhist[i]);
|
|
}
|
|
printf("\t%llu message%s with bad code fields\n",
|
|
icmpstat.icps_badcode, plural(icmpstat.icps_badcode));
|
|
printf("\t%llu message%s < minimum length\n",
|
|
icmpstat.icps_tooshort, plural(icmpstat.icps_tooshort));
|
|
printf("\t%llu bad checksum%s\n",
|
|
icmpstat.icps_checksum, plural(icmpstat.icps_checksum));
|
|
printf("\t%llu message%s with bad length\n",
|
|
icmpstat.icps_badlen, plural(icmpstat.icps_badlen));
|
|
/* Would be preferable to print this out iff kernel variable
|
|
icmp_nounsafe was set, but no easy way to query for that info */
|
|
if (icmpstat.icps_dropped != 0) {
|
|
printf("\t%llu REDIRECT message%s dropped\n",
|
|
icmpstat.icps_dropped,
|
|
plural(icmpstat.icps_dropped));
|
|
}
|
|
for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
|
|
if (icmpstat.icps_inhist[i] != 0) {
|
|
if (first) {
|
|
printf("\tInput histogram:\n");
|
|
first = 0;
|
|
}
|
|
printf("\t\t%s: %llu\n", icmpnames[i],
|
|
icmpstat.icps_inhist[i]);
|
|
}
|
|
printf("\t%llu message response%s generated\n",
|
|
icmpstat.icps_reflect, plural(icmpstat.icps_reflect));
|
|
#undef icmpstat
|
|
}
|
|
|
|
/*
|
|
* Dump IGMP statistics.
|
|
*/
|
|
void
|
|
igmp_stats(char *name)
|
|
{
|
|
struct kna tcpipstats;
|
|
register int i, first;
|
|
|
|
if (getkna(&tcpipstats)) { /* failed */
|
|
(void)fail("igmp_stats: failed sysmp MP_SAGET\n");
|
|
return;
|
|
}
|
|
#define igmpstat tcpipstats.igmpstat
|
|
|
|
printf("%s:\n", name );
|
|
printf("\t%llu message%s received\n",
|
|
igmpstat.igps_rcv_total, plural(igmpstat.igps_rcv_total));
|
|
printf("\t%llu message%s received with too few bytes\n",
|
|
igmpstat.igps_rcv_tooshort, plural(igmpstat.igps_rcv_tooshort));
|
|
printf("\t%llu message%s received with bad checksum\n",
|
|
igmpstat.igps_rcv_badsum, plural(igmpstat.igps_rcv_badsum));
|
|
printf("\t%llu membership quer%s received\n",
|
|
igmpstat.igps_rcv_queries, plural(igmpstat.igps_rcv_queries));
|
|
printf("\t%llu membership quer%s received with invalid field(s)\n",
|
|
igmpstat.igps_rcv_badqueries,
|
|
plural(igmpstat.igps_rcv_badqueries));
|
|
printf("\t%llu membership report%s received\n",
|
|
igmpstat.igps_rcv_reports,
|
|
plural(igmpstat.igps_rcv_reports));
|
|
printf("\t%llu membership report%s received with invalid field(s)\n",
|
|
igmpstat.igps_rcv_badreports,
|
|
plural(igmpstat.igps_rcv_badreports));
|
|
printf("\t%llu membership report%s received"
|
|
"for groups to which we belong\n",
|
|
igmpstat.igps_rcv_ourreports,
|
|
plural(igmpstat.igps_rcv_ourreports));
|
|
printf("\t%llu membership report%s sent\n",
|
|
igmpstat.igps_snd_reports, plural(igmpstat.igps_snd_reports));
|
|
|
|
#undef igmpstat
|
|
}
|
|
|
|
/*
|
|
* Pretty print an Internet address that might be a wildcard.
|
|
*/
|
|
static char*
|
|
inetname(__uint32_t x, int lim)
|
|
{
|
|
if (x == 0)
|
|
return "*";
|
|
return routename(x,lim);
|
|
}
|
|
|
|
/*
|
|
* Pretty print an Internet address (net address + port).
|
|
* If the nflag was specified, use numbers instead of names.
|
|
*/
|
|
static void
|
|
inetprint(register struct in_addr *in,
|
|
u_short port,
|
|
char *proto)
|
|
{
|
|
struct servent *sp = 0;
|
|
char line[80], *cp;
|
|
int width;
|
|
static struct {
|
|
u_short port;
|
|
char proto[8];
|
|
char portname[9];
|
|
} cache[16];
|
|
static int lru;
|
|
int i;
|
|
#ifdef _SESMGR
|
|
width = 16;
|
|
if (lflag)
|
|
width = 20;
|
|
else if (Aflag)
|
|
width = 18;
|
|
#else
|
|
width = Aflag ? 18 : 16;
|
|
#endif
|
|
sprintf(line, "%.*s.", width, inetname(in->s_addr, width));
|
|
cp = index(line, '\0');
|
|
for (i = 0; i < sizeof(cache)/sizeof(cache[0]); i++) {
|
|
lru = (lru+1) % (sizeof(cache)/sizeof(cache[0]));
|
|
if (!strcmp(proto, cache[lru].proto)
|
|
&& port == cache[lru].port) {
|
|
(void)strcat(cp,cache[lru].portname);
|
|
goto goit;
|
|
}
|
|
}
|
|
if (!nflag && port) {
|
|
sp = getservbyport((int)port, proto);
|
|
}
|
|
if (sp || port == 0)
|
|
sprintf(cp, "%.8s", sp ? sp->s_name : "*");
|
|
else
|
|
sprintf(cp, "%d", ntohs((u_short)port));
|
|
cache[lru].port = port;
|
|
strncpy(cache[lru].proto, proto, sizeof(cache[lru].proto)-1);
|
|
strncpy(cache[lru].portname, cp, sizeof(cache[lru].portname)-1);
|
|
goit:
|
|
lru = (lru+1) % (sizeof(cache)/sizeof(cache[0]));
|
|
#ifdef _SESMGR
|
|
width = 22;
|
|
if (lflag)
|
|
width = 20;
|
|
else if (Aflag)
|
|
width = 18;
|
|
#else
|
|
width = Aflag ? 18 : 22;
|
|
#endif
|
|
printf(" %-*.*s", width, width, line);
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct ipstat ipstat, zipstat;
|
|
|
|
void
|
|
initip(void)
|
|
{
|
|
bzero((char*)&zipstat, sizeof(zipstat));
|
|
}
|
|
|
|
void
|
|
zeroip(void)
|
|
{
|
|
zipstat = ipstat;
|
|
}
|
|
|
|
|
|
int
|
|
ck_y_off(int dsize, int y, int *y_off_ptr)
|
|
{
|
|
int y_off = *y_off_ptr;
|
|
y += dsize+1-BOS;
|
|
if (y < 0)
|
|
y = 0;
|
|
if (y_off > y)
|
|
*y_off_ptr = y_off = y;
|
|
return y_off;
|
|
}
|
|
|
|
|
|
void
|
|
move_print(int *yp, int *y_off_ptr, int dy, int x, char *pat, ...)
|
|
{
|
|
va_list args;
|
|
int y;
|
|
|
|
if (*y_off_ptr != 0) {
|
|
y = MIN(dy, *y_off_ptr);
|
|
dy -= y;
|
|
*y_off_ptr -= y;
|
|
if (dy == 0 || *y_off_ptr != 0)
|
|
return;
|
|
}
|
|
|
|
y = *yp;
|
|
if (pat != 0 && *pat != '\0' && y+MAX(dy,1) <= BOS) {
|
|
move(y,x);
|
|
va_start(args, pat);
|
|
vwprintw(win,pat,args);
|
|
va_end(args);
|
|
}
|
|
*yp = y + dy;
|
|
}
|
|
|
|
|
|
void
|
|
sprip(int y, int *y_off_ptr)
|
|
{
|
|
int y_off = ck_y_off(20, y, y_off_ptr);
|
|
struct kna tipstat;
|
|
struct ipstat *ipp;
|
|
#define COL0 1
|
|
#define ST tipstat.ipstat
|
|
#define MP(p,v) move_print(&y, &y_off, 1, COL0, p, v)
|
|
|
|
if (getkna(&tipstat)) {
|
|
(void)fail("sprip: failed sysmp MP_SAGET\n");
|
|
return;
|
|
}
|
|
get_ipforwarding();
|
|
|
|
ipp = (cmode == DELTA) ? &ipstat : &zipstat;
|
|
|
|
move(y,COL0);
|
|
printw("%10u total packets received\t",
|
|
ST.ips_total-ipp->ips_total);
|
|
MP("%10u with bad checksum",
|
|
ST.ips_badsum-ipp->ips_badsum);
|
|
MP("%10u with size smaller than minimum",
|
|
ST.ips_toosmall-ipp->ips_toosmall);
|
|
MP("%10u with data size < data length",
|
|
ST.ips_tooshort-ipp->ips_tooshort);
|
|
MP("%10u with header length < data size",
|
|
ST.ips_badhlen-ipp->ips_badhlen);
|
|
MP("%10u with data length < header length",
|
|
ST.ips_badlen-ipp->ips_badlen);
|
|
MP("%10u with bad options",
|
|
ST.ips_badoptions-ipp->ips_badoptions);
|
|
MP("%10u fragments received",
|
|
ST.ips_fragments-ipp->ips_fragments);
|
|
MP("%10u fragments dropped (dup or out of space)",
|
|
ST.ips_fragdropped-ipp->ips_fragdropped);
|
|
MP("%10u fragments dropped after timeout",
|
|
ST.ips_fragtimeout-ipp->ips_fragtimeout);
|
|
MP("%10u packets for this host",
|
|
ST.ips_delivered-ipp->ips_delivered);
|
|
MP("%10u packets recvd for unknown/unsupported protocol",
|
|
ST.ips_noproto-ipp->ips_noproto);
|
|
|
|
MP((ipforwarding
|
|
? "%10u packets forwarded (forwarding enabled)"
|
|
: "%10u packets forwarded (forwarding disabled)"),
|
|
ST.ips_forward-ipp->ips_forward);
|
|
MP("%10u packets not forwardable",
|
|
ST.ips_cantforward-ipp->ips_cantforward);
|
|
MP("%10u redirects sent",
|
|
ST.ips_redirectsent-ipp->ips_redirectsent);
|
|
|
|
MP("%10u packets sent from this host",
|
|
ST.ips_localout-ipp->ips_localout);
|
|
MP("%10u output packets dropped due to no bufs, etc.",
|
|
ST.ips_odropped-ipp->ips_odropped);
|
|
MP("%10u output packets discarded due to no route",
|
|
ST.ips_noroute-ipp->ips_noroute);
|
|
MP("%10u datagrams fragmented",
|
|
ST.ips_fragmented-ipp->ips_fragmented);
|
|
MP("%10u fragments created",
|
|
ST.ips_ofragments-ipp->ips_ofragments);
|
|
MP("%10u datagrams that can't be fragmented",
|
|
ST.ips_cantfrag-ipp->ips_cantfrag);
|
|
|
|
ipstat = ST;
|
|
#undef ST
|
|
#undef MP
|
|
#undef COL0
|
|
}
|
|
|
|
|
|
|
|
static struct icmpstat icmpstat, zicmpstat;
|
|
static unsigned char in_shown[ICMP_MAXTYPE];
|
|
static int total_in_shown = 1;
|
|
static unsigned char out_shown[ICMP_MAXTYPE];
|
|
static int total_out_shown = 1;
|
|
|
|
void
|
|
initicmp(void)
|
|
{
|
|
bzero(&zicmpstat, sizeof(zicmpstat));
|
|
}
|
|
|
|
void
|
|
zeroicmp(void)
|
|
{
|
|
zicmpstat = icmpstat;
|
|
}
|
|
|
|
void
|
|
spricmp(int y, int *y_off_ptr)
|
|
{
|
|
int y_off = ck_y_off(total_in_shown/2+total_out_shown/2+9, y,
|
|
y_off_ptr);
|
|
int i, x;
|
|
struct kna ticmpstat;
|
|
struct icmpstat *icmpp;
|
|
#define ST ticmpstat.icmpstat
|
|
#define COL0 5
|
|
#define COL1 1
|
|
#define COL2 33
|
|
#define MP(dy,x,p,v) move_print(&y, &y_off, dy, x, p, v)
|
|
|
|
if (getkna(&ticmpstat)) {
|
|
(void)fail("spricmp: failed sysmp MP_SAGET\n");
|
|
return;
|
|
}
|
|
|
|
icmpp = (cmode == DELTA) ? &icmpstat : &zicmpstat;
|
|
|
|
MP(1, COL0, "%10u messages with bad code fields",
|
|
ST.icps_badcode-icmpp->icps_badcode);
|
|
MP(1, COL0,"%10u messages < minimum length",
|
|
ST.icps_tooshort-icmpp->icps_tooshort);
|
|
MP(1, COL0,"%10u messages with bad checksum",
|
|
ST.icps_checksum-icmpp->icps_checksum);
|
|
MP(1, COL0,"%10u messages with bad length",
|
|
ST.icps_badlen-icmpp->icps_badlen);
|
|
MP(1, COL0,"%10u calls to icmp_error",
|
|
ST.icps_error-icmpp->icps_error);
|
|
MP(1, COL0,"%10u errors not generated 'cuz old message was icmp",
|
|
ST.icps_oldicmp-icmpp->icps_oldicmp);
|
|
MP(1, COL0,"%10u message responses generated",
|
|
ST.icps_reflect-icmpp->icps_reflect);
|
|
for (x = 0, i = 0; i < ICMP_MAXTYPE+1; i++) {
|
|
if (ST.icps_inhist[i] != 0 || in_shown[i]) {
|
|
if (x == 0)
|
|
MP(1, x = COL1, "Input histogram:",0);
|
|
move_print(&y, &y_off, x==COL1 ? 0 : 1, x,
|
|
"%7u %s",
|
|
ST.icps_inhist[i] - icmpp->icps_inhist[i],
|
|
icmpnames[i]);
|
|
x = (x==COL1) ? COL2 : COL1;
|
|
if (! in_shown[i]) {
|
|
in_shown[i] = 1;
|
|
total_in_shown++;
|
|
}
|
|
}
|
|
}
|
|
if (x == COL2)
|
|
MP(1, x, "", 0);
|
|
for (x = 0, i = 0; i < ICMP_MAXTYPE+1; i++) {
|
|
if (ST.icps_outhist[i] != 0 || out_shown[i]) {
|
|
if (x == 0)
|
|
MP(1, x = COL1, "Output histogram:",0);
|
|
move_print(&y, &y_off, x==COL1 ? 0 : 1, x,
|
|
"%7u %s",
|
|
ST.icps_outhist[i] - icmpp->icps_outhist[i],
|
|
icmpnames[i]);
|
|
x = (x==COL1) ? COL2 : COL1;
|
|
if (!out_shown[i]) {
|
|
out_shown[i] = 1;
|
|
total_out_shown++;
|
|
}
|
|
}
|
|
}
|
|
icmpstat = ST;
|
|
|
|
#undef COL0
|
|
#undef COL1
|
|
#undef COL2
|
|
#undef ST
|
|
#undef MP
|
|
}
|
|
|
|
|
|
static struct udpstat udpstat, zudpstat;
|
|
void
|
|
initudp(void)
|
|
{
|
|
bzero((char*)&zudpstat, sizeof(zudpstat));
|
|
}
|
|
|
|
void
|
|
zeroudp(void)
|
|
{
|
|
zudpstat = udpstat;
|
|
}
|
|
|
|
void
|
|
sprudp(int y, int *y_off_ptr)
|
|
{
|
|
int y_off = ck_y_off(9, y, y_off_ptr);
|
|
u_long delivered;
|
|
struct kna tudpstat;
|
|
struct udpstat *udpp;
|
|
#define COL0 1
|
|
#define ST tudpstat.udpstat
|
|
#define MP(p,v) move_print(&y, &y_off, 1, COL0, p, v)
|
|
|
|
if (getkna(&tudpstat)) {
|
|
(void)fail("sprudp: failed sysmp MP_SAGET\n");
|
|
return;
|
|
}
|
|
|
|
udpp = (cmode == DELTA) ? &udpstat : &zudpstat;
|
|
|
|
MP("%10u total datagrams received",
|
|
ST.udps_ipackets-udpp->udps_ipackets);
|
|
MP("%10u with incomplete header",
|
|
ST.udps_hdrops-udpp->udps_hdrops);
|
|
MP("%10u with bad data length field",
|
|
ST.udps_badlen-udpp->udps_badlen);
|
|
MP("%10u with bad checksum",
|
|
ST.udps_badsum-udpp->udps_badsum);
|
|
MP("%10u datagrams dropped due to no socket",
|
|
ST.udps_noport-udpp->udps_noport);
|
|
MP("%10u broadcast/multicast datagrams dropped due to no socket",
|
|
ST.udps_noportbcast-udpp->udps_noportbcast);
|
|
MP("%10u datagrams dropped due to full socket buffers",
|
|
ST.udps_fullsock-udpp->udps_fullsock);
|
|
delivered = ((ST.udps_ipackets - udpp->udps_ipackets)
|
|
- (ST.udps_hdrops - udpp->udps_hdrops)
|
|
- (ST.udps_badlen - udpp->udps_badlen)
|
|
- (ST.udps_badsum - udpp->udps_badsum)
|
|
- (ST.udps_noport - udpp->udps_noport)
|
|
- (ST.udps_noportbcast - udpp->udps_noportbcast)
|
|
- (ST.udps_fullsock - udpp->udps_fullsock));
|
|
|
|
MP("%10u datagrams delivered", delivered);
|
|
MP("%10u datagrams output",
|
|
ST.udps_opackets-udpp->udps_opackets);
|
|
|
|
udpstat = ST;
|
|
#undef ST
|
|
#undef MP
|
|
#undef COL0
|
|
}
|
|
|
|
|
|
static struct tcpstat tcpstat, ztcpstat;
|
|
void
|
|
inittcp(void)
|
|
{
|
|
bzero((char*)&ztcpstat, sizeof(ztcpstat));
|
|
}
|
|
|
|
void
|
|
zerotcp()
|
|
{
|
|
ztcpstat = tcpstat;
|
|
}
|
|
|
|
void
|
|
sprtcp(int y, int *y_off_ptr)
|
|
{
|
|
int y_off = ck_y_off(42, y, y_off_ptr);
|
|
struct kna ttcpstat;
|
|
struct tcpstat *tcpp;
|
|
#define COL0 1
|
|
#define P(f,p) move_print(&y,&y_off,1,COL0, p,ttcpstat.tcpstat.f - tcpp->f)
|
|
#define P2(f1, f2, p) move_print(&y,&y_off,1,COL0, p, \
|
|
ttcpstat.tcpstat.f1 - tcpp->f1,\
|
|
ttcpstat.tcpstat.f2 - tcpp->f2)
|
|
|
|
if (getkna(&ttcpstat)) {
|
|
(void)fail("sprtcp: failed sysmp MP_SAGET\n");
|
|
return;
|
|
}
|
|
|
|
tcpp = (cmode == DELTA) ? &tcpstat : &ztcpstat;
|
|
|
|
P(tcps_sndtotal, "%10u packets sent\t");
|
|
P2(tcps_sndpack, tcps_sndbyte,
|
|
"%18u data packets (%u bytes)\t\t");
|
|
P2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
|
|
"%18u retransmitted data packets (%u bytes)\t\t");
|
|
P2(tcps_sndacks, tcps_delack,
|
|
"%18u ack-only packets (%u delayed)\t\t");
|
|
P(tcps_sndurg, "%18u URG only packets\t\t");
|
|
P(tcps_sndprobe, "%18u window probe packets\t\t");
|
|
P(tcps_sndwinup, "%18u window update packets\t\t");
|
|
P(tcps_sndctrl, "%18u control packets\t\t");
|
|
P(tcps_rcvtotal, "%10u packets received\t");
|
|
P2(tcps_rcvackpack,tcps_rcvackbyte, "%18u acks (for %u bytes)\t\t");
|
|
P(tcps_predack, "%18u ack predictions ok\t");
|
|
P(tcps_rcvdupack, "%18u duplicate acks\t");
|
|
P(tcps_rcvacktoomuch, "%18u ACKs for unsent data\t\t");
|
|
P2(tcps_rcvpack, tcps_rcvbyte,
|
|
"%18u packets (%u bytes) received in-sequence\t\t");
|
|
P(tcps_preddat, "%18u in-sequence predictions ok\t");
|
|
P2(tcps_rcvduppack, tcps_rcvdupbyte,
|
|
"%18u completely duplicate packets (%u bytes)\t\t");
|
|
P2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
|
|
"%18u packets with some dup. data (%u bytes duped)\t\t");
|
|
P2(tcps_rcvoopack, tcps_rcvoobyte,
|
|
"%18u out-of-order packets (%u bytes)\t\t");
|
|
P2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
|
|
"%18u packets (%u bytes) of data after window\t\t");
|
|
P(tcps_rcvwinprobe, "%18u window probes\t\t");
|
|
P(tcps_rcvwinupd, "%18u window update packets\t\t");
|
|
P(tcps_rcvafterclose, "%18u packets received after close\t\t");
|
|
P(tcps_rcvbadsum, "%18u discarded for bad checksums\t");
|
|
P(tcps_rcvbadoff, "%18u discarded for bad header offset fields\t");
|
|
P(tcps_rcvshort, "%18u discarded because packet too short\t");
|
|
P(tcps_pawsdrop, "%18u discarded because of old timestamp\t\t");
|
|
P2(tcps_connattempt, tcps_accepts,
|
|
"%10u connection requests, %u connection accepts\t");
|
|
P(tcps_listendrop, "%18u listen queue overflows\t\t");
|
|
P(tcps_badsyn, "%18u bad connection attempt\t\t");
|
|
P(tcps_synpurge, "%18u drops from listen queue\t\t");
|
|
|
|
P(tcps_connects,
|
|
"%10u connections established (including accepts)\t");
|
|
P2(tcps_closed, tcps_drops,
|
|
"%10u connections closed (including %u drops)\t");
|
|
P(tcps_conndrops, "%10u embryonic connections dropped\t\t");
|
|
P2(tcps_rttupdated, tcps_segstimed,
|
|
"%10u segments updated rtt (of %u attempts)\t\t");
|
|
P2(tcps_rexmttimeo, tcps_keeptimeo,
|
|
"%10u retransmit timeouts, %u keepalive timeouts\t");
|
|
P(tcps_timeoutdrop, "%18u connection dropped by rexmit timeoutt\t");
|
|
P(tcps_persisttimeo, "%10u persist timeouts\t\t");
|
|
P(tcps_persistdrop,"%18u connections dropped by persist timeout\t\t");
|
|
P(tcps_keeptimeo, "%10u keepalive timeouts\t\t");
|
|
P(tcps_keepprobe, "%18u keepalive probes sent\t\t");
|
|
P(tcps_keepdrops, "%18u connections dropped by keepalive\t\t");
|
|
|
|
tcpstat = ttcpstat.tcpstat;
|
|
#undef COL0
|
|
#undef P
|
|
#undef P2
|
|
}
|
|
|
|
|
|
static int total_shown_sockstat;
|
|
static struct sockstat shown_sockstat, sockstat, zsockstat;
|
|
static struct socket_types {
|
|
int st_type;
|
|
char *st_name;
|
|
} socket_types[] = {
|
|
{ 0, "Zero/Illegal sockets" },
|
|
{ SOCK_DGRAM, "DATAGRAM/TPI_CLTS sockets" },
|
|
{ SOCK_STREAM, "STREAM sockets" },
|
|
{ _NC_TPI_COTS_ORD, "TPI_COTS_ORD sockets" },
|
|
{ SOCK_RAW, "RAW/TPI_RAW sockets" },
|
|
{ SOCK_RDM, "RDM sockets" },
|
|
{ SOCK_SEQPACKET, "SEQPACKET sockets" },
|
|
{ TCPSTAT_TPISOCKET, "TPI_COTS sockets" },
|
|
{ 0, 0 }
|
|
};
|
|
static struct tcp_states {
|
|
int tcp_type;
|
|
char *tcp_name;
|
|
} tcp_states[] = {
|
|
{ 0, "CLOSED state" }, /* refer to tcp_fsm.h for actual symbols */
|
|
{ 1, "LISTEN state" },
|
|
{ 2, "SYN_SENT state" },
|
|
{ 3, "SYN_RECEIVED state" },
|
|
{ 4, "ESTABLISHED state" },
|
|
{ 5, "CLOSE_WAIT state" },
|
|
{ 6, "FIN_WAIT_1 state" },
|
|
{ 7, "CLOSING state" },
|
|
{ 8, "LAST_ACK state" },
|
|
{ 9, "FIN_WAIT_2 state" },
|
|
{ 10, "TIME_WAIT state" },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
void
|
|
initsock(void)
|
|
{
|
|
bzero ((char*)&zsockstat, sizeof(zsockstat));
|
|
bzero ((char *)&shown_sockstat, sizeof(zsockstat));
|
|
}
|
|
|
|
void
|
|
zerosock()
|
|
{
|
|
zsockstat = sockstat;
|
|
}
|
|
|
|
void
|
|
sprsock(int y, int *y_off_ptr)
|
|
{
|
|
int y_off = ck_y_off(2+total_shown_sockstat, y, y_off_ptr);
|
|
struct sockstat seen_sockstat, tsockstat;
|
|
struct socket_types *sp;
|
|
struct tcp_states *tp;
|
|
u_long active_socks;
|
|
int err, i;
|
|
#define COL0 1
|
|
|
|
bzero (&seen_sockstat, sizeof(struct sockstat));
|
|
err = sysmp(MP_SAGET1, MPSA_SOCKSTATS, &tsockstat,
|
|
sizeof(struct sockstat), 0);
|
|
if (err < 0) {
|
|
(void)fail("sprsock: failed sysmp MPSA_SOCKSTATS; errno %d\n",
|
|
errno);
|
|
return;
|
|
}
|
|
for (i=0; i < TCPSTAT_NUM_SOCKTYPES; i++) {
|
|
if (tsockstat.open_sock[i] > 0) seen_sockstat.open_sock[i] = 1;
|
|
}
|
|
for (i=0; i < TCPSTAT_NUM_TCPSTATES; i++) {
|
|
if (tsockstat.tcp_sock[i] > 0) seen_sockstat.tcp_sock[i] = 1;
|
|
}
|
|
|
|
active_socks = 0;
|
|
for (i=0; i < TCPSTAT_NUM_SOCKTYPES; i++) {
|
|
active_socks += tsockstat.open_sock[i];
|
|
}
|
|
move_print(&y,&y_off,1,COL0, "%10u Active socket types\t\t",
|
|
active_socks);
|
|
for (sp = socket_types; sp->st_name; sp++) {
|
|
seen_sockstat.open_sock[sp->st_type] = 1;
|
|
if (tsockstat.open_sock[sp->st_type] == 0
|
|
&& !shown_sockstat.open_sock[sp->st_type]) {
|
|
continue;
|
|
}
|
|
move_print(&y,&y_off,1,COL0, "%18u %s\t\t",
|
|
tsockstat.open_sock[sp->st_type], sp->st_name);
|
|
if (! shown_sockstat.open_sock[sp->st_type]) {
|
|
shown_sockstat.open_sock[sp->st_type] = 1;
|
|
total_shown_sockstat++;
|
|
}
|
|
}
|
|
|
|
move_print(&y,&y_off,1,COL0, "%10u Total TCP connections\t\t",
|
|
tsockstat.open_sock[2]);
|
|
for (tp = tcp_states; tp->tcp_name && y < BOS-1; tp++) {
|
|
seen_sockstat.tcp_sock[tp->tcp_type] = 1;
|
|
if (tsockstat.tcp_sock[tp->tcp_type] == 0
|
|
&& !shown_sockstat.tcp_sock[tp->tcp_type]) {
|
|
continue;
|
|
}
|
|
move_print(&y,&y_off,1,COL0, "%18u %s\t\t",
|
|
tsockstat.tcp_sock[tp->tcp_type], tp->tcp_name);
|
|
shown_sockstat.tcp_sock[tp->tcp_type] = 1;
|
|
}
|
|
sockstat = tsockstat;
|
|
#undef COL0
|
|
}
|
|
|