AMPR-Rip44
view release on metacpan or search on metacpan
# 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);
if ($prefix_len < 0) {
warn "invalid netmask: $e_netmask_s\n" if ($verbose);
return (0, 'invalid netmask');
}
if ($prefix_len < $minimum_prefix_len) {
warn "$e_net_s/$e_netmask_s => $e_nexthop_s blocked, prefix too short\n";
return (0, 'prefix length too short');
}
# the network-netmask pair makes sense: network & netmask == network
if (($e_net_i & $e_netmask) != $e_net_i) {
#print "e_net '$e_net_i' e_netmask '$e_netmask' ANDs to " . ($e_net_i & $e_netmask) . "\n";
warn "$e_net_s/$e_netmask_s => $e_nexthop_s blocked, subnet-netmask pair does not make sense\n" if ($verbose);
return (0, 'invalid subnet-netmask pair');
}
# network is in 44/8
if ($e_net_s !~ /$net_44_regexp/) {
warn "$e_net_s/$e_netmask_s => $e_nexthop_s blocked, non-amprnet address\n" if ($verbose);
return (0, 'net not in 44/8');
}
# nexthop address is not in 44/8
if ($e_nexthop_s =~ /$net_44_regexp/) {
warn "$e_net_s/$e_netmask_s => $e_nexthop_s blocked, nexthop is within amprnet\n" if ($verbose);
return (0, 'nexthop is in 44/8');
}
# nexthop address does not point to self
if (defined $my_addresses{$e_nexthop_s}) {
warn "$e_net_s/$e_netmask_s => $e_nexthop_s blocked, local gw\n" if ($verbose);
return (0, 'local gw');
}
return (1, 'ok');
}
# process a RIPv2 route entry
sub process_rip_route_entry($)
{
my($entry) = @_;
my $e_af = unpack('n', substr($entry, 0, 2));
my $e_rtag = unpack('n', substr($entry, 2, 2));
if ($e_af == 0xFFFF) {
process_rip_auth_entry($entry);
return -1;
}
if ($e_af != AF_INET) {
warn "$me: RIPv2 entry has unsupported AF $e_af\n";
return 0;
}
my $e_net = substr($entry, 4, 4);
my $e_net_i = unpack('N', $e_net);
my $e_netmask = substr($entry, 8, 4);
my $e_netmask_i = unpack('N', $e_netmask);
my $e_nexthop = substr($entry, 12, 4);
my $e_metric = unpack('N', substr($entry, 16, 4));
my $e_net_s = inet_ntoa($e_net);
my $e_netmask_s = inet_ntoa($e_netmask);
my $e_nexthop_s = inet_ntoa($e_nexthop);
# Validate the route
my($result, $reason) = validate_route($e_net_i, $e_net_s, $e_netmask_i, $e_netmask_s, $e_nexthop_s);
if (!$result) {
warn "entry ignored ($reason): af $e_af rtag $e_rtag $e_net_s/$e_netmask_s via $e_nexthop_s metric $e_metric\n" if ($verbose);
return 0;
}
warn "entry: af $e_af rtag $e_rtag $e_net_s/$e_netmask_s via $e_nexthop_s metric $e_metric\n" if ($verbose > 1);
# Ok, we have a valid route, consider adding it in the kernel's routing table
consider_route($e_net_s, $e_netmask_s, $e_nexthop_s, $e_rtag);
return 1;
}
# process a RIP message
sub process_msg($$$)
{
my($addr_s, $perr_port, $msg) = @_;
# validate packet's length
if (length($msg) < RIP_HDR_LEN + RIP_ENTRY_LEN) {
warn "$me: ignored too short packet from $addr_s: " . length($msg) . "\n";
return -1;
( run in 1.139 second using v1.01-cache-2.11-cpan-d06a3f9ecfd )