Annotation of 43BSD/ucb/systat/netstat.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)netstat.c  5.2 (Berkeley) 12/11/85";
                      9: #endif not lint
                     10: 
                     11: /*
                     12:  * netstat
                     13:  */
                     14: #include "systat.h"
                     15: 
                     16: #include <sys/socket.h>
                     17: #include <sys/socketvar.h>
                     18: #include <sys/mbuf.h>
                     19: #include <sys/protosw.h>
                     20: 
                     21: #include <net/route.h>
                     22: #include <netinet/in_systm.h>
                     23: #include <netinet/in_pcb.h>
                     24: #include <netinet/ip.h>
                     25: #include <netinet/ip_icmp.h>
                     26: #include <netinet/icmp_var.h>
                     27: #include <netinet/ip_var.h>
                     28: #include <netinet/tcp.h>
                     29: #include <netinet/tcpip.h>
                     30: #include <netinet/tcp_seq.h>
                     31: #define TCPSTATES
                     32: #include <netinet/tcp_fsm.h>
                     33: #include <netinet/tcp_timer.h>
                     34: #include <netinet/tcp_var.h>
                     35: #include <netinet/tcp_debug.h>
                     36: #include <netinet/udp.h>
                     37: #include <netinet/udp_var.h>
                     38: 
                     39: #define        streq(a,b)      (strcmp(a,b)==0)
                     40: #define        YMAX(w)         ((w)->_maxy-1)
                     41: 
                     42: WINDOW *
                     43: opennetstat()
                     44: {
                     45: 
                     46:        sethostent(1);
                     47:        setnetent(1);
                     48:        return (subwin(stdscr, LINES-5-1, 0, 5, 0));
                     49: }
                     50: 
                     51: struct netinfo {
                     52:        struct  netinfo *ni_forw, *ni_prev;
                     53:        short   ni_line;                /* line on screen */
                     54:        short   ni_seen;                /* 0 when not present in list */
                     55:        short   ni_flags;
                     56: #define        NIF_LACHG       0x1             /* local address changed */
                     57: #define        NIF_FACHG       0x2             /* foreign address changed */
                     58:        short   ni_state;               /* tcp state */
                     59:        char    *ni_proto;              /* protocol */
                     60:        struct  in_addr ni_laddr;       /* local address */
                     61:        long    ni_lport;               /* local port */
                     62:        struct  in_addr ni_faddr;       /* foreign address */
                     63:        long    ni_fport;               /* foreign port */
                     64:        long    ni_rcvcc;               /* rcv buffer character count */
                     65:        long    ni_sndcc;               /* snd buffer character count */
                     66: };
                     67: 
                     68: static struct {
                     69:        struct  netinfo *ni_forw, *ni_prev;
                     70: } netcb;
                     71: 
                     72: static int aflag = 0;
                     73: static int nflag = 0;
                     74: static int lastrow = 1;
                     75: static char *inetname();
                     76: 
                     77: closenetstat(w)
                     78:         WINDOW *w;
                     79: {
                     80:        register struct netinfo *p;
                     81: 
                     82:        endhostent();
                     83:        endnetent();
                     84:        p = netcb.ni_forw;
                     85:        while (p != (struct netinfo *)&netcb) {
                     86:                if (p->ni_line != -1)
                     87:                        lastrow--;
                     88:                p->ni_line = -1;
                     89:                p = p->ni_forw;
                     90:        }
                     91:         if (w != NULL) {
                     92:                wclear(w);
                     93:                wrefresh(w);
                     94:                delwin(w);
                     95:        }
                     96: }
                     97: 
                     98: static struct nlist nlst[] = {
                     99: #define        X_TCB   0
                    100:        { "_tcb" },
                    101: #define        X_UDB   1
                    102:        { "_udb" },
                    103:         { "" },
                    104: };
                    105: 
                    106: initnetstat()
                    107: {
                    108: 
                    109:        nlist("/vmunix", nlst);
                    110:        if (nlst[X_TCB].n_value == 0) {
                    111:                error("No symbols in namelist");
                    112:                return(0);
                    113:        }
                    114:        netcb.ni_forw = netcb.ni_prev = (struct netinfo *)&netcb;
                    115:        protos = TCP|UDP;
                    116:        return(1);
                    117: }
                    118: 
                    119: fetchnetstat()
                    120: {
                    121:        register struct inpcb *prev, *next;
                    122:        register struct netinfo *p;
                    123:        struct inpcb inpcb;
                    124:        struct socket sockb;
                    125:        struct tcpcb tcpcb;
                    126:        off_t off;
                    127:        int istcp;
                    128: 
                    129:        if (nlst[X_TCB].n_value == 0)
                    130:                return;
                    131:        for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw)
                    132:                p->ni_seen = 0;
                    133:        if (protos == 0)
                    134:                error("No protocols to display");
                    135:        if (protos&TCP)
                    136:                off = nlst[X_TCB].n_value, istcp = 1;
                    137:        else if (protos&UDP)
                    138:                off = nlst[X_UDB].n_value, istcp = 0;
                    139: again:
                    140:        lseek(kmem, off, L_SET);
                    141:        read(kmem, &inpcb, sizeof (struct inpcb));
                    142:        prev = (struct inpcb *)off;
                    143:        for (; inpcb.inp_next != (struct inpcb *)off; prev = next) {
                    144:                next = inpcb.inp_next;
                    145:                lseek(kmem, (off_t)next, L_SET);
                    146:                read(kmem, &inpcb, sizeof (inpcb));
                    147:                if (inpcb.inp_prev != prev) {
                    148:                        p = netcb.ni_forw;
                    149:                        for (; p != (struct netinfo *)&netcb; p = p->ni_forw)
                    150:                                p->ni_seen = 1;
                    151:                        error("Kernel state in transition");
                    152:                        return;
                    153:                }
                    154:                if (!aflag && inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
                    155:                        continue;
                    156:                if (nhosts && !checkhost(&inpcb))
                    157:                        continue;
                    158:                if (nports && !checkport(&inpcb))
                    159:                        continue;
                    160:                lseek(kmem, (off_t)inpcb.inp_socket, L_SET);
                    161:                read(kmem, &sockb, sizeof (sockb));
                    162:                lseek(kmem, (off_t)inpcb.inp_ppcb, L_SET);
                    163:                if (istcp) {
                    164:                        read(kmem, &tcpcb, sizeof (tcpcb));
                    165:                        enter(&inpcb, &sockb, tcpcb.t_state, "tcp");
                    166:                } else
                    167:                        enter(&inpcb, &sockb, 0, "udp");
                    168:        }
                    169:        if (istcp && (protos&UDP)) {
                    170:                istcp = 0;
                    171:                off = nlst[X_UDB].n_value;
                    172:                goto again;
                    173:        }
                    174: }
                    175: 
                    176: static
                    177: enter(inp, so, state, proto)
                    178:        register struct inpcb *inp;
                    179:        register struct socket *so;
                    180:        int state;
                    181:        char *proto;
                    182: {
                    183:        register struct netinfo *p;
                    184: 
                    185:        /*
                    186:         * Only take exact matches, any sockets with
                    187:         * previously unbound addresses will be deleted
                    188:         * below in the display routine because they
                    189:         * will appear as ``not seen'' in the kernel
                    190:         * data structures.
                    191:         */
                    192:        for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw) {
                    193:                if (!streq(proto, p->ni_proto))
                    194:                        continue;
                    195:                if (p->ni_lport != inp->inp_lport ||
                    196:                    p->ni_laddr.s_addr != inp->inp_laddr.s_addr)
                    197:                        continue;
                    198:                if (p->ni_faddr.s_addr == inp->inp_faddr.s_addr &&
                    199:                    p->ni_fport == inp->inp_fport)
                    200:                        break;
                    201:        }
                    202:        if (p == (struct netinfo *)&netcb) {
                    203:                p = (struct netinfo *)malloc(sizeof (*p));
                    204:                if (p == 0) {
                    205:                        error("Out of memory");
                    206:                        return;
                    207:                }
                    208:                insque(p, &netcb);
                    209:                p->ni_line = -1;
                    210:                p->ni_laddr = inp->inp_laddr;
                    211:                p->ni_lport = inp->inp_lport;
                    212:                p->ni_faddr = inp->inp_faddr;
                    213:                p->ni_fport = inp->inp_fport;
                    214:                p->ni_proto = proto;
                    215:                p->ni_flags = NIF_LACHG|NIF_FACHG;
                    216:        }
                    217:        p->ni_rcvcc = so->so_rcv.sb_cc;
                    218:        p->ni_sndcc = so->so_snd.sb_cc;
                    219:        p->ni_state = state;
                    220:        p->ni_seen = 1;
                    221: }
                    222: 
                    223: /* column locations */
                    224: #define        LADDR   0
                    225: #define        FADDR   LADDR+23
                    226: #define        PROTO   FADDR+23
                    227: #define        RCVCC   PROTO+6
                    228: #define        SNDCC   RCVCC+7
                    229: #define        STATE   SNDCC+7
                    230: 
                    231: labelnetstat()
                    232: {
                    233: 
                    234:         if (nlst[X_TCB].n_type == 0)
                    235:                 return;
                    236:         wmove(wnd, 0, 0); wclrtobot(wnd);
                    237:        mvwaddstr(wnd, 0, LADDR, "Local Address");
                    238:        mvwaddstr(wnd, 0, FADDR, "Foreign Address");
                    239:        mvwaddstr(wnd, 0, PROTO, "Proto");
                    240:        mvwaddstr(wnd, 0, RCVCC, "Recv-Q");
                    241:        mvwaddstr(wnd, 0, SNDCC, "Send-Q");
                    242:        mvwaddstr(wnd, 0, STATE, "(state)"); 
                    243: }
                    244: 
                    245: shownetstat()
                    246: {
                    247:        register struct netinfo *p, *q;
                    248: 
                    249:        /*
                    250:         * First, delete any connections that have gone
                    251:         * away and adjust the position of connections
                    252:         * below to reflect the deleted line.
                    253:         */
                    254:        p = netcb.ni_forw;
                    255:        while (p != (struct netinfo *)&netcb) {
                    256:                if (p->ni_line == -1 || p->ni_seen) {
                    257:                        p = p->ni_forw;
                    258:                        continue;
                    259:                }
                    260:                wmove(wnd, p->ni_line, 0); wdeleteln(wnd);
                    261:                q = netcb.ni_forw;
                    262:                for (; q != (struct netinfo *)&netcb; q = q->ni_forw)
                    263:                        if (q != p && q->ni_line > p->ni_line) {
                    264:                                q->ni_line--;
                    265:                                /* this shouldn't be necessary */
                    266:                                q->ni_flags |= NIF_LACHG|NIF_FACHG;
                    267:                        }
                    268:                lastrow--;
                    269:                q = p->ni_forw;
                    270:                remque(p);
                    271:                free((char *)p);
                    272:                p = q;
                    273:        }
                    274:        /*
                    275:         * Update existing connections and add new ones.
                    276:         */
                    277:        for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw) {
                    278:                if (p->ni_line == -1) {
                    279:                        /*
                    280:                         * Add a new entry if possible.
                    281:                         */
                    282:                        if (lastrow > YMAX(wnd))
                    283:                                continue;
                    284:                        p->ni_line = lastrow++;
                    285:                        p->ni_flags |= NIF_LACHG|NIF_FACHG;
                    286:                }
                    287:                if (p->ni_flags & NIF_LACHG) {
                    288:                        wmove(wnd, p->ni_line, LADDR);
                    289:                        inetprint(&p->ni_laddr, p->ni_lport, p->ni_proto);
                    290:                        p->ni_flags &= ~NIF_LACHG;
                    291:                }
                    292:                if (p->ni_flags & NIF_FACHG) {
                    293:                        wmove(wnd, p->ni_line, FADDR);
                    294:                        inetprint(&p->ni_faddr, p->ni_fport, p->ni_proto);
                    295:                        p->ni_flags &= ~NIF_FACHG;
                    296:                }
                    297:                mvwaddstr(wnd, p->ni_line, PROTO, p->ni_proto);
                    298:                mvwprintw(wnd, p->ni_line, RCVCC, "%6d", p->ni_rcvcc);
                    299:                mvwprintw(wnd, p->ni_line, SNDCC, "%6d", p->ni_sndcc);
                    300:                if (streq(p->ni_proto, "tcp"))
                    301:                        if (p->ni_state < 0 || p->ni_state >= TCP_NSTATES)
                    302:                                mvwprintw(wnd, p->ni_line, STATE, "%d",
                    303:                                    p->ni_state);
                    304:                        else
                    305:                                mvwaddstr(wnd, p->ni_line, STATE,
                    306:                                    tcpstates[p->ni_state]);
                    307:                wclrtoeol(wnd);
                    308:        }
                    309:        if (lastrow < YMAX(wnd)) {
                    310:                wmove(wnd, lastrow, 0); wclrtobot(wnd);
                    311:                wmove(wnd, YMAX(wnd), 0); wdeleteln(wnd);       /* XXX */
                    312:        }
                    313: }
                    314: 
                    315: /*
                    316:  * Pretty print an Internet address (net address + port).
                    317:  * If the nflag was specified, use numbers instead of names.
                    318:  */
                    319: static
                    320: inetprint(in, port, proto)
                    321:        register struct in_addr *in;
                    322:        int port;
                    323:        char *proto;
                    324: {
                    325:        struct servent *sp = 0;
                    326:        char line[80], *cp, *index();
                    327: 
                    328:        sprintf(line, "%.*s.", 16, inetname(*in));
                    329:        cp = index(line, '\0');
                    330:        if (!nflag && port)
                    331:                sp = getservbyport(port, proto);
                    332:        if (sp || port == 0)
                    333:                sprintf(cp, "%.8s", sp ? sp->s_name : "*");
                    334:        else
                    335:                sprintf(cp, "%d", ntohs((u_short)port));
                    336:        /* pad to full column to clear any garbage */
                    337:        cp = index(line, '\0');
                    338:        while (cp - line < 22)
                    339:                *cp++ = ' ';
                    340:        *cp = '\0';
                    341:        waddstr(wnd, line);
                    342: }
                    343: 
                    344: /*
                    345:  * Construct an Internet address representation.
                    346:  * If the nflag has been supplied, give 
                    347:  * numeric value, otherwise try for symbolic name.
                    348:  */
                    349: static char *
                    350: inetname(in)
                    351:        struct in_addr in;
                    352: {
                    353:        char *cp = 0;
                    354:        static char line[50];
                    355:        struct hostent *hp;
                    356:        struct netent *np;
                    357: 
                    358:        if (!nflag && in.s_addr != INADDR_ANY) {
                    359:                int net = inet_netof(in);
                    360:                int lna = inet_lnaof(in);
                    361: 
                    362:                if (lna == INADDR_ANY) {
                    363:                        np = getnetbyaddr(net, AF_INET);
                    364:                        if (np)
                    365:                                cp = np->n_name;
                    366:                }
                    367:                if (cp == 0) {
                    368:                        hp = gethostbyaddr(&in, sizeof (in), AF_INET);
                    369:                        if (hp)
                    370:                                cp = hp->h_name;
                    371:                }
                    372:        }
                    373:        if (in.s_addr == INADDR_ANY)
                    374:                strcpy(line, "*");
                    375:        else if (cp)
                    376:                strcpy(line, cp);
                    377:        else {
                    378:                in.s_addr = ntohl(in.s_addr);
                    379: #define C(x)   ((x) & 0xff)
                    380:                sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
                    381:                        C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
                    382:        }
                    383:        return (line);
                    384: }
                    385: 
                    386: cmdnetstat(cmd, args)
                    387:         char *cmd, *args;
                    388: {
                    389:        register struct netinfo *p;
                    390: 
                    391:        if (prefix(cmd, "all")) {
                    392:                aflag = !aflag;
                    393:                goto fixup;
                    394:        }
                    395:        if  (prefix(cmd, "numbers") || prefix(cmd, "names")) {
                    396:                int new;
                    397: 
                    398:                new = prefix(cmd, "numbers");
                    399:                if (new == nflag)
                    400:                        return (1);
                    401:                p = netcb.ni_forw;
                    402:                for (; p != (struct netinfo *)&netcb; p = p->ni_forw) {
                    403:                        if (p->ni_line == -1)
                    404:                                continue;
                    405:                        p->ni_flags |= NIF_LACHG|NIF_FACHG;
                    406:                }
                    407:                nflag = new;
                    408:                goto redisplay;
                    409:        }
                    410:        if (!netcmd(cmd, args))
                    411:                return (0);
                    412: fixup:
                    413:        fetchnetstat();
                    414: redisplay:
                    415:        shownetstat();
                    416:        refresh();
                    417:        return (1);
                    418: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.