diff --git a/ddclient b/ddclient index 62ff478..86a32f3 100755 --- a/ddclient +++ b/ddclient @@ -2005,6 +2005,7 @@ sub geturl { my $url = $params->{url} // ''; my $login = $params->{login} // ''; my $password = $params->{password} // ''; + my $ipversion = $params->{ipversion} // ''; my $headers = $params->{headers} // ''; my $method = $params->{method} // 'GET'; my $data = $params->{data} // ''; @@ -2027,7 +2028,6 @@ sub geturl { if ($force_ssl || ($globals{'ssl'} and (caller(1))[3] ne 'main::get_ip')) { $use_ssl = 1; $default_port = 443; - load_ssl_support; } else { $use_ssl = 0; $default_port = 80; @@ -2036,6 +2036,7 @@ sub geturl { debug("protocol = %s", $use_ssl ? "https" : "http"); debug("server = %s", $server); debug("url = %s", $url); + debug("ip ver = %s", $ipversion); ## determine peer and port to use. $peer = $proxy || $server; @@ -2045,9 +2046,6 @@ sub geturl { $port = $default_port unless $port =~ /^\d+$/; $peer =~ s%:.*$%%; - my $to = sprintf "%s%s", $server, $proxy ? " via proxy $peer:$port" : ""; - verbose("CONNECT:", "%s", $to); - $request = "$method "; if (!$use_ssl) { $request .= "http://$server" if $proxy; @@ -2073,57 +2071,61 @@ sub geturl { $request .= $data; $rq .= $data; - - $0 = sprintf("%s - connecting to %s port %s", $program, $peer, $port); - if (!opt('exec')) { - debug("skipped network connection"); - verbose("SENDING:", "%s", $request); - } elsif ($use_ssl) { - $sd = IO::Socket::SSL->new( - PeerAddr => $peer, - PeerPort => $port, - Proto => 'tcp', - MultiHomed => 1, - Timeout => opt('timeout'), - ); - defined $sd or warning("cannot connect to %s:%s socket: %s %s", $peer, $port, $@, IO::Socket::SSL::errstr()); - } elsif ($globals{'ipv6'}) { + my $socket_class = 'IO::Socket::INET'; + if ($use_ssl) { + # IO::Socket::SSL will load IPv6 support if available on the system. + load_ssl_support; + $socket_class = 'IO::Socket::SSL'; + } elsif ($globals{'ipv6'} || $ipversion eq '6') { load_ipv6_support; - $sd = IO::Socket::INET6->new( - PeerAddr => $peer, - PeerPort => $port, - Proto => 'tcp', - MultiHomed => 1, - Timeout => opt('timeout'), - ); - defined $sd or warning("cannot connect to %s:%s socket: %s", $peer, $port, $@); - } else { - $sd = IO::Socket::INET->new( - PeerAddr => $peer, - PeerPort => $port, - Proto => 'tcp', - MultiHomed => 1, - Timeout => opt('timeout'), - ); - defined $sd or warning("cannot connect to %s:%s socket: %s", $peer, $port, $@); + $socket_class = 'IO::Socket::INET6'; + } + my %socket_args = ( + PeerAddr => $peer, + PeerPort => $port, + Proto => 'tcp', + MultiHomed => 1, + Timeout => opt('timeout'), + ); + if ($ipversion eq '4') { + $socket_args{Domain} = PF_INET; + $socket_args{Family} = AF_INET; + } elsif ($ipversion eq '6') { + $socket_args{Domain} = PF_INET6; + $socket_args{Family} = AF_INET6; + } elsif ($ipversion ne '') { + fatal("geturl passed unsupported 'ipversion' value %s", $ipversion); } + my $ipv = $ipversion eq '' ? '' : sprintf(" (IPv%s)", $ipversion); + my $peer_port_ipv = sprintf("%s:%s%s", $peer, $port, $ipv); + my $to = sprintf("%s%s%s", $server, $proxy ? " via proxy $peer:$port" : "", $ipv); + verbose("CONNECT:", "%s", $to); + $0 = sprintf("%s - connecting to %s", $program, $peer_port_ipv); + if (opt('exec')) { + $sd = $socket_class->new(%socket_args); + defined($sd) or warning("cannot connect to %s socket: %s%s", $peer_port_ipv, $@, + $use_ssl ? ' ' . IO::Socket::SSL::errstr() : ''); + } else { + debug("skipped network connection"); + verbose("SENDING:", "%s", $request); + } if (defined $sd) { ## send the request to the http server verbose("CONNECTED: ", $use_ssl ? 'using SSL' : 'using HTTP'); verbose("SENDING:", "%s", $request); - $0 = sprintf("%s - sending to %s port %s", $program, $peer, $port); + $0 = sprintf("%s - sending to %s", $program, $peer_port_ipv); my $result = syswrite $sd, $rq; if ($result != length($rq)) { - warning("cannot send to %s:%s (%s).", $peer, $port, $!); + warning("cannot send to %s (%s).", $peer_port_ipv, $!); } else { - $0 = sprintf("%s - reading from %s port %s", $program, $peer, $port); + $0 = sprintf("%s - reading from %s", $program, $peer_port_ipv); eval { local $SIG{'ALRM'} = sub { die "timeout"; }; alarm(opt('timeout')) if opt('timeout') > 0; while ($_ = <$sd>) { - $0 = sprintf("%s - read from %s port %s", $program, $peer, $port); + $0 = sprintf("%s - read from %s", $program, $peer_port_ipv); verbose("RECEIVE:", "%s", define($_, "")); $reply .= $_ if defined $_; } @@ -2140,7 +2142,7 @@ sub geturl { $reply = '' if !defined $reply; } } - $0 = sprintf("%s - closed %s port %s", $program, $peer, $port); + $0 = sprintf("%s - closed %s", $program, $peer_port_ipv); ## during testing simulate reading the URL if (opt('test')) {