~ubuntu-branches/ubuntu/jaunty/arp-scan/jaunty

« back to all changes in this revision

Viewing changes to arp-scan.c

  • Committer: Bazaar Package Importer
  • Author(s): Tim Brown
  • Date: 2007-05-22 21:57:35 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070522215735-42zr032pmyfi4m4m
Tags: 1.6-2
* Checksums weren't matching
* Upload sponsored by Philipp Hug <debian@hug.cx>

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * The ARP Scanner (arp-scan) is Copyright (C) 2005-2006 Roy Hills,
 
2
 * The ARP Scanner (arp-scan) is Copyright (C) 2005-2007 Roy Hills,
3
3
 * NTA Monitor Ltd.
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or
16
16
 * along with this program; if not, write to the Free Software
17
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
18
 *
19
 
 * $Id: arp-scan.c 8257 2006-07-21 18:52:02Z rsh $
 
19
 * $Id: arp-scan.c 10534 2007-04-10 10:17:13Z rsh $
20
20
 *
21
21
 * arp-scan -- The ARP Scanner
22
22
 *
37
37
 
38
38
#include "arp-scan.h"
39
39
 
40
 
static char const rcsid[] = "$Id: arp-scan.c 8257 2006-07-21 18:52:02Z rsh $";   /* RCS ID for ident(1) */
 
40
static char const rcsid[] = "$Id: arp-scan.c 10534 2007-04-10 10:17:13Z rsh $";   /* RCS ID for ident(1) */
41
41
 
42
42
/* Global variables */
43
43
static host_entry *helist = NULL;       /* Array of host entries */
46
46
static unsigned num_hosts = 0;          /* Number of entries in the list */
47
47
static unsigned responders = 0;         /* Number of hosts which responded */
48
48
static unsigned live_count;             /* Number of entries awaiting reply */
49
 
static unsigned max_iter;               /* Max iterations in find_host() */
50
49
static int verbose=0;                   /* Verbose level */
51
50
static int debug = 0;                   /* Debug flag */
52
51
static pcap_t *pcap_handle;             /* pcap handle */
98
97
   ARP_UINT64 loop_timediff;    /* Time since last packet sent in us */
99
98
   ARP_UINT64 host_timediff; /* Time since last pkt sent to this host (us) */
100
99
   int arg;
101
 
   int arg_str_space;           /* Used to avoid buffer overruns when copying */
102
100
   struct timeval last_packet_time;     /* Time last packet was sent */
103
101
   int req_interval;            /* Requested per-packet interval */
104
102
   int cum_err=0;               /* Cumulative timing error */
121
119
   unsigned char interface_mac[ETH_ALEN];
122
120
/*
123
121
 *      Open syslog channel and log arguments if required.
124
 
 *      We must be careful here to avoid overflowing the arg_str buffer
125
 
 *      which could result in a buffer overflow vulnerability.  That's why
126
 
 *      we use strncat and keep track of the remaining buffer space.
127
122
 */
128
123
#ifdef SYSLOG
129
124
   openlog("arp-scan", LOG_PID, SYSLOG_FACILITY);
130
125
   arg_str[0] = '\0';
131
 
   arg_str_space = MAXLINE;     /* Amount of space in the arg_str buffer */
132
126
   for (arg=0; arg<argc; arg++) {
133
 
      arg_str_space -= strlen(argv[arg]);
134
 
      if (arg_str_space > 0) {
135
 
         strncat(arg_str, argv[arg], (size_t) arg_str_space);
136
 
         if (arg < (argc-1)) {
137
 
            strncat(arg_str, " ", 1);
138
 
            arg_str_space--;
139
 
         }
 
127
      strlcat(arg_str, argv[arg], sizeof(arg_str));
 
128
      if (arg < (argc-1)) {
 
129
         strlcat(arg_str, " ", sizeof(arg_str));
140
130
      }
141
131
   }
142
132
   info_syslog("Starting: %s", arg_str);
236
226
      }
237
227
#endif /* BIOCIMMEDIATE */
238
228
#endif /* ARP_PCAP_BPF */
 
229
/*
 
230
 * For the DLPI pcap implementation on Solaris, set the bufmod timeout to
 
231
 * zero.  This has the side-effect tof setting the chink size to zero as
 
232
 * well, so bufmod will pass all incoming messages on immediately.
 
233
 */
 
234
#ifdef ARP_PCAP_DLPI
 
235
   {
 
236
      struct timeval time_zero = {0, 0};
 
237
 
 
238
      if (ioctl(pcap_fd, SBIOCSTIME, &time_zero) < 0)
 
239
         err_sys("ioctl SBIOCSTIME");
 
240
   }
 
241
#endif
239
242
   if (pcap_lookupnet(if_name, &localnet, &netmask, errbuf) < 0) {
240
243
      memset(&localnet, '\0', sizeof(localnet));
241
244
      memset(&netmask, '\0', sizeof(netmask));
381
384
 *      Check that we have at least one entry in the list.
382
385
 */
383
386
   if (!num_hosts)
384
 
      err_msg("No hosts to process.");
 
387
      err_msg("ERROR: No hosts to process.");
385
388
/*
386
389
 *      Create and initialise array of pointers to host entries.
387
390
 */
390
393
      helistptr[i] = &helist[i];
391
394
/*
392
395
 *      Randomise the list if required.
 
396
 *      Uses Knuth's shuffle algorithm.
393
397
 */
394
398
   if (random_flag) {
395
 
      unsigned seed;
 
399
      unsigned random_seed;
396
400
      struct timeval tv;
397
401
      int r;
398
402
      host_entry *temp;
399
403
 
400
404
      Gettimeofday(&tv);
401
 
      seed = tv.tv_usec ^ getpid();
402
 
      srandom(seed);
 
405
      random_seed = tv.tv_usec ^ getpid();      /* Unpredictable value */
 
406
      init_genrand(random_seed);
403
407
 
404
408
      for (i=num_hosts-1; i>0; i--) {
405
 
         r = random() % (i+1);     /* Random number 0<=r<i */
 
409
         r = (int)(genrand_real2() * i);  /* 0<=r<i */
406
410
         temp = helistptr[i];
407
411
         helistptr[i] = helistptr[r];
408
412
         helistptr[r] = temp;
859
863
   fprintf(stderr, "\t\t\tThis timeout is for the first packet sent to each host.\n");
860
864
   fprintf(stderr, "\t\t\tsubsequent timeouts are multiplied by the backoff\n");
861
865
   fprintf(stderr, "\t\t\tfactor which is set with --backoff.\n");
862
 
   fprintf(stderr, "\n--interval=<n> or -i <n> Set minimum packet interval to <n> ms, default=%d.\n", interval/1000);
 
866
   fprintf(stderr, "\n--interval=<n> or -i <n> Set minimum packet interval to <n> ms.\n");
863
867
   fprintf(stderr, "\t\t\tThis controls the outgoing bandwidth usage by limiting\n");
864
868
   fprintf(stderr, "\t\t\tthe rate at which packets can be sent.  The packet\n");
865
869
   fprintf(stderr, "\t\t\tinterval will be no smaller than this number.\n");
867
871
   fprintf(stderr, "\t\t\teasier to use the --bandwidth option instead.\n");
868
872
   fprintf(stderr, "\t\t\tThe interval specified is in milliseconds by default,\n");
869
873
   fprintf(stderr, "\t\t\tor in microseconds if \"u\" is appended to the value.\n");
870
 
   fprintf(stderr, "\n--bandwidth=<n> or -B <n> Set desired outbound bandwidth to <n>.\n");
 
874
   fprintf(stderr, "\n--bandwidth=<n> or -B <n> Set desired outbound bandwidth to <n>, default=%d.\n", DEFAULT_BANDWIDTH);
871
875
   fprintf(stderr, "\t\t\tThe value is in bits per second by default.  If you\n");
872
876
   fprintf(stderr, "\t\t\tappend \"K\" to the value, then the units are kilobits\n");
873
877
   fprintf(stderr, "\t\t\tper sec; and if you append \"M\" to the value, the\n");
1095
1099
 */
1096
1100
   string_len=strlen(pattern)+1;
1097
1101
   patcopy=Malloc(string_len);
1098
 
   strncpy(patcopy, pattern, string_len);
 
1102
   strlcpy(patcopy, pattern, string_len);
1099
1103
 
1100
1104
   if (!(regexec(&ipslash_pat, patcopy, 0, NULL, 0))) { /* IPnet/bits */
1101
1105
/*
1255
1259
 
1256
1260
   if (numeric_flag) {
1257
1261
      result = inet_pton(AF_INET, host_name, &addr);
1258
 
      if (result <= 0)
1259
 
         warn_sys("WARNING: inet_pton failed for \"%s\" - target ignored",
1260
 
                  host_name);
 
1262
      if (result < 0) {
 
1263
         err_sys("ERROR: inet_pton failed for %s", host_name);
 
1264
      } else if (result == 0) {
 
1265
         warn_msg("WARNING: \"%s\" is not a valid IPv4 address - target ignored");
 
1266
         return;
 
1267
      }
1261
1268
   } else {
1262
1269
      hp = get_host_address(host_name, AF_INET, &addr, &ga_err_msg);
1263
 
      if (hp == NULL)
 
1270
      if (hp == NULL) {
1264
1271
         warn_msg("WARNING: get_host_address failed for \"%s\": %s - target ignored",
1265
1272
                  host_name, ga_err_msg);
 
1273
         return;
 
1274
      }
1266
1275
   }
1267
1276
 
1268
1277
   if (!num_left) {     /* No entries left, allocate some more */
1384
1393
 
1385
1394
   if (debug) {print_times(); printf("find_host: found=%d, iterations=%u\n", found, iterations);}
1386
1395
 
1387
 
   if (iterations > max_iter)
1388
 
      max_iter=iterations;
1389
 
 
1390
1396
   if (found)
1391
1397
      return *p;
1392
1398
   else
1430
1436
 * indicate if there is input waiting on a BPF device.
1431
1437
 */
1432
1438
#ifdef ARP_PCAP_BPF
1433
 
      if ((pcap_dispatch(pcap_handle, -1, callback, NULL)) < 0)
 
1439
      if ((pcap_dispatch(pcap_handle, -1, callback, NULL)) == -1)
1434
1440
         err_sys("pcap_dispatch: %s\n", pcap_geterr(pcap_handle));
1435
1441
#endif
1436
1442
      return;   /* Timeout */
1437
1443
   }
1438
 
   if ((pcap_dispatch(pcap_handle, -1, callback, NULL)) < 0)
 
1444
   if ((pcap_dispatch(pcap_handle, -1, callback, NULL)) == -1)
1439
1445
      err_sys("pcap_dispatch: %s\n", pcap_geterr(pcap_handle));
1440
1446
}
1441
1447
 
1596
1602
         int result;
1597
1603
 
1598
1604
         case 'f':      /* --file */
1599
 
            strncpy(filename, optarg, MAXLINE);
 
1605
            strlcpy(filename, optarg, sizeof(filename));
1600
1606
            filename_flag=1;
1601
1607
            break;
1602
1608
         case 'h':      /* --help */
1603
1609
            usage(EXIT_SUCCESS);
1604
 
            break;
 
1610
            break;      /* NOTREACHED */
1605
1611
         case 'r':      /* --retry */
1606
1612
            retry=Strtoul(optarg, 10);
1607
1613
            break;
1609
1615
            timeout=Strtoul(optarg, 10);
1610
1616
            break;
1611
1617
         case 'i':      /* --interval */
1612
 
            strncpy(interval_str, optarg, MAXLINE);
 
1618
            strlcpy(interval_str, optarg, sizeof(interval_str));
1613
1619
            interval_len=strlen(interval_str);
1614
1620
            if (interval_str[interval_len-1] == 'u') {
1615
1621
               interval=Strtoul(interval_str, 10);
1626
1632
         case 'V':      /* --version */
1627
1633
            arp_scan_version();
1628
1634
            exit(0);
1629
 
            break;
 
1635
            break;      /* NOTREACHED */
1630
1636
         case 'd':      /* --debug */
1631
1637
            debug++;
1632
1638
            break;
1649
1655
            numeric_flag=1;
1650
1656
            break;
1651
1657
         case 'B':      /* --bandwidth */
1652
 
            strncpy(bandwidth_str, optarg, MAXLINE);
 
1658
            strlcpy(bandwidth_str, optarg, sizeof(bandwidth_str));
1653
1659
            bandwidth_len=strlen(bandwidth_str);
1654
1660
            if (bandwidth_str[bandwidth_len-1] == 'M') {
1655
1661
               bandwidth=1000000 * Strtoul(bandwidth_str, 10);
1660
1666
            }
1661
1667
            break;
1662
1668
         case 'O':      /* --ouifile */
1663
 
            strncpy(ouifilename, optarg, MAXLINE);
 
1669
            strlcpy(ouifilename, optarg, sizeof(ouifilename));
1664
1670
            break;
1665
1671
         case 'F':      /* --iabfile */
1666
 
            strncpy(iabfilename, optarg, MAXLINE);
 
1672
            strlcpy(iabfilename, optarg, sizeof(iabfilename));
1667
1673
            break;
1668
1674
         case 'm':      /* --macfile */
1669
 
            strncpy(macfilename, optarg, MAXLINE);
 
1675
            strlcpy(macfilename, optarg, sizeof(macfilename));
1670
1676
            break;
1671
1677
         case 's':      /* --arpspa */
1672
1678
            arp_spa_flag = 1;
1729
1735
            break;
1730
1736
         default:       /* Unknown option */
1731
1737
            usage(EXIT_FAILURE);
1732
 
            break;
 
1738
            break;      /* NOTREACHED */
1733
1739
      }
1734
1740
   }
1735
1741
}
1746
1752
void
1747
1753
arp_scan_version (void) {
1748
1754
   fprintf(stderr, "%s\n\n", PACKAGE_STRING);
1749
 
   fprintf(stderr, "Copyright (C) 2005-2006 Roy Hills, NTA Monitor Ltd.\n");
 
1755
   fprintf(stderr, "Copyright (C) 2005-2007 Roy Hills, NTA Monitor Ltd.\n");
1750
1756
   fprintf(stderr, "arp-scan comes with NO WARRANTY to the extent permitted by law.\n");
1751
1757
   fprintf(stderr, "You may redistribute copies of arp-scan under the terms of the GNU\n");
1752
1758
   fprintf(stderr, "General Public License.\n");
1753
1759
   fprintf(stderr, "For more information about these matters, see the file named COPYING.\n");
1754
1760
   fprintf(stderr, "\n");
 
1761
   fprintf(stderr, "%s\n", pcap_lib_version());
1755
1762
/* We use rcsid here to prevent it being optimised away */
1756
1763
   fprintf(stderr, "%s\n", rcsid);
1757
1764
   error_use_rcsid();
1951
1958
 *      Inputs:
1952
1959
 *
1953
1960
 *      table           The handle of the hash table
1954
 
 *      filename        The name of the file containing the mappings
 
1961
 *      map_filename    The name of the file containing the mappings
1955
1962
 *
1956
1963
 *      Returns:
1957
1964
 *
1958
1965
 *      The number of entries added to the hash table.
1959
1966
 */
1960
1967
int
1961
 
add_mac_vendor(struct hash_control *table, const char *filename) {
 
1968
add_mac_vendor(struct hash_control *table, const char *map_filename) {
1962
1969
   static int first_call=1;
1963
1970
   FILE *fp;    /* MAC/Vendor file handle */
1964
1971
   static const char *oui_pat_str = "([^\t]+)\t[\t ]*([^\t\r\n]+)";
1989
1996
/*
1990
1997
 *      Open the file.
1991
1998
 */
1992
 
   if ((fp = fopen(filename, "r")) == NULL) {
1993
 
      warn_sys("WARNING: Cannot open MAC/Vendor file %s", filename);
 
1999
   if ((fp = fopen(map_filename, "r")) == NULL) {
 
2000
      warn_sys("WARNING: Cannot open MAC/Vendor file %s", map_filename);
1994
2001
      return 0;
1995
2002
   }
1996
2003
   line_count=0;
2013
2020
         data_len = pmatch[2].rm_eo - pmatch[2].rm_so;
2014
2021
         key=Malloc(key_len+1);
2015
2022
         data=Malloc(data_len+1);
 
2023
/*
 
2024
 * We cannot use strlcpy because the source is not guaranteed to be null
 
2025
 * terminated.  Therefore we use strncpy, specifying one less that the total
 
2026
 * length, and manually null terminate the destination.
 
2027
 */
2016
2028
         strncpy(key, line+pmatch[1].rm_so, key_len);
2017
2029
         key[key_len] = '\0';
2018
2030
         strncpy(data, line+pmatch[2].rm_so, data_len);