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>