Annotation of 43BSDReno/usr.bin/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.4 (Berkeley) 4/11/90";
        !             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/ip.h>
        !            24: #include <netinet/in_pcb.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: #include <paths.h>
        !            39: 
        !            40: #define        streq(a,b)      (strcmp(a,b)==0)
        !            41: #define        YMAX(w)         ((w)->_maxy-1)
        !            42: 
        !            43: WINDOW *
        !            44: opennetstat()
        !            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:        nlist(_PATH_UNIX, nlst);
        !           109:        if (nlst[X_TCB].n_value == 0) {
        !           110:                error("No symbols in namelist");
        !           111:                return(0);
        !           112:        }
        !           113:        netcb.ni_forw = netcb.ni_prev = (struct netinfo *)&netcb;
        !           114:        protos = TCP|UDP;
        !           115:        return(1);
        !           116: }
        !           117: 
        !           118: fetchnetstat()
        !           119: {
        !           120:        register struct inpcb *prev, *next;
        !           121:        register struct netinfo *p;
        !           122:        struct inpcb inpcb;
        !           123:        struct socket sockb;
        !           124:        struct tcpcb tcpcb;
        !           125:        off_t off;
        !           126:        int istcp;
        !           127: 
        !           128:        if (nlst[X_TCB].n_value == 0)
        !           129:                return;
        !           130:        for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw)
        !           131:                p->ni_seen = 0;
        !           132:        if (protos == 0)
        !           133:                error("No protocols to display");
        !           134:        if (protos&TCP)
        !           135:                off = nlst[X_TCB].n_value, istcp = 1;
        !           136:        else if (protos&UDP)
        !           137:                off = nlst[X_UDB].n_value, istcp = 0;
        !           138: again:
        !           139:        lseek(kmem, off, L_SET);
        !           140:        read(kmem, &inpcb, sizeof (struct inpcb));
        !           141:        prev = (struct inpcb *)off;
        !           142:        for (; inpcb.inp_next != (struct inpcb *)off; prev = next) {
        !           143:                next = inpcb.inp_next;
        !           144:                lseek(kmem, (off_t)next, L_SET);
        !           145:                read(kmem, &inpcb, sizeof (inpcb));
        !           146:                if (inpcb.inp_prev != prev) {
        !           147:                        p = netcb.ni_forw;
        !           148:                        for (; p != (struct netinfo *)&netcb; p = p->ni_forw)
        !           149:                                p->ni_seen = 1;
        !           150:                        error("Kernel state in transition");
        !           151:                        return;
        !           152:                }
        !           153:                if (!aflag && inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
        !           154:                        continue;
        !           155:                if (nhosts && !checkhost(&inpcb))
        !           156:                        continue;
        !           157:                if (nports && !checkport(&inpcb))
        !           158:                        continue;
        !           159:                lseek(kmem, (off_t)inpcb.inp_socket, L_SET);
        !           160:                read(kmem, &sockb, sizeof (sockb));
        !           161:                lseek(kmem, (off_t)inpcb.inp_ppcb, L_SET);
        !           162:                if (istcp) {
        !           163:                        read(kmem, &tcpcb, sizeof (tcpcb));
        !           164:                        enter(&inpcb, &sockb, tcpcb.t_state, "tcp");
        !           165:                } else
        !           166:                        enter(&inpcb, &sockb, 0, "udp");
        !           167:        }
        !           168:        if (istcp && (protos&UDP)) {
        !           169:                istcp = 0;
        !           170:                off = nlst[X_UDB].n_value;
        !           171:                goto again;
        !           172:        }
        !           173: }
        !           174: 
        !           175: static
        !           176: enter(inp, so, state, proto)
        !           177:        register struct inpcb *inp;
        !           178:        register struct socket *so;
        !           179:        int state;
        !           180:        char *proto;
        !           181: {
        !           182:        register struct netinfo *p;
        !           183: 
        !           184:        /*
        !           185:         * Only take exact matches, any sockets with
        !           186:         * previously unbound addresses will be deleted
        !           187:         * below in the display routine because they
        !           188:         * will appear as ``not seen'' in the kernel
        !           189:         * data structures.
        !           190:         */
        !           191:        for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw) {
        !           192:                if (!streq(proto, p->ni_proto))
        !           193:                        continue;
        !           194:                if (p->ni_lport != inp->inp_lport ||
        !           195:                    p->ni_laddr.s_addr != inp->inp_laddr.s_addr)
        !           196:                        continue;
        !           197:                if (p->ni_faddr.s_addr == inp->inp_faddr.s_addr &&
        !           198:                    p->ni_fport == inp->inp_fport)
        !           199:                        break;
        !           200:        }
        !           201:        if (p == (struct netinfo *)&netcb) {
        !           202:                p = (struct netinfo *)malloc(sizeof (*p));
        !           203:                if (p == 0) {
        !           204:                        error("Out of memory");
        !           205:                        return;
        !           206:                }
        !           207:                insque(p, &netcb);
        !           208:                p->ni_line = -1;
        !           209:                p->ni_laddr = inp->inp_laddr;
        !           210:                p->ni_lport = inp->inp_lport;
        !           211:                p->ni_faddr = inp->inp_faddr;
        !           212:                p->ni_fport = inp->inp_fport;
        !           213:                p->ni_proto = proto;
        !           214:                p->ni_flags = NIF_LACHG|NIF_FACHG;
        !           215:        }
        !           216:        p->ni_rcvcc = so->so_rcv.sb_cc;
        !           217:        p->ni_sndcc = so->so_snd.sb_cc;
        !           218:        p->ni_state = state;
        !           219:        p->ni_seen = 1;
        !           220: }
        !           221: 
        !           222: /* column locations */
        !           223: #define        LADDR   0
        !           224: #define        FADDR   LADDR+23
        !           225: #define        PROTO   FADDR+23
        !           226: #define        RCVCC   PROTO+6
        !           227: #define        SNDCC   RCVCC+7
        !           228: #define        STATE   SNDCC+7
        !           229: 
        !           230: labelnetstat()
        !           231: {
        !           232:        if (nlst[X_TCB].n_type == 0)
        !           233:                return;
        !           234:        wmove(wnd, 0, 0); wclrtobot(wnd);
        !           235:        mvwaddstr(wnd, 0, LADDR, "Local Address");
        !           236:        mvwaddstr(wnd, 0, FADDR, "Foreign Address");
        !           237:        mvwaddstr(wnd, 0, PROTO, "Proto");
        !           238:        mvwaddstr(wnd, 0, RCVCC, "Recv-Q");
        !           239:        mvwaddstr(wnd, 0, SNDCC, "Send-Q");
        !           240:        mvwaddstr(wnd, 0, STATE, "(state)"); 
        !           241: }
        !           242: 
        !           243: shownetstat()
        !           244: {
        !           245:        register struct netinfo *p, *q;
        !           246: 
        !           247:        /*
        !           248:         * First, delete any connections that have gone
        !           249:         * away and adjust the position of connections
        !           250:         * below to reflect the deleted line.
        !           251:         */
        !           252:        p = netcb.ni_forw;
        !           253:        while (p != (struct netinfo *)&netcb) {
        !           254:                if (p->ni_line == -1 || p->ni_seen) {
        !           255:                        p = p->ni_forw;
        !           256:                        continue;
        !           257:                }
        !           258:                wmove(wnd, p->ni_line, 0); wdeleteln(wnd);
        !           259:                q = netcb.ni_forw;
        !           260:                for (; q != (struct netinfo *)&netcb; q = q->ni_forw)
        !           261:                        if (q != p && q->ni_line > p->ni_line) {
        !           262:                                q->ni_line--;
        !           263:                                /* this shouldn't be necessary */
        !           264:                                q->ni_flags |= NIF_LACHG|NIF_FACHG;
        !           265:                        }
        !           266:                lastrow--;
        !           267:                q = p->ni_forw;
        !           268:                remque(p);
        !           269:                free((char *)p);
        !           270:                p = q;
        !           271:        }
        !           272:        /*
        !           273:         * Update existing connections and add new ones.
        !           274:         */
        !           275:        for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw) {
        !           276:                if (p->ni_line == -1) {
        !           277:                        /*
        !           278:                         * Add a new entry if possible.
        !           279:                         */
        !           280:                        if (lastrow > YMAX(wnd))
        !           281:                                continue;
        !           282:                        p->ni_line = lastrow++;
        !           283:                        p->ni_flags |= NIF_LACHG|NIF_FACHG;
        !           284:                }
        !           285:                if (p->ni_flags & NIF_LACHG) {
        !           286:                        wmove(wnd, p->ni_line, LADDR);
        !           287:                        inetprint(&p->ni_laddr, p->ni_lport, p->ni_proto);
        !           288:                        p->ni_flags &= ~NIF_LACHG;
        !           289:                }
        !           290:                if (p->ni_flags & NIF_FACHG) {
        !           291:                        wmove(wnd, p->ni_line, FADDR);
        !           292:                        inetprint(&p->ni_faddr, p->ni_fport, p->ni_proto);
        !           293:                        p->ni_flags &= ~NIF_FACHG;
        !           294:                }
        !           295:                mvwaddstr(wnd, p->ni_line, PROTO, p->ni_proto);
        !           296:                mvwprintw(wnd, p->ni_line, RCVCC, "%6d", p->ni_rcvcc);
        !           297:                mvwprintw(wnd, p->ni_line, SNDCC, "%6d", p->ni_sndcc);
        !           298:                if (streq(p->ni_proto, "tcp"))
        !           299:                        if (p->ni_state < 0 || p->ni_state >= TCP_NSTATES)
        !           300:                                mvwprintw(wnd, p->ni_line, STATE, "%d",
        !           301:                                    p->ni_state);
        !           302:                        else
        !           303:                                mvwaddstr(wnd, p->ni_line, STATE,
        !           304:                                    tcpstates[p->ni_state]);
        !           305:                wclrtoeol(wnd);
        !           306:        }
        !           307:        if (lastrow < YMAX(wnd)) {
        !           308:                wmove(wnd, lastrow, 0); wclrtobot(wnd);
        !           309:                wmove(wnd, YMAX(wnd), 0); wdeleteln(wnd);       /* XXX */
        !           310:        }
        !           311: }
        !           312: 
        !           313: /*
        !           314:  * Pretty print an Internet address (net address + port).
        !           315:  * If the nflag was specified, use numbers instead of names.
        !           316:  */
        !           317: static
        !           318: inetprint(in, port, proto)
        !           319:        register struct in_addr *in;
        !           320:        int port;
        !           321:        char *proto;
        !           322: {
        !           323:        struct servent *sp = 0;
        !           324:        char line[80], *cp, *index();
        !           325: 
        !           326:        sprintf(line, "%.*s.", 16, inetname(*in));
        !           327:        cp = index(line, '\0');
        !           328:        if (!nflag && port)
        !           329:                sp = getservbyport(port, proto);
        !           330:        if (sp || port == 0)
        !           331:                sprintf(cp, "%.8s", sp ? sp->s_name : "*");
        !           332:        else
        !           333:                sprintf(cp, "%d", ntohs((u_short)port));
        !           334:        /* pad to full column to clear any garbage */
        !           335:        cp = index(line, '\0');
        !           336:        while (cp - line < 22)
        !           337:                *cp++ = ' ';
        !           338:        *cp = '\0';
        !           339:        waddstr(wnd, line);
        !           340: }
        !           341: 
        !           342: /*
        !           343:  * Construct an Internet address representation.
        !           344:  * If the nflag has been supplied, give 
        !           345:  * numeric value, otherwise try for symbolic name.
        !           346:  */
        !           347: static char *
        !           348: inetname(in)
        !           349:        struct in_addr in;
        !           350: {
        !           351:        char *cp = 0;
        !           352:        static char line[50];
        !           353:        struct hostent *hp;
        !           354:        struct netent *np;
        !           355: 
        !           356:        if (!nflag && in.s_addr != INADDR_ANY) {
        !           357:                int net = inet_netof(in);
        !           358:                int lna = inet_lnaof(in);
        !           359: 
        !           360:                if (lna == INADDR_ANY) {
        !           361:                        np = getnetbyaddr(net, AF_INET);
        !           362:                        if (np)
        !           363:                                cp = np->n_name;
        !           364:                }
        !           365:                if (cp == 0) {
        !           366:                        hp = gethostbyaddr(&in, sizeof (in), AF_INET);
        !           367:                        if (hp)
        !           368:                                cp = hp->h_name;
        !           369:                }
        !           370:        }
        !           371:        if (in.s_addr == INADDR_ANY)
        !           372:                strcpy(line, "*");
        !           373:        else if (cp)
        !           374:                strcpy(line, cp);
        !           375:        else {
        !           376:                in.s_addr = ntohl(in.s_addr);
        !           377: #define C(x)   ((x) & 0xff)
        !           378:                sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
        !           379:                        C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
        !           380:        }
        !           381:        return (line);
        !           382: }
        !           383: 
        !           384: cmdnetstat(cmd, args)
        !           385:        char *cmd, *args;
        !           386: {
        !           387:        register struct netinfo *p;
        !           388: 
        !           389:        if (prefix(cmd, "all")) {
        !           390:                aflag = !aflag;
        !           391:                goto fixup;
        !           392:        }
        !           393:        if  (prefix(cmd, "numbers") || prefix(cmd, "names")) {
        !           394:                int new;
        !           395: 
        !           396:                new = prefix(cmd, "numbers");
        !           397:                if (new == nflag)
        !           398:                        return (1);
        !           399:                p = netcb.ni_forw;
        !           400:                for (; p != (struct netinfo *)&netcb; p = p->ni_forw) {
        !           401:                        if (p->ni_line == -1)
        !           402:                                continue;
        !           403:                        p->ni_flags |= NIF_LACHG|NIF_FACHG;
        !           404:                }
        !           405:                nflag = new;
        !           406:                goto redisplay;
        !           407:        }
        !           408:        if (!netcmd(cmd, args))
        !           409:                return (0);
        !           410: fixup:
        !           411:        fetchnetstat();
        !           412: redisplay:
        !           413:        shownetstat();
        !           414:        refresh();
        !           415:        return (1);
        !           416: }

unix.superglobalmegacorp.com

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