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

Annotation of src/usr.bin/systat/if.c, Revision 1.15

1.15    ! jasper      1: /*     $OpenBSD: if.c,v 1.14 2009/06/25 15:53:12 claudio Exp $ */
1.1       markus      2: /*
                      3:  * Copyright (c) 2004 Markus Friedl <markus@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
1.15    ! jasper     17:
1.1       markus     18: #include <sys/param.h>
                     19: #include <sys/types.h>
                     20: #include <sys/socket.h>
                     21: #include <sys/sysctl.h>
                     22: #include <net/if.h>
                     23: #include <net/if_dl.h>
                     24: #include <net/route.h>
1.13      deraadt    25: #include <sys/sockio.h>
1.15    ! jasper     26: #include <sys/ioctl.h>
1.1       markus     27:
                     28: #include <stdlib.h>
1.5       deraadt    29: #include <string.h>
1.15    ! jasper     30: #include <unistd.h>
1.1       markus     31:
                     32: #include "systat.h"
                     33:
                     34: static  enum state { BOOT, TIME, RUN } state = TIME;
                     35:
                     36: struct ifcount {
1.11      mk         37:        u_int64_t       ifc_ib;                 /* input bytes */
                     38:        u_int64_t       ifc_ip;                 /* input packets */
                     39:        u_int64_t       ifc_ie;                 /* input errors */
                     40:        u_int64_t       ifc_ob;                 /* output bytes */
                     41:        u_int64_t       ifc_op;                 /* output packets */
                     42:        u_int64_t       ifc_oe;                 /* output errors */
                     43:        u_int64_t       ifc_co;                 /* collisions */
1.7       claudio    44:        int             ifc_flags;              /* up / down */
                     45:        int             ifc_state;              /* link state */
1.1       markus     46: } sum;
                     47:
                     48: struct ifstat {
                     49:        char            ifs_name[IFNAMSIZ];     /* interface name */
1.13      deraadt    50:        char            ifs_description[IFDESCRSIZE];
1.1       markus     51:        struct ifcount  ifs_cur;
                     52:        struct ifcount  ifs_old;
                     53:        struct ifcount  ifs_now;
                     54: } *ifstats;
                     55:
                     56: static int nifs = 0;
1.12      canacar    57: static int num_ifs = 0;
1.1       markus     58:
1.12      canacar    59: void print_if(void);
                     60: int read_if(void);
                     61: int select_if(void);
                     62: int if_keyboard_callback(int);
                     63:
                     64: static void fetchifstat(void);
                     65: static void showifstat(struct ifstat *);
                     66: static void showtotal(void);
                     67:
                     68:
                     69: /* Define fields */
                     70: field_def fields_if[] = {
                     71:        {"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
1.13      deraadt    72:        {"STATE", 4, 6, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
1.12      canacar    73:        {"IPKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
                     74:        {"IBYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
                     75:        {"IERRS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
                     76:        {"OPKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
                     77:        {"OBYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
                     78:        {"OERRS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
                     79:        {"COLLS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
1.13      deraadt    80:        {"DESC", 14, 64, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
1.12      canacar    81: };
                     82:
                     83:
                     84: #define FIELD_ADDR(x) (&fields_if[x])
                     85:
                     86: #define FLD_IF_IFACE   FIELD_ADDR(0)
                     87: #define FLD_IF_STATE   FIELD_ADDR(1)
                     88: #define FLD_IF_IPKTS   FIELD_ADDR(2)
                     89: #define FLD_IF_IBYTES  FIELD_ADDR(3)
                     90: #define FLD_IF_IERRS   FIELD_ADDR(4)
                     91: #define FLD_IF_OPKTS   FIELD_ADDR(5)
                     92: #define FLD_IF_OBYTES  FIELD_ADDR(6)
                     93: #define FLD_IF_OERRS   FIELD_ADDR(7)
                     94: #define FLD_IF_COLLS   FIELD_ADDR(8)
1.13      deraadt    95: #define FLD_IF_DESC    FIELD_ADDR(9)
1.12      canacar    96:
                     97:
                     98: /* Define views */
                     99: field_def *view_if_0[] = {
1.13      deraadt   100:        FLD_IF_IFACE, FLD_IF_STATE, FLD_IF_DESC, FLD_IF_IPKTS,
                    101:        FLD_IF_IBYTES, FLD_IF_IERRS, FLD_IF_OPKTS, FLD_IF_OBYTES,
                    102:        FLD_IF_OERRS, FLD_IF_COLLS, NULL
1.12      canacar   103: };
                    104:
                    105: /* Define view managers */
                    106:
                    107: struct view_manager ifstat_mgr = {
                    108:        "Ifstat", select_if, read_if, NULL, print_header,
                    109:        print_if, if_keyboard_callback, NULL, NULL
                    110: };
                    111:
                    112: field_view views_if[] = {
                    113:        {view_if_0, "ifstat", '1', &ifstat_mgr},
                    114:        {NULL, NULL, 0, NULL}
                    115: };
1.7       claudio   116:
1.1       markus    117:
                    118: int
                    119: initifstat(void)
                    120: {
1.12      canacar   121:        field_view *v;
                    122:        read_if();
                    123:        for (v = views_if; v->name != NULL; v++)
                    124:                add_view(v);
1.1       markus    125:
                    126:        return(1);
                    127: }
                    128:
                    129: #define UPDATE(x, y) do { \
1.2       deraadt   130:                ifs->ifs_now.x = ifm.y; \
1.1       markus    131:                ifs->ifs_cur.x = ifs->ifs_now.x - ifs->ifs_old.x; \
1.4       dlg       132:                if (state == TIME) {\
                    133:                        ifs->ifs_old.x = ifs->ifs_now.x; \
                    134:                        ifs->ifs_cur.x /= naptime; \
                    135:                } \
1.1       markus    136:                sum.x += ifs->ifs_cur.x; \
                    137:        } while(0)
                    138:
                    139:
                    140: void
                    141: rt_getaddrinfo(struct sockaddr *sa, int addrs, struct sockaddr **info)
                    142: {
                    143:        int i;
                    144:
                    145:        for (i = 0; i < RTAX_MAX; i++) {
                    146:                if (addrs & (1 << i)) {
                    147:                        info[i] = sa;
                    148:                        sa = (struct sockaddr *) ((char *)(sa) +
                    149:                            roundup(sa->sa_len, sizeof(long)));
                    150:                } else
                    151:                        info[i] = NULL;
                    152:        }
                    153: }
                    154:
1.12      canacar   155:
                    156:
                    157: int
                    158: select_if(void)
                    159: {
                    160:        num_disp = num_ifs + 1;
                    161:        return (0);
                    162: }
                    163:
                    164: int
                    165: read_if(void)
                    166: {
                    167:        fetchifstat();
                    168:        num_disp = num_ifs + 1;
                    169:
                    170:        return 0;
                    171: }
                    172:
1.1       markus    173: void
1.12      canacar   174: print_if(void)
                    175: {
                    176:        int n, i, count = 0;
                    177:
                    178:        for (n = 0, i = 0; n < nifs; n++) {
                    179:                if (ifstats[n].ifs_name[0] == '\0')
                    180:                        continue;
                    181:                if (i++ < dispstart)
                    182:                        continue;
                    183:                if (i == num_disp)
                    184:                        break;
                    185:                showifstat(ifstats + n);
                    186:                if (maxprint > 0 && ++count >= maxprint)
                    187:                        return;
                    188:        }
                    189:        showtotal();
                    190: }
                    191:
                    192:
                    193: static void
1.1       markus    194: fetchifstat(void)
                    195: {
                    196:        struct ifstat *newstats, *ifs;
1.2       deraadt   197:        struct if_msghdr ifm;
1.1       markus    198:        struct sockaddr *info[RTAX_MAX];
                    199:        struct sockaddr_dl *sdl;
                    200:        char *buf, *next, *lim;
1.13      deraadt   201:        static int s = -1;
1.5       deraadt   202:        int mib[6];
1.1       markus    203:        size_t need;
                    204:
                    205:        mib[0] = CTL_NET;
                    206:        mib[1] = AF_ROUTE;
                    207:        mib[2] = 0;
                    208:        mib[3] = 0;
                    209:        mib[4] = NET_RT_IFLIST;
                    210:        mib[5] = 0;
                    211:
                    212:        if (sysctl(mib, 6, NULL, &need, NULL, 0) == -1)
                    213:                return;
                    214:        if ((buf = malloc(need)) == NULL)
                    215:                return;
                    216:        if (sysctl(mib, 6, buf, &need, NULL, 0) == -1) {
                    217:                free(buf);
                    218:                return;
                    219:        }
                    220:
                    221:        bzero(&sum, sizeof(sum));
1.12      canacar   222:        num_ifs = 0;
1.1       markus    223:
                    224:        lim = buf + need;
1.2       deraadt   225:        for (next = buf; next < lim; next += ifm.ifm_msglen) {
                    226:                bcopy(next, &ifm, sizeof ifm);
1.14      claudio   227:                if (ifm.ifm_version != RTM_VERSION ||
                    228:                    ifm.ifm_type != RTM_IFINFO ||
                    229:                    !(ifm.ifm_addrs & RTA_IFP))
1.1       markus    230:                        continue;
1.2       deraadt   231:                if (ifm.ifm_index >= nifs) {
1.12      canacar   232:                        if ((newstats = realloc(ifstats, (ifm.ifm_index + 4)
                    233:                            * sizeof(struct ifstat))) == NULL)
1.1       markus    234:                                continue;
                    235:                        ifstats = newstats;
1.2       deraadt   236:                        for (; nifs < ifm.ifm_index + 4; nifs++)
1.12      canacar   237:                                bzero(&ifstats[nifs], sizeof(*ifstats));
1.1       markus    238:                }
1.2       deraadt   239:                ifs = &ifstats[ifm.ifm_index];
1.1       markus    240:                if (ifs->ifs_name[0] == '\0') {
                    241:                        bzero(&info, sizeof(info));
1.2       deraadt   242:                        rt_getaddrinfo(
                    243:                            (struct sockaddr *)((struct if_msghdr *)next + 1),
                    244:                            ifm.ifm_addrs, info);
1.13      deraadt   245:                        sdl = (struct sockaddr_dl *)info[RTAX_IFP];
                    246:
                    247:                        if (sdl && sdl->sdl_family == AF_LINK &&
                    248:                            sdl->sdl_nlen > 0) {
                    249:                                struct ifreq ifrdesc;
                    250:                                char ifdescr[IFDESCRSIZE];
                    251:                                int s;
                    252:
                    253:                                bcopy(sdl->sdl_data, ifs->ifs_name,
                    254:                                      sdl->sdl_nlen);
                    255:                                ifs->ifs_name[sdl->sdl_nlen] = '\0';
                    256:
                    257:                                /* Get the interface description */
                    258:                                memset(&ifrdesc, 0, sizeof(ifrdesc));
                    259:                                strlcpy(ifrdesc.ifr_name, ifs->ifs_name,
                    260:                                        sizeof(ifrdesc.ifr_name));
                    261:                                ifrdesc.ifr_data = (caddr_t)&ifdescr;
                    262:
                    263:                                s = socket(AF_INET, SOCK_DGRAM, 0);
                    264:                                if (s != -1) {
                    265:                                        if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0)
                    266:                                                strlcpy(ifs->ifs_description,
                    267:                                                    ifrdesc.ifr_data,
                    268:                                                    sizeof(ifs->ifs_description));
                    269:                                        close(s);
1.3       dlg       270:                                }
1.1       markus    271:                        }
                    272:                        if (ifs->ifs_name[0] == '\0')
                    273:                                continue;
                    274:                }
1.12      canacar   275:                num_ifs++;
1.1       markus    276:                UPDATE(ifc_ip, ifm_data.ifi_ipackets);
                    277:                UPDATE(ifc_ib, ifm_data.ifi_ibytes);
                    278:                UPDATE(ifc_ie, ifm_data.ifi_ierrors);
                    279:                UPDATE(ifc_op, ifm_data.ifi_opackets);
                    280:                UPDATE(ifc_ob, ifm_data.ifi_obytes);
                    281:                UPDATE(ifc_oe, ifm_data.ifi_oerrors);
                    282:                UPDATE(ifc_co, ifm_data.ifi_collisions);
1.7       claudio   283:                ifs->ifs_cur.ifc_flags = ifm.ifm_flags;
                    284:                ifs->ifs_cur.ifc_state = ifm.ifm_data.ifi_link_state;
1.1       markus    285:        }
                    286:        free(buf);
                    287: }
                    288:
                    289:
1.12      canacar   290: static void
                    291: showifstat(struct ifstat *ifs)
1.1       markus    292: {
1.12      canacar   293:        print_fld_str(FLD_IF_IFACE, ifs->ifs_name);
1.1       markus    294:
1.12      canacar   295:        tb_start();
                    296:        tbprintf("%s", ifs->ifs_cur.ifc_flags & IFF_UP ?
                    297:                 "up" : "dn");
1.7       claudio   298:
1.12      canacar   299:        switch (ifs->ifs_cur.ifc_state) {
1.7       claudio   300:        case LINK_STATE_UP:
1.8       reyk      301:        case LINK_STATE_HALF_DUPLEX:
                    302:        case LINK_STATE_FULL_DUPLEX:
1.12      canacar   303:                tbprintf(":U");
                    304:                break;
1.7       claudio   305:        case LINK_STATE_DOWN:
1.12      canacar   306:                tbprintf (":D");
                    307:                break;
1.7       claudio   308:        }
1.12      canacar   309:
                    310:        print_fld_tb(FLD_IF_STATE);
1.13      deraadt   311:
                    312:        print_fld_str(FLD_IF_DESC, ifs->ifs_description);
1.12      canacar   313:
                    314:        print_fld_size(FLD_IF_IBYTES, ifs->ifs_cur.ifc_ib);
                    315:        print_fld_size(FLD_IF_IPKTS, ifs->ifs_cur.ifc_ip);
                    316:        print_fld_size(FLD_IF_IERRS, ifs->ifs_cur.ifc_ie);
                    317:
                    318:        print_fld_size(FLD_IF_OBYTES, ifs->ifs_cur.ifc_ob);
                    319:        print_fld_size(FLD_IF_OPKTS, ifs->ifs_cur.ifc_op);
                    320:        print_fld_size(FLD_IF_OERRS, ifs->ifs_cur.ifc_oe);
                    321:
                    322:        print_fld_size(FLD_IF_COLLS, ifs->ifs_cur.ifc_co);
                    323:
                    324:        end_line();
1.7       claudio   325: }
1.6       deraadt   326:
1.12      canacar   327: static void
                    328: showtotal(void)
1.1       markus    329: {
1.12      canacar   330:        print_fld_str(FLD_IF_IFACE, "Totals");
                    331:
                    332:        print_fld_size(FLD_IF_IBYTES, sum.ifc_ib);
                    333:        print_fld_size(FLD_IF_IPKTS, sum.ifc_ip);
                    334:        print_fld_size(FLD_IF_IERRS, sum.ifc_ie);
                    335:
                    336:        print_fld_size(FLD_IF_OBYTES, sum.ifc_ob);
                    337:        print_fld_size(FLD_IF_OPKTS, sum.ifc_op);
                    338:        print_fld_size(FLD_IF_OERRS, sum.ifc_oe);
                    339:
                    340:        print_fld_size(FLD_IF_COLLS, sum.ifc_co);
                    341:
                    342:        end_line();
1.1       markus    343:
                    344: }
                    345:
                    346: int
1.12      canacar   347: if_keyboard_callback(int ch)
1.1       markus    348: {
                    349:        struct ifstat *ifs;
                    350:
1.12      canacar   351:        switch (ch) {
                    352:        case 'r':
                    353:                for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
                    354:                        ifs->ifs_old = ifs->ifs_now;
1.1       markus    355:                state = RUN;
1.12      canacar   356:                gotsig_alarm = 1;
                    357:
                    358:                break;
                    359:        case 'b':
1.1       markus    360:                state = BOOT;
                    361:                for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
                    362:                        bzero(&ifs->ifs_old, sizeof(ifs->ifs_old));
1.12      canacar   363:                gotsig_alarm = 1;
                    364:                break;
                    365:        case 't':
1.1       markus    366:                state = TIME;
1.12      canacar   367:                gotsig_alarm = 1;
                    368:                break;
                    369:        default:
                    370:                return keyboard_callback(ch);
                    371:        };
                    372:
                    373:        return 1;
1.1       markus    374: }
1.12      canacar   375: