Annotation of embedaddon/iftop/options.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * options.c:
        !             3:  *
        !             4:  *
        !             5:  */
        !             6: 
        !             7: #include "config.h"
        !             8: 
        !             9: #include <sys/types.h>
        !            10: 
        !            11: #include <stdio.h>
        !            12: #include <string.h>
        !            13: #include <stdlib.h>
        !            14: #include <unistd.h>
        !            15: 
        !            16: #include <sys/ioctl.h>
        !            17: #include <sys/socket.h>
        !            18: #include <netinet/in.h>
        !            19: #include <arpa/inet.h>
        !            20: #include <net/if.h>
        !            21: 
        !            22: #include "iftop.h"
        !            23: #include "options.h"
        !            24: #include "cfgfile.h"
        !            25: #include "integers.h"
        !            26: 
        !            27: #if !defined(HAVE_INET_ATON) && defined(HAVE_INET_PTON)
        !            28: #   define inet_aton(a, b)  inet_pton(AF_INET, (a), (b))
        !            29: #endif
        !            30: 
        !            31: options_t options;
        !            32: 
        !            33: char optstr[] = "+i:f:nNF:hpbBPm:c:";
        !            34: 
        !            35: /* Global options. */
        !            36: 
        !            37: /* Selecting an interface on which to listen: */
        !            38: 
        !            39: /* This is a list of interface name prefixes which are `bad' in the sense
        !            40:  * that they don't refer to interfaces of external type on which we are
        !            41:  * likely to want to listen. We also compare candidate interfaces to lo. */
        !            42: static char *bad_interface_names[] = {
        !            43:             "lo:",
        !            44:             "lo",
        !            45:             "stf",     /* pseudo-device 6to4 tunnel interface */
        !            46:             "gif",     /* psuedo-device generic tunnel interface */
        !            47:             "dummy",
        !            48:             "vmnet",
        !            49:             NULL        /* last entry must be NULL */
        !            50:         };
        !            51: 
        !            52: config_enumeration_type sort_enumeration[] = {
        !            53:        { "2s", OPTION_SORT_DIV1 },
        !            54:        { "10s", OPTION_SORT_DIV2 },
        !            55:        { "40s", OPTION_SORT_DIV3 },
        !            56:        { "source", OPTION_SORT_SRC },
        !            57:        { "destination", OPTION_SORT_SRC },
        !            58:        { NULL, -1 }
        !            59: };
        !            60: 
        !            61: config_enumeration_type linedisplay_enumeration[] = {
        !            62:        { "two-line", OPTION_LINEDISPLAY_TWO_LINE },
        !            63:        { "one-line-both", OPTION_LINEDISPLAY_ONE_LINE_BOTH },
        !            64:        { "one-line-sent", OPTION_LINEDISPLAY_ONE_LINE_SENT },
        !            65:        { "one-line-received", OPTION_LINEDISPLAY_ONE_LINE_RECV },
        !            66:        { NULL, -1 }
        !            67: };
        !            68: 
        !            69: config_enumeration_type showports_enumeration[] = {
        !            70:        { "off", OPTION_PORTS_OFF },
        !            71:        { "source-only", OPTION_PORTS_SRC },
        !            72:        { "destination-only", OPTION_PORTS_DEST },
        !            73:        { "on", OPTION_PORTS_ON },
        !            74:        { NULL, -1 }
        !            75: };
        !            76: 
        !            77: static int is_bad_interface_name(char *i) {
        !            78:     char **p;
        !            79:     for (p = bad_interface_names; *p; ++p)
        !            80:         if (strncmp(i, *p, strlen(*p)) == 0)
        !            81:             return 1;
        !            82:     return 0;
        !            83: }
        !            84: 
        !            85: /* This finds the first interface which is up and is not the loopback
        !            86:  * interface or one of the interface types listed in bad_interface_names. */
        !            87: static char *get_first_interface(void) {
        !            88:     struct if_nameindex * nameindex;
        !            89:     char *i = NULL;
        !            90:     int j = 0;
        !            91:     /* Use if_nameindex(3) instead? */
        !            92: 
        !            93:     nameindex = if_nameindex();
        !            94:     if(nameindex == NULL) {
        !            95:         return NULL;
        !            96:     }
        !            97: 
        !            98:     while(nameindex[j].if_index != 0) {
        !            99:         if (strcmp(nameindex[j].if_name, "lo") != 0 && !is_bad_interface_name(nameindex[j].if_name)) {
        !           100:             i = xstrdup(nameindex[j].if_name);
        !           101:             break;
        !           102:         }
        !           103:         j++;
        !           104:     }
        !           105:     if_freenameindex(nameindex);
        !           106:     return i;
        !           107: }
        !           108: 
        !           109: void options_set_defaults() {
        !           110:     char *s;
        !           111:     /* Should go through the list of interfaces, and find the first one which
        !           112:      * is up and is not lo or dummy*. */
        !           113:     options.interface = get_first_interface();
        !           114:     if (!options.interface)
        !           115:         options.interface = "eth0";
        !           116: 
        !           117:     options.filtercode = NULL;
        !           118:     options.netfilter = 0;
        !           119:     inet_aton("10.0.1.0", &options.netfilternet);
        !           120:     inet_aton("255.255.255.0", &options.netfiltermask);
        !           121:     options.dnsresolution = 1;
        !           122:     options.portresolution = 1;
        !           123: #ifdef NEED_PROMISCUOUS_FOR_OUTGOING
        !           124:     options.promiscuous = 1;
        !           125:     options.promiscuous_but_choosy = 1;
        !           126: #else
        !           127:     options.promiscuous = 0;
        !           128:     options.promiscuous_but_choosy = 0;
        !           129: #endif
        !           130:     options.showbars = 1;
        !           131:     options.showports = OPTION_PORTS_OFF;
        !           132:     options.aggregate_src = 0;
        !           133:     options.aggregate_dest = 0;
        !           134:     options.paused = 0;
        !           135:     options.showhelp = 0;
        !           136:     options.bandwidth_in_bytes = 0;
        !           137:     options.sort = OPTION_SORT_DIV2;
        !           138:     options.screenfilter = NULL;
        !           139:     options.freezeorder = 0;
        !           140:     options.linedisplay = OPTION_LINEDISPLAY_TWO_LINE;
        !           141:     options.screen_offset = 0;
        !           142:     options.show_totals = 0;
        !           143:     options.max_bandwidth = 0; /* auto */
        !           144:     options.log_scale = 0;
        !           145:     options.bar_interval = 1;
        !           146: 
        !           147:     /* Figure out the name for the config file */
        !           148:     s = getenv("HOME");
        !           149:     if(s != NULL) {
        !           150:         int i = strlen(s) + 9 + 1;
        !           151:         options.config_file = xmalloc(i);
        !           152:         snprintf(options.config_file,i,"%s/.iftoprc",s);
        !           153:     }
        !           154:     else {
        !           155:         options.config_file = xstrdup("iftoprc");
        !           156:     }
        !           157:     options.config_file_specified = 0;
        !           158:     
        !           159: }
        !           160: 
        !           161: static void die(char *msg) {
        !           162:     fprintf(stderr, msg);
        !           163:     exit(1);
        !           164: }
        !           165: 
        !           166: static void set_max_bandwidth(char* arg) {
        !           167:     char* units;
        !           168:     long long mult = 1;
        !           169:     long long value;
        !           170:     units = arg + strspn(arg, "0123456789");
        !           171:     if(strlen(units) > 1) {
        !           172:         die("Invalid units\n");
        !           173:     }
        !           174:     if(strlen(units) == 1) {
        !           175:         if(*units == 'k' || *units == 'K') {
        !           176:             mult = 1024;
        !           177:         }
        !           178:         else if(*units == 'm' || *units == 'M') {
        !           179:             mult = 1024 * 1024;
        !           180:         }
        !           181:         else if(*units == 'g' || *units == 'G') {
        !           182:             mult = 1024 * 1024 * 1024;
        !           183:         }
        !           184:     }
        !           185:     *units = '\0';
        !           186:     if(sscanf(arg, "%lld", &value) != 1) {
        !           187:         die("Error reading max bandwidth\n");
        !           188:     }
        !           189:     options.max_bandwidth = value * mult;
        !           190: }
        !           191: 
        !           192: static void set_net_filter(char* arg) {
        !           193:     char* mask;
        !           194: 
        !           195:     mask = strchr(arg, '/');
        !           196:     if (mask == NULL) {
        !           197:         die("Could not parse net/mask\n");
        !           198:     }
        !           199:     *mask = '\0';
        !           200:     mask++;
        !           201:     if (inet_aton(arg, &options.netfilternet) == 0)
        !           202:         die("Invalid network address\n");
        !           203:     /* Accept a netmask like /24 or /255.255.255.0. */
        !           204:     if (mask[strspn(mask, "0123456789")] == '\0') {
        !           205:         /* Whole string is numeric */
        !           206:         int n;
        !           207:         n = atoi(mask);
        !           208:         if (n > 32) {
        !           209:             die("Invalid netmask");
        !           210:         }
        !           211:         else {
        !           212:             if(n == 32) {
        !           213:               /* This needs to be special cased, although I don't fully 
        !           214:                * understand why -pdw 
        !           215:                */
        !           216:               options.netfiltermask.s_addr = htonl(0xffffffffl);
        !           217:             }
        !           218:             else {
        !           219:               u_int32_t mm = 0xffffffffl;
        !           220:               mm >>= n;
        !           221:               options.netfiltermask.s_addr = htonl(~mm);
        !           222:             }
        !           223:         }
        !           224:     } 
        !           225:     else if (inet_aton(mask, &options.netfiltermask) == 0) {
        !           226:         die("Invalid netmask\n");
        !           227:     }
        !           228:     options.netfilternet.s_addr = options.netfilternet.s_addr & options.netfiltermask.s_addr;
        !           229: 
        !           230:     options.netfilter = 1;
        !           231: 
        !           232: }
        !           233: 
        !           234: /* usage:
        !           235:  * Print usage information. */
        !           236: static void usage(FILE *fp) {
        !           237:     fprintf(fp,
        !           238: "iftop: display bandwidth usage on an interface by host\n"
        !           239: "\n"
        !           240: "Synopsis: iftop -h | [-npbBP] [-i interface] [-f filter code] [-N net/mask]\n"
        !           241: "\n"
        !           242: "   -h                  display this message\n"
        !           243: "   -n                  don't do hostname lookups\n"
        !           244: "   -N                  don't convert port numbers to services\n"
        !           245: "   -p                  run in promiscuous mode (show traffic between other\n"
        !           246: "                       hosts on the same network segment)\n"
        !           247: "   -b                  don't display a bar graph of traffic\n"
        !           248: "   -B                  Display bandwidth in bytes\n"
        !           249: "   -i interface        listen on named interface\n"
        !           250: "   -f filter code      use filter code to select packets to count\n"
        !           251: "                       (default: none, but only IP packets are counted)\n"
        !           252: "   -F net/mask         show traffic flows in/out of network\n"
        !           253: "   -P                  show ports as well as hosts\n"
        !           254: "   -m limit            sets the upper limit for the bandwidth scale\n"
        !           255: "   -c config file      specifies an alternative configuration file\n"
        !           256: "\n"
        !           257: "iftop, version " IFTOP_VERSION "\n"
        !           258: "copyright (c) 2002 Paul Warren <pdw@ex-parrot.com> and contributors\n"
        !           259:             );
        !           260: }
        !           261: 
        !           262: void options_read_args(int argc, char **argv) {
        !           263:     int opt;
        !           264: 
        !           265:     opterr = 0;
        !           266:     while ((opt = getopt(argc, argv, optstr)) != -1) {
        !           267:         switch (opt) {
        !           268:             case 'h':
        !           269:                 usage(stdout);
        !           270:                 exit(0);
        !           271: 
        !           272:             case 'n':
        !           273:                 config_set_string("dns-resolution","false");
        !           274:                 break;
        !           275: 
        !           276:             case 'N':
        !           277:                 config_set_string("port-resolution","false");
        !           278:                 break;
        !           279: 
        !           280:             case 'i':
        !           281:                 config_set_string("interface", optarg);
        !           282:                 break;
        !           283: 
        !           284:             case 'f':
        !           285:                 config_set_string("filter-code", optarg);
        !           286:                 break;
        !           287: 
        !           288:             case 'p':
        !           289:                 config_set_string("promiscuous", "true");
        !           290:                 break;
        !           291: 
        !           292:             case 'P':
        !           293:                 config_set_string("port-display", "on");
        !           294:                 break;
        !           295: 
        !           296:             case 'F':
        !           297:                 config_set_string("net-filter", optarg);
        !           298:                 break;
        !           299:             
        !           300:             case 'm':
        !           301:                 config_set_string("max-bandwidth", optarg);
        !           302:                 break;
        !           303: 
        !           304:             case 'b':
        !           305:                 config_set_string("show-bars", "true");
        !           306:                 break;
        !           307: 
        !           308:             case 'B':
        !           309:                 config_set_string("use-bytes", "true");
        !           310:                 break;
        !           311: 
        !           312:             case 'c':
        !           313:                 xfree(options.config_file);
        !           314:                 options.config_file = xstrdup(optarg);
        !           315:                 options.config_file_specified = 1;
        !           316:                 break;
        !           317: 
        !           318:             case '?':
        !           319:                 fprintf(stderr, "iftop: unknown option -%c\n", optopt);
        !           320:                 usage(stderr);
        !           321:                 exit(1);
        !           322: 
        !           323:             case ':':
        !           324:                 fprintf(stderr, "iftop: option -%c requires an argument\n", optopt);
        !           325:                 usage(stderr);
        !           326:                 exit(1);
        !           327:         }
        !           328:     }
        !           329: 
        !           330:     if (optind != argc) {
        !           331:         fprintf(stderr, "iftop: found arguments following options\n");
        !           332:         fprintf(stderr, "*** some options have changed names since v0.9 ***\n");
        !           333:         usage(stderr);
        !           334:         exit(1);
        !           335:     }
        !           336: }
        !           337: 
        !           338: /* options_config_get_string:
        !           339:  * Gets a value from the config, sets *value to a copy of the value, if
        !           340:  * found.  Leaves the option unchanged otherwise. */
        !           341: int options_config_get_string(const char *name, char** value) {
        !           342:     char *s;
        !           343:     s = config_get_string(name);
        !           344:     if(s != NULL) {
        !           345:         *value = xstrdup(s);
        !           346:         return 1;
        !           347:     }
        !           348:     return 0;
        !           349: }
        !           350: 
        !           351: int options_config_get_bool(const char *name, int* value) {
        !           352:     if(config_get_string(name)) {
        !           353:         *value = config_get_bool(name);
        !           354:         return 1;
        !           355:     }
        !           356:     return 0;
        !           357: }
        !           358: 
        !           359: int options_config_get_int(const char *name, int* value) {
        !           360:     if(config_get_string(name)) {
        !           361:         config_get_int(name, value);
        !           362:         return 1;
        !           363:     }
        !           364:     return 0;
        !           365: }
        !           366: 
        !           367: int options_config_get_enum(char *name, config_enumeration_type* enumeration, int *result) {
        !           368:     int i;
        !           369:     if(config_get_string(name)) {
        !           370:         if(config_get_enum(name, enumeration, &i)) {
        !           371:             *result = i; 
        !           372:             return 1;
        !           373:         }
        !           374:     }
        !           375:     return 0;
        !           376: }
        !           377: 
        !           378: int options_config_get_promiscuous() {
        !           379:     if(config_get_string("promiscuous")) {
        !           380:         options.promiscuous = config_get_bool("promiscuous");
        !           381:         if(options.promiscuous) {
        !           382:             /* User has explicitly requested promiscuous mode, so don't be
        !           383:              * choosy */
        !           384:             options.promiscuous_but_choosy = 0;
        !           385:         }
        !           386:         return 1;
        !           387:     }
        !           388:     return 0;
        !           389: }
        !           390: 
        !           391: int options_config_get_bw_rate(char *directive, long long* result) {
        !           392:     char* units;
        !           393:     long long mult = 1;
        !           394:     long long value;
        !           395:     char *s;
        !           396:     s = config_get_string(directive);
        !           397:     if(s) {
        !           398:         units = s + strspn(s, "0123456789");
        !           399:         if(strlen(units) > 1) {
        !           400:             fprintf(stderr, "Invalid units in value: %s\n", s);
        !           401:             return 0;
        !           402:         }
        !           403:         if(strlen(units) == 1) {
        !           404:             if(*units == 'k' || *units == 'K') {
        !           405:                 mult = 1024;
        !           406:             }
        !           407:             else if(*units == 'm' || *units == 'M') {
        !           408:                 mult = 1024 * 1024;
        !           409:             }
        !           410:             else if(*units == 'g' || *units == 'G') {
        !           411:                 mult = 1024 * 1024 * 1024;
        !           412:             }
        !           413:             else if(*units == 'b' || *units == 'B') {
        !           414:                 /* bits => mult = 1 */
        !           415:             }
        !           416:             else {
        !           417:                 fprintf(stderr, "Invalid units in value: %s\n", s);
        !           418:                 return 0;
        !           419:             }
        !           420:         }
        !           421:         *units = '\0';
        !           422:         if(sscanf(s, "%lld", &value) != 1) {
        !           423:             fprintf(stderr, "Error reading rate: %s\n", s);
        !           424:         }
        !           425:         options.max_bandwidth = value * mult;
        !           426:         return 1;
        !           427:     }
        !           428:     return 0;
        !           429: }
        !           430: 
        !           431: /*
        !           432:  * Read the net filter option.  
        !           433:  */
        !           434: int options_config_get_net_filter() {
        !           435:     char* s;
        !           436:     s = config_get_string("net-filter");
        !           437:     if(s) {
        !           438:         char* mask;
        !           439: 
        !           440:         mask = strchr(s, '/');
        !           441:         if (mask == NULL) {
        !           442:             fprintf(stderr, "Could not parse net/mask: %s\n", s);
        !           443:             return 0;
        !           444:         }
        !           445:         *mask = '\0';
        !           446:         mask++;
        !           447:         if (inet_aton(s, &options.netfilternet) == 0) {
        !           448:             fprintf(stderr, "Invalid network address: %s\n", s);
        !           449:             return 0;
        !           450:         }
        !           451:         /* Accept a netmask like /24 or /255.255.255.0. */
        !           452:         if (mask[strspn(mask, "0123456789")] == '\0') {
        !           453:             /* Whole string is numeric */
        !           454:             int n;
        !           455:             n = atoi(mask);
        !           456:             if (n > 32) {
        !           457:                 fprintf(stderr, "Invalid netmask: %s\n", s);
        !           458:             }
        !           459:             else {
        !           460:                 if(n == 32) {
        !           461:                   /* This needs to be special cased, although I don't fully 
        !           462:                    * understand why -pdw 
        !           463:                    */
        !           464:                   options.netfiltermask.s_addr = htonl(0xffffffffl);
        !           465:                 }
        !           466:                 else {
        !           467:                   u_int32_t mm = 0xffffffffl;
        !           468:                   mm >>= n;
        !           469:                   options.netfiltermask.s_addr = htonl(~mm);
        !           470:                 }
        !           471:             }
        !           472:         } 
        !           473:         else if (inet_aton(mask, &options.netfiltermask) == 0) {
        !           474:             fprintf(stderr, "Invalid netmask: %s\n", s);
        !           475:         }
        !           476:         options.netfilternet.s_addr = options.netfilternet.s_addr & options.netfiltermask.s_addr;
        !           477:         options.netfilter = 1;
        !           478:         return 1;
        !           479:     }
        !           480:     return 0;
        !           481: }
        !           482: 
        !           483: 
        !           484: void options_make() {
        !           485:     options_config_get_string("interface", &options.interface);
        !           486:     options_config_get_bool("dns-resolution", &options.dnsresolution);
        !           487:     options_config_get_bool("port-resolution", &options.portresolution);
        !           488:     options_config_get_string("filter-code", &options.filtercode);
        !           489:     options_config_get_bool("show-bars", &options.showbars);
        !           490:     options_config_get_promiscuous();
        !           491:     options_config_get_bool("hide-source", &options.aggregate_src);
        !           492:     options_config_get_bool("hide-destination", &options.aggregate_dest);
        !           493:     options_config_get_bool("use-bytes", &options.bandwidth_in_bytes);
        !           494:     options_config_get_enum("sort", sort_enumeration, (int*)&options.sort);
        !           495:     options_config_get_enum("line-display", linedisplay_enumeration, (int*)&options.linedisplay);
        !           496:     options_config_get_bool("show-totals", &options.show_totals);
        !           497:     options_config_get_bool("log-scale", &options.log_scale);
        !           498:     options_config_get_bw_rate("max-bandwidth", &options.max_bandwidth);
        !           499:     options_config_get_enum("port-display", showports_enumeration, (int*)&options.showports);
        !           500:     options_config_get_string("screen-filter", &options.screenfilter);
        !           501:     options_config_get_net_filter();
        !           502: };

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>