File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / arping / src / arping.c
Revision 1.1.1.1.2.1: download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 00:12:50 2013 UTC (11 years ago) by misho
Branches: v2_09p0
Diff to: branchpoint 1.1.1.1: preferred, unified
patch0

    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_NET_BPF_H
   79: #include <net/bpf.h>
   80: #endif
   81: 
   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>