Skip to content

Commit

Permalink
Added --writepkttofile and --readpktfromfile options.
Browse files Browse the repository at this point in the history
Added new check-packet and check-decode tests.
Two bug fixes: avoid closing fd 0 with --filename=-, and
set the frame type correctly for LLC/SNAP framing.


git-svn-id: svn+ssh://svn.nta-monitor.com/trunk/opensource/arp-scan@18088 062a1500-4a13-0410-a63b-ee65f32af78f
  • Loading branch information
royhills committed Jan 30, 2011
1 parent 7fc5084 commit 7879b75
Show file tree
Hide file tree
Showing 15 changed files with 341 additions and 15 deletions.
25 changes: 25 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
$Id$

2011-01-30 Roy Hills <Roy.Hills@nta-monitor.com>

* check-packet, check-decode: New checks to check packet creation and
packet decoding.

* pkt-custom-request.dat, pkt-custom-request-llc.dat,
pkt-custom-request-padding.dat, pkt-custom-request-vlan.dat,
pkt-padding-response.dat, pkt-simple-request.dat,
pkt-simple-response.dat: Data files for check-packet and check-decode
scripts.

* Makefile.am: Add new check scripts and data files.

* arp-scan.c, arp-scan.h: Added undocumented options --writepkttofile
and --readpktfromfile to allow data to be written to or read from a
file instead of the network for testing.

* arp-scan.c: Use "stdin" instead of fdopen(0,"r") when using
--filename=-, fixing a bug which was causing fd 0 to be closed.
Set the frame type correctly for LLC/SNAP format frames: before
it was always set to 0x0806.

* configure.ac: Add headers required for --writepkttofile and
--readpktfromfile. Increment version number to 1.7.5.

2011-01-09 Roy Hills <Roy.Hills@nta-monitor.com>

* COPYING: Changed license from GPLv2 to GPLv3.
Expand Down
3 changes: 2 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ bin_PROGRAMS = arp-scan
#
dist_bin_SCRIPTS = get-oui get-iab arp-fingerprint
#
dist_check_SCRIPTS = check-run1
dist_check_SCRIPTS = check-run1 check-packet check-decode
#
dist_man_MANS = arp-scan.1 get-oui.1 get-iab.1 arp-fingerprint.1 mac-vendor.5
#
Expand All @@ -17,3 +17,4 @@ arp_scan_LDADD = $(LIBOBJS)
dist_pkgdata_DATA = ieee-oui.txt ieee-iab.txt mac-vendor.txt
#
TESTS = $(dist_check_SCRIPTS)
EXTRA_DIST = pkt-simple-request.dat pkt-custom-request.dat pkt-custom-request-padding.dat pkt-custom-request-llc.dat pkt-custom-request-vlan.dat pkt-simple-response.dat pkt-padding-response.dat
7 changes: 7 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,10 @@ trailers will send an additional "trailer ARP reply" packet'. Trailer
encapsulation itself is detailed in RFC 893.

Replace MT19937 PRNG with SFMT19937.

Support LLC/SNAP encapsulation with 802.1Q VLAN tagging (--llc --vlan=n) and
generate the correct packet format. Currently the VLAN tag is added first,
which is incorrect.

link-dlpi.c: In function `dlpi_msg':
link-dlpi.c:150: warning: comparison between signed and unsigned
75 changes: 65 additions & 10 deletions arp-scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ static struct hash_control *hash_table;
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_filename_flag=0; /* Write packet to file flag */
static int pkt_read_filename_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 read_pkt_from_file=0; /* Read packet from file for debugging */

int
main(int argc, char *argv[]) {
Expand Down Expand Up @@ -336,9 +341,7 @@ main(int argc, char *argv[]) {
char *cp;

if ((strcmp(filename, "-")) == 0) { /* Filename "-" means stdin */
if ((fp = fdopen(0, "r")) == NULL) {
err_sys("fdopen");
}
fp = stdin;
} else {
if ((fp = fopen(filename, "r")) == NULL) {
err_sys("fopen");
Expand All @@ -351,7 +354,9 @@ main(int argc, char *argv[]) {
*cp = '\0';
add_host_pattern(line, timeout);
}
fclose(fp);
if (fp != stdin) {
fclose(fp);
}
} else if (localnet_flag) { /* Populate list from i/f addr & mask */
struct in_addr if_network;
struct in_addr if_netmask;
Expand Down Expand Up @@ -386,6 +391,22 @@ main(int argc, char *argv[]) {
*/
if (!num_hosts)
err_msg("ERROR: No hosts to process.");
/*
* If --writepkttofile was specified, open the specified output file.
*/
if (pkt_filename_flag) {
write_pkt_to_file = open(pkt_filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (write_pkt_to_file == -1)
err_sys("open %s", pkt_filename);
}
/*
* If --readpktfromfile was specified, open the specified input file.
*/
if (pkt_read_filename_flag) {
read_pkt_from_file = open(pkt_filename, O_RDONLY);
if (read_pkt_from_file == -1)
err_sys("open %s", pkt_filename);
}
/*
* Create and initialise array of pointers to host entries.
*/
Expand Down Expand Up @@ -557,6 +578,10 @@ main(int argc, char *argv[]) {

link_close(link_handle);
clean_up();
if (write_pkt_to_file)
close(write_pkt_to_file);
if (read_pkt_from_file)
close(read_pkt_from_file);

Gettimeofday(&end_time);
timeval_diff(&end_time, &start_time, &elapsed_time);
Expand Down Expand Up @@ -731,6 +756,7 @@ send_packet(link_t *link_handle, host_entry *he,
size_t buflen;
ether_hdr frame_hdr;
arp_ether_ipv4 arpei;
int nsent;
/*
* Construct Ethernet frame header
*/
Expand Down Expand Up @@ -788,9 +814,14 @@ send_packet(link_t *link_handle, host_entry *he,
if (verbose > 1)
warn_msg("---\tSending packet #%u to host %s tmo %d", he->num_sent,
my_ntoa(he->addr), he->timeout);
if ((link_send(link_handle, buf, buflen)) < 0) {
err_sys("ERROR: failed to send packet");
if (write_pkt_to_file) {
nsent = write(write_pkt_to_file, buf, buflen);
} else {
nsent = link_send(link_handle, buf, buflen);
}
if (nsent < 0)
err_sys("ERROR: failed to send packet");

return buflen;
}

Expand Down Expand Up @@ -1447,7 +1478,7 @@ recvfrom_wto(int s, int tmo) {
if (debug) {print_times(); printf("recvfrom_wto: select end, tmo=%d, n=%d\n", tmo, n);}
if (n < 0) {
err_sys("select");
} else if (n == 0) {
} else if (n == 0 && read_pkt_from_file == 0) {
/*
* For the BPF pcap implementation, we call pcap_dispatch() even if select
* times out. This is because on many BPF implementations, select() doesn't
Expand All @@ -1459,8 +1490,21 @@ recvfrom_wto(int s, int tmo) {
#endif
return; /* Timeout */
}
if ((pcap_dispatch(pcap_handle, -1, callback, NULL)) == -1)
err_sys("pcap_dispatch: %s\n", pcap_geterr(pcap_handle));
if (read_pkt_from_file == 0) {
if ((pcap_dispatch(pcap_handle, -1, callback, NULL)) == -1)
err_sys("pcap_dispatch: %s\n", pcap_geterr(pcap_handle));
} else { /* Read from file */
unsigned char buf[MAX_FRAME];
struct pcap_pkthdr header;

if ((n = read(read_pkt_from_file, buf, MAX_FRAME)) < 0) {
err_sys("ERROR: read");
}
Gettimeofday(&(header.ts));
header.caplen = n;
header.len = n;
callback(NULL, &header, buf);
}
}

/*
Expand Down Expand Up @@ -1615,6 +1659,8 @@ process_options(int argc, char *argv[]) {
{"llc", no_argument, 0, 'L'},
{"vlan", required_argument, 0, 'Q'},
{"pcapsavefile", required_argument, 0, 'W'},
{"writepkttofile", required_argument, 0, OPT_WRITEPKTTOFILE},
{"readpktfromfile", required_argument, 0, OPT_READPKTFROMFILE},
{0, 0, 0, 0}
};
const char *short_options =
Expand Down Expand Up @@ -1754,6 +1800,14 @@ process_options(int argc, char *argv[]) {
case 'W': /* --pcapsavefile */
strlcpy(pcap_savefile, optarg, sizeof(pcap_savefile));
break;
case OPT_WRITEPKTTOFILE: /* --writepkttofile */
strlcpy(pkt_filename, optarg, sizeof(pkt_filename));
pkt_filename_flag=1;
break;
case OPT_READPKTFROMFILE: /* --readpktfromfile */
strlcpy(pkt_filename, optarg, sizeof(pkt_filename));
pkt_read_filename_flag=1;
break;
default: /* Unknown option */
usage(EXIT_FAILURE);
break; /* NOTREACHED */
Expand Down Expand Up @@ -1882,7 +1936,7 @@ void
marshal_arp_pkt(unsigned char *buffer, ether_hdr *frame_hdr,
arp_ether_ipv4 *arp_pkt, size_t *buf_siz,
const unsigned char *frame_padding, size_t frame_padding_len) {
unsigned char llc_snap[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06};
unsigned char llc_snap[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char vlan_tag[] = {0x81, 0x00, 0x00, 0x00};
unsigned char *cp;
size_t packet_size;
Expand Down Expand Up @@ -1934,6 +1988,7 @@ marshal_arp_pkt(unsigned char *buffer, ether_hdr *frame_hdr,
*/
if (llc_flag) {
memcpy(cp, llc_snap, sizeof(llc_snap));
memcpy(cp+6, &(frame_hdr->frame_type), sizeof(frame_hdr->frame_type));
cp += sizeof(llc_snap);
packet_size += sizeof(llc_snap);
}
Expand Down
10 changes: 10 additions & 0 deletions arp-scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@
#include <regex.h> /* Posix regular expression functions */
#endif

#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif

#ifdef HAVE_PCAP_H
#include <pcap.h>
#endif
Expand Down Expand Up @@ -153,6 +161,8 @@
#define FRAMING_ETHERNET_II 0 /* Standard Ethernet-II Framing */
#define FRAMING_LLC_SNAP 1 /* 802.3 with LLC/SNAP */
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
#define OPT_WRITEPKTTOFILE 256 /* --writepkttofile option */
#define OPT_READPKTFROMFILE 257 /* --readpktfromfile option */

/* Structures */

Expand Down
93 changes: 93 additions & 0 deletions check-decode
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/bin/sh
# The ARP Scanner (arp-scan) is Copyright (C) 2005-2011 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/>.
#
# $Id$
#
# check-packet - Shell script to test arp-scan packet decoding
#
# Author: Roy Hills
# Date: 30 January 2011
#
# This script checks that arp-scan decodes and displays ARP response packets
# correctly. It uses the undocumented arp-scan option --readpktfromfile to
# read the packet from a file rather than from the network.
#

# Check that the user is root. Skip this check if they are not.
ID=`id | sed 's/(.*//'`
if test "$ID" != "uid=0"
then
echo "User is not root, skipping check-decode test..."
exit 0
fi
#
ARPSCANOUTPUT=/tmp/arp-scan-output.$$.tmp
EXAMPLEOUTPUT=/tmp/example-output.$$.tmp
#
SAMPLE01="$srcdir/pkt-simple-response.dat"
SAMPLE02="$srcdir/pkt-padding-response.dat"

echo "Checking simple ARP response packet decode using $SAMPLE01 ..."
cat >$EXAMPLEOUTPUT <<_EOF_
127.0.0.1 08:00:2b:06:07:08 DIGITAL EQUIPMENT CORPORATION
_EOF_
ARPARGS="--retry=1"
$srcdir/arp-scan $ARPARGS --readpktfromfile=$SAMPLE01 127.0.0.1 | grep -v '^Starting arp-scan ' | grep -v '^Interface: ' | grep -v '^Ending arp-scan ' | grep -v '^[0-9]* packets received ' > $ARPSCANOUTPUT 2>&1
if test $? -ne 0; then
rm -f $ARPSCANOUTPUT
rm -f $EXAMPLEOUTPUT
echo "FAILED"
exit 1
fi
cmp -s $ARPSCANOUTPUT $EXAMPLEOUTPUT
if test $? -ne 0; then
rm -f $ARPSCANOUTPUT
rm -f $EXAMPLEOUTPUT
echo "FAILED"
exit 1
fi
echo "ok"
rm -f $ARPSCANOUTPUT
rm -f $EXAMPLEOUTPUT
#
echo "Checking padded ARP response packet decode using $SAMPLE02 ..."
cat >$EXAMPLEOUTPUT <<_EOF_
127.0.0.1 08:00:2b:06:07:08 DIGITAL EQUIPMENT CORPORATION Padding=55aa55aa55aa55aa55aa55aa55aa55aa55aa
_EOF_
ARPARGS="--retry=1 --verbose"
$srcdir/arp-scan $ARPARGS --readpktfromfile=$SAMPLE02 127.0.0.1 | grep -v '^DEBUG: ' | grep -v '^Starting arp-scan ' | grep -v '^Interface: ' | grep -v '^Ending arp-scan ' | grep -v '^[0-9]* packets received ' > $ARPSCANOUTPUT 2>&1
if test $? -ne 0; then
rm -f $ARPSCANOUTPUT
rm -f $EXAMPLEOUTPUT
echo "FAILED"
exit 1
fi
cmp -s $ARPSCANOUTPUT $EXAMPLEOUTPUT
if test $? -ne 0; then
rm -f $ARPSCANOUTPUT
rm -f $EXAMPLEOUTPUT
echo "FAILED"
exit 1
fi
echo "ok"
rm -f $ARPSCANOUTPUT
rm -f $EXAMPLEOUTPUT

Loading

0 comments on commit 7879b75

Please sign in to comment.