Skip to content

Instantly share code, notes, and snippets.

@dynax60
Created August 9, 2010 09:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dynax60/515174 to your computer and use it in GitHub Desktop.
Save dynax60/515174 to your computer and use it in GitHub Desktop.
Non-blocked arping sample using POE
#!/usr/bin/perl
use strict;
use warnings;
use POE qw(Wheel::Run Filter::Reference);
sub MAX_CONCURRENT_TASKS () { 25 }
use Net::Netmask;
use Data::Dumper;
my $interface = shift or die;
my $prefix = shift or die;
my $t = new Net::Netmask($prefix);
my $payload = { map { $_ => { 'loss' => '', 'mac' => [], 'dup' => undef } } $t->enumerate() };
delete $payload->{$_} foreach ($t->first, $t->nth(1), $t->last);
my @commands;
for (keys %{$payload}) {
push @commands, "/usr/local/sbin/arping -w100000 -c 10 -i $interface $_";
}
POE::Session->create(
inline_states => {
_start => \&start_tasks,
next_task => \&start_tasks,
task_result => \&handle_task_result,
task_done => \&handle_task_done,
sig_child => \&sig_child,
}
);
sub start_tasks {
my ($kernel, $heap) = @_[KERNEL, HEAP];
while (keys(%{$heap->{task}}) < MAX_CONCURRENT_TASKS) {
my $next_task = shift @commands;
last unless defined $next_task;
my $task = POE::Wheel::Run->new(
Program => sub { do_stuff($next_task) },
StdoutFilter => POE::Filter::Reference->new(),
StdoutEvent => "task_result",
CloseEvent => "task_done",
);
$heap->{task}->{$task->ID} = $task;
$kernel->sig_child($task->PID, "sig_child");
}
}
sub do_stuff {
binmode(STDOUT);
my $task = shift;
my $filter = POE::Filter::Reference->new();
undef $/;
my %result = (
task => $task,
out => qx{ $task },
);
my $output = $filter->put([\%result]);
print @$output;
}
sub handle_task_result {
my $result = $_[ARG0];
my ($ip) = ($result->{out} =~ m{^ARPING (\S+)});
my ($loss) = ($result->{out} =~ m{(\S+) unanswered}s);
$payload->{$ip}->{loss} = $loss;
my %mac=();
while( $result->{out} =~ m/bytes from (\S+)/g) {
$mac{$1}=1;
}
push @{$payload->{$ip}->{mac}}, keys %mac;
$payload->{$ip}->{dup} = scalar(keys %mac) > 1 ? 1 : 0;
}
sub handle_task_done {
my ($kernel, $heap, $task_id) = @_[KERNEL, HEAP, ARG0];
delete $heap->{task}->{$task_id};
$kernel->yield("next_task");
}
sub sig_child {
my ($heap, $sig, $pid, $exit_val) = @_[HEAP, ARG0, ARG1, ARG2];
my $details = delete $heap->{$pid};
}
$poe_kernel->run();
print Dumper($payload);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment