AMPR-Rip44

 view release on metacpan or  search on metacpan

bin/rip44d  view on Meta::CPAN

sub fill_local_ifs()
{
	my $s = `$ifconfig -a`;
	
	while ($s =~ s/inet addr:(\d+\.\d+\.\d+\.\d+)//) {
		warn "found local address: $1\n" if ($verbose);
		$my_addresses{$1} = 1;
	}
}

# Convert a netmask (in integer form) to the corresponding prefix length,
# and validate it too. This is a bit ugly, optimizations are welcome.

sub mask2prefix($)
{
	my($mask) = @_; # integer
	
	# convert to a string of 1's and 0's, like this (/25):
	# 11111111111111111111111110000000
	my($bits) = unpack("B32", pack('N', $mask));
	
	# There should be a continuous row of 1's in the
	# beginning, and a continuous row of 0's in the end.
	# Regexp is our hammer, again.
	return -1 if ($bits !~ /^(1*)(0*)$/);
	
	# The amount of 1's in the beginning is the prefix length.
	return length($1);
}

# 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

bin/rip44d  view on Meta::CPAN

	
	# 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

bin/rip44d  view on Meta::CPAN

	
	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;
	}
	
	if (length($msg) > RIP_HDR_LEN + RIP_ENTRY_LEN*25) {
		warn "$me: ignored too long packet from $addr_s: " . length($msg) . "\n";
		return -1;
	}
	
	# packet's length must be divisible by the length of an entry
	if ((length($msg) - RIP_HDR_LEN) % RIP_ENTRY_LEN != 0) {
		warn "$me: ignored invalid length packet from $addr_s: " . length($msg) . "\n";
		return -1;
	}
	
	# validate RIP packet header
	my $hdr = substr($msg, 0, 4);
	my $entries = substr($msg, 4);
	
	my($rip_command, $rip_version, $zero1, $zero2) = unpack('C*', $hdr);
	if ($rip_command != RIP_CMD_RESPONSE) {
		warn "$me: ignored non-response RIP packet from $addr_s\n";

bin/rip44d  view on Meta::CPAN

	my $init_msg = 0;
	
	# if password auth is required, require it!
	if (defined $rip_passwd) {
		return -1 if (!process_rip_auth_entry(substr($entries, 0, RIP_ENTRY_LEN)));
		$init_msg += RIP_ENTRY_LEN;
	}
	
	# 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;
}

#

bin/rip44d  view on Meta::CPAN

	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;

lib/AMPR/Rip44.pm  view on Meta::CPAN

Figure out local interface IP addresses so that routes to them can be ignored

=cut

sub fill_local_ifs() {

}

=head2 mask2prefix

Convert a netmask (in integer form) to the corresponding prefix length,
and validate it too. This is a bit ugly, optimizations are welcome.

=cut

sub mask2prefix ($) {
	my($mask) = @_; # integer

}




( run in 0.595 second using v1.01-cache-2.11-cpan-65fba6d93b7 )