Fix programming typo that breaks with recent perl
[manu/send_arp.git] / send_arp.pl
1 #!/usr/bin/perl -w
2 # Send arp packets for ip takeover
3
4 # Copyright (C) 2007-2011 Emmanuel Lacour <elacour@home-dn.net>
5 #
6 # This file is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by the
8 # Free Software Foundation; either version 2, or (at your option) any
9 # later version.
10 #
11 # This file is distributed in the hope that it will be
12 # useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this file; see the file COPYING.  If not, write to the Free
18 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 use strict;
23 use Getopt::Long;
24 use Time::HiRes qw(usleep);
25 use Socket;
26 use Net::Interface;
27
28 # Disable STDOUT buffering
29 $| = 1;
30
31 my $VERSION = '1.0';
32 my $AUTHOR = 'Emmanuel Lacour, <elacour@home-dn.net>';
33
34
35 # Defaults
36
37 # Command line options
38 my %opts;
39 GetOptions (\%opts,
40     'address=s',
41     'iface=s',
42     'dest=s',
43     'count|c=i',
44     'interval|i=i',
45     'verbose|v',
46     'help|h',
47     'version');
48
49 $opts{'count'} = 5 if (!$opts{'count'});
50 $opts{'interval'} = 100 if (!$opts{'interval'});
51
52 if ($opts{'help'} || !$opts{'address'} || !$opts{'iface'} || !$opts{'dest'}) {
53     &usage;
54 }
55
56 if ($opts{'version'}) {
57     print "send_arpl.pl $VERSION\n";
58     print "Written by $AUTHOR\n";
59     exit;
60 }
61
62 sub usage() {
63     print "Usage: send_arp.pl [OPTION]...
64     --address=IP         source IP address
65     --iface=IFACE        network interface
66     --dest=IP            destination IP address or broadcast
67 -c, --count=NUMBER       count of ARP to send (default: 5)
68 -i, --interval=NUMBER    interval between ARP requests (ms) (default: 100)
69 -v, --verbose            print debugging information
70 -h, --help               print this help, then exit
71     --version            print this program version number
72 ";
73
74     exit;
75 }
76
77 sub sendARPReply($$$$$) {
78     my ($add,$iface,$ipdest,$count,$interval) = @_;
79     my $bmac = 'FF:FF:FF:FF:FF:FF';
80     my $netinfo = Net::Interface->new($iface);
81     my $hexmac = $netinfo->hwaddress();
82     my $mac = unpack("H*",$hexmac);
83             
84     my $hexbmac = lc ($bmac);
85     $hexbmac =~ s/://g;
86     $hexbmac =~ s/([a-f0-9][a-f0-9])/chr(hex($1))/eg;
87             
88     my $sock;
89             
90     socket($sock, PF_INET, 10, 0x300);
91     select($sock); $|++;
92     select(STDOUT);
93
94     return if (! $sock);
95
96     my $arpreply =
97             $hexbmac.               # MAC cible
98             $hexmac.                # MAC source
99             "\x08\x06".             # Format d'en-tete ARP
100             "\x00\x01".             # Protocole (IP)
101             "\x08\x00".             # Longueur de l'adresse physique
102             "\x06\x04".             # Longueur de l'adresse reseau
103             "\x00\x02".             # Operation (reply)
104             $hexmac.                # MAC source
105             inet_aton($add).        # IP source
106             $hexbmac.               # MAC cible
107             inet_aton($ipdest)      # IP cible
108             ;
109
110     my $dest = ("\x00" x 2).$iface.("\x00" x (14 - length($iface)));
111     # Send at least one time
112     my $i = 1;
113     print "Sending ARP to $ipdest, source $add (HW: $mac), on $iface:" if ($opts{'verbose'});
114     while ($i le $count) {
115             print " ." if ($opts{'verbose'});
116             send($sock, $arpreply, 0, $dest);
117             usleep ($interval * 1000);
118             $i++;
119     }
120     print " done.\n" if ($opts{'verbose'});
121 }
122
123 sendARPReply($opts{'address'},$opts{'iface'},$opts{'dest'},$opts{'count'},$opts{'interval'});
124