AMPR-Rip44
view release on metacpan or search on metacpan
}
# Ok, process the actual route entries
my $routes = 0;
for (my $i = $init_msg; $i < length($entries); $i += RIP_ENTRY_LEN) {
my $entry = substr($entries, $i, RIP_ENTRY_LEN);
my $n = process_rip_route_entry($entry);
return -1 if ($n < 0);
$routes += $n;
}
return $routes;
}
#
####### main #############################################
#
# command line parsing
my %opts;
getopts('i:p:a:vd', \%opts);
if (defined $opts{'i'}) {
$tunnel_if = $opts{'i'};
}
if (defined $opts{'p'}) {
$rip_passwd = $opts{'p'};
}
if ($opts{'v'} && !$verbose) {
$verbose = 1;
}
if ($opts{'d'}) {
$verbose = 2;
}
if ($opts{'a'}) {
foreach my $a (split(',', $opts{'a'})) {
$my_addresses{$a} = 1;
}
}
fill_local_ifs();
# Enable multicast on the tunnel interface, the flag is
# not set by default
system($ifconfig, $tunnel_if, 'multicast') == 0 or die "ifconfig $tunnel_if multicast failed: $?\n";
# Create the UDP multicast socket to receive RIP broadcasts
warn "opening UDP socket...\n" if ($verbose);
my $socket = IO::Socket::Multicast->new(
LocalPort => 520,
ReuseAddr => 1,
) or die $!;
$socket->mcast_add('224.0.0.9', $tunnel_if) or die $!;
my $expire_interval = 60*60;
my $next_expire = time() + $expire_interval;
# Main loop: receive broadcasts, check that they're from the correct
# address and port, and pass them on to processing
warn "entering main loop, waiting for RIPv2 datagrams\n" if ($verbose);
while (1) {
my $msg;
my $remote_address = recv($socket, $msg, 1500, 0);
if (!defined $remote_address) {
next;
}
my ($peer_port, $peer_addr) = unpack_sockaddr_in($remote_address);
my $addr_s = inet_ntoa($peer_addr);
if ($addr_s ne '44.0.0.1' || $peer_port ne 520) {
warn "$me: ignored packet from $addr_s: $peer_port: " . length($msg) . "\n";
next;
}
warn "received from $addr_s: $peer_port: " . length($msg) . " bytes\n" if ($verbose);
my $routes = process_msg($addr_s, $peer_port, $msg);
warn "processed $routes route entries\n" if ($verbose && $routes >= 0);
# Consider expiring old routes. This is actually never run if we do not receive
# any RIP broadcasts at all (the recv() is blocking)
# The (desired) side effect is that if the RIP announcer
# dies, the entries do not time out.
if (time() > $next_expire || $next_expire > time() + $expire_interval) {
$next_expire = time() + $expire_interval;
expire_routes();
}
}
( run in 0.890 second using v1.01-cache-2.11-cpan-f0fbb3f571b )