The following patch adds basic IPv6 support to ldirectord.  This allows you
to add virtual & real servers (use brackets), but does not support address
ranges.  I've only successfully tested it using an external checkcommand, I
haven't gotten any of the built-in tests to work yet.  This applies to
Linux-HA-Dev-beta-2.99.1.

Vince

--- ldirectord.in.orig  2008-09-29 03:34:36.000000000 -0700
+++ ldirectord.in       2008-10-21 14:28:45.000000000 -0700
@@ -305,8 +305,8 @@
 Defines a real service by IP-address (or hostname) and port (or
 servicename). If the port is omitted then a 0 will be used, this is
 intended primarily for fwmark services where the port for real servers is
-ignored. Optionally a range of IP addresses (or two hostnames) may be
-given, in which case each IP address in the range will be treated as a real
+ignored. Optionally a range of IPv4 addresses (or two hostnames) may be
+given, in which case each IPv4 address in the range will be treated as a real
 server using the given port. The second argument defines the forwarding
 method, must be B<gate>, B<ipip> or B<masq>.  The thrid argument is
 optional and defines the weight for that real server. If omitted then a
@@ -583,6 +583,11 @@
 
 Default: no separate logging of service checks.
 
+=head1 IPv6
+
+IPv6 addresses specified for virtual and real servers should be enclosed by
+brackets ([3ff3:ffff::abcd]:80).
+
 =head1 FILES
 
 B<@sysconfdir@/ha.d/ldirectord.cf>
@@ -705,6 +710,7 @@
 #use English;
 #use Time::HiRes qw( gettimeofday tv_interval );
 use Socket;
+use Socket6;
 use Sys::Hostname;
 use POSIX qw(setsid :sys_wait_h);
 use Sys::Syslog qw(:DEFAULT setlogsock);
@@ -1112,6 +1118,13 @@
                                $virtual_id = $ip_port = "$1:$2";
                        } elsif ($vattr =~ /^(\d+)/){
                                $virtual_id = $fwm = $1;
+                       } elsif ($vattr =~ /^\[([0-9A-Fa-f:]+)\]:(\d+)/) {
+                               my $v6addr = $1;
+                               my $v6port = $2;
+                               if (!inet_pton(AF_INET6,$v6addr)) {
+                                       &config_error($line,"invalid ipv6 
address for virtual server");
+                               }
+                               $virtual_id = $ip_port = "[$v6addr]:$v6port";
                        } else {
                                &config_error($line, 
                                        "invalid address for virtual server");
@@ -1495,7 +1508,10 @@
 
        if($ip_port){
                $ip_port=&ld_gethostservbyname($ip_port, $vsrv->{protocol});
-               if($ip_port){
+               if ($ip_port =~ /(\[[0-9A-Fa-f:]+\]):(\d+)/) {
+                       $vsrv->{server} = $1;
+                       $vsrv->{port} = $2;
+               } elsif($ip_port){
                        ($vsrv->{server}, $vsrv->{port}) = split /:/, $ip_port;
                }
                else {
@@ -1665,7 +1681,7 @@
 
        for $i (@$rsrv_todo) {
                ($str, $line)[EMAIL PROTECTED];
-               $str =~  
/(\d+\.\d+\.\d+\.\d+|[A-Za-z0-9.-]+)(->(\d+\.\d+\.\d+\.\d+|[A-Za-z0-9.-]+))?(:(\d+|[A-Za-z0-9-]+))?\s+(.*)/
+               $str =~  
/(\d+\.\d+\.\d+\.\d+|[A-Za-z0-9.-]+|\[[0-9A-fa-f:]+\])(->(\d+\.\d+\.\d+\.\d+|[A-Za-z0-9.-]+|\[[0-9A-fa-f:]+\]))?(:(\d+|[A-Za-z0-9-]+))?\s+(.*)/
                        or &config_error($line, 
                                "invalid address for real server" .
                                 " (wrong format)");
@@ -1776,6 +1792,7 @@
        my $new_rsrv;
        my $rsrv;
 
+       if ($ip =~ /:/) { $ip = "[" . $ip . "]"; }
        $new_rsrv = {"server"=>$ip, "port"=>$port};
 
        $flags =~ /(\w+)(.*)/ && ($1 eq "gate" || $1 eq "masq" || $1 eq "ipip")
@@ -2108,16 +2125,16 @@
                if (not defined $line) {
                        last;
                }
-               if ($line =~ 
/^(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\d+)\s+(\w+)\s+persistent\s+(\d+)\s+mask\s+(.*)/)
 {
+               if ($line =~ 
/^(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\[[0-9A-Fa-f:]+\]:\d+|\d+)\s+(\w+)\s+persistent\s+(\d+)\s+mask\s+(.*)/)
 {
                        $real_service = "$2 ".lc($1);
                        $oldsrv{"$real_service"} = {"real"=>{}, 
"scheduler"=>$3, "persistent"=>$4, "netmask"=>$5};
-               } elsif ($line =~ 
/^(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\d+)\s+(\w+)\s+persistent\s+(\d+)/) {
+               } elsif ($line =~ 
/^(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\[[0-9A-Fa-f:]+\]:\d+|\d+)\s+(\w+)\s+persistent\s+(\d+)/)
 {
                        $real_service = "$2 ".lc($1);
                        $oldsrv{"$real_service"} = {"real"=>{}, 
"scheduler"=>$3, "persistent"=>$4};
-               } elsif ($line =~ 
/^(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\d+)\s+(\w+)/) {
+               } elsif ($line =~ 
/^(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\[[0-9A-Fa-f:]+\]:\d+|\d+)\s+(\w+)/) {
                        $real_service = "$2 ".lc($1);
                        $oldsrv{"$real_service"} = {"real"=>{}, 
"scheduler"=>$3};
-               } elsif ($line =~ /^  
->\s+(\d+\.\d+\.\d+\.\d+\:\d+)\s+(\w+)\s+(\d+)/) {
+               } elsif ($line =~ /^  
->\s+(\d+\.\d+\.\d+\.\d+\:\d+|\[[0-9A-Fa-f:]+\]:\d+)\s+(\w+)\s+(\d+)/) {
                        if (not defined( $real_service)) {
                                &ld_debug(2, "Real server read from ipvsadm " .
                                          "doesn't seem to be inside a " .
@@ -4157,6 +4174,11 @@
 {
          my ($alleged_ip)=(@_);
 
+         if ($alleged_ip =~ /:/) {
+               unless(inet_pton(AF_INET6,$alleged_ip)){ return 0; }
+               return(1);
+         }
+
          #If we don't have four, . delimited numbers then we have no hope
          unless($alleged_ip=~m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { return 0; }
 
@@ -4370,17 +4392,24 @@
 sub ld_open_socket
 {
        my ($remote, $port, $protocol) = @_;
-       my ($iaddr, $paddr, $pro, $result);
+       my ($iaddr, $paddr, $pro, $result, $pf);
        local *SOCK;
 
-       $iaddr = inet_aton($remote) || die "no host: $remote";
-       $paddr = sockaddr_in($port, $iaddr);
+       if (inet_pton(AF_INET6,$remote)) {
+           $iaddr = inet_pton(AF_INET6,$remote);
+           $paddr = pack_sockaddr_in6($port, $iaddr);
+           $pf = PF_INET6;
+       } else {
+           $iaddr = inet_aton($remote) || die "no host: $remote";
+           $paddr = sockaddr_in($port, $iaddr);
+           $pf = PF_INET;
+       }
        $pro = getprotobyname($protocol);
        if ($protocol eq "udp") {
-               socket(SOCK, PF_INET, SOCK_DGRAM, $pro) || die "socket: $!";
+           socket(SOCK, $pf, SOCK_DGRAM, $pro) || die "socket: $!";
        }
        else {
-               socket(SOCK, PF_INET, SOCK_STREAM, $pro) || die "socket: $!";
+               socket(SOCK, $pf, SOCK_STREAM, $pro) || die "socket: $!";
        }
        $result = connect(SOCK, $paddr);
        unless ($result) {
@@ -4511,9 +4540,15 @@
 {
        my ($name)=(@_);
 
-       my @host=gethostbyname($name);
-
-       return((@host and defined($host[4]))?inet_ntoa($host[4]):undef);
+       if ($name =~ /\[(.*)\]/) {
+               $name = $1;
+       }
+       my @host = getaddrinfo($name,0);
+       if (!defined($host[3])) {
+               return undef;
+       }
+       my @ret = getnameinfo($host[3], NI_NUMERICHOST | NI_NUMERICSERV);
+       return $ret[0];
 }
 
 
@@ -4557,13 +4592,18 @@
        my $ip;
        my $port;
 
-       $hostserv =~ 
+       if ($hostserv =~ /(\[[0-9A-Fa-f:]+\])(:(\d+|[A-Za-z0-9-]+))?/) {
+               $ip=$1;
+               $port=$3;
+       } else {
+               $hostserv =~ 
                /(\d+\.\d+\.\d+\.\d+|[A-Za-z0-9.-]+)(:(\d+|[A-Za-z0-9-]+))?/ 
                or return(undef);
-       $ip=$1;
-       $port=$3;
+               $ip=$1;
+               $port=$3;
 
-       $ip=&ld_gethostbyname($ip)  or return(undef);
+               $ip=&ld_gethostbyname($ip)  or return(undef);
+       }
 
        if(defined($port)){
            $port=&ld_getservbyname($port, $protocol);
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/

Reply via email to