httpd-test-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Philippe M. Chiasson" <go...@cpan.org>
Subject Re: [Patch] Better IPv6 detection and configuration
Date Tue, 30 Mar 2004 00:50:20 GMT
On Mon, 2004-03-29 at 16:21 -0800, Stas Bekman wrote:
> Philippe M. Chiasson wrote:
> > On Mon, 2004-03-29 at 15:43 -0800, Stas Bekman wrote:
> > 
> >>Philippe M. Chiasson wrote:
> >>
> >>>After a bit of poking around different flavors of IPv6 systems, I've
> >>>encountered a few situations where Apache::Test ends up configuring
> >>>httpd in a way that can't be tested.
> >>>
> >>>This typically only happens on a system that has IPv4-mapped IPv6
> >>>addresses disabled, i.e. OpenBSD. If the hostname that is picked
> >>>to form the Listen directives happens to have both an IPv4 and an
> >>>IPv6 address, i.e localhot on OpenBSD, the server will start but will
> >>>only be listening on an IPv6 address.
> >>>
> >>>And since LWP doesn't do requests over IPv6, all tests will fail.
> >>>
> >>>The following patch attempts to do handle all this by doing one of a few
> >>>many things.
> >>
> >>gozer++
> >>
> >>
> >>>If the server has ipv4-mapped addresses, Listen to *:port, forcing the
> >>>use of ipv4-mapped addresses and insuring that the server will be
> >>>available over it's ipv4 address.
> >>>
> >>>Otherwise try to use Socket6 to see if the hostname is both v4 and v6
> >>>and Listen to *:port as well. Without Socket6 (not part of the Perl
> >>>core), just warn the user about possible problems he/she will run into
> >>>if the selected hostname happens to be ipv6.
> >>
> >>[...]
> >>
> >>>+        else {
> >>>+            if (eval { require Socket6 }) {
> >>>+                if (Socket6::gethostbyname2($name, Socket6::AF_INET6()))
{
> >>>+                    $self->{vars}{listen_addr} = '*';
> >>>+                }
> >>>+            }
> >>>+            else {
> >>>+                warning "Socket6 not installed";
> >>>+                warning "Test might fail if your hostname: '$name' has an
IPv6 address";
> >>
> >>I think we should die here:
> >>
> >>   error << EOI;
> >>Your system is configured to run both ipv6 and ipv4, but the right interface

> >>can't be selected.
> >>Please install the perl CPAN module Socket6 and re-run the last command.
> >>EOI
> >>   die "\n";
> > 
> > 
> > That's something I considered, but I figured it was better to be gentle
> > and just warn people that things might not work. I am perfectly fine
> > with die instead.
> > 
> > 
> >>and if Socket6 builds everywhere, and including older perls, we should include

> >>it in Apache-Test's %PREREQ_PM.
> > 
> > 
> > Well, I built it successfully with a combination of 5.8.x and 5.6.x on
> > linux, freebsd and openbsd. I am not sure if it builds on systems
> > without ipv4 support though.
> 
> OK, so let's keep it warning/out of prereq for now while we polish it.

Sure!

> but please replace s/warning/error/ so it'll more prominent. thanks.

Patch following:

Index: Apache-Test/lib/Apache/TestConfig.pm
===================================================================
RCS file: /home/cvs/httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfig.pm,v
retrieving revision 1.213
diff -u -I$Id -r1.213 TestConfig.pm
--- Apache-Test/lib/Apache/TestConfig.pm	4 Mar 2004 05:51:31 -0000	1.213
+++ Apache-Test/lib/Apache/TestConfig.pm	30 Mar 2004 00:48:58 -0000
@@ -63,6 +63,7 @@
    documentroot    => 'DocumentRoot (default is $ServerRoot/htdocs',
    port            => 'Port [port_number|select] (default ' . DEFAULT_PORT . ')',
    servername      => 'ServerName (default is localhost)',
+   listen_addr     => 'The address to use in Listen directives',
    user            => 'User to run test server as (default is $USER)',
    group           => 'Group to run test server as (default is $GROUP)',
    bindir          => 'Apache bin/ dir (default is apxs -q BINDIR)',
@@ -272,7 +273,7 @@
     $vars->{servername}   ||= $self->default_servername;
     $vars->{port}           = $self->select_first_port;
     $vars->{remote_addr}  ||= $self->our_remote_addr;
-
+    $vars->{listen_addr}  ||= $self->default_localhost;
     $vars->{user}         ||= $self->default_user;
     $vars->{group}        ||= $self->default_group;
     $vars->{serveradmin}  ||= $self->default_serveradmin;
@@ -286,6 +287,8 @@
     $self->inherit_config; #see TestConfigParse.pm
     $self->configure_httpd_eapi; #must come after inherit_config
 
+    $self->check_ipv6;
+
     $self->default_module(cgi    => [qw(mod_cgi mod_cgid)]);
     $self->default_module(thread => [qw(worker threaded)]);
     $self->default_module(ssl    => [qw(mod_ssl)]);
@@ -637,6 +640,45 @@
     $remote_addr ||= Socket::inet_ntoa($iaddr);
 }
 
+my  $apr_ipv6;
+sub apr_has_ipv6 {
+    my $self = shift;
+    return $apr_ipv6 if defined $apr_ipv6;
+    foreach my $key (keys %{$self->{httpd_defines}}) {
+        return $apr_ipv6 = $key if $key =~ /^APR_HAVE_IPV6/;
+    }
+}
+
+sub apr_has_ipv4_mapped {
+    my $self = shift;
+    return $self->apr_has_ipv6 =~ /IPv4-mapped addresses enabled/;
+}
+
+sub check_ipv6 {
+    my $self = shift;
+    
+    return if $self->{vars}{listen_addr} ne $self->default_localhost;
+    
+    my $name = $self->{vars}{servername};
+
+    if ($self->apr_has_ipv6) {
+        if ($self->apr_has_ipv4_mapped) {
+            $self->{vars}{listen_addr} = '*';
+        }
+        else {
+            if (eval { require Socket6 }) {
+                if (Socket6::gethostbyname2($name, Socket6::AF_INET6())) {
+                    $self->{vars}{listen_addr} = '*';
+                }
+            }
+            else {
+                error "Socket6 not installed";
+                error "Test might fail if your hostname: '$name' has an IPv6 address";
+            }
+        }
+    }
+}
+
 sub default_loopback {
     '127.0.0.1';
 }
@@ -1017,7 +1059,7 @@
     my @out_config = ();
     if ($self->{vhosts}->{$module}->{namebased} < 2) {
         #extra config that should go *outside* the <VirtualHost ...>
-        @out_config = ([Listen => $vars->{servername} . ':' . $port]);
+        @out_config = ([Listen => $vars->{listen_addr} . ':' . $port]);
 
         if ($self->{vhosts}->{$module}->{namebased}) {
             push @out_config => [NameVirtualHost => "*:$port"];
@@ -1785,7 +1827,7 @@
 
 
 __DATA__
-Listen     @ServerName@:@Port@
+Listen     @Listen_Addr@:@Port@
 
 ServerRoot   "@ServerRoot@"
 DocumentRoot "@DocumentRoot@"
Index: Apache-Test/lib/Apache/TestConfigPerl.pm
===================================================================
RCS file: /home/cvs/httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfigPerl.pm,v
retrieving revision 1.85
diff -u -I$Id -r1.85 TestConfigPerl.pm
--- Apache-Test/lib/Apache/TestConfigPerl.pm	16 Mar 2004 03:10:32 -0000	1.85
+++ Apache-Test/lib/Apache/TestConfigPerl.pm	30 Mar 2004 00:48:58 -0000
@@ -222,7 +222,7 @@
     my($self, $module, $args) = @_;
     my $port = $self->new_vhost($module);
     my $vars = $self->{vars};
-    $self->postamble(Listen => $vars->{servername} . ':' . $port);
+    $self->postamble(Listen => $vars->{listen_addr} . ':' . $port);
 }
 
 my %add_hook_config = (


> -- 
> __________________________________________________________________
> Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
> http://stason.org/     mod_perl Guide ---> http://perl.apache.org
> mailto:stas@stason.org http://use.perl.org http://apacheweek.com
> http://modperlbook.org http://apache.org   http://ticketmaster.com

Mime
View raw message