2.11BSD/src/new/crash/dispnet.c
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#if defined(DO_SCCS) && !defined(lint)
static char sccsid[] = "@(#)dispnet.c 5.6 (Berkeley) 8/22/87";
#endif
#include <stdio.h>
#include <sys/param.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#define KERNEL /* to get routehash and RTHASHSIZ */
#include <net/route.h>
#undef KERNEL
#include <net/if.h>
#include <net/raw_cb.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/in_pcb.h>
#include <arpa/inet.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcpip.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <sys/un.h>
#include <sys/unpcb.h>
#include "crash.h"
#include "net.h"
char *subhead; /* pntr to sub-heading */
struct arenas arenash = {0}; /* list head */
long lseek();
char *hoststr(),
*sprintf();
char DASHES[] = "---------";
char FWARN[] = "\tWARNING:";
char Fccd[] = "%schar count discrepancy in %s queue; survey gives %d\n";
/*
* Header portion of struct mbufx, defined in mbuf.h
*/
struct mbufxh { /* external part of mbuf */
struct mbuf *mh_mbuf; /* back pointer to mbuf */
short mh_ref; /* reference counter */
};
char *mbtmsgs[] = {
"bget(cache) ",
"bget(alloc) ",
" bfree",
"ioget ",
"sget ",
" sfree",
"MBXGET ",
" MBXFREE",
"MGET ",
" MFREE",
};
#define NMBTMSGS 10
/*
* The following defines are taken from mbuf11.c. They should
* be in an include file.
*/
struct mbuf *mbcache[256]; /* mbuf cache for fast allocation */
u_int mbfree;
u_int mbend;
/* End of stuff taken from mbuf11.c */
struct mbstat mbstat;
struct ipstat ipstat;
int in_ckodd; /* from in_cksum.c */
struct prname {
int pr_id;
char *pr_name;
};
struct prname inetprotos[] = {
{ IPPROTO_ICMP, "icmp" },
{ IPPROTO_GGP, "ggp", },
{ IPPROTO_TCP, "tcp", },
{ IPPROTO_EGP, "egp", },
{ IPPROTO_PUP, "pup", },
{ IPPROTO_UDP, "udp", },
{ IPPROTO_IDP, "idp", },
{ IPPROTO_RAW, "raw", },
0
};
struct prname impprotos[] = {
{ IMPLINK_IP, "ip" },
0
};
struct pfname {
int pf_id;
char *pf_name;
struct prname *pf_protos;
} pfnames[] = {
{ PF_UNSPEC, "unspec", 0 },
{ PF_UNIX, "unix", 0 },
{ PF_INET, "inet", inetprotos },
{ PF_IMPLINK, "implink", impprotos },
{ PF_PUP, "pup", 0 },
{ PF_CHAOS, "chaos", 0 },
{ PF_NS, "ns", 0 },
{ PF_NBS, "nbs", 0 },
{ PF_ECMA, "ecma", 0 },
{ PF_DATAKIT, "datakit", 0 },
{ PF_CCITT, "ccitt", 0 },
{ PF_SNA, "sna", 0 },
{ PF_DECnet, "DECnet", 0 },
{ PF_DLI, "dli", 0 },
{ PF_LAT, "lat", 0 },
{ PF_HYLINK, "hylink", 0 },
{ PF_APPLETALK, "apple", 0 },
0
};
int internetprint();
struct sockname {
int sa_id;
char *sa_name;
int (*sa_printer)();
} addrnames[] = {
{ AF_UNSPEC, "unspec", 0 },
{ AF_UNIX, "unix", 0 },
{ AF_INET, "inet", internetprint },
{ AF_IMPLINK, "implink", internetprint },
{ AF_PUP, "pup", 0 },
{ AF_CHAOS, "chaos", 0 },
{ AF_NS, "ns", 0 },
{ AF_NBS, "nbs", 0 },
{ AF_ECMA, "ecma", 0 },
{ AF_DATAKIT, "datakit", 0 },
{ AF_CCITT, "ccitt", 0 },
{ AF_SNA, "sna", 0 },
{ AF_DECnet, "DECnet", 0 },
{ AF_DLI, "dli", 0 },
{ AF_LAT, "lat", 0 },
{ AF_HYLINK, "hylink", 0 },
{ AF_APPLETALK, "apple", 0 },
0
};
int kmem, /* Global FD for core file */
line;
int nflag = 0; /* Ineternet addresses as 1.2.3.4 ? */
int aflag = 1; /* Display all connections ? */
int Aflag = 1; /* Display pcb address ? */
int tflag = 1; /* Display interface timer ? */
char *interface = NULL; /* interface name */
int unit; /* interface unit */
struct fetch fetchnet[] = {
"_mbstat", (char *) &mbstat, sizeof mbstat,
"_mbfree", (char *) &mbfree, sizeof mbfree,
"_mbend", (char *) &mbend, sizeof mbend,
"_mbcache", (char *) mbcache, sizeof mbcache,
"_alloct", (char *) &alloct, sizeof alloct,
"_in_ckod", (char *) &in_ckodd, sizeof in_ckodd,
END
};
struct display net_tab[] = {
"\nMBUFS:\tfree (low water mark)", (char *) &(mbstat.m_mbufs),DEC,0,
"\tfree (current)", (char *) &(mbstat.m_mbfree), DEC,0,
"\n\tmbufs in mbuf cache", (char *) &mbstat.m_incache, DEC,0,
"\tdrops", (char *) &(mbstat.m_drops), DEC,0,
"\nMBUFX area:\tStart click", (char *) &mbstat.m_mbxbase, MAD,0,
"\tEnd click", (char *) &mbend, MAD,0,
"\n\tSize in bytes", (char *) &mbstat.m_mbxsize, MAD,0,
"\tmbufx free list (mbfree)", (char *) &mbfree, MAD,0,
"\nARENA:\tallocs", (char *) &allocs, MAD,0,
"\talloct", (char *) &alloct, MAD,0,
"\n\tchars free (low water mark)",(char *) &(mbstat.m_clusters),DEC,0,
"\tchars free (current)", (char *) &(mbstat.m_clfree), DEC,0,
"\nMIO area:\tstart of free area", (char *) &mbstat.m_iobase, MAD,0,
"\tchars free", (char *) &mbstat.m_iosize, MAD,0,
"\nMISC:\tin_ckodd", (char *) &in_ckodd, DEC,0,
END
};
struct display mbuf_tab[] = {
"\nnext", (char *) &((struct mbuf *)0)->m_next, MAD,0,
"\toff", (char *) &((struct mbuf *)0)->m_off, MAD,0,
"\tlen", (char *) &((struct mbuf *)0)->m_len, MAD,0,
"\ttype", (char *) &((struct mbuf *)0)->m_type, MAD,0,
"\tclick", (char *) &((struct mbuf *)0)->m_click, MAD,0,
"\tact", (char *) &((struct mbuf *)0)->m_act, MAD,0,
END
};
struct display mbufx_tab[] = {
"\tm_mbuf", (char *) &((struct mbufxh *)0)->mh_mbuf,MAD,0,
"\tm_ref", (char *) &((struct mbufxh *)0)->mh_ref, DEC,0,
END
};
/*
* Display mbuf status info
*/
dispnet()
{
char arena[NWORDS*2];
subhead = "Network Data";
arenap = &arena[0]; /* fill in static variables */
fetch(fetchnet);
allocs = findv("_allocs"); /* fill in automatic variables */
vf("_allocs",(char *)arena, sizeof arena);
newpage();
display(net_tab,0);
putchar('\n'); /* misc checks */
if (alloct-allocs != (NWORDS-1)*2)
printf("%s allocs/alloct inconsistent. Recompile ???\n", FWARN);
if (mbfree != 0 && !VALMBXA(mbfree))
printf("%s mbfree pointer bad\n", FWARN);
if (mbstat.m_incache < 0 || mbstat.m_incache >= mbstat.m_totcache)
printf("%s mbcache pointer bad\n", FWARN);
arenack();
mbufpr();
newpage();
protopr((off_t)findv("_tcb"), "tcp");
protopr((off_t)findv("_udb"), "udp");
rawpr();
tcp_stats((off_t)findv("_tcpstat"), "tcp");
udp_stats((off_t)findv("_udpstat"), "udp");
ip_stats((off_t)findv("_ipstat"), "ip");
icmp_stats((off_t)findv("_icmpstat"), "icmp");
intpr(0,(off_t)findv("_ifnet"));
routepr((off_t)findv("_rthost"),
(off_t)findv("_rtnet"),
(off_t)findv("_rthashsize"));
rt_stats((off_t)findv("_rtstat"));
#ifdef INET
queuepr("_ipintrq", "ip");
#endif INET
queuepr("_rawintr", "raw");
orphans();
clrars(); /* return memory to pool */
}
queuepr(qname, qlbl)
char *qname, *qlbl;
{
struct ifqueue ifqueue; /* packet input queue */
putchar('\n');
if(vf(qlbl, (char *) &ifqueue, sizeof ifqueue)) {
chasedm(ifqueue.ifq_head,"input",ifqueue.ifq_len);
printf("%s input queue:\n", qname);
printf("--head=%o tail=%o len=%d maxlen=%d drops=%d\n",
ifqueue.ifq_head, ifqueue.ifq_tail, ifqueue.ifq_len,
ifqueue.ifq_maxlen, ifqueue.ifq_drops);
}
}
rawpr()
{
register struct rawcb *prev, *next;
struct rawcb *pcbp;
struct rawcb *arawcb;
struct socket *sockp;
struct protosw proto;
struct rawcb rawcb;
int rcvct; /* number of mbufs in receive queue */
int sndct; /* number of mbufs in send queue */
printf("raw:\n");
if (!vf("_rawcb", (char *) &rawcb, sizeof rawcb)) return;
arawcb = (struct rawcb *)findv("_rawcb");
pcbp = &rawcb;
prev = arawcb;
while (pcbp->rcb_next != arawcb) {
next = pcbp->rcb_next;
if (!VALADD(next, struct rawcb)) {
printf("bad rawcb address (");
DUMP((unsigned)next);
puts(")");
break;
}
(putars((unsigned)next,sizeof(struct rawcb),
AS_RAWCB))->as_ref++;
pcbp = XLATE(next, struct rawcb *);
if (pcbp->rcb_prev != prev) {
puts("???");
break;
}
printf("%6o ", next);
if (!VALADD(pcbp->rcb_socket, struct socket)) {
printf("bad socket address (");
DUMP((unsigned)pcbp->rcb_socket);
puts(")");
break;
}
(putars((unsigned)pcbp->rcb_socket,sizeof(struct socket),
AS_SOCK))->as_ref++;
sockp = XLATE(pcbp->rcb_socket, struct socket *);
klseek(kmem, (off_t)sockp->so_proto, 0);
read(kmem, &proto, sizeof (proto));
/* chase the chains of mbufs */
rcvct = chasem(sockp->so_rcv.sb_mb,"recv",sockp->so_rcv.sb_cc);
sndct = chasem(sockp->so_snd.sb_mb,"send",sockp->so_snd.sb_cc);
printaddress(&pcbp->rcb_laddr);
printaddress(&pcbp->rcb_faddr);
printf(" %4d%3d %4d%3d ",sockp->so_rcv.sb_cc, rcvct,
sockp->so_snd.sb_cc, sndct);
printproto(&proto);
putchar('\n');
prev = next;
}
}
mbufpr()
{
struct mbufxh mbufx;
register i, j, k;
unsigned base;
int count;
int freect;
line = 22;
printf("\n\t\t\tMbuf dump\n\nmbcache:");
for (i=0, count=0; i<mbstat.m_totcache; i++) {
if ((count++)%4 == 0) {
putchar('\n');
line++;
}
DUMP((unsigned)mbcache[i]);
fputs(VALMBA(mbcache[i]) ? " " : "(bad) ",stdout);
}
printf("\n\n");
#ifdef DIAGNOSTIC
{ char mbts[32];
for(i=0, j=mbstat.m_tbindex; i<mbstat.m_tbcount; i++, j--) {
if (j < 0)
j = mbstat.m_tbcount - 1;
k = (mbstat.m_tbuf[j].mt_type>>4)&0x0fff;
printf("%3d %s %4x %4x(%2d) ", i,
((k<NMBTMSGS) ? mbtmsgs[k] :
sprintf(mbts, "%16d", k)),
mbstat.m_tbuf[j].mt_arg,
mbstat.m_tbuf[j].mt_pc,
mbstat.m_tbuf[j].mt_type&0x0f);
symbol(mbstat.m_tbuf[j].mt_pc, ISYM,
mbstat.m_tbuf[j].mt_type&0x0f);
putchar('\n');
}
}
#endif DIAGNOSTIC
/* print header */
line += 6;
puts("\n\n\t\t\tMbufs\n\n click mbuf ref next off len act click(mbuf)\n\n");
base = mbstat.m_mbxbase;
for(i=0, freect=0; i<mbstat.m_total ; i++) {
lseek(kmem, ((long)base<<6), 0);
read(kmem, &mbufx, sizeof mbufx);
DUMP(base);
putchar(' ');
DUMP((unsigned)mbufx.mh_mbuf);
printf("%5d ",mbufx.mh_ref);
/* check for validity */
if (mbufx.mh_ref == 0) {
/* free */
freect++;
printf( "%sfree" , DASHES);
if (mbufx.mh_mbuf && !VALMBXA(mbufx.mh_mbuf))
fputs(" (bad pointer)",stdout);
} else if (!VALMBA(mbufx.mh_mbuf)) {
printf( "%sbad mbuf pointer" , DASHES);
} else {
struct arenas *asp;
register int j;
int found = 0;
asp = putars(mbufx.mh_mbuf,sizeof(struct mbuf),AS_MBUF);
for (j=0; j<mbstat.m_totcache && j<mbstat.m_incache;
j++) {
if(mbufx.mh_mbuf == mbcache[j]) {
found++;
break;
}
}
if (found) {
/* in free cache */
freect++;
asp->as_ref++;
printf("%sin free cache",DASHES);
if (mbufx.mh_ref != 1)
fputs("--bad ref count",stdout);
} else {
struct mbuf *mbptr;
mbptr = XLATE(mbufx.mh_mbuf, struct mbuf *);
DUMP(mbptr->m_next);
printf(" %5d ",mbptr->m_off);
printf(" %5d ",mbptr->m_len);
printf(" %5d ",mbptr->m_type);
DUMP(mbptr->m_act);
if ((mbptr->m_click) != base) {
putchar(' ');
DUMP(mbptr->m_click);
}
}
}
putchar('\n');
line++;
if (line > LINESPERPAGE) {
newpage();
puts("\n click mbuf ref next off len act click(mbuf)\n");
}
base += (MSIZE >> 6);
}
if (freect != mbstat.m_mbfree) {
printf("\n%s free count discrepancy--\n", FWARN);
printf("\n\tmbufx survey is %d, mbstat.m_mbfree is %d\n",
freect, mbstat.m_mbfree);
}
}
/*
* Dump mbuf information
* Flag mbufs as free or unaccounted for
*/
orphans()
{
register i;
struct arenas *ap;
puts("\n\t\tMbufs Unaccounted For\n\n\n addr next off len click act\n");
ap = &arenash;
while (ap = ap->as_next) {
struct mbuf *mbptr;
if (ap->as_ref ||
(!(ap->as_flags & AS_MBUF) &&
ap->as_size != sizeof(struct mbuf)))
continue;
mbptr = XLATE(ap->as_addr, struct mbuf *);
DUMP(ap->as_addr);
putchar(' ');
DUMP(mbptr->m_next);
putchar(' ');
DUMP(mbptr->m_off);
printf(" %5d ",mbptr->m_len);
DUMP(mbptr->m_click);
putchar(' ');
DUMP(mbptr->m_act);
if (!(ap->as_flags & AS_MBUF))
fputs(" no refs at all",stdout);
putchar('\n');
}
puts("\n\t\tA Trip through the Arena\n");
ap = &arenash;
while (ap = ap->as_next) {
if (ap->as_ref || (ap->as_flags & AS_MBUF) == AS_MBUF) continue;
printf("addr=%4x size=%d flags=%4x ", ap->as_addr,
ap->as_size, ap->as_flags);
switch (ap->as_size) {
case sizeof(struct ifnet):
puts("ifnet");
break;
case sizeof(struct in_addr):
puts("in_addr");
break;
case sizeof(struct in_ifaddr):
puts("in_ifaddr");
break;
case sizeof(struct inpcb):
puts("inpcb");
break;
case sizeof(struct ipasfrag):
puts("ipasfrag");
break;
case sizeof(struct ipq):
puts("ipq");
break;
case sizeof(struct mbuf):
puts("mbuf");
break;
#ifdef notyet
case sizeof(struct ns_ifaddr):
puts("ns_ifaddr");
break;
case sizeof(struct nspcb):
puts("nspcb");
break;
case sizeof(struct sppcb):
puts("sppcb");
break;
#endif
case sizeof(struct protosw):
puts("protosw");
break;
case sizeof(struct rawcb):
puts("rawcb");
break;
case sizeof(struct rtentry):
puts("rtentry");
break;
case sizeof(struct sockaddr_in):
puts("sockaddr_in");
break;
case sizeof(struct socket):
puts("socket");
break;
case sizeof(struct tcpcb):
puts("tcpcb");
break;
case sizeof(struct tcpiphdr):
puts("tcpiphdr");
break;
case sizeof(struct unpcb):
puts("unpcb");
break;
default:
puts("unknown size");
break;
}
}
}
printproto(sp)
register struct protosw *sp;
{
register struct pfname *pf = pfnames;
register struct prname *pr;
#ifdef HACK
while (pf->pf_name) {
if (pf->pf_id == sp->pr_family) {
printf("%7s/", pf->pf_name);
if (pr = pf->pf_protos)
while (pr->pr_name) {
if (pr->pr_id == sp->pr_protocol) {
printf("%-5s", pr->pr_name);
return;
}
pr++;
}
printf("%-5d", sp->pr_protocol);
return;
}
pf++;
}
printf("%7d/%-5d", sp->pr_family, sp->pr_protocol);
#endif HACK
}
printaddress(sa)
register struct sockaddr *sa;
{
register struct sockname *sn;
for (sn = addrnames; sn->sa_name; sn++)
if (sn->sa_id == sa->sa_family) {
printf("%8s,", sn->sa_name);
if (!sn->sa_printer) goto generic;
(*sn->sa_printer)(sa);
return;
}
printf("%8d,", sa->sa_family);
generic:
printf("%-8s", "?");
}
internetprint(sin)
register struct sockaddr_in *sin;
{
inetprint(&sin->sin_addr, sin->sin_port, "tcp");
}
/*
* Chase list of mbufs, using m_next and m_act fields.
*/
chasedm(mbufp,str,cc)
register struct mbuf *mbufp;
char *str;
int cc;
{
register struct arenas *asp;
int count = 0;
int chcnt = 0;
register struct mbuf *mbptr; /* points into arena */
while (mbufp) {
count += chaseit(mbufp,str,&chcnt);
if (!VALMBA(mbufp)) {
printf("---------bad mbuf pointer in %s queue (=%o)\n",
str,mbufp);
break;
}
if (!(asp=getars(mbufp)) ||
(asp->as_flags&AS_MBUF) != AS_MBUF) {
printf("---------mbuf in %s queue not in list (=%o)\n",
str,mbufp);
break;
}
mbptr = XLATE(mbufp, struct mbuf *);
mbufp = mbptr->m_act;
}
if (cc != chcnt)
printf( Fccd, DASHES, str, chcnt);
return(count);
}
/*
* Chase list of mbufs, using only m_next field.
*/
chasem(mbufp,str,cc)
register struct mbuf *mbufp;
char *str;
int cc;
{
register struct arenas *asp;
int count = 0;
int chcnt = 0;
register struct mbuf *mbptr; /* points into arena */
count = chaseit(mbufp, str, &chcnt);
if (cc != chcnt)
printf( Fccd, DASHES, str, chcnt);
return(count);
}
chaseit(mbufp,str,achcnt)
register struct mbuf *mbufp;
char *str;
int *achcnt;
{
register struct arenas *asp;
int count = 0;
register struct mbuf *mbptr; /* points into arena */
while (mbufp) {
int err = 0;
count++;
if (!VALMBA(mbufp)) {
printf("%sbad mbuf pointer in %s queue (=%o)\n",
DASHES, str,mbufp);
break;
}
else if (!(asp=getars(mbufp)) ||
(asp->as_flags&AS_MBUF) != AS_MBUF) {
printf("%smbuf in %s queue not in list (=%o)\n",
DASHES, str,mbufp);
asp = putars(mbufp,sizeof(struct mbuf),AS_MBUF);
mbptr = XLATE(mbufp, struct mbuf *);
printf("%soff=%d len=%d type=%d act=%o click=%o",DASHES,
mbptr->m_off, mbptr->m_len, mbptr->m_type,
mbptr->m_act, mbptr->m_click);
if(!VALMBXA(mbptr->m_click))
printf("(bad)");
putchar('\n');
}
asp->as_ref++;
mbptr = XLATE(mbufp, struct mbuf *);
if (mbptr->m_len < 0 || mbptr->m_len > MLEN) {
printf("---------bad mbuf length in %s queue;\n",str);
err++;
}
if (mbptr->m_off < MMINOFF || mbptr->m_off >MMAXOFF) {
printf("---------bad mbuf offset in %s queue;\n",str);
err++;
}
if (err)
printf("---------off=%d len=%d type=%d act=%o click=%o\n",
mbptr->m_off, mbptr->m_len, mbptr->m_type,
mbptr->m_act, mbptr->m_click);
*achcnt += mbptr->m_len;
mbufp = mbptr->m_next;
}
return(count);
}
clrars()
{
register struct arenas *asp;
register struct arenas *next = arenash.as_next;
while (asp = next) {
next = asp->as_next;
free(asp);
}
arenash.as_next = (struct arenas *) 0;
}
/*
* Put entry for arena block in arena statistics list
* This version allows entries with the same address
*/
struct arenas *
putars(addr,size,flags)
register unsigned addr;
int size, flags;
{
register struct arenas *asp = &arenash;
register struct arenas *prev;
unsigned temp;
/* calculate size and get busy flag from info in arena */
temp = *(int *)(arenap + (unsigned)addr - allocs - 2);
if (temp&01==0) /* make sure not marked as free */
flags |= AS_FREE;
if ((temp&~01) - addr != size)
flags |= AS_BDSZ;
while(1) {
prev = asp;
asp = asp->as_next;
if (asp == 0 || addr < asp->as_addr) {
if (!(prev->as_next = (struct arenas *)malloc(sizeof(struct arenas)))) barf("out of memory");
prev = prev->as_next;
prev->as_next = asp;
prev->as_size = size;
prev->as_ref = 0;
prev->as_addr = addr;
prev->as_flags = flags;
return(prev);
}
if (addr == asp->as_addr && (!(asp->as_flags & ~AS_ARCK)) && asp->as_size == size && !asp->as_ref) {
asp->as_flags |= flags;
return(asp);
}
}
}
/*
* Find arena stat structure in list
* Return zero if not found.
*/
struct arenas *
getars(addr)
register unsigned addr;
{
register struct arenas *asp = &arenash;
while (asp=asp->as_next) {
if (asp->as_addr == addr)
return(asp);
}
return((struct arenas *)0);
}
/*
* Check arena for consistency
*/
arenack()
{
unsigned ptr = allocs;
unsigned temp;
unsigned next;
int busy;
int size;
int fsize = 0; /* free size, should equal mbstat.clfree */
fputs("\narena check:",stdout);
for (;;) {
temp = *(int *)(ptr - allocs + (unsigned)arenap);
busy = temp & 01;
next = temp & ~01;
if (next < allocs || next > alloct ||
(ptr > next && (ptr != alloct || next != allocs))){
printf("\n%s arena clobbered; location: ", FWARN);
DUMP(ptr);
fputs(" pointer: ",stdout);
DUMP(temp);
return;
}
if (ptr > next) {
printf("\n\tfree count: %d.\n",fsize);
return;
}
size = next - ptr -2;
if (!busy)
fsize += (size+2);
else
putars(ptr+2,size,AS_ARCK);
ptr = next;
}
}
char *
hoststr(addr)
long addr;
{
struct hostent *hp;
hp = gethostbyaddr((char *) &addr, sizeof addr, AF_INET);
if (hp)
return(hp->h_name);
else
return(inet_ntoa(addr));
}
char *
getnet(addr)
union {
long a_long;
char a_octet[4];
} addr;
{
char buf[32];
struct netent *np;
np = getnetbyaddr(inet_netof(addr.a_long), AF_INET);
if (np)
return(np->n_name);
else {
sprintf(buf, "%u", (unsigned)addr.a_octet[0]);
if((unsigned)addr.a_octet[0] >= 128)
sprintf(buf+strlen(buf), ".%u", (unsigned)addr.a_octet[1]);
if((unsigned)addr.a_octet[0] >= 192)
sprintf(buf+strlen(buf), ".%u", (unsigned)addr.a_octet[2]);
return(buf);
}
}
char *
plural(n)
long n;
{
return (n != 1 ? "s" : "");
}
#ifdef for_handy_reference
struct tcpcb {
struct tcpiphdr *seg_next; /* sequencing queue */
struct tcpiphdr *seg_prev;
short t_state; /* state of this connection */
short t_timer[TCPT_NTIMERS]; /* tcp timers */
short t_rxtshift; /* log(2) of rexmt exp. backoff */
struct mbuf *t_tcpopt; /* tcp options */
u_short t_maxseg; /* maximum segment size */
char t_force; /* 1 if forcing out a byte */
u_char t_flags;
#define TF_ACKNOW 0x01 /* ack peer immediately */
#define TF_DELACK 0x02 /* ack, but try to delay it */
#define TF_NODELAY 0x04 /* don't delay packets to coalesce */
#define TF_NOOPT 0x08 /* don't use tcp options */
#define TF_SENTFIN 0x10 /* have sent FIN */
struct tcpiphdr *t_template; /* skeletal packet for transmit */
struct inpcb *t_inpcb; /* back pointer to internet pcb */
/*
* The following fields are used as in the protocol specification.
* See RFC783, Dec. 1981, page 21.
*/
/* send sequence variables */
tcp_seq snd_una; /* send unacknowledged */
tcp_seq snd_nxt; /* send next */
tcp_seq snd_up; /* send urgent pointer */
tcp_seq snd_wl1; /* window update seg seq number */
tcp_seq snd_wl2; /* window update seg ack number */
tcp_seq iss; /* initial send sequence number */
u_short snd_wnd; /* send window */
/* receive sequence variables */
u_short rcv_wnd; /* receive window */
tcp_seq rcv_nxt; /* receive next */
tcp_seq rcv_up; /* receive urgent pointer */
tcp_seq irs; /* initial receive sequence number */
/*
* Additional variables for this implementation.
*/
/* receive variables */
tcp_seq rcv_adv; /* advertised window */
/* retransmit variables */
tcp_seq snd_max; /* highest sequence number sent
* used to recognize retransmits
*/
/* congestion control (for source quench) */
u_short snd_cwnd; /* congestion-controlled window */
/* transmit timing stuff */
short t_idle; /* inactivity time */
short t_rtt; /* round trip time */
u_short max_rcvd; /* most peer has sent into window */
tcp_seq t_rtseq; /* sequence number being timed */
short t_srtt; /* smoothed round-trip time (*10) */
u_short max_sndwnd; /* largest window peer has offered */
/* out-of-band data */
char t_oobflags; /* have some */
char t_iobc; /* input character */
#define TCPOOB_HAVEDATA 0x01
#define TCPOOB_HADDATA 0x02
};
#endif for_handy_reference