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/