AMPR-Rip44
view release on metacpan or search on metacpan
# delete a route from the kernel's table
sub route_delete($)
{
my($rkey) = @_;
# This is ugly and slow - we fork /sbin/ip twice for every route change.
# Should talk to the netlink device instead, but this is easier to
# do right now, and good enough for this little routing table.
my($out, $cmd);
$cmd = "LANG=C $routebin route del $rkey";
$out = `$cmd 2>&1`;
if ($?) {
if ($verbose > 1 || $out !~ /No such process/) {
warn "route del failed: '$cmd': $out\n";
}
}
}
# expire old routes
sub expire_routes()
{
warn "expiring old routes\n" if ($verbose);
my $exp_t = time() - $route_ttl;
my $now = time();
foreach my $rkey (keys %current_routes) {
if ($current_routes{$rkey}->{'t'} < $exp_t) {
# expire route
warn "route $rkey has expired, deleting\n" if ($verbose);
route_delete($rkey);
delete $current_routes{$rkey};
} elsif ($current_routes{$rkey}->{'t'} > $now) {
# clock has jumped backwards, the time is in
# the future - set 't' to $now so that the route
# will be expired eventually
$current_routes{$rkey}->{'t'} = $now;
}
}
}
# Consider adding a route in the routing table
sub consider_route($$$$)
{
my($net, $mask, $nexthop, $rtag) = @_;
my $rkey = "$net/$mask";
if (defined $current_routes{$rkey}
&& $current_routes{$rkey}->{'nh'} eq $nexthop
&& $current_routes{$rkey}->{'rtag'} eq $rtag) {
# ok, current route is fine
warn "route $rkey is installed and current\n" if ($verbose > 1);
$current_routes{$rkey}->{'t'} = time();
return;
}
warn "route $rkey updated: via $nexthop rtag $rtag\n" if ($verbose > 1);
$current_routes{$rkey} = {
'nh' => $nexthop,
'rtag' => $rtag,
't' => time()
};
# now go and update the routing table
route_delete($rkey);
my($out, $cmd);
$cmd = "LANG=C $routebin route add $rkey via $nexthop dev $tunnel_if window $tcp_window onlink";
$out = `$cmd 2>&1\n`;
if ($?) {
warn "route add failed: '$cmd': $out\n";
}
}
# process a RIPv2 password authentication entry
sub process_rip_auth_entry($)
{
my($entry) = @_;
my $e_af = unpack('n', substr($entry, 0, 2));
if ($e_af != 0xFFFF) {
warn "RIPv2 first message does not contain auth password: ignoring\n" if ($verbose);
return 0;
}
my $e_type = unpack('n', substr($entry, 2, 2));
if ($e_type != RIP_AUTH_PASSWD) {
warn "ignoring unsupported rip auth type $e_type\n" if ($verbose);
return 0;
}
my $e_passwd = substr($entry, 4, 16);
$e_passwd =~ s/\0*$//; # it's null-padded in the end
if (!defined $rip_passwd) {
warn "RIPv2 packet contains password $e_passwd but we require none\n" if ($verbose);
return 0;
}
if ($e_passwd ne $rip_passwd) {
warn "RIPv2 invalid password $e_passwd\n" if ($verbose);
return 0;
}
return 1;
}
# validate a route entry, make sure we can rather safely
# insert it in the routing table
sub validate_route($$$$$)
{
my($e_net_i, $e_net_s, $e_netmask, $e_netmask_s, $e_nexthop_s) = @_;
# netmask is correct and not too wide
my $prefix_len = mask2prefix($e_netmask);
( run in 0.712 second using v1.01-cache-2.11-cpan-bbe5e583499 )