Learn more  » Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

universal / arp-scan-dbg   deb

Repository URL to install this package:

Version: 1.9+git0+7d710d916c-r0.0 

/*
 * The ARP Scanner (arp-scan) is Copyright (C) 2005-2016 Roy Hills,
 * NTA Monitor Ltd.
 *
 * This file is part of arp-scan.
 *
 * arp-scan is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * arp-scan is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with arp-scan.  If not, see <http://www.gnu.org/licenses/>.
 *
 * arp-scan -- The ARP Scanner
 *
 * Author:	Roy Hills
 * Date:	13 October 2005
 *
 * Usage:
 *    arp-scan [options] [host...]
 *
 * Description:
 *
 * arp-scan sends the specified ARP packet to the specified hosts
 * and displays any responses received.
 *
 * The ARP protocol is defined in RFC 826 Ethernet Address Resolution Protocol
 *
 */

#include "arp-scan.h"

/* Global variables */
static host_entry *helist = NULL;	/* Array of host entries */
static host_entry **helistptr;		/* Array of pointers to host entries */
static host_entry **cursor;		/* Pointer to current host entry ptr */
static unsigned num_hosts = 0;		/* Number of entries in the list */
static unsigned responders = 0;		/* Number of hosts which responded */
static unsigned live_count;		/* Number of entries awaiting reply */
static int verbose=0;			/* Verbose level */
static char filename[MAXLINE];		/* Target list file name */
static int filename_flag=0;		/* Set if using target list file */
static int random_flag=0;		/* Randomise the list */
static int numeric_flag=0;		/* IP addresses only */
static unsigned interval=0;		/* Desired interval between packets */
static unsigned bandwidth=DEFAULT_BANDWIDTH; /* Bandwidth in bits per sec */
static unsigned retry = DEFAULT_RETRY;	/* Number of retries */
static unsigned timeout = DEFAULT_TIMEOUT; /* Per-host timeout */
static float backoff_factor = DEFAULT_BACKOFF_FACTOR;	/* Backoff factor */
static int snaplen = SNAPLEN;		/* Pcap snap length */
static char *if_name=NULL;		/* Interface name, e.g. "eth0" */
static int quiet_flag=0;		/* Don't decode the packet */
static int ignore_dups=0;		/* Don't display duplicate packets */
static uint32_t arp_spa;		/* Source IP address */
static int arp_spa_flag=0;		/* Source IP address specified */
static int arp_spa_is_tpa=0;		/* Source IP is dest IP */
static unsigned char arp_sha[ETH_ALEN];	/* Source Ethernet MAC Address */
static int arp_sha_flag=0;		/* Source MAC address specified */
static char ouifilename[MAXLINE];	/* OUI filename */
static char iabfilename[MAXLINE];	/* IAB filename */
static char macfilename[MAXLINE];	/* MAC filename */
static char pcap_savefile[MAXLINE];	/* pcap savefile filename */
static int arp_op=DEFAULT_ARP_OP;	/* ARP Operation code */
static int arp_hrd=DEFAULT_ARP_HRD;	/* ARP hardware type */
static int arp_pro=DEFAULT_ARP_PRO;	/* ARP protocol */
static int arp_hln=DEFAULT_ARP_HLN;	/* Hardware address length */
static int arp_pln=DEFAULT_ARP_PLN;	/* Protocol address length */
static int eth_pro=DEFAULT_ETH_PRO;	/* Ethernet protocol type */
static unsigned char arp_tha[6] = {0, 0, 0, 0, 0, 0};
static unsigned char target_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static unsigned char source_mac[6];
static int source_mac_flag = 0;
static unsigned char *padding=NULL;
static size_t padding_len=0;
static int localnet_flag=0;		/* Scan local network */
static int llc_flag=0;			/* Use 802.2 LLC with SNAP */
static int ieee_8021q_vlan=-1;		/* Use 802.1Q VLAN tagging if >= 0 */
static int pkt_write_file_flag=0;	/* Write packet to file flag */
static int pkt_read_file_flag=0;	/* Read packet from file flag */
static char pkt_filename[MAXLINE];	/* Read/Write packet to file filename */
static int write_pkt_to_file=0;		/* Write packet to file for debugging */
static int rtt_flag=0;			/* Display round-trip time */
static pcap_dumper_t *pcap_dump_handle = NULL;	/* pcap savefile handle */
static int plain_flag=0;		/* Only show host information */
unsigned int random_seed=0;

int
main(int argc, char *argv[]) {
   struct timeval now;
   struct timeval diff;         /* Difference between two timevals */
   int select_timeout;          /* Select timeout */
   ARP_UINT64 loop_timediff;    /* Time since last packet sent in us */
   ARP_UINT64 host_timediff; /* Time since last pkt sent to this host (us) */
   struct timeval last_packet_time;     /* Time last packet was sent */
   int req_interval;		/* Requested per-packet interval */
   int cum_err=0;               /* Cumulative timing error */
   struct timeval start_time;   /* Program start time */
   struct timeval end_time;     /* Program end time */
   struct timeval elapsed_time; /* Elapsed time as timeval */
   double elapsed_seconds;      /* Elapsed time in seconds */
   int reset_cum_err;
   int pass_no = 0;
   int first_timeout=1;
   unsigned i;
   char errbuf[PCAP_ERRBUF_SIZE];
   struct bpf_program filter;
   char *filter_string;
   bpf_u_int32 netmask;
   bpf_u_int32 localnet;
   int datalink;
   int get_addr_status = 0;
   int pcap_fd;			/* Pcap file descriptor */
   unsigned char interface_mac[ETH_ALEN];
   pcap_t *pcap_handle;		/* pcap handle */
/*
 *      Initialise file names to the empty string.
 */
   ouifilename[0] = '\0';
   iabfilename[0] = '\0';
   macfilename[0] = '\0';
   pcap_savefile[0] = '\0';
/*
 *      Process options.
 */
   process_options(argc, argv);
/*
 *      Get program start time for statistics displayed on completion.
 */
   Gettimeofday(&start_time);
/*
 *	Obtain network interface details unless we're reading
 *	from a pcap file or writing to a binary file.
 */
   if (!pkt_read_file_flag && !pkt_write_file_flag) {
/*
 *	Determine network interface to use. If the interface was specified
 *	with the --interface option then use that, otherwise use
 *	pcap_lookupdev() to pick a suitable interface.
 */
   if (!if_name) {
      if (!(if_name=pcap_lookupdev(errbuf))) {
         err_msg("pcap_lookupdev: %s", errbuf);
      }
   }
/*
 *	Obtain the MAC address for the selected interface, and use this
 *	as default for the source hardware addresses in the frame header
 *	and ARP packet if the user has not specified their values.
 *
 *	Die with an error if we can't get the MAC address, as this
 *	indicates that the interface doesn't have a MAC address, so is
 *	probably not a compatible interface type.
 */
      get_hardware_address(if_name, interface_mac);
      if (interface_mac[0]==0 && interface_mac[1]==0 &&
          interface_mac[2]==0 && interface_mac[3]==0 &&
          interface_mac[4]==0 && interface_mac[5]==0) {
         err_msg("ERROR: Could not obtain MAC address for interface %s",
                 if_name);
      }
      if (source_mac_flag == 0)
         memcpy(source_mac, interface_mac, ETH_ALEN);
      if (arp_sha_flag == 0)
         memcpy(arp_sha, interface_mac, ETH_ALEN);
/*
 *	If the user has not specified the ARP source address, obtain the
 *	interface IP address and use that as the default value.
 */
      if (arp_spa_flag == 0) {
         get_addr_status = get_source_ip(if_name, &arp_spa);
         if (get_addr_status == -1) {
            warn_msg("WARNING: Could not obtain IP address for interface %s. "
                     "Using 0.0.0.0 for", if_name);
            warn_msg("the source address, which is probably not what you want.");
            warn_msg("Either configure %s with an IP address, or manually specify"
                     " the address", if_name);
            warn_msg("with the --arpspa option.");
            memset(&arp_spa, '\0', sizeof(arp_spa));
         }
      }
   }
/*
 *	Open the network device for reading with pcap, or the pcap file if we
 *	have specified --readpktfromfile. If we are writing packets to a binary
 *	file, then set pcap_handle to NULL as we don't need to read packets in
 *	this case.
 */
   if (pkt_read_file_flag) {
      if (!(pcap_handle = pcap_open_offline(pkt_filename, errbuf)))
         err_msg("pcap_open_offline: %s", errbuf);
   } else if (!pkt_write_file_flag) {
      if (!(pcap_handle = pcap_create(if_name, errbuf)))
         err_msg("pcap_create: %s", errbuf);
      if ((pcap_set_snaplen(pcap_handle, snaplen)) < 0)
         err_msg("pcap_set_snaplen: %s", pcap_geterr(pcap_handle));
      if ((pcap_set_promisc(pcap_handle, PROMISC)) < 0)
         err_msg("pcap_set_promisc: %s", pcap_geterr(pcap_handle));
      if ((pcap_set_timeout(pcap_handle, TO_MS)) < 0)
         err_msg("pcap_set_timeout: %s", pcap_geterr(pcap_handle));
      if ((pcap_activate(pcap_handle)) < 0)
         err_msg("pcap_activate: %s", pcap_geterr(pcap_handle));
   } else {
      pcap_handle = NULL;
   }
/*
 *	If we are reading data with pcap, get and display the datalink details
 */
   if (pcap_handle) {
      if ((datalink=pcap_datalink(pcap_handle)) < 0)
         err_msg("pcap_datalink: %s", pcap_geterr(pcap_handle));
      if (!plain_flag) {
         printf("Interface: %s, datalink type: %s (%s)\n",
                pkt_read_file_flag ? "savefile" : if_name,
                pcap_datalink_val_to_name(datalink),
                pcap_datalink_val_to_description(datalink));
      }
      if (datalink != DLT_EN10MB) {
         warn_msg("WARNING: Unsupported datalink type");
      }
   }
/*
 *	If we are reading from a network device, then get the associated file
 *	descriptor and configure it, determine the interface IP network and
 *	netmask, and install a pcap filter to receive only ARP responses.
 *	If we are reading from a pcap file, or writing to a binary file, just
 *	set the file descriptor to -1 to indicate that it is not associated
 *	with a network device.
 */
   if (!pkt_read_file_flag && !pkt_write_file_flag) {
      if ((pcap_fd=pcap_get_selectable_fd(pcap_handle)) < 0)
         err_msg("pcap_fileno: %s", pcap_geterr(pcap_handle));
      if ((pcap_setnonblock(pcap_handle, 1, errbuf)) < 0)
         err_msg("pcap_setnonblock: %s", errbuf);
/*
 * For the BPF pcap implementation, set the BPF device into immediate mode,
 * otherwise it will buffer the responses.
 */
#ifdef ARP_PCAP_BPF
#ifdef BIOCIMMEDIATE
      {
         unsigned int one = 1;

         if (ioctl(pcap_fd, BIOCIMMEDIATE, &one) < 0)
            err_sys("ioctl BIOCIMMEDIATE");
      }
#endif /* BIOCIMMEDIATE */
#endif /* ARP_PCAP_BPF */
/*
 * For the DLPI pcap implementation on Solaris, set the bufmod timeout to
 * zero. This has the side-effect of setting the chunk size to zero as
 * well, so bufmod will pass all incoming messages on immediately.
 */
#ifdef ARP_PCAP_DLPI
      {
         struct timeval time_zero = {0, 0};

         if (ioctl(pcap_fd, SBIOCSTIME, &time_zero) < 0)
            err_sys("ioctl SBIOCSTIME");
      }
#endif
      if (pcap_lookupnet(if_name, &localnet, &netmask, errbuf) < 0) {
         memset(&localnet, '\0', sizeof(localnet));
         memset(&netmask, '\0', sizeof(netmask));
         if (localnet_flag) {
            warn_msg("ERROR: Could not obtain interface IP address and netmask");
            err_msg("ERROR: pcap_lookupnet: %s", errbuf);
         }
      }
/*
 *	The filter string selects packets addressed to the ARP source address
 *	that are Ethernet-II ARP packets, 802.3 LLC/SNAP ARP packets,
 *	802.1Q tagged ARP packets or 802.1Q tagged 802.3 LLC/SNAP ARP packets.
 */
      filter_string=make_message("ether dst %.2x:%.2x:%.2x:%.2x:%.2x:%.2x and "
                                 "(arp or (ether[14:4]=0xaaaa0300 and "
                                 "ether[20:2]=0x0806) or (ether[12:2]=0x8100 "
                                 "and ether[16:2]=0x0806) or "
                                 "(ether[12:2]=0x8100 and "
                                 "ether[18:4]=0xaaaa0300 and "
                                 "ether[24:2]=0x0806))",
                                 arp_sha[0], arp_sha[1],
                                 arp_sha[2], arp_sha[3],
                                 arp_sha[4], arp_sha[5]);
      if (verbose > 1)
         warn_msg("DEBUG: pcap filter string: \"%s\"", filter_string);
      if ((pcap_compile(pcap_handle, &filter, filter_string, OPTIMISE,
           netmask)) < 0)
         err_msg("pcap_compile: %s", pcap_geterr(pcap_handle));
      free(filter_string);
      if ((pcap_setfilter(pcap_handle, &filter)) < 0)
         err_msg("pcap_setfilter: %s", pcap_geterr(pcap_handle));
   } else {	/* Reading packets from file */
      pcap_fd = -1;
   }
/*
 *      Drop SUID privileges.
 */
   if ((setuid(getuid())) < 0) {
      err_sys("setuid");
   }
/*
 *	Open pcap savefile is the --pcapsavefile (-W) option was specified
 */
   if (*pcap_savefile != '\0') {
      if (!(pcap_dump_handle=pcap_dump_open(pcap_handle, pcap_savefile))) {
         err_msg("pcap_dump_open: %s", pcap_geterr(pcap_handle));
      }
   }
/*
 *      Check that the combination of specified options and arguments is
 *      valid.
 */
   if (interval && bandwidth != DEFAULT_BANDWIDTH)
      err_msg("ERROR: You cannot specify both --bandwidth and --interval.");
   if (localnet_flag) {
      if ((argc - optind) > 0)
         err_msg("ERROR: You can not specify targets with the --localnet option");
      if (filename_flag)
         err_msg("ERROR: You can not specify both --file and --localnet options");
   }
/*
 *      If we're not reading from a file, and --localnet was not specified, then
 *	we must have some hosts given as command line arguments.
 */
   if (!filename_flag && !localnet_flag)
      if ((argc - optind) < 1)
         usage(EXIT_FAILURE, 0);
/*
 * Create MAC/Vendor hash table if quiet if not in effect.
 */
   if (!quiet_flag) {
      char *fn;
      int count;

      if ((hcreate(HASH_TABLE_SIZE)) == 0)
         err_sys("hcreate");

      fn = get_mac_vendor_filename(ouifilename, DATADIR, OUIFILENAME);
      count = add_mac_vendor(fn);
Loading ...