#!/usr/bin/perl -w

$whois='/usr/bin/whois';
$dir=$ENV{HOME}.'/.cache';

use MIME::Base64;
use Socket;
use lib '/usr/local/lib/mime_parse_scan';
use BE::Lib;

open(CACHE,'+>>',"$dir/wcc-cache") || die "open $dir/wcc-cache";

my $a;
$host='whois.thur.de';

my $abuseonly = 0;

if(defined $ARGV[0]) {
	if("$ARGV[0]" eq '-h') {
		$host=$ARGV[1];
		splice @ARGV,0,2;
	}

	if($ARGV[0] eq '-a')
	{
		splice(@ARGV,0,1);
		$abuseonly=1;
}	}

my %mail_override;
loadtable(%mail_override,"$ENV{'HOME'}/.config/fsmtpd/email.xlat");
{
	my %l;
	loadlist(@l,"$ENV{'HOME'}/.config/fsmtpd/email.noabuse");
	for my $d (@l) {
		$d=~s/\s.*//;
		$mail_override{"abuse\@$d"}='-';
}	}

my %no_postmaster;
{
	my @l;
	loadlist(@l,"$ENV{'HOME'}/.config/fsmtpd/email.nopostmaster");
	for my $l (@l) {
		$l=~s/\s.*//;
		$no_postmaster{$l}=1;
	}
}


#NOTE: I tried removing '*@foo' when 'abuse@foo' was mentioned. Didn't work.
my @lp_override_sec=('security','abuse-security','cert');
my @lp_override_noc=('noc','NOC','nbso','gc-noc','netmaster','noc-team',
	'ipnoc','ncc','network','networks','NetAbuse','net-admin','nemesys');
my @lp_override_ipadm=(
	'ip','ip-adm','ip.admin','ipadmin','IPadmin','ip_admin1',
	'ip_admin2','ip_admin_hb',
	'ipnetworks','ipoperations',
	'ipreq','ip-req','IP.RegistrationService','ip-alloc',
	'dns-admin','ipaddressing','addressing','WebFarm.IPAllocation',
	'asignacionip','dns-info',
	'CNIPEO-Ip-registration','cernet-helpdesk-ip','ipsupport','sh-ip'
);
my @lp_override_iptech=('ip.tech','ip-tech','tech');
my @lp_override_tech=('tech-group','contact-tech','techadmin');
my @lp_override_support=(
	'support','info','isp.support',
	'helpdesk','help4u','suporte','suport','service');
my @lp_override_abuse=('abuse','spamabuse','internet.abuse','abuse_hb');
my @lp_override_admin=('admins','DIA.ADMIN','admin','admin2','sysadmin');
my @lp_override_antispam=('anti_spam','anti-spam','antispam','spam',
	'abuse-mail','mail-abuse','spam_hb');
my @lp_override_xmaster=('postmaster','hostmaster','webmaster');
my @lp_override_other=(
	'domain','peering','swipper','mgr','add-req.tac','isp','ris-nic');
my @lp_override_ripe=('ripe','ripe.hm','ripe-guardian','arin','Admin_ripe',
	'Ripe-relations','arin_tech','ripe-staff','adminis.ripe');

my @lp_override=(@lp_override_antispam,@lp_override_abuse,@lp_override_sec,
	@lp_override_noc,@lp_override_tech,@lp_override_iptech,@lp_override_admin,
	@lp_override_support,@lp_override_ipadm,@lp_override_other,
	@lp_override_xmaster,@lp_override_ripe);

this_ip:
while($a = pop(@ARGV)) {

	seek(CACHE,0,0);

	while(<CACHE>) {
		my ($first,$last,$q,$abuse,$msg)=split;
		my $nfirst=unpack('N',inet_aton($first));
		my $nlast=unpack('N',inet_aton($last));
		my $na=0;
		if($a=~/\d+(\.\d+){3}/) {
			$na=unpack('N',inet_aton($a));
		}
		
		if(($q eq $a)
		|| (($na >= $nfirst)
		 && ($na <= $nlast))){
			if(!$abuseonly){print decode_base64($msg)."\n";}
			print "$abuse\n";
			next this_ip;
	}	}
	
	open(WHOIS,'-|',($whois,'-H','-h',$host,$a));
	my $foundrange;
	my $res='';
	my ($maila,$mailb);
	my $redir=2;
	my $skip_rest;
	my %have_seen=();
	my %mails;
	my $reset=1;
	my $ignore_line_jpnic=0;
	restart:while(<WHOIS>) {
		if($reset){
			$foundrange=0;
			$skip_rest=0;
			$res='';
			%mails=();
			$reset=0;
		}
		if($skip_rest
		|| /^(?:changed|notify|remarks:\s+changed): /i
		|| ($ignore_line_jpnic && /^\s+\S+\@\S+$/)
		|| /^remarks:\s+This object can only be modified by APNIC hostmaster(?:s\.)?$/
		|| /^remarks:\s+If you wish to modify this object details please$/
		|| /^remarks:\s+send email to hostmaster\@apnic\.net with your organisation$/
		|| /^remarks:\s+account name in the subject line\.$/
		|| /^remarks:\s+To update this object, please contact APNIC$/
		|| /^remarks:\s+hostmasters and include your organisation\'s account$/
		|| /^remarks:\s+name in the subject line\.$/
		|| /^remarks:\s+[-+@]+$/
		){next}
		if(/^\[Last Update\]\s+/){
			$ignore_line_jpnic=1;
			next;
		}
		$res .= "$_";
		if(!$abuseonly){print}
		chomp;
		if(/^$/){
			next;
		} elsif(/^#? (KOREAN)$/) {
			$have_seen{"$1"}=1;
			if($have_seen{"ENGLISH"}){$skip_rest=1;next}
		} elsif(/^# (ENGLISH)$/) {
			$have_seen{"ENGLISH"}=1;
		} elsif(/^(NetRange|inetnum|IPv4 Address\s+):.*\b(\d+(\.\d+){3})\s*-\s*(\d+(\.\d+){3})\s*$/) {
			my $mfirst=unpack('N',inet_aton($2));
			my $mlast=unpack('N',inet_aton($4));
			if($foundrange==0
			|| (($mfirst >= $first)
			 && ($mlast  <= $last))){
				$first=$mfirst;
				$last=$mlast;
				$foundrange=1;
			} else {
				$foundrange+=1;
			}
		} elsif(/^(CIDR|inetnum):.*?\b(\d+(\.\d+){0,3})\/(\d+)\s*$/) {
			my $mbase=$2;
			my $mrange=$4;
			while(!($mbase=~/\d+(\.\d+){3}/)){$mbase.=".0"}
			$mbase=unpack('N',inet_aton($mbase));
			my $mlast=(~(-1 << (32-$mrange)) | $mbase);
			if($foundrange==0
			|| (($mbase >= $first)
			 && ($mlast  <= $last))){
				$first=$mbase;
				$last=$mlast;
				$foundrange=1;
			} elsif(
			! (($mbase eq $first)
			&& ($mlast eq $last))){
				$foundrange+=1;
			}
		} elsif(($redir && /^NetType:    Early Registrations, Transferred to APNIC$/)
		||      ($redir && /^OrgTechEmail:\s+search-apnic-not-arin\@apnic\.net/)) {
			open(WHOIS,'-|',($whois,'-H','-h','whois.apnic.net',$a));
			$redir--;
			$reset=1;
			next restart;
		} elsif($redir && /^remarks:      KRNIC whois server at whois.krnic.net.$/) {
			open(WHOIS,'-|',($whois,'-H','-h','whois.krnic.net',$a));
			$redir--;
			$reset=1;
			next restart;
		} elsif($redir && /^NetType:    Early Registrations, Transferred to RIPE NCC$/) {
			open(WHOIS,'-|',($whois,'-H','-h','whois.ripe.net',$a));
			$redir--;
			$reset=1;
			next restart;
		} elsif($redir && /^Comment:    the RIPE database at http:\/\/www\.ripe\.net\/whois$/) {
			open(WHOIS,'-|',($whois,'-H','-h','whois.ripe.net',$a));
			$redir--;
			$reset=1;
			next restart;
		} elsif($redir && m,^remarks:\s+http://whois.nida.or.kr/english/index.html$,) {
			open(WHOIS,'-|',($whois,'-H','-h','whois.nida.or.kr',$a));
			$redir--;
			$reset=1;
			next restart;
		} elsif($redir && /^Comment:\s+(?:or check the )?WHOIS server located at whois\.lacnic\.net$/) {
			open(WHOIS,'-|',($whois,'-H','-h','whois.lacnic.net',$a));
			$redir--;
			$reset=1;
			next restart;
		}  elsif($redir && /^remarks:\s+at whois\.registro\.br and at http:\/\/whois\.nic\.br$/){
			open(WHOIS,'-|',($whois,'-H','-h','whois.registro.br',$a));
			$redir--;
			$reset=1;
			next restart;
		}  elsif($redir && /^remarks:\s+JPNIC whois server at whois\.nic\.ad\.jp\./){
			open(WHOIS,'-|',($whois,'-H','-h','whois.nic.ad.jp',$a));
			$redir--;
			$reset=1;
			next restart;
		}  elsif($redir && /^Comment:\s+available at rwhois\.verio\.net port 4321$/){
			open(WHOIS,'-|',($whois,'-H','-h','rwhois.verio.net',$a));
			$redir--;
			$reset=1;
			next restart;
		}  elsif($redir && /^remarks:\s+TWNIC whois server at whois\.twnic\.net\.$/){
			open(WHOIS,'-|',($whois,'-H','-h','whois.twnic.net',$a));
			$redir--;
			$reset=1;
			next restart;
		}  elsif($redir && /^Comment:\s+available at rwhois\.egix\.net:4321:rwhois$/){
			open(WHOIS,'-|',($whois,'-H','-h','rwhois.egix.net',$a));
			$redir--;
			$reset=1;
			next restart;
		} elsif(/(?:^|\s|mailto:|<|\")([-_.a-z0-9]+(?:\@|_at_)[-.a-z0-9]+)(?:\s|,|>|\"|$)/i) {
			/^/g;
			/\@/||s/_at_/\@/g;
			while(/\G.*?(?:\b|mailto:|<)([-_.a-z0-9]+\@[-.a-z0-9]+)(?:\s|,|>|$)/ig) {
				my $s=$1;
				$s =~ s/\.+$//;
				$mails{$s}=1;
			}
		}
	}

	$maila="()";
	for my $a (keys(%mails)){
#		print "checking $a\n";
		if (my $b=$mail_override{$a}) {
			delete($mails{$a});
			$mails{$b}=1;
#			print "$a -> $b\n";
		}
		if($a=~/\@(.*)/){if($no_postmaster{$1}){delete($mails{$a});}}
	}
	delete($mails{'-'});

	for my $a (keys(%mails)){
		if(!$mails{$a}){next}
		$a=~/^(.*)(\@.*)$/;
		my ($lp,$d) = ($1,$2);
		my @b=@lp_override;
		while(@b && ($lp ne shift(@b))){};
		if(!@b){next}
#		print "trying $lp$d\n";
		for $c (@b){
#				if(defined($mails{"$c$d"})){print "deleted $c$d for $lp\n"}
				delete($mails{"$c$d"});
	}	}

	# These are usurally mentioned as "if the above contacts are unreachable"
	# We will try the other addresses first
	if(2==scalar keys(%mails)) {
		for my $a ('abuse@kornet.net','abuse@hanaro.com',
			'abuse@dreamcity.co.kr','ip-alloc@nic.ad.jp','jpnic@pwd.ad.jp',
			'hostmaster@nic.ad.jp'){
			if(2==scalar keys(%mails)) {
				delete($mails{$a});
	}	}	}

	if(scalar keys(%mails) == 1) { #we found the one
		($maila)=keys(%mails);
	} else {
		my $s="Mails: ".join(', ',keys(%mails))."\n";
		if(!$abuseonly){print $s}
		$res.=$s;
		if(keys(%mails)){$maila='()'}
		else{$maila='<>'}
	}

	print $maila."\n";
	if($foundrange!=1) {
		$first = '255.255.255.255';
		$last = '0.0.0.0';
	} else {
		$first=inet_ntoa(pack('N',$first));
		$last=inet_ntoa(pack('N',$last));
	}
	(my $t=encode_base64($res))=~s/\n//g;
	print CACHE "$first\t$last\t$a\t$maila\t$t\n";
}
