On Tuesday 05 September 2006 12:11, Mike Williams wrote:
> On Tuesday 05 September 2006 00:18, Ask Bjørn Hansen wrote:
> > Could we call the other relayclients file something else than
> > relayclients2?
> >
> > (Or just not use two files...)
>
> Hmm...
> How about itterating over the array from qp->config, pushing lines into one
> of two other arrays depending if it's got a prefix or not, then doing the
> "binary compare" and "strip off another 8 bits" methods on those?
> ip_splitprefix won't return a prefix if it wasn't supplied one, although it
> will return an illegal one...
@crelay_clients for comparing, @srelay_clients for stripping
--
Mike Williams
Index: config/relayclients
===================================================================
--- config/relayclients (revision 658)
+++ config/relayclients (working copy)
@@ -1,4 +1,17 @@
# Format is IP, or IP part with trailing dot
# e.g. "127.0.0.1", or "192.168."
+# e.g. "2001:618:400:fedf:20f:3dff:feae:74c1", or "2001:618:400:"
+# and/or CIDR notation
+# legal 2001:618:400:fedf::/64
+# illegal 2001:618:400:fedf::/48 !
+# legal 2001:618:400::/48
+# legal 192.168.0.0/24
+# illegal 192.168.30.0/16 !
+# legal 192.168.30.0/24
+
127.0.0.1
192.168.
+2001:618:400:fedf::/64
+2001:618:400:
+192.168.0.0/24
+192.168.30.0/24
Index: plugins/check_relay
===================================================================
--- plugins/check_relay (revision 658)
+++ plugins/check_relay (working copy)
@@ -2,25 +2,69 @@
# $ENV{RELAYCLIENT} to see if relaying is allowed.
#
+use Net::IP qw(:PROC);
+
sub hook_connect {
my ($self, $transaction) = @_;
my $connection = $self->qp->connection;
# Check if this IP is allowed to relay
+ my $client_ip = $self->qp->connection->remote_ip;
+
+ # @crelay... for comparing, @srelay... for stripping
+ my (@crelay_clients, @srelay_clients);
+
my @relay_clients = $self->qp->config("relayclients");
- my $more_relay_clients = $self->qp->config("morerelayclients", "map");
- my %relay_clients = map { $_ => 1 } @relay_clients;
- my $client_ip = $self->qp->connection->remote_ip;
- while ($client_ip) {
- if (exists($ENV{RELAYCLIENT}) or
- exists($relay_clients{$client_ip}) or
- exists($more_relay_clients->{$client_ip}))
- {
- $connection->relay_client(1);
- last;
+ for (@relay_clients) {
+ my ($range_ip, $range_prefix) = ip_splitprefix($_);
+ if($range_prefix){
+ # has a prefix, so due for comparing
+ push @crelay_clients, $_;
}
- $client_ip =~ s/(\d|\w|::)+(:|\.)?$//; # strip off another 8 bits
+ else {
+ # has no prefix, so due for splitting
+ push @srelay_clients, $_;
+ }
}
+ if (@crelay_clients){
+ my ($range_ip, $range_prefix, $rversion, $begin, $end, $bin_client_ip);
+ my $cversion = ip_get_version($client_ip);
+ for (@crelay_clients) {
+ # Get just the IP from the CIDR range, to get the IP version, so we can
+ # get the start and end of the range
+ ($range_ip, $range_prefix) = ip_splitprefix($_);
+ $rversion = ip_get_version($range_ip);
+ ($begin, $end) = ip_normalize($_, $rversion);
+
+ # expand the client address (zero pad it) before converting to binary
+ $bin_client_ip = ip_iptobin(ip_expand_address($client_ip, $cversion), $cversion);
+
+ if (ip_bincomp($bin_client_ip, 'gt', ip_iptobin($begin, $rversion))
+ && ip_bincomp($bin_client_ip, 'lt', ip_iptobin($end, $rversion)))
+ {
+ $connection->relay_client(1);
+ last;
+ }
+ }
+ }
+
+ # If relay_client is already set, no point checking again
+ if (@srelay_clients && !$connection->relay_client) {
+ my $more_relay_clients = $self->qp->config("morerelayclients", "map");
+ my %srelay_clients = map { $_ => 1 } @srelay_clients;
+ $client_ip =~ s/::/:/;
+
+ while ($client_ip) {
+ if (exists($ENV{RELAYCLIENT}) or
+ exists($srelay_clients{$client_ip}) or
+ exists($more_relay_clients->{$client_ip}))
+ {
+ $connection->relay_client(1);
+ last;
+ }
+ $client_ip =~ s/(\d|\w)+(:|\.)?$//; # strip off another 8 bits
+ }
+ }
return (DECLINED);
}