Annotation of 43BSD/ucb/systat/netstat.c, revision 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.