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);
 }

Reply via email to