#!/usr/bin/perl -w
# Send arp packets for ip takeover

# Copyright (C) 2007-2011 Emmanuel Lacour <elacour@home-dn.net>
#
# This file 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 2, or (at your option) any
# later version.
#
# This file 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 this file; see the file COPYING.  If not, write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301, USA.


use strict;
use Getopt::Long;
use Time::HiRes qw(usleep);
use Socket;
use Net::Interface;

# Disable STDOUT buffering
$| = 1;

my $VERSION = '1.0';
my $AUTHOR = 'Emmanuel Lacour, <elacour@home-dn.net>';


# Defaults

# Command line options
my %opts;
GetOptions (\%opts,
    'address=s',
    'iface=s',
    'dest=s',
    'count|c=i',
    'interval|i=i',
    'verbose|v',
    'help|h',
    'version|');

$opts{'count'} = 5 if (!$opts{'count'});
$opts{'interval'} = 100 if (!$opts{'interval'});

if ($opts{'help'} || !$opts{'address'} || !$opts{'iface'} || !$opts{'dest'}) {
    &usage;
}

if ($opts{'version'}) {
    print "send_arpl.pl $VERSION\n";
    print "Written by $AUTHOR\n";
    exit;
}

sub usage() {
    print "Usage: send_arp.pl [OPTION]...
    --address=IP         source IP address
    --iface=IFACE        network interface
    --dest=IP            destination IP address or broadcast
-c, --count=NUMBER       count of ARP to send (default: 5)
-i, --interval=NUMBER    interval between ARP requests (ms) (default: 100)
-v, --verbose            print debugging information
-h, --help               print this help, then exit
    --version            print this program version number
";

    exit;
}

sub sendARPReply($$$$$) {
    my ($add,$iface,$ipdest,$count,$interval) = @_;
    my $bmac = 'FF:FF:FF:FF:FF:FF';
    my $netinfo = Net::Interface->new($iface);
    my $hexmac = $netinfo->hwaddress();
    my $mac = unpack("H*",$hexmac);
            
    my $hexbmac = lc ($bmac);
    $hexbmac =~ s/://g;
    $hexbmac =~ s/([a-f0-9][a-f0-9])/chr(hex($1))/eg;
            
    my $sock;
            
    socket($sock, PF_INET, 10, 0x300);
    select($sock); $|++;
    select(STDOUT);

    return if (! $sock);

    my $arpreply =
            $hexbmac.               # MAC cible
            $hexmac.                # MAC source
            "\x08\x06".             # Format d'en-tete ARP
            "\x00\x01".             # Protocole (IP)
            "\x08\x00".             # Longueur de l'adresse physique
            "\x06\x04".             # Longueur de l'adresse reseau
            "\x00\x02".             # Operation (reply)
            $hexmac.                # MAC source
            inet_aton($add).        # IP source
            $hexbmac.               # MAC cible
            inet_aton($ipdest)      # IP cible
            ;

    my $dest = ("\x00" x 2).$iface.("\x00" x (14 - length($iface)));
    # Send at least one time
    my $i = 1;
    print "Sending ARP to $ipdest, source $add (HW: $mac), on $iface:" if ($opts{'verbose'});
    while ($i le $count) {
            print " ." if ($opts{'verbose'});
            send($sock, $arpreply, 0, $dest);
            usleep ($interval * 1000);
            $i++;
    }
    print " done.\n" if ($opts{'verbose'});
}

sendARPReply($opts{'address'},$opts{'iface'},$opts{'dest'},$opts{'count'},$opts{'interval'});

