diff --git a/man/mosh.1 b/man/mosh.1 index 3b6b3a1..cce87da 100644 --- a/man/mosh.1 +++ b/man/mosh.1 @@ -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 diff --git a/scripts/mosh.pl b/scripts/mosh.pl index f60ebce..dc735b1 100755 --- a/scripts/mosh.pl +++ b/scripts/mosh.pl @@ -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 ) {