Annotation of embedaddon/arping/src/arping.c, revision 1.1.1.1.2.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: 
1.1.1.1.2.1! misho      78: #if HAVE_NET_BPF_H
        !            79: #include <net/bpf.h>
        !            80: #endif
        !            81: 
1.1       misho      82: #if HAVE_WIN32_LIBNET_H
                     83: #include <win32/libnet.h>
                     84: #endif
                     85: #include <pcap.h>
                     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>