From 84fea950fd61b14fd89888346ba09e3e93af6f45 Mon Sep 17 00:00:00 2001 From: William Heimbigner Date: Thu, 14 Jan 2016 13:52:04 -0700 Subject: Process DNS lookups when syncing ban/quietlists asynchronously --- lib/ASM/Event.pm | 35 +++++++++++++++++++++++++++++------ lib/ASM/Util.pm | 39 +++++++++++++++++++++++++++++++-------- meta.pl | 5 +++-- 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/lib/ASM/Event.pm b/lib/ASM/Event.pm index 5137d29..90ba542 100644 --- a/lib/ASM/Event.pm +++ b/lib/ASM/Event.pm @@ -9,6 +9,7 @@ use POSIX qw(strftime); use Regexp::Wildcards; use HTTP::Request; use Array::Utils qw(:all); +use Net::DNS::Async; no if $] >= 5.017011, warnings => 'experimental::smartmatch'; sub new @@ -16,6 +17,7 @@ sub new my $module = shift; my ($conn, $inspector) = @_; my $self = {}; + $self->{DNS} = Net::DNS::Async->new(QueueSize => 5000, Retries => 3); $self->{CONN} = $conn; $self->{INSPECTOR} = $inspector; ASM::Util->dprint('Installing handler routines...', 'startup'); @@ -772,9 +774,19 @@ sub on_banlist } $::sc{$chan}{bans}{$ban} = { bannedBy => $banner, bannedOn => $bantime }; if ($ban =~ /^\*\!\*\@(.*)$/) { - # ASM::Util->dprint("banlist hostname $ban $1", 'sync'); - my $ip = ASM::Util->getHostIP($1); - $::sc{$chan}{ipbans}{$ip} = { bannedBy => $banner, bannedOn => $bantime } if defined($ip); + my $host = $1; + my $ip = ASM::Util->getHostIPFast($host); + if (defined($ip)) { + $::sc{$chan}{ipbans}{$ip} = { bannedBy => $banner, bannedOn => $bantime }; + } elsif ( $host =~ /^(([a-z0-9]([a-z0-9\-]*[a-z0-9])?\.)*([a-z0-9]([a-z0-9\-]*[a-z0-9])?\.?))$/i) { + ASM::Util->dprint("banlist hostname $chan $host", 'dns'); + $::event->{DNS}->add( + sub { + my ($packet) = @_; + $ip = ASM::Util->stripResp($packet); + $::sc{$chan}{ipbans}{$ip} = { bannedBy => $banner, bannedOn => $bantime } if defined($ip); + }, $host, 'A'); + } } } @@ -794,9 +806,19 @@ sub on_quietlist } $::sc{$chan}{quiets}{$ban} = { bannedBy => $banner, bannedOn => $bantime }; if ($ban =~ /^\*\!\*\@(.*)$/) { - # ASM::Util->dprint("quietlist hostname $ban $1", 'sync'); - my $ip = ASM::Util->getHostIP($1); - $::sc{$chan}{ipquiets}{$ip} = { bannedBy => $banner, bannedOn => $bantime } if defined($ip); + my $host = $1; + my $ip = ASM::Util->getHostIPFast($host); + if (defined($ip)) { + $::sc{$chan}{ipquiets}{$ip} = { bannedBy => $banner, bannedOn => $bantime }; + } elsif ( $host =~ /^(([a-z0-9]([a-z0-9\-]*[a-z0-9])?\.)*([a-z0-9]([a-z0-9\-]*[a-z0-9])?\.?))$/i) { + ASM::Util->dprint("quietlist hostname $chan $host", 'dns'); + $::event->{DNS}->add( + sub { + my ($packet) = @_; + $ip = ASM::Util->stripResp($packet); + $::sc{$chan}{ipquiets}{$ip} = { bannedBy => $banner, bannedOn => $bantime } if defined($ip); + }, $host, 'A'); + } } } @@ -964,6 +986,7 @@ sub on_quietlistend } else { $rx = sprintf("%.2fKB", $conn->{_rx}/1024); } + $::event->{DNS}->await(); $conn->privmsg($::settings->{masterchan}, "Finished syncing after " . (time - $::starttime) . " seconds. " . "I'm tracking " . (scalar (keys %::sn)) . " nicks" . " across " . (scalar (keys %::sc)) . " tracked channels." . diff --git a/lib/ASM/Util.pm b/lib/ASM/Util.pm index 3ec0cd9..7b910a1 100644 --- a/lib/ASM/Util.pm +++ b/lib/ASM/Util.pm @@ -7,6 +7,7 @@ use strict; use Term::ANSIColor qw (:constants); use Socket qw( inet_aton inet_ntoa ); use Data::Dumper; + no if $] >= 5.017011, warnings => 'experimental::smartmatch'; %::RISKS = @@ -225,7 +226,7 @@ sub dprint { sub intToDottedQuad { my ($module, $num) = @_; - return inet_ntoa(pack('N', $num)); + return inet_ntoa(pack('N', $num)); } sub dottedQuadToInt @@ -234,25 +235,47 @@ sub dottedQuadToInt return unpack('N', inet_aton($dottedquad)); } -sub getHostIP +sub stripResp +{ + my $module = shift; + my $response = shift; + my @answer = $response->answer; + if ($response->{header}->{rcode} ne "NOERROR") { + dprint($module, Dumper($response), 'dns'); + return; + } + if ((!(@answer)) || ($answer[0]->{type} ne 'A')) { + return undef; + } + return dottedQuadToInt($module, $answer[0]->{address}); +} + +sub getHostIPFast { my ($module, $host) = @_; if ( ($host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) or ($host =~ /^gateway\/web\/.*\/ip\.(\d+)\.(\d+)\.(\d+)\.(\d+)$/) ) { - #yay, easy IP! + #yay, easy IP! return dottedQuadToInt(undef, "$1.$2.$3.$4"); } elsif ($host =~ /^2001:0:/) { my @splitip = split(/:/, $host); return unless defined($splitip[6]) && defined($splitip[7]); - #I think I can just do (hex($splitip[6] . $splitip[7]) ^ hex('ffffffff')) here but meh my $host = join('.', unpack('C4', pack('N', (hex($splitip[6] . $splitip[7])^hex('ffffffff'))))); return dottedQuadToInt(undef, $host); - } elsif ($host !~ /^(([a-z0-9]([a-z0-9\-]*[a-z0-9])?\.)*([a-z0-9]([a-z0-9\-]*[a-z0-9])?\.?))$/i) { - return; } - $ENV{RES_OPTIONS} = "timeout:1 attempts:1"; + return undef; +} + +sub getHostIP +{ + my ($module, $host) = @_; + my $ip = getHostIPFast($module, $host); + return $ip if defined($ip); + if ( $host !~ /^(([a-z0-9]([a-z0-9\-]*[a-z0-9])?\.)*([a-z0-9]([a-z0-9\-]*[a-z0-9])?\.?))$/i) { + return undef; + } my @resolve = gethostbyname($host); - return unless @resolve; + return undef unless @resolve; return dottedQuadToInt(undef, join('.', unpack('C4', $resolve[4]))); } diff --git a/meta.pl b/meta.pl index b306226..f7fea0f 100755 --- a/meta.pl +++ b/meta.pl @@ -63,7 +63,8 @@ $::settingschanged = 0; "latency" => RED, "statsp" => MAGENTA, "ctcp" => 0, #RED, - "logger" => 0 + "logger" => 0, + "dns" => 0 ); %::dsock = (); %::spy = (); @@ -133,7 +134,7 @@ sub init { $::inspector = ASM::Inspect->new(); $::services = ASM::Services->new(); $::commander = ASM::Commander->new(); - ASM::Event->new($conn, $::inspector); + $::event = ASM::Event->new($conn, $::inspector); $::classes = ASM::Classes->new(); $::fifo = ASM::Fifo->new($irc, $conn); my @nickbl = io('nick_blacklist.txt')->getlines; -- cgit v1.2.3