Annotation of embedaddon/arping/src/arping.c, revision 1.1

1.1     ! misho       1: /** arping/src/arping.c
        !             2:  *
        !             3:  * arping
        !             4:  *
        !             5:  * By Thomas Habets <thomas@habets.pp.se>
        !             6:  *
        !             7:  * ARP 'ping' utility
        !             8:  *
        !             9:  * Broadcasts a who-has ARP packet on the network and prints answers.
        !            10:  * *VERY* useful when you are trying to pick an unused IP for a net that
        !            11:  * you don't yet have routing to. Then again, if you have no idea what I'm
        !            12:  * talking about then you prolly don't need it.
        !            13:  *
        !            14:  * Also finds out IP of specified MAC
        !            15:  *
        !            16:  */
        !            17: /*
        !            18:  *  Copyright (C) 2000-2010 Thomas Habets <thomas@habets.pp.se>
        !            19:  *
        !            20:  *  This library is free software; you can redistribute it and/or
        !            21:  *  modify it under the terms of the GNU General Public
        !            22:  *  License as published by the Free Software Foundation; either
        !            23:  *  version 2 of the License, or (at your option) any later version.
        !            24:  *
        !            25:  *  This library is distributed in the hope that it will be useful,
        !            26:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            27:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            28:  *  General Public License for more details.
        !            29:  *
        !            30:  *  You should have received a copy of the GNU General Public License along
        !            31:  *  with this program; if not, write to the Free Software Foundation, Inc.,
        !            32:  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
        !            33:  */
        !            34: #if HAVE_CONFIG_H
        !            35: #include "config.h"
        !            36: #endif
        !            37: 
        !            38: #include <stdio.h>
        !            39: #include <stdlib.h>
        !            40: #include <poll.h>
        !            41: 
        !            42: #if HAVE_UNISTD_H
        !            43: #include <unistd.h>
        !            44: #endif
        !            45: 
        !            46: #if HAVE_STDINT_H
        !            47: #include <stdint.h>
        !            48: #endif
        !            49: 
        !            50: #if HAVE_INTTYPES_H
        !            51: #include <inttypes.h>
        !            52: #endif
        !            53: 
        !            54: #if HAVE_SYS_TIME_H
        !            55: #include <sys/time.h>
        !            56: #endif
        !            57: 
        !            58: #if HAVE_SYS_TYPES_H
        !            59: #include <sys/types.h>
        !            60: #endif
        !            61: 
        !            62: #if HAVE_SYS_SOCKET_H
        !            63: #include <sys/socket.h>
        !            64: #endif
        !            65: 
        !            66: #if HAVE_NETINET_IN_H
        !            67: #include <netinet/in.h>
        !            68: #endif
        !            69: 
        !            70: #if HAVE_ARPA_INET_H
        !            71: #include <arpa/inet.h>
        !            72: #endif
        !            73: 
        !            74: #if HAVE_LIBNET_H
        !            75: #include <libnet.h>
        !            76: #endif
        !            77: 
        !            78: #if HAVE_WIN32_LIBNET_H
        !            79: #include <win32/libnet.h>
        !            80: #endif
        !            81: #include <pcap.h>
        !            82: 
        !            83: #if HAVE_NET_BPF_H
        !            84: #include <net/bpf.h>
        !            85: #endif
        !            86: 
        !            87: #ifndef ETH_ALEN
        !            88: #define ETH_ALEN 6
        !            89: #endif
        !            90: 
        !            91: #ifndef IP_ALEN
        !            92: #define IP_ALEN 4
        !            93: #endif
        !            94: 
        !            95: #ifndef WIN32
        !            96: #define WIN32 0
        !            97: #endif
        !            98: 
        !            99: /**
        !           100:  * OS-specific interface finding using routing table. See findif_*.c
        !           101:  */
        !           102: const char *
        !           103: arping_lookupdev(const char *ifname,
        !           104:                  uint32_t srcip,
        !           105:                  uint32_t dstip,
        !           106:                  char *ebuf);
        !           107: 
        !           108: static const char *version = VERSION; /* from autoconf */
        !           109: 
        !           110: static libnet_t *libnet = 0;
        !           111: 
        !           112: static struct timeval lastpacketsent;
        !           113: 
        !           114: uint32_t srcip, dstip;
        !           115: 
        !           116: static int beep = 0;
        !           117: static int reverse_beep = 0;
        !           118: static int verbose = 0;
        !           119: static int alsototal = 0;
        !           120: /*static int pingmac = 0; */
        !           121: static int finddup = 0;
        !           122: static int dupfound = 0;
        !           123: static unsigned int numsent = 0;
        !           124: static unsigned int numrecvd = 0;
        !           125: static unsigned int numdots = 0;
        !           126: static int addr_must_be_same = 0;
        !           127: /* RAWRAW is RAW|RRAW */
        !           128: static enum { NORMAL, QUIET, RAW, RRAW, RAWRAW, DOT } display = NORMAL;
        !           129: static char *target = "huh? bug in arping?";
        !           130: static uint8_t ethnull[ETH_ALEN];
        !           131: static uint8_t ethxmas[ETH_ALEN];
        !           132: static char srcmac[ETH_ALEN];
        !           133: static char dstmac[ETH_ALEN];
        !           134: static char lastreplymac[ETH_ALEN];
        !           135: 
        !           136: /* doesn't need to be volatile */
        !           137: volatile int time_to_die = 0;
        !           138: 
        !           139: /**
        !           140:  *
        !           141:  */
        !           142: static void
        !           143: count_missing_dots()
        !           144: {
        !           145:         while (numsent > numdots) {
        !           146:                 putchar('.');
        !           147:                 numdots++;
        !           148:         }
        !           149: }
        !           150: 
        !           151: /**
        !           152:  *
        !           153:  */    
        !           154: void
        !           155: do_libnet_init(const char *ifname)
        !           156: {
        !           157:        char ebuf[LIBNET_ERRBUF_SIZE];
        !           158:        if (verbose > 1) {
        !           159:                printf("libnet_init(%s)\n", ifname?ifname:"<null>");
        !           160:        }
        !           161:        if (libnet) {
        !           162:                /* prolly going to switch interface from temp to real */
        !           163:                libnet_destroy(libnet);
        !           164:                libnet = 0;
        !           165:        }
        !           166:        if (getuid() && geteuid()) {
        !           167:                fprintf(stderr, "arping: must run as root\n");
        !           168:                exit(1);
        !           169:        }
        !           170: 
        !           171:        if (!(libnet = libnet_init(LIBNET_LINK,
        !           172:                                   (char*)ifname,
        !           173:                                   ebuf))) {
        !           174:                fprintf(stderr, "arping: libnet_init(): %s\n", ebuf);
        !           175:                exit(1);
        !           176:        }
        !           177: }
        !           178: 
        !           179: /**
        !           180:  *
        !           181:  */
        !           182: const char *
        !           183: arping_lookupdev_default(const char *ifname,
        !           184:                         uint32_t srcip, uint32_t dstip,
        !           185:                         char *ebuf)
        !           186: {
        !           187: #if WIN32
        !           188:        WCHAR buf[LIBNET_ERRBUF_SIZE + PCAP_ERRBUF_SIZE];
        !           189:        WCHAR* ret = (WCHAR*)pcap_lookupdev((char*)buf);
        !           190:        if (ret != NULL) {
        !           191:                wcstombs(ebuf, ret, LIBNET_ERRBUF_SIZE + PCAP_ERRBUF_SIZE);
        !           192:                return ebuf;
        !           193:        }
        !           194:        return NULL;
        !           195: #else
        !           196:        return pcap_lookupdev(ebuf);
        !           197: #endif
        !           198: }
        !           199: 
        !           200: #if WIN32
        !           201: static BOOL WINAPI arping_console_ctrl_handler(DWORD dwCtrlType)
        !           202: {
        !           203:        if(verbose) {
        !           204:                printf("arping_console_ctrl_handler( %d )\n", (int)dwCtrlType);
        !           205:        }
        !           206:        time_to_die = 1;
        !           207: 
        !           208: #if 0
        !           209:        /* if SetConsoleCtrlHandler() does what I think, this isn't needed */
        !           210:        if (display == NORMAL) {
        !           211:                printf("\n--- %s statistics ---\n"
        !           212:                       "%d packets transmitted, %d packets received, %3.0f%% "
        !           213:                       "unanswered\n",target,numsent,numrecvd,
        !           214:                       100.0 - 100.0 * (float)(numrecvd)/(float)numsent);
        !           215:         }
        !           216: #endif
        !           217:        return TRUE;
        !           218: }
        !           219: #endif
        !           220: 
        !           221: 
        !           222: /**
        !           223:  *
        !           224:  */
        !           225: static void sigint(int i)
        !           226: {
        !           227:        time_to_die = 1;
        !           228: }
        !           229: 
        !           230: /**
        !           231:  *
        !           232:  */
        !           233: static void
        !           234: extended_usage()
        !           235: {
        !           236:        printf("\nOptions:\n");
        !           237:        printf("\n"
        !           238:               "    -0     Use this option to ping with source IP address 0.0.0.0. Use this\n"
        !           239:               "           when you haven't configured your interface yet.  Note that  this\n"
        !           240:               "           may  get  the  MAC-ping  unanswered.   This  is  an alias for -S\n"
        !           241:               "           0.0.0.0.\n"
        !           242:               "    -a     Audiable ping.\n"
        !           243:               "    -A     Only count addresses matching  requested  address  (This  *WILL*\n"
        !           244:               "           break  most things you do. Only useful if you are arpinging many\n"
        !           245:               "           hosts at once. See arping-scan-net.sh for an example).\n"
        !           246:               "    -b     Like -0 but source broadcast source  address  (255.255.255.255).\n"
        !           247:               "           Note that this may get the arping unanswered since it's not nor-\n"
        !           248:               "           mal behavior for a host.\n"
        !           249:               "    -B     Use instead of host if you want to address 255.255.255.255.\n"
        !           250:               "    -c count\n"
        !           251:               "           Only send count requests.\n"
        !           252:               "    -d     Find duplicate replies. Exit with 1 if there are "
        !           253:                "answers from\n"
        !           254:                "           two different MAC addresses.\n"
        !           255:               "    -D     Display answers as dots and missing packets as exclamation points.\n"
        !           256:                "    -e     Like -a but beep when there is no reply.\n"
        !           257:               "    -F     Don't try to be smart about the interface name.  (even  if  this\n"
        !           258:               "           switch is not given, -i overrides smartness)\n"
        !           259:               "    -h     Displays a help message and exits.\n"
        !           260:               "    -i interface\n"
        !           261:               "           Use the specified interface.\n"
        !           262:               "    -q     Does not display messages, except error messages.\n"
        !           263:               "    -r     Raw output: only the MAC/IP address is displayed for each reply.\n"
        !           264:               "    -R     Raw output: Like -r but shows \"the other one\", can  be  combined\n"
        !           265:               "           with -r.\n"
        !           266:               "    -s MAC Set source MAC address. You may need to use -p with this.\n"
        !           267:               "    -S IP  Like  -b and -0 but with set source address.  Note that this may\n"
        !           268:               "           get the arping unanswered if the target does not have routing to\n"
        !           269:               "           the  IP.  If you don't own the IP you are using, you may need to\n"
        !           270:               "           turn on promiscious mode on the interface (with -p).  With  this\n"
        !           271:               "           switch  you can find out what IP-address a host has without tak-\n"
        !           272:               "           ing an IP-address yourself.\n"
        !           273:               "    -t MAC Set target MAC address to use when pinging IP address.\n"
        !           274:               "    -T IP  Use -T as target address when pinging MACs that won't respond to\n"
        !           275:               "           a broadcast ping but perhaps to a directed broadcast.\n"
        !           276:               "           Example:\n"
        !           277:               "           To check the address of MAC-A, use knowledge of MAC-B and  IP-B.\n"
        !           278:               "           $ arping -S <IP-B> -s <MAC-B> -p <MAC-A>\n"
        !           279:               "    -p     Turn  on  promiscious  mode  on interface, use this if you don't\n"
        !           280:               "           \"own\" the MAC address you are using.\n"
        !           281:               "    -u     Show index=received/sent instead  of  just  index=received  when\n"
        !           282:               "           pinging MACs.\n"
        !           283:               "    -v     Verbose output. Use twice for more messages.\n"
        !           284:               "    -w     Time to wait between pings, in microseconds.\n");
        !           285:         printf("Report bugs to: thomas@habets.pp.se\n"
        !           286:                "Arping home page: <http://www.habets.pp.se/synscan/>\n"
        !           287:                "Development repo: http://github.com/ThomasHabets/arping\n");
        !           288: }
        !           289: 
        !           290: /**
        !           291:  *
        !           292:  */
        !           293: static void
        !           294: standard_usage()
        !           295: {
        !           296:        printf("ARPing %s, by Thomas Habets <thomas@habets.pp.se>\n",
        !           297:               version);
        !           298:         printf("usage: arping [ -0aAbdDeFpqrRuv ] [ -w <us> ] "
        !           299:                "[ -S <host/ip> ]\n"
        !           300:                "              "
        !           301:                "[ -T <host/ip ] "
        !           302:                "[ -s <MAC> ] [ -t <MAC> ] [ -c <count> ]\n"
        !           303:                "              "
        !           304:                "[ -i <interface> ] "
        !           305:                "<host/ip/MAC | -B>\n");
        !           306: }
        !           307: 
        !           308: /**
        !           309:  *
        !           310:  */
        !           311: static void
        !           312: usage(int ret)
        !           313: {
        !           314:         standard_usage();
        !           315:         if (WIN32) {
        !           316:                 extended_usage();
        !           317:         } else {
        !           318:                 printf("For complete usage info, use --help"
        !           319:                        " or check the manpage.\n");
        !           320:         }
        !           321:        exit(ret);
        !           322: }
        !           323: 
        !           324: /**
        !           325:  * It was unclear from msdn.microsoft.com if their scanf() supported
        !           326:  * [0-9a-fA-F], so I'll stay away from it.
        !           327:  */
        !           328: static int is_mac_addr(const char *p)
        !           329: {
        !           330:        /* cisco-style */
        !           331:        if (3*5-1 == strlen(p)) {
        !           332:                unsigned int c;
        !           333:                for (c = 0; c < strlen(p); c++) {
        !           334:                        if ((c % 5) == 4) {
        !           335:                                if ('.' != p[c]) {
        !           336:                                        goto checkcolon;
        !           337:                                }
        !           338:                        } else {
        !           339:                                if (!isxdigit(p[c])) {
        !           340:                                        goto checkcolon;
        !           341:                                }
        !           342:                        }
        !           343:                }
        !           344:                return 1;
        !           345:        }
        !           346:        /* windows-style */
        !           347:        if (6*3-1 == strlen(p)) {
        !           348:                unsigned int c;
        !           349:                for (c = 0; c < strlen(p); c++) {
        !           350:                        if ((c % 3) == 2) {
        !           351:                                if ('-' != p[c]) {
        !           352:                                        goto checkcolon;
        !           353:                                }
        !           354:                        } else {
        !           355:                                if (!isxdigit(p[c])) {
        !           356:                                        goto checkcolon;
        !           357:                                }
        !           358:                        }
        !           359:                }
        !           360:                return 1;
        !           361:        }
        !           362: 
        !           363:  checkcolon:
        !           364:        /* unix */
        !           365:        return strchr(p, ':') ? 1 : 0;
        !           366: }
        !           367: 
        !           368: /**
        !           369:  * lots of parms since C arrays suck
        !           370:  */
        !           371: static int get_mac_addr(const char *in,
        !           372:                        unsigned int *n0,
        !           373:                        unsigned int *n1,
        !           374:                        unsigned int *n2,
        !           375:                        unsigned int *n3,
        !           376:                        unsigned int *n4,
        !           377:                        unsigned int *n5)
        !           378: {
        !           379:        if (6 == sscanf(in, "%x:%x:%x:%x:%x:%x",n0,n1,n2,n3,n4,n5)) {
        !           380:                return 1;
        !           381:        } else if(6 == sscanf(in, "%2x%x.%2x%x.%2x%x",n0,n1,n2,n3,n4,n5)) {
        !           382:                return 1;
        !           383:        } else if(6 == sscanf(in, "%x-%x-%x-%x-%x-%x",n0,n1,n2,n3,n4,n5)) {
        !           384:                return 1;
        !           385:        }
        !           386:        return 0;
        !           387: }
        !           388: 
        !           389: /**
        !           390:  * as always, the answer is 42
        !           391:  *
        !           392:  * in this case the question is how many bytes buf needs to be.
        !           393:  * Assuming a 33 byte max %d
        !           394:  *
        !           395:  * Still, I'm using at least 128bytes below
        !           396:  *
        !           397:  * (because snprintf() sadly isn't as portable, that's why)
        !           398:  */
        !           399: static char *tv2str(const struct timeval *tv, const struct timeval *tv2,
        !           400:                    char *buf)
        !           401: {
        !           402:        double f,f2;
        !           403:        int exp = 0;
        !           404: 
        !           405:        f = tv->tv_sec + (double)tv->tv_usec / 1000000;
        !           406:        f2 = tv2->tv_sec + (double)tv2->tv_usec / 1000000;
        !           407:        f = (f2 - f) * 1000000;
        !           408:        while (f > 1000) {
        !           409:                exp+= 3;
        !           410:                f /= 1000;
        !           411:        }
        !           412:        switch (exp) {
        !           413:        case 0:
        !           414:                sprintf(buf, "%.3f usec", f);
        !           415:                break;
        !           416:        case 3:
        !           417:                sprintf(buf, "%.3f msec", f);
        !           418:                break;
        !           419:        case 6:
        !           420:                sprintf(buf, "%.3f sec", f);
        !           421:                break;
        !           422:        case 9:
        !           423:                sprintf(buf, "%.3f sec", f*1000);
        !           424:                break;
        !           425:         default:
        !           426:                /* huh, uh, huhuh */
        !           427:                sprintf(buf, "%.3fe%d sec", f, exp-6);
        !           428:        }
        !           429:        return buf;
        !           430: }
        !           431: 
        !           432: 
        !           433: 
        !           434: /** Send directed IPv4 ICMP echo request.
        !           435:  *
        !           436:  * \param srcmac  Source MAC. From -s switch or autodetected
        !           437:  * \param dstmac  Destination/target MAC. Target command line.
        !           438:  * \param srcip   From -S switch or autodetected
        !           439:  * \param dstip   From -D switch, or 255.255.255.255
        !           440:  * \param id      IP id
        !           441:  * \param seq     Ping seq
        !           442:  */
        !           443: static void
        !           444: pingmac_send(uint8_t *srcmac, uint8_t *dstmac,
        !           445:             uint32_t srcip, uint32_t dstip,
        !           446:             uint16_t id, uint16_t seq)
        !           447: {
        !           448:        static libnet_ptag_t icmp = 0, ipv4 = 0,eth=0;
        !           449:        int c;
        !           450: 
        !           451:        if (-1 == (icmp = libnet_build_icmpv4_echo(ICMP_ECHO, /* type */
        !           452:                                                   0, /* code */
        !           453:                                                   0, /* checksum */
        !           454:                                                   id, /* id */
        !           455:                                                   seq, /* seq */
        !           456:                                                   NULL, /* payload */
        !           457:                                                   0, /* payload len */
        !           458:                                                   libnet,
        !           459:                                                   icmp))) {
        !           460:                fprintf(stderr, "libnet_build_icmpv4_echo(): %s\n",
        !           461:                        libnet_geterror(libnet));
        !           462:                sigint(0);
        !           463:        }
        !           464: 
        !           465:        if (-1==(ipv4 = libnet_build_ipv4(LIBNET_IPV4_H
        !           466:                                          + LIBNET_ICMPV4_ECHO_H + 0,
        !           467:                                          0, /* ToS */
        !           468:                                          id, /* id */
        !           469:                                          0, /* frag */
        !           470:                                          64, /* ttl */
        !           471:                                          IPPROTO_ICMP,
        !           472:                                          0, /* checksum */
        !           473:                                          srcip,
        !           474:                                          dstip,
        !           475:                                          NULL, /* payload */
        !           476:                                          0,
        !           477:                                          libnet,
        !           478:                                          ipv4))) {
        !           479:                fprintf(stderr, "libnet_build_ipv4(): %s\n",
        !           480:                        libnet_geterror(libnet));
        !           481:                sigint(0);
        !           482:        }
        !           483:        if (-1 == (eth = libnet_build_ethernet(dstmac,
        !           484:                                               srcmac,
        !           485:                                               ETHERTYPE_IP,
        !           486:                                               NULL,
        !           487:                                               0,
        !           488:                                               libnet,
        !           489:                                               eth))) {
        !           490:                fprintf(stderr, "libnet_build_ethernet(): %s\n",
        !           491:                        libnet_geterror(libnet));
        !           492:                sigint(0);
        !           493:        }
        !           494:        if(verbose>1) {
        !           495:                if (-1 == gettimeofday(&lastpacketsent, NULL)) {
        !           496:                        fprintf(stderr, "arping: gettimeofday(): %s\n",
        !           497:                                strerror(errno));
        !           498:                        sigint(0);
        !           499:                }
        !           500:                printf("arping: sending packet at time %d %d\n",
        !           501:                       lastpacketsent.tv_sec,
        !           502:                       lastpacketsent.tv_usec);
        !           503:        }
        !           504:        if (-1 == (c = libnet_write(libnet))) {
        !           505:                fprintf(stderr, "arping: libnet_write(): %s\n",
        !           506:                        libnet_geterror(libnet));
        !           507:                sigint(0);
        !           508:        }
        !           509:        if (-1 == gettimeofday(&lastpacketsent, NULL)) {
        !           510:                fprintf(stderr, "arping: gettimeofday(): %s\n",
        !           511:                        strerror(errno));
        !           512:                sigint(0);
        !           513:        }
        !           514:        numsent++;
        !           515: }
        !           516: 
        !           517: /** Send ARP who-has.
        !           518:  *
        !           519:  * \param srcmac   -s or autodetected
        !           520:  * \param dstmac   -t or ff:ff:ff:ff:ff:ff
        !           521:  * \param srcip    -S or autodetected
        !           522:  * \param dstip    -T or or cmdline
        !           523:  *
        !           524:  */
        !           525: static void
        !           526: pingip_send(uint8_t *srcmac, uint8_t *dstmac,
        !           527:            uint32_t srcip, uint32_t dstip)
        !           528: {
        !           529:        static libnet_ptag_t arp=0,eth=0;
        !           530:        if (-1 == (arp = libnet_build_arp(ARPHRD_ETHER,
        !           531:                                          ETHERTYPE_IP,
        !           532:                                          ETH_ALEN,
        !           533:                                          IP_ALEN,
        !           534:                                          ARPOP_REQUEST,
        !           535:                                          srcmac,
        !           536:                                          (uint8_t*)&srcip,
        !           537:                                          ethnull,
        !           538:                                          (uint8_t*)&dstip,
        !           539:                                          NULL,
        !           540:                                          0,
        !           541:                                          libnet,
        !           542:                                          arp))) {
        !           543:                fprintf(stderr, "arping: libnet_build_arp(): %s\n",
        !           544:                        libnet_geterror(libnet));
        !           545:                sigint(0);
        !           546:        }
        !           547:        if (-1 == (eth = libnet_build_ethernet(dstmac,
        !           548:                                               srcmac,
        !           549:                                               ETHERTYPE_ARP,
        !           550:                                               NULL,
        !           551:                                               0,
        !           552:                                               libnet,
        !           553:                                               eth))) {
        !           554:                fprintf(stderr, "arping: libnet_build_ethernet(): %s\n",
        !           555:                        libnet_geterror(libnet));
        !           556:                sigint(0);
        !           557:        }
        !           558:        if(verbose>1) {
        !           559:                if (-1 == gettimeofday(&lastpacketsent, NULL)) {
        !           560:                        fprintf(stderr, "arping: gettimeofday(): %s\n",
        !           561:                                strerror(errno));
        !           562:                        sigint(0);
        !           563:                }
        !           564:                printf("arping: sending packet at time %d %d\n",
        !           565:                       lastpacketsent.tv_sec,
        !           566:                       lastpacketsent.tv_usec);
        !           567:        }
        !           568:        if (-1 == libnet_write(libnet)) {
        !           569:                fprintf(stderr, "arping: libnet_write(): %s\n", 
        !           570:                        libnet_geterror(libnet));
        !           571:                sigint(0);
        !           572:        }
        !           573:        if (-1 == gettimeofday(&lastpacketsent, NULL)) {
        !           574:                fprintf(stderr, "arping: gettimeofday(): %s\n",
        !           575:                        strerror(errno));
        !           576:                sigint(0);
        !           577:        }
        !           578:        numsent++;
        !           579: }
        !           580: 
        !           581: /** handle incoming packet when pinging an IP address.
        !           582:  *
        !           583:  * \param h       packet metadata
        !           584:  * \param packet  packet data
        !           585:  */
        !           586: static void
        !           587: pingip_recv(const char *unused, struct pcap_pkthdr *h,
        !           588:            uint8_t *packet)
        !           589: {
        !           590:        struct libnet_802_3_hdr *heth;
        !           591:        struct libnet_arp_hdr *harp;
        !           592:        struct timeval arrival;
        !           593:        int c;
        !           594: 
        !           595:        if(verbose>2) {
        !           596:                printf("arping: received response for ip ping\n");
        !           597:        }
        !           598: 
        !           599:        if (-1 == gettimeofday(&arrival, NULL)) {
        !           600:                fprintf(stderr, "arping: gettimeofday(): %s\n",
        !           601:                        strerror(errno));
        !           602:                sigint(0);
        !           603:        }
        !           604:        heth = (void*)packet;
        !           605:        harp = (void*)((char*)heth + LIBNET_ETH_H);
        !           606: 
        !           607:        if ((htons(harp->ar_op) == ARPOP_REPLY)
        !           608:            && (htons(harp->ar_pro) == ETHERTYPE_IP)
        !           609:            && (htons(harp->ar_hrd) == ARPHRD_ETHER)) {
        !           610:                uint32_t ip;
        !           611:                memcpy(&ip, (char*)harp + harp->ar_hln
        !           612:                       + LIBNET_ARP_H,4);
        !           613:                if (addr_must_be_same
        !           614:                    && (memcmp((u_char*)harp+sizeof(struct libnet_arp_hdr),
        !           615:                               dstmac, ETH_ALEN))) {
        !           616:                        return;
        !           617:                }
        !           618:                if (dstip == ip) {
        !           619:                        switch(display) {
        !           620:                        case DOT:
        !           621:                                numdots++;
        !           622:                                count_missing_dots();
        !           623:                                putchar('!');
        !           624:                                break;
        !           625:                        case NORMAL: {
        !           626:                                char buf[128];
        !           627:                                printf("%d bytes from ", h->len);
        !           628:                                for (c = 0; c < 6; c++) {
        !           629:                                        printf("%.2x%c", heth->_802_3_shost[c],
        !           630:                                               (c<5)?':':' ');
        !           631:                                }
        !           632:                                
        !           633:                                printf("(%s): index=%d",
        !           634:                                       libnet_addr2name4(ip,0),
        !           635:                                       numrecvd);
        !           636:                                if (alsototal) {
        !           637:                                        printf("/%u", numsent-1);
        !           638:                                }
        !           639:                                printf(" time=%s",
        !           640:                                       tv2str(&lastpacketsent,
        !           641:                                              &arrival,buf));
        !           642:                                break; }
        !           643:                        case QUIET:
        !           644:                                break;
        !           645:                        case RAWRAW:
        !           646:                                for (c = 0; c < 6; c++) {
        !           647:                                        printf("%.2x%c", heth->_802_3_shost[c],
        !           648:                                               (c<5)?':':' ');
        !           649:                                }
        !           650:                                printf("%s", libnet_addr2name4(ip,0));
        !           651:                                break;
        !           652:                        case RRAW:
        !           653:                                printf("%s", libnet_addr2name4(ip,0));
        !           654:                                break;
        !           655:                        case RAW:
        !           656:                                for (c = 0; c < 6; c++) {
        !           657:                                        printf("%.2x%s", heth->_802_3_shost[c],
        !           658:                                               (c<5)?":":"");
        !           659:                                }
        !           660:                                break;
        !           661:                        default:
        !           662:                                fprintf(stderr, "arping: can't happen!\n");
        !           663:                        }
        !           664: 
        !           665:                         switch (display) {
        !           666:                         case QUIET:
        !           667:                         case DOT:
        !           668:                                 break;
        !           669:                         default:
        !           670:                                 if (beep) {
        !           671:                                         printf("\a");
        !           672:                                 }
        !           673:                                 printf("\n");
        !           674:                         }
        !           675:                         if (numrecvd) {
        !           676:                                 if (memcmp(lastreplymac,
        !           677:                                            heth->_802_3_shost, ETH_ALEN)) {
        !           678:                                         dupfound = 1;
        !           679:                                 }
        !           680:                         }
        !           681:                         memcpy(lastreplymac, heth->_802_3_shost, ETH_ALEN);
        !           682: 
        !           683:                        numrecvd++;
        !           684:                }
        !           685:        }
        !           686: }
        !           687: 
        !           688: /** handle incoming packet when pinging an MAC address.
        !           689:  *
        !           690:  * \param h       packet metadata
        !           691:  * \param packet  packet data
        !           692:  */
        !           693: static void
        !           694: pingmac_recv(const char *unused, struct pcap_pkthdr *h,
        !           695:             uint8_t *packet)
        !           696: {
        !           697:        struct libnet_802_3_hdr *heth;
        !           698:        struct libnet_ipv4_hdr *hip;
        !           699:        struct libnet_icmpv4_hdr *hicmp;
        !           700:        struct timeval arrival;
        !           701:        int c;
        !           702: 
        !           703:        if(verbose>2) {
        !           704:                printf("arping: received response for mac ping\n");
        !           705:        }
        !           706: 
        !           707:        if (-1 == gettimeofday(&arrival, NULL)) {
        !           708:                fprintf(stderr, "arping: gettimeofday(): %s\n",
        !           709:                        strerror(errno));
        !           710:                sigint(0);
        !           711:        }
        !           712: 
        !           713:        heth = (void*)packet;
        !           714:        hip = (void*)((char*)heth + LIBNET_ETH_H);
        !           715:        hicmp = (void*)((char*)hip + LIBNET_IPV4_H);
        !           716: 
        !           717:        if ((htons(hicmp->icmp_type) == ICMP_ECHOREPLY)
        !           718:            && ((!memcmp(heth->_802_3_shost, dstmac,ETH_ALEN)
        !           719:                 || !memcmp(dstmac, ethxmas, ETH_ALEN)))
        !           720:            && !memcmp(heth->_802_3_dhost, srcmac, ETH_ALEN)) {
        !           721:                if (addr_must_be_same) {
        !           722:                        uint32_t tmp;
        !           723:                        memcpy(&tmp, &hip->ip_src, 4);
        !           724:                        if (dstip != tmp) {
        !           725:                                return;
        !           726:                        }
        !           727:                }
        !           728:                switch(display) {
        !           729:                case QUIET:
        !           730:                        break;
        !           731:                case NORMAL: {
        !           732:                        char buf[128];
        !           733:                        printf("%d bytes from %s (",h->len,
        !           734:                               libnet_addr2name4(*(int*)&hip->ip_src, 0));
        !           735:                        for (c = 0; c < 6; c++) {
        !           736:                                printf("%.2x%c", heth->_802_3_shost[c],
        !           737:                                       (c<5)?':':')');
        !           738:                        }
        !           739:                        printf(": icmp_seq=%d time=%s",
        !           740:                               htons(hicmp->icmp_seq),tv2str(&lastpacketsent,
        !           741:                                                      &arrival,buf));
        !           742:                        break; }
        !           743:                case RAW:
        !           744:                        printf("%s",
        !           745:                               libnet_addr2name4(hip->ip_src.s_addr, 0));
        !           746:                        break;
        !           747:                case RRAW:
        !           748:                        for (c = 0; c < 6; c++) {
        !           749:                                printf("%.2x%s", heth->_802_3_shost[c],
        !           750:                                       (c<5)?":":"");
        !           751:                        }
        !           752:                        break;
        !           753:                case RAWRAW:
        !           754:                        for (c = 0; c < 6; c++) {
        !           755:                                printf("%.2x%c", heth->_802_3_shost[c],
        !           756:                                       (c<5)?':':' ');
        !           757:                        }
        !           758:                        printf("%s",
        !           759:                               libnet_addr2name4(hip->ip_src.s_addr, 0));
        !           760:                        break;
        !           761:                default:
        !           762:                        fprintf(stderr, "arping: can't-happen-bug\n");
        !           763:                        sigint(0);
        !           764:                }
        !           765:                if (display != QUIET) {
        !           766:                        printf(beep?"\a\n":"\n");
        !           767:                }
        !           768:                numrecvd++;
        !           769:        }
        !           770: }
        !           771: 
        !           772: 
        !           773: #if WIN32
        !           774: /**
        !           775:  * untested for a long time. Maybe since arping 2.05 or so.
        !           776:  */
        !           777: static void
        !           778: ping_recv_win32(pcap_t *pcap,uint32_t packetwait, pcap_handler func)
        !           779: {
        !           780:        struct timeval tv,tv2;
        !           781:        char done = 0;
        !           782:        /* windows won't let us do select() */
        !           783:        if (-1 == gettimeofday(&tv2,NULL)) {
        !           784:               fprintf(stderr, "arping: gettimeofday(): %s\n",
        !           785:                       strerror(errno));
        !           786:                sigint(0);
        !           787:        }
        !           788:        while (!done && !time_to_die) {
        !           789:               struct pcap_pkthdr *pkt_header;
        !           790:               u_char *pkt_data;
        !           791:               if (pcap_next_ex(pcap, &pkt_header, &pkt_data) == 1) {
        !           792:                       func(pcap, pkt_header, pkt_data);
        !           793:               }
        !           794:               if (-1 == gettimeofday(&tv,NULL)) {
        !           795:                       fprintf(stderr, "arping: "
        !           796:                               "gettimeofday(): %s\n",
        !           797:                               strerror(errno));
        !           798:                       sigint(0);
        !           799:               }
        !           800:                /*
        !           801:                 * setup next timeval, not very exact
        !           802:                 */
        !           803:                tv.tv_sec  = (packetwait / 1000000)
        !           804:                       - (tv.tv_sec - tv2.tv_sec);
        !           805:               tv.tv_usec = (packetwait % 1000000)
        !           806:                       - (tv.tv_usec - tv2.tv_usec);
        !           807:               while (tv.tv_usec < 0) {
        !           808:                       tv.tv_sec--;
        !           809:                       tv.tv_usec += 1000000;
        !           810:               }
        !           811:               usleep(10);
        !           812:               if (tv.tv_sec < 0) {
        !           813:                       done=1;
        !           814:               }
        !           815:        }
        !           816: }
        !           817: #endif
        !           818: 
        !           819: /**
        !           820:  * while negative microseconds, take from whole seconds.
        !           821:  * help function for measuring deltas.
        !           822:  */
        !           823: static void
        !           824: fixup_timeval(struct timeval *tv)
        !           825: {
        !           826:        while (tv->tv_usec < 0) {
        !           827:                tv->tv_sec--;
        !           828:                tv->tv_usec += 1000000;
        !           829:        }
        !           830: }
        !           831: 
        !           832: /**
        !           833:  * idiot-proof gettimeofday() wrapper
        !           834:  */
        !           835: static void
        !           836: gettv(struct timeval *tv)
        !           837: {
        !           838:        if (-1 == gettimeofday(tv,NULL)) {
        !           839:                fprintf(stderr, "arping: "
        !           840:                        "gettimeofday(): %s\n",
        !           841:                        strerror(errno));
        !           842:                sigint(0);
        !           843:        }
        !           844: }
        !           845: 
        !           846: 
        !           847: /**
        !           848:  * 
        !           849:  */
        !           850: static void
        !           851: ping_recv_unix(pcap_t *pcap,uint32_t packetwait, pcap_handler func)
        !           852: {
        !           853:        struct timeval tv;
        !           854:        struct timeval endtime;
        !           855:        char done = 0;
        !           856: 
        !           857:        gettv(&tv);
        !           858:        endtime.tv_sec = tv.tv_sec + (packetwait / 1000000);
        !           859:        endtime.tv_usec = tv.tv_usec + (packetwait % 1000000);
        !           860:        fixup_timeval(&endtime);
        !           861: 
        !           862:        int fd;
        !           863: 
        !           864:        fd = pcap_get_selectable_fd(pcap);
        !           865: 
        !           866:        for (;!done;) {
        !           867:               int trydispatch = 0;
        !           868: 
        !           869:               gettv(&tv);
        !           870:               tv.tv_sec = endtime.tv_sec - tv.tv_sec;
        !           871:               tv.tv_usec = endtime.tv_usec - tv.tv_usec;
        !           872:               fixup_timeval(&tv);
        !           873:               if (tv.tv_sec < 0) {
        !           874:                       tv.tv_sec = 0;
        !           875:                       tv.tv_usec = 1;
        !           876:                       done = 1;
        !           877:               }
        !           878:               if (time_to_die) {
        !           879:                       return;
        !           880:               }
        !           881: 
        !           882:               /* try to wait for data */
        !           883:               {
        !           884:                       struct pollfd p;
        !           885:                       int r;
        !           886:                       p.fd = fd;
        !           887:                       p.events = POLLIN | POLLPRI;
        !           888: 
        !           889:                       r = poll(&p, 1, tv.tv_sec * 1000 + tv.tv_usec / 1000);
        !           890:                       switch (r) {
        !           891:                       case 0: /* timeout */
        !           892:                               done = 1;
        !           893:                               break;
        !           894:                       case -1: /* error */
        !           895:                               if (errno != EINTR) {
        !           896:                                       done = 1;
        !           897:                                       sigint(0);
        !           898:                                       fprintf(stderr,
        !           899:                                               "arping: poll() failed: %s\n",
        !           900:                                               strerror(errno));
        !           901:                               }
        !           902:                               break;
        !           903:                       default: /* data returned */
        !           904:                               trydispatch = 1;
        !           905:                               break;
        !           906:                       }
        !           907:               }
        !           908: 
        !           909:               if (trydispatch) {
        !           910:                       int ret;
        !           911:                       if (1 != (ret = pcap_dispatch(pcap, 1,
        !           912:                                                     func,
        !           913:                                                     NULL))) {
        !           914:                               /* rest, so we don't take 100% CPU... mostly
        !           915:                                   hmm... does usleep() exist everywhere? */
        !           916:                               usleep(1);
        !           917: 
        !           918:                               /* weird is normal on bsd :) */
        !           919:                               if (verbose > 3) {
        !           920:                                       fprintf(stderr,
        !           921:                                               "arping: poll says ok, "
        !           922:                                               "pcap_dispatch=%d!\n",
        !           923:                                               ret);
        !           924:                               }
        !           925:                       }
        !           926:               }
        !           927:        }
        !           928: }
        !           929: 
        !           930: /**
        !           931:  * 
        !           932:  */
        !           933: static void
        !           934: ping_recv(pcap_t *pcap,uint32_t packetwait, pcap_handler func)
        !           935: {
        !           936:        if(verbose>3) {
        !           937:                printf("arping: receiving packets...\n");
        !           938:        }
        !           939: 
        !           940: #if WIN32
        !           941:        ping_recv_win32(pcap,packetwait,func);
        !           942: #else
        !           943:        ping_recv_unix(pcap,packetwait,func);
        !           944: #endif
        !           945: }
        !           946: 
        !           947: /**
        !           948:  *
        !           949:  */
        !           950: int main(int argc, char **argv)
        !           951: {
        !           952:        char ebuf[LIBNET_ERRBUF_SIZE + PCAP_ERRBUF_SIZE];
        !           953:        char *cp;
        !           954:        int promisc = 0;
        !           955:        int srcip_given = 0;
        !           956:        int srcmac_given = 0;
        !           957:        int dstip_given = 0;
        !           958:        const char *ifname = NULL;
        !           959:        char *parm;
        !           960:        int c;
        !           961:        unsigned int maxcount = -1;
        !           962:        int dont_use_arping_lookupdev=0;
        !           963:        struct bpf_program bp;
        !           964:        pcap_t *pcap;
        !           965:        static enum { NONE, PINGMAC, PINGIP } mode = NONE;
        !           966:        unsigned int packetwait = 1000000;
        !           967: 
        !           968:         for (c = 1; c < argc; c++) {
        !           969:                 if (!strcmp(argv[c], "--help")) {
        !           970:                         standard_usage();
        !           971:                         extended_usage();
        !           972:                         exit(0);
        !           973:                 }
        !           974:         }
        !           975: 
        !           976:        memset(ethnull, 0, ETH_ALEN);
        !           977: 
        !           978:        srcip = 0;
        !           979:        dstip = 0xffffffff;
        !           980:        memset(dstmac, 0xff, ETH_ALEN);
        !           981:        memset(ethxmas, 0xff, ETH_ALEN);
        !           982: 
        !           983:        while (EOF!=(c=getopt(argc,argv,"0aAbBc:dDeFhi:I:pqrRs:S:t:T:uvw:"))) {
        !           984:                switch(c) {
        !           985:                case '0':
        !           986:                        srcip = 0;
        !           987:                        srcip_given = 1;
        !           988:                        break;
        !           989:                case 'a':
        !           990:                        beep = 1;
        !           991:                        break;
        !           992:                case 'A':
        !           993:                        addr_must_be_same = 1;
        !           994:                        break;
        !           995:                case 'b':
        !           996:                        srcip = 0xffffffff;
        !           997:                        srcip_given = 1;
        !           998:                        break;
        !           999:                case 'B':
        !          1000:                        dstip = 0xffffffff;
        !          1001:                        dstip_given = 1;
        !          1002:                        break;
        !          1003:                case 'c':
        !          1004:                        maxcount = atoi(optarg);
        !          1005:                        break;
        !          1006:                case 'd':
        !          1007:                        finddup = 1;
        !          1008:                        break;
        !          1009:                case 'D':
        !          1010:                        display = DOT;
        !          1011:                        break;
        !          1012:                 case 'e':
        !          1013:                         reverse_beep = 1;
        !          1014:                         break;
        !          1015:                case 'F':
        !          1016:                        dont_use_arping_lookupdev=1;
        !          1017:                        break;
        !          1018:                case 'h':
        !          1019:                        usage(0);
        !          1020:                case 'i':
        !          1021:                        if (strchr(optarg, ':')) {
        !          1022:                                fprintf(stderr, "arping: If you're trying to "
        !          1023:                                        "feed me an interface alias then you "
        !          1024:                                        "don't really\nknow what this programs"
        !          1025:                                        " does, do you?\nUse -I if you really"
        !          1026:                                        " mean it (undocumented on "
        !          1027:                                        "purpose)\n");
        !          1028:                                exit(1);
        !          1029:                        }
        !          1030:                case 'I': /* FALL THROUGH */
        !          1031:                        ifname = optarg;
        !          1032:                        break;
        !          1033:                case 'p':
        !          1034:                        promisc = 1;
        !          1035:                        break;
        !          1036:                case 'q':
        !          1037:                        display = QUIET;
        !          1038:                        break;
        !          1039:                case 'r':
        !          1040:                        display = (display==RRAW)?RAWRAW:RAW;
        !          1041:                        break;
        !          1042:                case 'R':
        !          1043:                        display = (display==RAW)?RAWRAW:RRAW;
        !          1044:                        break;
        !          1045:                case 's': { /* spoof source MAC */
        !          1046:                        unsigned int n[6];
        !          1047:                        if (!get_mac_addr(optarg,
        !          1048:                                          &n[0],&n[1],&n[2],
        !          1049:                                          &n[3],&n[4],&n[5])){
        !          1050:                                fprintf(stderr, "arping: Weird MAC addr %s\n",
        !          1051:                                        optarg);
        !          1052:                                exit(1);
        !          1053:                        }
        !          1054:                        for (c = 0; c < 6; c++) {
        !          1055:                                srcmac[c] = n[c] & 0xff;
        !          1056:                        }
        !          1057:                        srcmac_given = 1;
        !          1058:                        break;
        !          1059:                }
        !          1060:                case 'S': /* set source IP, may be null for don't-know */
        !          1061:                        do_libnet_init(ifname);
        !          1062:                        if (-1 == (srcip = libnet_name2addr4(libnet,
        !          1063:                                                             optarg,
        !          1064:                                                             LIBNET_RESOLVE))){
        !          1065:                                fprintf(stderr, "arping: Can't resolve %s, or "
        !          1066:                                        "%s is broadcast. If it is, use -b"
        !          1067:                                        " instead of -S\n", optarg,optarg);
        !          1068:                                exit(1);
        !          1069:                        }
        !          1070:                        srcip_given = 1;
        !          1071:                        break;
        !          1072:                case 't': { /* set taget mac */
        !          1073:                        unsigned int n[6];
        !          1074:                        if (mode == PINGMAC) {
        !          1075:                                fprintf(stderr, "arping: -t can only be used "
        !          1076:                                        "in IP ping mode\n");
        !          1077:                                exit(1);
        !          1078:                        }
        !          1079:                        if (!get_mac_addr(optarg,
        !          1080:                                          &n[0],&n[1],&n[2],
        !          1081:                                          &n[3],&n[4],&n[5])){
        !          1082:                                fprintf(stderr, "Illegal MAC addr %s\n",
        !          1083:                                        optarg);
        !          1084:                                exit(1);
        !          1085:                        }
        !          1086:                        for (c = 0; c < 6; c++) {
        !          1087:                                dstmac[c] = n[c] & 0xff;
        !          1088:                        }
        !          1089:                        mode = PINGIP;
        !          1090:                        break;
        !          1091:                }
        !          1092:                case 'T': /* set destination IP */
        !          1093:                        if (mode == PINGIP) {
        !          1094:                                fprintf(stderr, "arping: -T can only be used "
        !          1095:                                        "in MAC ping mode\n");
        !          1096:                                exit(1);
        !          1097:                        }
        !          1098:                        do_libnet_init(ifname);
        !          1099:                        if (-1 == (dstip = libnet_name2addr4(libnet,
        !          1100:                                                             optarg,
        !          1101:                                                             LIBNET_RESOLVE))){
        !          1102:                                fprintf(stderr,"arping: Can't resolve %s, or "
        !          1103:                                        "%s is broadcast. If it is, use -B "
        !          1104:                                        "instead of -T\n",optarg,optarg);
        !          1105:                                exit(1);
        !          1106:                        }
        !          1107:                        mode = PINGMAC;
        !          1108:                        break;
        !          1109:                case 'u':
        !          1110:                        alsototal = 1;
        !          1111:                        break;
        !          1112:                case 'v':
        !          1113:                        verbose++;
        !          1114:                        break;
        !          1115:                case 'w':
        !          1116:                        packetwait = (unsigned)atoi(optarg);
        !          1117:                        break;
        !          1118:                default:
        !          1119:                        usage(1);
        !          1120:                }
        !          1121:        }
        !          1122: 
        !          1123:         if (display == DOT) {
        !          1124:                 setvbuf(stdout, NULL, _IONBF, 0);
        !          1125:         }
        !          1126: 
        !          1127:         if (finddup && maxcount == -1) {
        !          1128:                 maxcount = 3;
        !          1129:         }
        !          1130: 
        !          1131:        parm = (optind < argc) ? argv[optind] : NULL;
        !          1132: 
        !          1133:         /* default to own IP address when doing -d */
        !          1134:         if (finddup && !parm) {
        !          1135:                 dstip_given = 1;
        !          1136:                 do_libnet_init(ifname);
        !          1137:                 dstip = libnet_get_ipaddr4(libnet);
        !          1138:                 if (verbose) {
        !          1139:                         printf("defaulting to checking dup for %s\n",
        !          1140:                                libnet_addr2name4(dstip, 0));
        !          1141:                 }
        !          1142:         }
        !          1143: 
        !          1144:        /*
        !          1145:         * Handle dstip_given instead of ip address after parms (-B really)
        !          1146:         */
        !          1147:        if (mode == NONE) {
        !          1148:                if (optind + 1 == argc) {
        !          1149:                        mode = is_mac_addr(parm)?PINGMAC:PINGIP;
        !          1150:                } else if (dstip_given) {
        !          1151:                        mode = PINGIP;
        !          1152:                        do_libnet_init(ifname);
        !          1153:                        parm = strdup(libnet_addr2name4(dstip,0));
        !          1154:                        if (!parm) {
        !          1155:                                fprintf(stderr, "arping: out of mem\n");
        !          1156:                                exit(1);
        !          1157:                        }
        !          1158:                }
        !          1159:        }
        !          1160: 
        !          1161:        if (!parm) {
        !          1162:                usage(1);
        !          1163:        }
        !          1164: 
        !          1165:        /*
        !          1166:         *
        !          1167:         */
        !          1168:        if (mode == NONE) {
        !          1169:                usage(1);
        !          1170:        }
        !          1171: 
        !          1172:        /*
        !          1173:         * libnet init (may be done already for resolving)
        !          1174:         */
        !          1175:        do_libnet_init(ifname);
        !          1176:        
        !          1177:        /*
        !          1178:         * Make sure dstip and parm like eachother
        !          1179:         */
        !          1180:        if (mode == PINGIP && (!dstip_given)) {
        !          1181:                if (is_mac_addr(parm)) {
        !          1182:                        fprintf(stderr, "arping: Options given only apply to "
        !          1183:                                "IP ping, but MAC address given as argument"
        !          1184:                                "\n");
        !          1185:                        exit(1);
        !          1186:                }
        !          1187:                if (-1 == (dstip = libnet_name2addr4(libnet,
        !          1188:                                                     parm,
        !          1189:                                                     LIBNET_RESOLVE))) {
        !          1190:                        fprintf(stderr, "arping: Can't resolve %s\n", parm);
        !          1191:                        exit(1);
        !          1192:                }
        !          1193:                parm = strdup(libnet_addr2name4(dstip,0));
        !          1194:        }
        !          1195: 
        !          1196:        /*
        !          1197:         * parse parm into dstmac
        !          1198:         */
        !          1199:        if (mode == PINGMAC) {
        !          1200:                unsigned int n[6];
        !          1201:                if (optind + 1 != argc) {
        !          1202:                        usage(1);
        !          1203:                }
        !          1204:                if (!is_mac_addr(parm)) {
        !          1205:                        fprintf(stderr, "arping: Options given only apply to "
        !          1206:                                "MAC ping, but no MAC address given as "
        !          1207:                                "argument\n");
        !          1208:                        exit(1);
        !          1209:                }
        !          1210:                if (!get_mac_addr(argv[optind],
        !          1211:                                  &n[0],&n[1],&n[2],
        !          1212:                                  &n[3],&n[4],&n[5])) {
        !          1213:                        fprintf(stderr, "arping: Illegal mac addr %s\n",
        !          1214:                                argv[optind]);
        !          1215:                        return 1;
        !          1216:                }
        !          1217:                for (c = 0; c < 6; c++) {
        !          1218:                        dstmac[c] = n[c] & 0xff;
        !          1219:                }
        !          1220:        }       
        !          1221: 
        !          1222:        target = parm;
        !          1223:        /*
        !          1224:         * Argument processing done, parameters considered sane below
        !          1225:         */
        !          1226: 
        !          1227:        /*
        !          1228:         * Get some good iface.
        !          1229:         */
        !          1230:        if (!ifname) {
        !          1231:                if (dont_use_arping_lookupdev) {
        !          1232:                        ifname = arping_lookupdev_default(ifname,
        !          1233:                                                          srcip,dstip,ebuf);
        !          1234:                } else {
        !          1235:                        ifname = arping_lookupdev(ifname,srcip,dstip,ebuf);
        !          1236:                }
        !          1237:                if (!ifname) {
        !          1238:                        fprintf(stderr, "arping: arping_lookupdev(): %s\n",
        !          1239:                                ebuf);
        !          1240:                        exit(1);
        !          1241:                }
        !          1242:                /* FIXME: check for other probably-not interfaces */
        !          1243:                if (!strcmp(ifname, "ipsec")
        !          1244:                    || !strcmp(ifname,"lo")) {
        !          1245:                        fprintf(stderr, "arping: Um.. %s looks like the wrong "
        !          1246:                                "interface to use. Is it? "
        !          1247:                                "(-i switch)\n", ifname);
        !          1248:                        fprintf(stderr, "arping: using it anyway this time\n");
        !          1249:                }
        !          1250:        }
        !          1251: 
        !          1252:        /*
        !          1253:         * Init libnet again, because we now know the interface name.
        !          1254:         * We should know it by know at least
        !          1255:         */
        !          1256:        do_libnet_init(ifname);
        !          1257: 
        !          1258:        /*
        !          1259:         * pcap init
        !          1260:         */
        !          1261:        if (!(pcap = pcap_open_live((char*)ifname, 100, promisc, 10, ebuf))) {
        !          1262:                fprintf(stderr, "arping: pcap_open_live(): %s\n",ebuf);
        !          1263:                exit(1);
        !          1264:        }
        !          1265:        if (pcap_setnonblock(pcap, 1, ebuf)) {
        !          1266:                fprintf(stderr, "arping: pcap_set_nonblock(): %s\n", ebuf);
        !          1267:                exit(1);
        !          1268:        }
        !          1269:        if (verbose) {
        !          1270:                printf("pcap_get_selectable(): %d\n",
        !          1271:                       pcap_get_selectable_fd(pcap));
        !          1272:        }
        !          1273: 
        !          1274: #if HAVE_NET_BPF_H
        !          1275:        {
        !          1276:                uint32_t on = 1;
        !          1277:                if (0 < (ioctl(pcap_fileno(pcap), BIOCIMMEDIATE,
        !          1278:                               &on))) {
        !          1279:                        fprintf(stderr, "arping: ioctl(fd,BIOCIMMEDIATE, 1) "
        !          1280:                                "failed, continuing anyway, YMMV: %s\n",
        !          1281:                                strerror(errno));
        !          1282:                }
        !          1283:        }
        !          1284: #endif
        !          1285: 
        !          1286:        if (mode == PINGIP) {
        !          1287:                /* FIXME: better filter with addresses? */
        !          1288:                if (-1 == pcap_compile(pcap, &bp, "arp", 0,-1)) {
        !          1289:                        fprintf(stderr, "arping: pcap_compile(): error\n");
        !          1290:                        exit(1);
        !          1291:                }
        !          1292:        } else { /* ping mac */
        !          1293:                /* FIXME: better filter with addresses? */
        !          1294:                if (-1 == pcap_compile(pcap, &bp, "icmp", 0,-1)) {
        !          1295:                        fprintf(stderr, "arping: pcap_compile(): error\n");
        !          1296:                        exit(1);
        !          1297:                }
        !          1298:        }
        !          1299:        if (-1 == pcap_setfilter(pcap, &bp)) {
        !          1300:                fprintf(stderr, "arping: pcap_setfilter(): error\n");
        !          1301:                exit(1);
        !          1302:        }
        !          1303: 
        !          1304:        /*
        !          1305:         * final init
        !          1306:         */
        !          1307:        if (!srcmac_given) {
        !          1308:                if (!(cp = (char*)libnet_get_hwaddr(libnet))) {
        !          1309:                        fprintf(stderr, "arping: libnet_get_hwaddr(): %s\n",
        !          1310:                                libnet_geterror(libnet));
        !          1311:                        exit(1);
        !          1312:                }
        !          1313:                memcpy(srcmac, cp, ETH_ALEN);
        !          1314:        }
        !          1315:        if (!srcip_given) {
        !          1316:                if (-1 == (srcip = libnet_get_ipaddr4(libnet))) {
        !          1317:                        fprintf(stderr, "arping: libnet_get_ipaddr4(libnet): "
        !          1318:                                "%s\n", libnet_geterror(libnet));
        !          1319:                        exit(1);
        !          1320:                }
        !          1321:        }
        !          1322: #if WIN32
        !          1323:        /* SetConsoleCtrlHandler(NULL, TRUE); */
        !          1324:        SetConsoleCtrlHandler(arping_console_ctrl_handler, TRUE);
        !          1325: #else
        !          1326:        signal(SIGINT, sigint);
        !          1327: #endif
        !          1328: 
        !          1329:        if (verbose) {
        !          1330:                printf("This box:   Interface: %s  IP: %s   MAC address: ",
        !          1331:                       ifname, libnet_addr2name4(libnet_get_ipaddr4(libnet),
        !          1332:                                                 0));
        !          1333:                for (c = 0; c < ETH_ALEN - 1; c++) {
        !          1334:                        printf("%.2x:", (uint8_t)srcmac[c]);
        !          1335:                }
        !          1336:                printf("%.2x\n", (uint8_t)srcmac[ETH_ALEN - 1]);
        !          1337:        }
        !          1338: 
        !          1339: 
        !          1340:        if (display == NORMAL) {
        !          1341:                printf("ARPING %s\n", parm);
        !          1342:        }
        !          1343: 
        !          1344:        /*
        !          1345:         * let's roll
        !          1346:         */
        !          1347:        if (mode == PINGIP) {
        !          1348:                unsigned int c;
        !          1349:                 unsigned int r;
        !          1350:                for (c = 0; c < maxcount && !time_to_die; c++) {
        !          1351:                        pingip_send(srcmac, dstmac, srcip, dstip);
        !          1352:                         r = numrecvd;
        !          1353:                        ping_recv(pcap,packetwait,
        !          1354:                                  (pcap_handler)pingip_recv);
        !          1355:                         if (reverse_beep && !time_to_die && (r == numrecvd)) {
        !          1356:                                 printf("\a");
        !          1357:                                 fflush(stdout);
        !          1358:                         }
        !          1359:                }
        !          1360:        } else { /* PINGMAC */
        !          1361:                unsigned int c;
        !          1362:                 unsigned int r;
        !          1363:                for (c = 0; c < maxcount && !time_to_die; c++) {
        !          1364:                        pingmac_send(srcmac, dstmac, srcip, dstip, rand(), c);
        !          1365:                         r = numrecvd;
        !          1366:                        ping_recv(pcap,packetwait,
        !          1367:                                  (pcap_handler)pingmac_recv);
        !          1368:                         if (reverse_beep && !time_to_die && (r == numrecvd)) {
        !          1369:                                 printf("\a");
        !          1370:                                 fflush(stdout);
        !          1371:                         }
        !          1372:                }
        !          1373:        }
        !          1374:         if (display == DOT) {
        !          1375:                 count_missing_dots();
        !          1376:                 printf("\t%3.0f%% packet loss\n",
        !          1377:                        100.0 - 100.0 * (float)(numrecvd)/(float)numsent);
        !          1378:         } else if (display == NORMAL) {
        !          1379:                 float succ;
        !          1380:                 succ = 100.0 - 100.0 * (float)(numrecvd)/(float)numsent;
        !          1381:                 printf("\n--- %s statistics ---\n"
        !          1382:                        "%d packets transmitted, "
        !          1383:                        "%d packets received, "
        !          1384:                        "%3.0f%% "
        !          1385:                        "unanswered (%d extra)\n",
        !          1386:                        target,numsent,numrecvd,
        !          1387:                        (succ < 0.0) ? 0.0 : succ,
        !          1388:                        (succ < 0.0) ? (numrecvd - numsent): 0); 
        !          1389:        }
        !          1390: 
        !          1391:         if (finddup) {
        !          1392:                 return dupfound;
        !          1393:         } else {
        !          1394:                 return !numrecvd;
        !          1395:         }
        !          1396: }

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