[BACK]Return to netstat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / systat

Annotation of src/usr.bin/systat/netstat.c, Revision 1.26

1.26    ! deraadt     1: /*     $OpenBSD: netstat.c,v 1.25 2004/04/26 19:22:30 itojun Exp $     */
1.1       deraadt     2: /*     $NetBSD: netstat.c,v 1.3 1995/06/18 23:53:07 cgd Exp $  */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1980, 1992, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
1.24      millert    16:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
                     33: #ifndef lint
                     34: #if 0
                     35: static char sccsid[] = "@(#)netstat.c  8.1 (Berkeley) 6/6/93";
                     36: #endif
1.26    ! deraadt    37: static char rcsid[] = "$OpenBSD: netstat.c,v 1.25 2004/04/26 19:22:30 itojun Exp $";
1.1       deraadt    38: #endif /* not lint */
                     39:
                     40: /*
                     41:  * netstat
                     42:  */
                     43: #include <sys/param.h>
                     44: #include <sys/socket.h>
                     45: #include <sys/socketvar.h>
                     46: #include <sys/mbuf.h>
                     47: #include <sys/protosw.h>
                     48:
                     49: #include <netinet/in.h>
                     50: #include <net/route.h>
                     51: #include <netinet/in_systm.h>
                     52: #include <netinet/ip.h>
                     53: #include <netinet/in_pcb.h>
                     54: #include <netinet/ip_icmp.h>
                     55: #include <netinet/icmp_var.h>
                     56: #include <netinet/ip_var.h>
                     57: #include <netinet/tcp.h>
                     58: #include <netinet/tcpip.h>
                     59: #include <netinet/tcp_seq.h>
                     60: #define TCPSTATES
                     61: #include <netinet/tcp_fsm.h>
                     62: #include <netinet/tcp_timer.h>
                     63: #include <netinet/tcp_var.h>
                     64: #include <netinet/tcp_debug.h>
                     65: #include <netinet/udp.h>
                     66: #include <netinet/udp_var.h>
1.7       millert    67: #include <arpa/inet.h>
1.1       deraadt    68:
                     69: #include <netdb.h>
                     70: #include <stdlib.h>
                     71: #include <string.h>
1.16      pvalchev   72: #include <err.h>
1.1       deraadt    73: #include <nlist.h>
                     74: #include <paths.h>
                     75: #include "systat.h"
                     76: #include "extern.h"
                     77:
1.21      millert    78: static void enter(struct inpcb *, struct socket *, int, char *);
                     79: static const char *inetname(struct in_addr);
                     80: static void inetprint(struct in_addr *, int, char *);
                     81: static const char *inet6name(struct in6_addr *);
                     82: static void inet6print(struct in6_addr *, int, char *);
1.1       deraadt    83:
                     84: #define        streq(a,b)      (strcmp(a,b)==0)
1.2       mickey     85: #define        YMAX(w)         ((w)->_maxy-1)
1.1       deraadt    86:
                     87: WINDOW *
1.22      deraadt    88: opennetstat(void)
1.1       deraadt    89: {
                     90:        sethostent(1);
                     91:        setnetent(1);
                     92:        return (subwin(stdscr, LINES-5-1, 0, 5, 0));
                     93: }
                     94:
                     95: struct netinfo {
1.11      angelos    96:        struct  netinfo *nif_forw, *nif_prev;
1.12      itojun     97:        int     nif_family;
1.11      angelos    98:        short   nif_line;               /* line on screen */
                     99:        short   nif_seen;               /* 0 when not present in list */
                    100:        short   nif_flags;
1.1       deraadt   101: #define        NIF_LACHG       0x1             /* local address changed */
                    102: #define        NIF_FACHG       0x2             /* foreign address changed */
1.11      angelos   103:        short   nif_state;              /* tcp state */
                    104:        char    *nif_proto;             /* protocol */
                    105:        struct  in_addr nif_laddr;      /* local address */
1.12      itojun    106:        struct  in6_addr nif_laddr6;    /* local address */
1.11      angelos   107:        long    nif_lport;              /* local port */
                    108:        struct  in_addr nif_faddr;      /* foreign address */
1.12      itojun    109:        struct  in6_addr nif_faddr6;    /* foreign address */
1.11      angelos   110:        long    nif_fport;              /* foreign port */
                    111:        long    nif_rcvcc;              /* rcv buffer character count */
                    112:        long    nif_sndcc;              /* snd buffer character count */
1.1       deraadt   113: };
                    114:
                    115: static struct {
1.11      angelos   116:        struct  netinfo *nif_forw, *nif_prev;
1.1       deraadt   117: } netcb;
                    118:
                    119: static int aflag = 0;
                    120: static int lastrow = 1;
                    121:
                    122: void
1.22      deraadt   123: closenetstat(WINDOW *w)
1.1       deraadt   124: {
1.17      mpech     125:        struct netinfo *p;
1.1       deraadt   126:
                    127:        endhostent();
                    128:        endnetent();
1.11      angelos   129:        p = (struct netinfo *)netcb.nif_forw;
1.1       deraadt   130:        while (p != (struct netinfo *)&netcb) {
1.11      angelos   131:                if (p->nif_line != -1)
1.1       deraadt   132:                        lastrow--;
1.11      angelos   133:                p->nif_line = -1;
                    134:                p = p->nif_forw;
1.1       deraadt   135:        }
1.20      deraadt   136:        if (w != NULL) {
1.1       deraadt   137:                wclear(w);
                    138:                wrefresh(w);
                    139:                delwin(w);
                    140:        }
                    141: }
                    142:
                    143: static struct nlist namelist[] = {
1.23      deraadt   144: #define        X_TCBTABLE      0               /* no sysctl */
1.1       deraadt   145:        { "_tcbtable" },
1.23      deraadt   146: #define        X_UDBTABLE      1               /* no sysctl */
1.1       deraadt   147:        { "_udbtable" },
                    148:        { "" },
                    149: };
                    150:
                    151: int
1.22      deraadt   152: initnetstat(void)
1.1       deraadt   153: {
1.14      ericj     154:        int ret;
                    155:
                    156:        if ((ret = kvm_nlist(kd, namelist)) == -1)
                    157:                errx(1, "%s", kvm_geterr(kd));
                    158:        else if (ret)
1.1       deraadt   159:                nlisterr(namelist);
                    160:        if (namelist[X_TCBTABLE].n_value == 0) {
                    161:                error("No symbols in namelist");
                    162:                return(0);
                    163:        }
1.11      angelos   164:        netcb.nif_forw = netcb.nif_prev = (struct netinfo *)&netcb;
1.1       deraadt   165:        protos = TCP|UDP;
                    166:        return(1);
                    167: }
                    168:
                    169: void
1.22      deraadt   170: fetchnetstat(void)
1.1       deraadt   171: {
                    172:        struct inpcbtable pcbtable;
1.17      mpech     173:        struct inpcb *head, *prev, *next;
                    174:        struct netinfo *p;
1.1       deraadt   175:        struct inpcb inpcb;
                    176:        struct socket sockb;
                    177:        struct tcpcb tcpcb;
                    178:        void *off;
                    179:        int istcp;
                    180:
                    181:        if (namelist[X_TCBTABLE].n_value == 0)
                    182:                return;
1.11      angelos   183:        for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw)
                    184:                p->nif_seen = 0;
1.1       deraadt   185:        if (protos&TCP) {
1.20      deraadt   186:                off = NPTR(X_TCBTABLE);
1.1       deraadt   187:                istcp = 1;
1.20      deraadt   188:        } else if (protos&UDP) {
                    189:                off = NPTR(X_UDBTABLE);
1.1       deraadt   190:                istcp = 0;
1.20      deraadt   191:        } else {
1.1       deraadt   192:                error("No protocols to display");
                    193:                return;
                    194:        }
                    195: again:
                    196:        KREAD(off, &pcbtable, sizeof (struct inpcbtable));
                    197:        prev = head = (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue;
                    198:        next = pcbtable.inpt_queue.cqh_first;
                    199:        while (next != head) {
                    200:                KREAD(next, &inpcb, sizeof (inpcb));
                    201:                if (inpcb.inp_queue.cqe_prev != prev) {
1.22      deraadt   202:                        printf("prev = %p, head = %p, next = %p, inpcb...prev = %p\n",
                    203:                            prev, head, next, inpcb.inp_queue.cqe_prev);
1.11      angelos   204:                        p = netcb.nif_forw;
                    205:                        for (; p != (struct netinfo *)&netcb; p = p->nif_forw)
                    206:                                p->nif_seen = 1;
1.1       deraadt   207:                        error("Kernel state in transition");
                    208:                        return;
                    209:                }
                    210:                prev = next;
                    211:                next = inpcb.inp_queue.cqe_next;
                    212:
1.12      itojun    213:                if (inpcb.inp_flags & INP_IPV6)
1.1       deraadt   214:                        continue;
1.12      itojun    215:
                    216:                if (!aflag) {
1.20      deraadt   217:                        if (!(inpcb.inp_flags & INP_IPV6) &&
                    218:                            inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
1.12      itojun    219:                                continue;
1.20      deraadt   220:                        if ((inpcb.inp_flags & INP_IPV6) &&
                    221:                            IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6))
1.12      itojun    222:                                continue;
                    223:                }
1.1       deraadt   224:                if (nhosts && !checkhost(&inpcb))
                    225:                        continue;
                    226:                if (nports && !checkport(&inpcb))
                    227:                        continue;
                    228:                KREAD(inpcb.inp_socket, &sockb, sizeof (sockb));
                    229:                if (istcp) {
                    230:                        KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
                    231:                        enter(&inpcb, &sockb, tcpcb.t_state, "tcp");
                    232:                } else
                    233:                        enter(&inpcb, &sockb, 0, "udp");
                    234:        }
                    235:        if (istcp && (protos&UDP)) {
                    236:                istcp = 0;
                    237:                off = NPTR(X_UDBTABLE);
                    238:                goto again;
                    239:        }
                    240: }
                    241:
                    242: static void
1.22      deraadt   243: enter(struct inpcb *inp, struct socket *so, int state, char *proto)
1.1       deraadt   244: {
1.17      mpech     245:        struct netinfo *p;
1.1       deraadt   246:
                    247:        /*
                    248:         * Only take exact matches, any sockets with
                    249:         * previously unbound addresses will be deleted
                    250:         * below in the display routine because they
                    251:         * will appear as ``not seen'' in the kernel
                    252:         * data structures.
                    253:         */
1.12      itojun    254:        for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {
                    255:                if (p->nif_family == AF_INET && (inp->inp_flags & INP_IPV6))
                    256:                        continue;
                    257:                if (p->nif_family == AF_INET6 && !(inp->inp_flags & INP_IPV6))
                    258:                        continue;
1.11      angelos   259:                if (!streq(proto, p->nif_proto))
1.1       deraadt   260:                        continue;
1.12      itojun    261:                if (p->nif_family == AF_INET) {
                    262:                        if (p->nif_lport != inp->inp_lport ||
                    263:                            p->nif_laddr.s_addr != inp->inp_laddr.s_addr)
                    264:                                continue;
                    265:                        if (p->nif_faddr.s_addr == inp->inp_faddr.s_addr &&
                    266:                            p->nif_fport == inp->inp_fport)
                    267:                                break;
                    268:
1.26    ! deraadt   269:                } else if (p->nif_family == AF_INET6) {
1.12      itojun    270:                        if (p->nif_lport != inp->inp_lport ||
                    271:                            !IN6_ARE_ADDR_EQUAL(&p->nif_laddr6, &inp->inp_laddr6))
                    272:                                continue;
1.13      itojun    273:                        if (IN6_ARE_ADDR_EQUAL(&p->nif_faddr6, &inp->inp_faddr6) &&
1.12      itojun    274:                            p->nif_fport == inp->inp_fport)
                    275:                                break;
1.26    ! deraadt   276:                } else
1.1       deraadt   277:                        continue;
                    278:        }
                    279:        if (p == (struct netinfo *)&netcb) {
                    280:                if ((p = malloc(sizeof(*p))) == NULL) {
                    281:                        error("Out of memory");
                    282:                        return;
                    283:                }
1.11      angelos   284:                p->nif_prev = (struct netinfo *)&netcb;
                    285:                p->nif_forw = netcb.nif_forw;
                    286:                netcb.nif_forw->nif_prev = p;
                    287:                netcb.nif_forw = p;
                    288:                p->nif_line = -1;
                    289:                p->nif_lport = inp->inp_lport;
                    290:                p->nif_fport = inp->inp_fport;
                    291:                p->nif_proto = proto;
                    292:                p->nif_flags = NIF_LACHG|NIF_FACHG;
1.12      itojun    293:                if (inp->inp_flags & INP_IPV6) {
                    294:                        p->nif_laddr6 = inp->inp_laddr6;
                    295:                        p->nif_faddr6 = inp->inp_faddr6;
                    296:                        p->nif_family = AF_INET6;
1.26    ! deraadt   297:                } else {
1.12      itojun    298:                        p->nif_laddr = inp->inp_laddr;
                    299:                        p->nif_faddr = inp->inp_faddr;
                    300:                        p->nif_family = AF_INET;
                    301:                }
1.11      angelos   302:        }
                    303:        p->nif_rcvcc = so->so_rcv.sb_cc;
                    304:        p->nif_sndcc = so->so_snd.sb_cc;
                    305:        p->nif_state = state;
                    306:        p->nif_seen = 1;
1.1       deraadt   307: }
                    308:
                    309: /* column locations */
                    310: #define        LADDR   0
                    311: #define        FADDR   LADDR+23
                    312: #define        PROTO   FADDR+23
                    313: #define        RCVCC   PROTO+6
                    314: #define        SNDCC   RCVCC+7
                    315: #define        STATE   SNDCC+7
                    316:
                    317:
                    318: void
1.22      deraadt   319: labelnetstat(void)
1.1       deraadt   320: {
                    321:        if (namelist[X_TCBTABLE].n_type == 0)
                    322:                return;
                    323:        wmove(wnd, 0, 0); wclrtobot(wnd);
                    324:        mvwaddstr(wnd, 0, LADDR, "Local Address");
                    325:        mvwaddstr(wnd, 0, FADDR, "Foreign Address");
                    326:        mvwaddstr(wnd, 0, PROTO, "Proto");
                    327:        mvwaddstr(wnd, 0, RCVCC, "Recv-Q");
                    328:        mvwaddstr(wnd, 0, SNDCC, "Send-Q");
1.20      deraadt   329:        mvwaddstr(wnd, 0, STATE, "(state)");
1.1       deraadt   330: }
                    331:
                    332: void
1.22      deraadt   333: shownetstat(void)
1.1       deraadt   334: {
1.17      mpech     335:        struct netinfo *p, *q;
1.1       deraadt   336:
                    337:        /*
                    338:         * First, delete any connections that have gone
                    339:         * away and adjust the position of connections
                    340:         * below to reflect the deleted line.
                    341:         */
1.11      angelos   342:        p = netcb.nif_forw;
1.1       deraadt   343:        while (p != (struct netinfo *)&netcb) {
1.11      angelos   344:                if (p->nif_line == -1 || p->nif_seen) {
                    345:                        p = p->nif_forw;
1.1       deraadt   346:                        continue;
                    347:                }
1.11      angelos   348:                wmove(wnd, p->nif_line, 0); wdeleteln(wnd);
                    349:                q = netcb.nif_forw;
                    350:                for (; q != (struct netinfo *)&netcb; q = q->nif_forw)
                    351:                        if (q != p && q->nif_line > p->nif_line) {
                    352:                                q->nif_line--;
1.1       deraadt   353:                                /* this shouldn't be necessary */
1.11      angelos   354:                                q->nif_flags |= NIF_LACHG|NIF_FACHG;
1.1       deraadt   355:                        }
                    356:                lastrow--;
1.11      angelos   357:                q = p->nif_forw;
                    358:                p->nif_prev->nif_forw = p->nif_forw;
                    359:                p->nif_forw->nif_prev = p->nif_prev;
1.1       deraadt   360:                free(p);
                    361:                p = q;
                    362:        }
                    363:        /*
                    364:         * Update existing connections and add new ones.
                    365:         */
1.12      itojun    366:        for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {
1.11      angelos   367:                if (p->nif_line == -1) {
1.1       deraadt   368:                        /*
                    369:                         * Add a new entry if possible.
                    370:                         */
                    371:                        if (lastrow > YMAX(wnd))
                    372:                                continue;
1.11      angelos   373:                        p->nif_line = lastrow++;
                    374:                        p->nif_flags |= NIF_LACHG|NIF_FACHG;
1.1       deraadt   375:                }
1.11      angelos   376:                if (p->nif_flags & NIF_LACHG) {
                    377:                        wmove(wnd, p->nif_line, LADDR);
1.12      itojun    378:                        switch (p->nif_family) {
                    379:                        case AF_INET:
                    380:                                inetprint(&p->nif_laddr, p->nif_lport,
                    381:                                        p->nif_proto);
                    382:                                break;
                    383:                        case AF_INET6:
                    384:                                inet6print(&p->nif_laddr6, p->nif_lport,
                    385:                                        p->nif_proto);
                    386:                                break;
                    387:                        }
1.11      angelos   388:                        p->nif_flags &= ~NIF_LACHG;
1.1       deraadt   389:                }
1.11      angelos   390:                if (p->nif_flags & NIF_FACHG) {
                    391:                        wmove(wnd, p->nif_line, FADDR);
1.12      itojun    392:                        switch (p->nif_family) {
                    393:                        case AF_INET:
                    394:                                inetprint(&p->nif_faddr, p->nif_fport,
                    395:                                        p->nif_proto);
                    396:                                break;
                    397:                        case AF_INET6:
                    398:                                inet6print(&p->nif_faddr6, p->nif_fport,
                    399:                                        p->nif_proto);
                    400:                                break;
                    401:                        }
1.11      angelos   402:                        p->nif_flags &= ~NIF_FACHG;
1.1       deraadt   403:                }
1.11      angelos   404:                mvwaddstr(wnd, p->nif_line, PROTO, p->nif_proto);
1.12      itojun    405:                if (p->nif_family == AF_INET6)
                    406:                        waddstr(wnd, "6");
1.11      angelos   407:                mvwprintw(wnd, p->nif_line, RCVCC, "%6d", p->nif_rcvcc);
                    408:                mvwprintw(wnd, p->nif_line, SNDCC, "%6d", p->nif_sndcc);
1.20      deraadt   409:                if (streq(p->nif_proto, "tcp")) {
1.11      angelos   410:                        if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES)
                    411:                                mvwprintw(wnd, p->nif_line, STATE, "%d",
                    412:                                    p->nif_state);
1.1       deraadt   413:                        else
1.11      angelos   414:                                mvwaddstr(wnd, p->nif_line, STATE,
                    415:                                    tcpstates[p->nif_state]);
1.20      deraadt   416:                }
1.1       deraadt   417:                wclrtoeol(wnd);
                    418:        }
                    419:        if (lastrow < YMAX(wnd)) {
                    420:                wmove(wnd, lastrow, 0); wclrtobot(wnd);
                    421:                wmove(wnd, YMAX(wnd), 0); wdeleteln(wnd);       /* XXX */
                    422:        }
                    423: }
                    424:
                    425: /*
                    426:  * Pretty print an Internet address (net address + port).
                    427:  * If the nflag was specified, use numbers instead of names.
                    428:  */
                    429: static void
1.22      deraadt   430: inetprint(struct in_addr *in, int port, char *proto)
1.1       deraadt   431: {
                    432:        struct servent *sp = 0;
1.6       millert   433:        char line[80], *cp;
1.1       deraadt   434:
1.8       deraadt   435:        snprintf(line, sizeof line, "%.*s.", 16, inetname(*in));
1.6       millert   436:        cp = strchr(line, '\0');
1.1       deraadt   437:        if (!nflag && port)
                    438:                sp = getservbyport(port, proto);
                    439:        if (sp || port == 0)
1.8       deraadt   440:                snprintf(cp, sizeof line - strlen(cp), "%.8s",
                    441:                    sp ? sp->s_name : "*");
1.1       deraadt   442:        else
1.8       deraadt   443:                snprintf(cp, sizeof line - strlen(cp), "%d",
                    444:                    ntohs((u_short)port));
1.1       deraadt   445:        /* pad to full column to clear any garbage */
1.6       millert   446:        cp = strchr(line, '\0');
1.10      deraadt   447:        while (cp - line < 22 && cp - line < sizeof line-1)
1.1       deraadt   448:                *cp++ = ' ';
                    449:        *cp = '\0';
                    450:        waddstr(wnd, line);
                    451: }
                    452:
1.12      itojun    453: static void
1.22      deraadt   454: inet6print(struct in6_addr *in6, int port, char *proto)
1.12      itojun    455: {
                    456:        struct servent *sp = 0;
                    457:        char line[80], *cp;
                    458:
                    459:        snprintf(line, sizeof line, "%.*s.", 16, inet6name(in6));
                    460:        cp = strchr(line, '\0');
                    461:        if (!nflag && port)
                    462:                sp = getservbyport(port, proto);
                    463:        if (sp || port == 0)
                    464:                snprintf(cp, sizeof line - strlen(cp), "%.8s",
                    465:                    sp ? sp->s_name : "*");
                    466:        else
                    467:                snprintf(cp, sizeof line - strlen(cp), "%d",
                    468:                    ntohs((u_short)port));
                    469:        /* pad to full column to clear any garbage */
                    470:        cp = strchr(line, '\0');
                    471:        while (cp - line < 22 && cp - line < sizeof line-1)
                    472:                *cp++ = ' ';
                    473:        *cp = '\0';
                    474:        waddstr(wnd, line);
                    475: }
                    476:
1.1       deraadt   477: /*
                    478:  * Construct an Internet address representation.
1.20      deraadt   479:  * If the nflag has been supplied, give
1.1       deraadt   480:  * numeric value, otherwise try for symbolic name.
                    481:  */
1.12      itojun    482: static const char *
1.22      deraadt   483: inetname(struct in_addr in)
1.1       deraadt   484: {
                    485:        char *cp = 0;
                    486:        static char line[50];
                    487:        struct hostent *hp;
                    488:        struct netent *np;
                    489:
                    490:        if (!nflag && in.s_addr != INADDR_ANY) {
                    491:                int net = inet_netof(in);
                    492:                int lna = inet_lnaof(in);
                    493:
                    494:                if (lna == INADDR_ANY) {
                    495:                        np = getnetbyaddr(net, AF_INET);
                    496:                        if (np)
                    497:                                cp = np->n_name;
                    498:                }
                    499:                if (cp == 0) {
                    500:                        hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
                    501:                        if (hp)
                    502:                                cp = hp->h_name;
                    503:                }
                    504:        }
1.9       deraadt   505:        if (in.s_addr == INADDR_ANY) {
1.15      lebel     506:                strlcpy(line, "*", sizeof line);
1.9       deraadt   507:        } else if (cp) {
1.15      lebel     508:                strlcpy(line, cp, sizeof line);
1.9       deraadt   509:        } else {
1.1       deraadt   510:                in.s_addr = ntohl(in.s_addr);
                    511: #define C(x)   ((x) & 0xff)
1.8       deraadt   512:                snprintf(line, sizeof line, "%u.%u.%u.%u", C(in.s_addr >> 24),
1.20      deraadt   513:                    C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
1.1       deraadt   514:        }
                    515:        return (line);
                    516: }
1.12      itojun    517:
                    518: static const char *
1.22      deraadt   519: inet6name(struct in6_addr *in6)
1.12      itojun    520: {
                    521:        static char line[NI_MAXHOST];
                    522:        struct sockaddr_in6 sin6;
                    523:        int flags;
                    524:
1.25      itojun    525:        flags = nflag ? NI_NUMERICHOST : 0;
1.12      itojun    526:        if (IN6_IS_ADDR_UNSPECIFIED(in6))
                    527:                return "*";
                    528:        memset(&sin6, 0, sizeof(sin6));
                    529:        sin6.sin6_family = AF_INET6;
                    530:        sin6.sin6_len = sizeof(struct sockaddr_in6);
                    531:        sin6.sin6_addr = *in6;
                    532:        if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
1.20      deraadt   533:            line, sizeof(line), NULL, 0, flags) == 0)
1.12      itojun    534:                return line;
                    535:        return "?";
                    536: }
1.1       deraadt   537:
                    538: int
1.22      deraadt   539: cmdnetstat(char *cmd, char *args)
1.1       deraadt   540: {
1.17      mpech     541:        struct netinfo *p;
1.1       deraadt   542:
                    543:        if (prefix(cmd, "all")) {
                    544:                aflag = !aflag;
                    545:                goto fixup;
                    546:        }
                    547:        if  (prefix(cmd, "numbers") || prefix(cmd, "names")) {
                    548:                int new;
                    549:
                    550:                new = prefix(cmd, "numbers");
                    551:                if (new == nflag)
                    552:                        return (1);
1.11      angelos   553:                p = netcb.nif_forw;
                    554:                for (; p != (struct netinfo *)&netcb; p = p->nif_forw) {
                    555:                        if (p->nif_line == -1)
1.1       deraadt   556:                                continue;
1.11      angelos   557:                        p->nif_flags |= NIF_LACHG|NIF_FACHG;
1.1       deraadt   558:                }
                    559:                nflag = new;
1.4       deraadt   560:                wclear(wnd);
                    561:                labelnetstat();
1.1       deraadt   562:                goto redisplay;
                    563:        }
                    564:        if (!netcmd(cmd, args))
                    565:                return (0);
                    566: fixup:
                    567:        fetchnetstat();
                    568: redisplay:
                    569:        shownetstat();
                    570:        refresh();
                    571:        return (1);
                    572: }