Add options to prefer v4 or v6 on connect; make prefer-inet the default.

Resolves #764, mostly.
This commit is contained in:
John Hood
2016-06-10 11:58:29 -04:00
parent 1b2ddc2e81
commit af8ddd090e
2 changed files with 32 additions and 16 deletions
+20 -11
View File
@@ -143,23 +143,32 @@ Only use IPv4 for the SSH connection and Mosh session.
.TP
.B \-\-family=inet6
Only use IPv6 for the SSH connection and Mosh session. This and the
following two dual-stack modes require Perl's IO::Socket::IP or
IO::Socket::INET6 modules.
.TP
.B \-\-family=all
Choose an address from all available IPv4 or IPv6 address, even for
dual-stack hosts. This is the most convenient option, but requires
dual-stack connectivity when roaming with dual-stack servers. This is
the default.
following modes require Perl's IO::Socket::IP or IO::Socket::INET6
modules.
.TP
.B \-\-family=auto
Autodetect IPv4 or IPv6 for hosts that only have addresses
in a single family. Hosts with both IPv4 and IPv6 addresses will
raise an error, and require re-invocation of \fBmosh\fP with another
.B \-\-family
option.
\fB\-\-family\fP option.
.TP
.B \-\-family=all
Choose an address from all available IPv4 or IPv6 address, even for
dual-stack hosts. This is the most convenient option, but requires
dual-stack connectivity, and Mosh 1.2.5 or later on the server, when
roaming with dual-stack servers.
.TP
.B \-\-family=prefer-inet
Similar to \fB\-\-family=all\fP, but attempt connects to the IPv4
addresses first. This is the default.
.TP
.B \-\-family=prefer-inet6
Similar to \fB\-\-family=all\fP, but attempt connects to the IPv6
addresses first.
.TP
.B \-4
+12 -5
View File
@@ -63,7 +63,7 @@ my $bind_ip = undef;
my $use_remote_ip = 'proxy';
my $family = 'all';
my $family = 'prefer-inet';
my $port_request = undef;
my @ssh = ('ssh');
@@ -91,8 +91,10 @@ qq{Usage: $0 [options] [--] [user@]host [command...]
-4 --family=inet use IPv4 only
-6 --family=inet6 use IPv6 only
--family=auto autodetect network type for single-family hosts
--family=all try all network types [default]
--family=auto autodetect network type for single-family hosts only
--family=all try all network types
--family=prefer-inet use all network types, but try IPv4 first [default]
--family=prefer-inet6 use all network types, but try IPv6 first
-p PORT[:PORT2]
--port=PORT[:PORT2] server-side UDP port or range
--bind-server={ssh|any|IP} ask the server to reply from an IP address
@@ -453,7 +455,7 @@ sub resolvename {
my $af;
# If the user selected a specific family, parse it.
if ( defined( $family ) && ( $family ne "auto" && $family ne "all" )) {
if ( defined( $family ) && ( $family eq 'inet' || $family eq 'inet6' )) {
# Choose an address family, or cause pain.
my $afstr = 'AF_' . uc( $family );
$af = eval { IO::Socket->$afstr } or die "$0: Invalid family $family\n";
@@ -480,9 +482,14 @@ sub resolvename {
@res = @newres;
}
# If v4 or v6 was specified, reduce the host list.
if ( defined( $af )) {
# If v4 or v6 was specified, reduce the host list.
@res = grep {$_->{family} == $af} @res;
} elsif ( $family =~ /^prefer-/ ) {
# If prefer-* was specified, reorder the host list to put that family first.
my $prefer_afstr = 'AF_' . uc( ($family =~ /prefer-(.*)/)[0] );
my $prefer_af = eval { IO::Socket->$prefer_afstr } or die "$0: Invalid preferred family $family\n";
@res = (grep({$_->{family} == $prefer_af} @res), grep({$_->{family} != $prefer_af} @res));
} elsif ( $family ne 'all' ) {
# If v4/v6/all were not specified, verify that this host only has one address family available.
for my $ai ( @res ) {