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

Annotation of src/usr.bin/systat/netcmds.c, Revision 1.19

1.19    ! gilles      1: /*     $OpenBSD: netcmds.c,v 1.18 2007/08/09 02:38:09 ray Exp $        */
1.1       deraadt     2: /*     $NetBSD: netcmds.c,v 1.4 1995/05/21 17:14:38 mycroft 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.12      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[] = "@(#)netcmds.c  8.1 (Berkeley) 6/6/93";
                     36: #endif
1.19    ! gilles     37: static char rcsid[] = "$OpenBSD: netcmds.c,v 1.18 2007/08/09 02:38:09 ray Exp $";
1.1       deraadt    38: #endif /* not lint */
                     39:
                     40: /*
                     41:  * Common network command support routines.
                     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 <net/route.h>
                     50: #include <netinet/in.h>
                     51: #include <netinet/in_systm.h>
                     52: #include <netinet/ip.h>
                     53: #include <netinet/in_pcb.h>
                     54:
                     55: #include <arpa/inet.h>
                     56:
1.18      ray        57: #include <errno.h>
1.1       deraadt    58: #include <netdb.h>
                     59: #include <stdlib.h>
                     60: #include <string.h>
                     61: #include <ctype.h>
                     62: #include "systat.h"
                     63: #include "extern.h"
                     64:
                     65: #define        streq(a,b)      (strcmp(a,b)==0)
                     66:
                     67: static struct hitem {
1.5       itojun     68:        struct sockaddr_storage addr;
1.1       deraadt    69:        int     onoff;
                     70: } *hosts;
                     71:
1.18      ray        72: size_t nports, nhosts;
                     73: int protos;
1.1       deraadt    74:
1.10      millert    75: static void changeitems(char *, int);
                     76: static int selectproto(char *);
                     77: static void showprotos(void);
                     78: static int selectport(long, int);
                     79: static void showports(void);
                     80: static int addrcmp(struct sockaddr *, struct sockaddr *);
                     81: static int selecthost(struct sockaddr *, int);
                     82: static void showhosts(void);
1.1       deraadt    83:
                     84: int
1.11      deraadt    85: netcmd(char *cmd, char *args)
1.1       deraadt    86: {
                     87:
                     88:        if (prefix(cmd, "tcp") || prefix(cmd, "udp")) {
                     89:                selectproto(cmd);
                     90:                return (1);
                     91:        }
                     92:        if (prefix(cmd, "ignore") || prefix(cmd, "display")) {
                     93:                changeitems(args, prefix(cmd, "display"));
                     94:                return (1);
                     95:        }
                     96:        if (prefix(cmd, "reset")) {
                     97:                selectproto(0);
                     98:                selecthost(0, 0);
1.15      cloder     99:                selectport(htons(-1), 0);
1.1       deraadt   100:                return (1);
                    101:        }
                    102:        if (prefix(cmd, "show")) {
1.16      deraadt   103:                move(CMDLINE, 0);
                    104:                clrtoeol();
1.1       deraadt   105:                if (*args == '\0') {
                    106:                        showprotos();
                    107:                        showhosts();
                    108:                        showports();
                    109:                        return (1);
                    110:                }
                    111:                if (prefix(args, "protos"))
                    112:                        showprotos();
                    113:                else if (prefix(args, "hosts"))
                    114:                        showhosts();
                    115:                else if (prefix(args, "ports"))
                    116:                        showports();
                    117:                else
                    118:                        addstr("show what?");
                    119:                return (1);
                    120:        }
                    121:        return (0);
                    122: }
                    123:
                    124:
                    125: static void
1.11      deraadt   126: changeitems(char *args, int onoff)
1.1       deraadt   127: {
1.6       mpech     128:        char *cp;
1.1       deraadt   129:        struct servent *sp;
1.5       itojun    130:        struct addrinfo hints, *res0, *res;
1.1       deraadt   131:
1.19    ! gilles    132:        args[strcspn(args, "\n")] = '\0';
        !           133:
1.1       deraadt   134:        for (;;args = cp) {
1.17      tedu      135:                for (cp = args; isspace(*cp); cp++)
1.1       deraadt   136:                        ;
                    137:                args = cp;
                    138:                for (; *cp && !isspace(*cp); cp++)
                    139:                        ;
                    140:                if (*cp)
                    141:                        *cp++ = '\0';
                    142:                if (cp - args == 0)
                    143:                        break;
                    144:                sp = getservbyname(args,
                    145:                    protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
                    146:                if (sp) {
                    147:                        selectport(sp->s_port, onoff);
                    148:                        continue;
                    149:                }
1.5       itojun    150:
                    151:                memset(&hints, 0, sizeof(hints));
                    152:                hints.ai_family = PF_UNSPEC;
                    153:                hints.ai_socktype = SOCK_DGRAM;
                    154:                if (getaddrinfo(args, "0", &hints, &res0) != 0) {
                    155:                        error("%s: unknown host or port", args);
                    156:                        continue;
1.1       deraadt   157:                }
1.5       itojun    158:                for (res = res0; res; res = res->ai_next)
                    159:                        selecthost(res->ai_addr, onoff);
                    160:                freeaddrinfo(res0);
1.1       deraadt   161:        }
                    162: }
                    163:
                    164: static int
1.11      deraadt   165: selectproto(char *proto)
1.1       deraadt   166: {
                    167:        int new = protos;
                    168:
                    169:        if (proto == 0 || streq(proto, "all"))
                    170:                new = TCP|UDP;
                    171:        else if (streq(proto, "tcp"))
                    172:                new = TCP;
                    173:        else if (streq(proto, "udp"))
                    174:                new = UDP;
1.4       millert   175:        return (protos = new);
1.1       deraadt   176: }
                    177:
                    178: static void
1.11      deraadt   179: showprotos(void)
1.1       deraadt   180: {
                    181:
                    182:        if ((protos&TCP) == 0)
                    183:                addch('!');
                    184:        addstr("tcp ");
                    185:        if ((protos&UDP) == 0)
                    186:                addch('!');
                    187:        addstr("udp ");
                    188: }
                    189:
                    190: static struct pitem {
                    191:        long    port;
                    192:        int     onoff;
                    193: } *ports;
                    194:
                    195: static int
1.11      deraadt   196: selectport(long port, int onoff)
1.1       deraadt   197: {
1.6       mpech     198:        struct pitem *p;
1.1       deraadt   199:
1.15      cloder    200:        if (ntohs(port) == -1) {
1.1       deraadt   201:                if (ports == 0)
                    202:                        return (0);
1.16      deraadt   203:                free(ports);
                    204:                ports = NULL;
1.1       deraadt   205:                nports = 0;
                    206:                return (1);
                    207:        }
                    208:        for (p = ports; p < ports+nports; p++)
                    209:                if (p->port == port) {
                    210:                        p->onoff = onoff;
                    211:                        return (0);
                    212:                }
1.18      ray       213:        if (nports + 1 > SIZE_MAX / sizeof(*p) ||
                    214:            (p = realloc(ports, (nports + 1) * sizeof(*p))) == NULL) {
                    215:                error("selectport: %s", strerror(ENOMEM));
                    216:                die();
                    217:        }
                    218:        ports = p;
                    219:
1.1       deraadt   220:        p = &ports[nports++];
                    221:        p->port = port;
                    222:        p->onoff = onoff;
                    223:        return (1);
                    224: }
                    225:
                    226: int
1.11      deraadt   227: checkport(struct inpcb *inp)
1.1       deraadt   228: {
1.6       mpech     229:        struct pitem *p;
1.1       deraadt   230:
                    231:        if (ports)
                    232:        for (p = ports; p < ports+nports; p++)
                    233:                if (p->port == inp->inp_lport || p->port == inp->inp_fport)
                    234:                        return (p->onoff);
                    235:        return (1);
                    236: }
                    237:
                    238: static void
1.11      deraadt   239: showports(void)
1.1       deraadt   240: {
1.6       mpech     241:        struct pitem *p;
1.1       deraadt   242:        struct servent *sp;
                    243:
                    244:        for (p = ports; p < ports+nports; p++) {
                    245:                sp = getservbyport(p->port,
1.4       millert   246:                    protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
1.1       deraadt   247:                if (!p->onoff)
                    248:                        addch('!');
                    249:                if (sp)
                    250:                        printw("%s ", sp->s_name);
                    251:                else
1.15      cloder    252:                        printw("%d ", ntohs(p->port));
1.1       deraadt   253:        }
                    254: }
                    255:
                    256: static int
1.11      deraadt   257: addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
1.5       itojun    258: {
                    259:        if (sa1->sa_family != sa2->sa_family)
                    260:                return 0;
                    261:        if (sa1->sa_len != sa2->sa_len)
                    262:                return 0;
                    263:        switch (sa1->sa_family) {
                    264:        case AF_INET:
                    265:                if (((struct sockaddr_in *)sa1)->sin_addr.s_addr ==
1.16      deraadt   266:                    ((struct sockaddr_in *)sa2)->sin_addr.s_addr)
1.5       itojun    267:                        return 1;
                    268:                break;
                    269:        case AF_INET6:
                    270:                if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)sa1)->sin6_addr,
1.16      deraadt   271:                    &((struct sockaddr_in6 *)sa2)->sin6_addr))
1.5       itojun    272:                        return 1;
                    273:                break;
                    274:        default:
                    275:                if (memcmp(sa1, sa2, sa1->sa_len) == 0)
                    276:                        return 1;
                    277:                break;
                    278:        }
                    279:        return 0;
                    280: }
                    281:
                    282: static int
1.11      deraadt   283: selecthost(struct sockaddr *sa, int onoff)
1.1       deraadt   284: {
1.6       mpech     285:        struct hitem *p;
1.1       deraadt   286:
1.5       itojun    287:        if (sa == 0) {
1.1       deraadt   288:                if (hosts == 0)
                    289:                        return (0);
1.16      deraadt   290:                free(hosts);
                    291:                hosts = NULL;
1.1       deraadt   292:                nhosts = 0;
                    293:                return (1);
                    294:        }
                    295:        for (p = hosts; p < hosts+nhosts; p++)
1.5       itojun    296:                if (addrcmp((struct sockaddr *)&p->addr, sa)) {
1.1       deraadt   297:                        p->onoff = onoff;
                    298:                        return (0);
                    299:                }
1.5       itojun    300:        if (sa->sa_len > sizeof(struct sockaddr_storage))
                    301:                return (-1);    /*XXX*/
1.18      ray       302:        if (nhosts + 1 > SIZE_MAX / sizeof(*p) ||
                    303:            (p = realloc(hosts, (nhosts + 1) * sizeof(*p))) == NULL) {
                    304:                error("selecthost: %s", strerror(ENOMEM));
                    305:                die();
                    306:        }
                    307:        hosts = p;
                    308:
1.1       deraadt   309:        p = &hosts[nhosts++];
1.5       itojun    310:        memcpy(&p->addr, sa, sa->sa_len);
1.1       deraadt   311:        p->onoff = onoff;
                    312:        return (1);
                    313: }
                    314:
                    315: int
1.11      deraadt   316: checkhost(struct inpcb *inp)
1.1       deraadt   317: {
1.6       mpech     318:        struct hitem *p;
1.1       deraadt   319:
                    320:        if (hosts)
1.5       itojun    321:        for (p = hosts; p < hosts+nhosts; p++) {
1.9       deraadt   322:                if (((struct sockaddr *)&p->addr)->sa_family == AF_INET &&
                    323:                    !(inp->inp_flags & INP_IPV6)) {
1.5       itojun    324:                        struct sockaddr_in *sin;
                    325:                        sin = (struct sockaddr_in *)&p->addr;
                    326:                        if (sin->sin_addr.s_addr == inp->inp_laddr.s_addr ||
                    327:                            sin->sin_addr.s_addr == inp->inp_faddr.s_addr)
                    328:                                return (p->onoff);
                    329:                }
1.9       deraadt   330:                if (((struct sockaddr *)&p->addr)->sa_family == AF_INET6 &&
                    331:                    (inp->inp_flags & INP_IPV6)) {
1.5       itojun    332:                        struct sockaddr_in6 *sin6;
                    333:                        sin6 = (struct sockaddr_in6 *)&p->addr;
                    334:                        if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_laddr6) ||
                    335:                            IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_faddr6))
                    336:                                return (p->onoff);
                    337:                }
                    338:        }
1.1       deraadt   339:        return (1);
                    340: }
                    341:
                    342: static void
1.11      deraadt   343: showhosts(void)
1.1       deraadt   344: {
1.6       mpech     345:        struct hitem *p;
1.5       itojun    346:        char hbuf[NI_MAXHOST];
                    347:        struct sockaddr *sa;
                    348:        int flags;
1.1       deraadt   349:
1.5       itojun    350:        flags = nflag ? NI_NUMERICHOST : 0;
1.1       deraadt   351:        for (p = hosts; p < hosts+nhosts; p++) {
1.5       itojun    352:                sa = (struct sockaddr *)&p->addr;
                    353:                if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
1.16      deraadt   354:                    flags) != 0)
1.9       deraadt   355:                        strlcpy(hbuf, "(invalid)", sizeof hbuf);
1.1       deraadt   356:                if (!p->onoff)
                    357:                        addch('!');
1.5       itojun    358:                printw("%s ", hbuf);
1.1       deraadt   359:        }
                    360: }