#!/usr/bin/perl

# this script made by pallotron@freaknet.org
#
# this script sniffs to an interface, searching for packets that match 
# the filter rule, it sends an email we this occurs with a simply and stupid
# email flood protection 

use Config::General;
use Net::Pcap;
use NetPacket::TCP;
use NetPacket::IP qw(:strip);
use NetPacket::Ethernet qw(:strip);
use Email::Send;
use Email::Send::SMTP;
use strict;

STDOUT->autoflush(1);

my ($email_to, $listen_if, $filter_name, $filter_rule, $notification_period);
my ($email_from, $smtp_server);

my $last_timestamp = 0;
my $curr_timestamp = time;
my $send_email = 1;

sub sniff {
	my ($dev, $email, $name, $filter) = @_;
	my ($pcap_t, $filter_t);
	my ($err, $net, $mask);
	my $promisc = 0;
	my $snaplen = 256;
	my $to_ms = 0;
	my $opt = 1;

	if ( (Net::Pcap::lookupnet($dev, \$net, \$mask, \$err) ) == -1 ) {
		die "Net::Pcap::lookupnet failed.  Error was $err";
	}

	my $pcap_t = Net::Pcap::open_live($dev, $snaplen, $promisc, $to_ms, \$err);
	$pcap_t || die "Can't create packet descriptor.  Error was $err";


	if ( Net::Pcap::compile($pcap_t, \$filter_t, $filter, $opt, $net) == -1 ) {
		die "Unable to compile filter string '$filter'\n";
	}

	Net::Pcap::setfilter($pcap_t, $filter_t);
	Net::Pcap::loop($pcap_t, -1, \&process_pkt, 0);
}

sub process_pkt {
	my ($user_data, $hdr, $pkt) = @_;

	my $tcp_obj = NetPacket::TCP->decode(ip_strip(eth_strip($pkt)));
	my $ip_obj  = NetPacket::IP->decode(eth_strip($pkt));

	$curr_timestamp = time;

	if( ($curr_timestamp - $last_timestamp >= $notification_period) or $send_email) {
		my $msgtxt = sprintf("%s: %s.\nDetails: %s:%s -> %s:%s\n\n",
			$curr_timestamp, $filter_name, $ip_obj->{src_ip},
			$tcp_obj->{src_port}, $ip_obj->{dest_ip}, $tcp_obj->{dest_port});

		print $msgtxt;
		my $subject = $filter_name;
		print "Mando email\n";
		sendemail($email_to, $subject, $msgtxt);
		$send_email=0;
		$last_timestamp = time;
	}

	#print($tcp_obj->{data});
}

sub sendemail {
	my ($to, $sbj, $msg) = @_;

	my $message=<<MESSAGE;
To: $to
From: $email_from
Subject: $sbj

$msg
		  
MESSAGE

	my $sender = Email::Send->new({mailer => 'SMTP'});
	$sender->mailer_args([Host => $smtp_server]);
	$sender->send($message);

}

sub main {
	my $numArgs = $#ARGV + 1;

	if ( $numArgs == 0 ) {
		print "You must provide the configfile path as an argument!\n";
		exit -1;
	}

	my $cfgfile = $ARGV[0];

	my $conf = new Config::General($cfgfile);
	my %config = $conf->getall;

	chomp(%config);

	$email_to            = $config{email_to};
	$listen_if           = $config{listen_interface};
	$filter_name         = $config{filter_name};
	$filter_rule         = $config{filter_rule};
	$notification_period = $config{notification_period};
	$email_from          = $config{email_from};
	$smtp_server         = $config{smtp_server};

	sniff($listen_if, $email_to, $filter_name, $filter_rule);
}

main;