Support port range as -p/--port PORT[:HIGHPORT].
Extend mosh and mosh-server to support parsing a high port from the desired_port argument. The first (low) port must not be greater than the second (high) port. If only one value is provided, behaviour is as before; bind to one port. Also tweak the formatting in mosh-server(1) synopsis to be consistent. This resolves mosh issue # 296. Signed-off-by: Luke Mewburn <luke@mewburn.net>
This commit is contained in:
committed by
Keith Winstein
parent
b99da057bb
commit
141ec239da
+6
-6
@@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.TH MOSH 1 "February 2012"
|
.TH MOSH 1 "October 2012"
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
.\"
|
.\"
|
||||||
.\" Some roff macros, for reference:
|
.\" Some roff macros, for reference:
|
||||||
@@ -22,9 +22,9 @@ mosh-server \- server-side helper for mosh
|
|||||||
new
|
new
|
||||||
[\-s]
|
[\-s]
|
||||||
[\-v]
|
[\-v]
|
||||||
[\-i IP]
|
[\-i \fIIP\fP]
|
||||||
[\-p port]
|
[\-p \fIPORT\fP[:\fIPORT2\fP]]
|
||||||
[\-c colors]
|
[\-c \fICOLORS\fP]
|
||||||
[\-\- command...]
|
[\-\- command...]
|
||||||
.br
|
.br
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@@ -69,8 +69,8 @@ Print some debugging information even after detaching.
|
|||||||
IP address of the local interface to bind (for multihomed hosts)
|
IP address of the local interface to bind (for multihomed hosts)
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-p \fIPORT\fP
|
.B \-p \fIPORT\fP[:\fIPORT2\fP]
|
||||||
UDP port number to bind
|
UDP port number or port-range to bind
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-c \fICOLORS\fP
|
.B \-c \fICOLORS\fP
|
||||||
|
|||||||
+4
-3
@@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.TH MOSH 1 "February 2012"
|
.TH MOSH 1 "October 2012"
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
.\"
|
.\"
|
||||||
.\" Some roff macros, for reference:
|
.\" Some roff macros, for reference:
|
||||||
@@ -121,8 +121,9 @@ Synonym for \-\-predict=always
|
|||||||
Synonym for \-\-predict=never
|
Synonym for \-\-predict=never
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-p \fINUM\fP, \-\-port=\fINUM\fP
|
.B \-p \fIPORT\fP[:\fIPORT2\fP], \-\-port=\fIPORT\fP[:\fIPORT2\fP]
|
||||||
Use a particular server-side UDP port, for example, if this is the
|
Use a particular server-side UDP port or port range,
|
||||||
|
for example, if this is the
|
||||||
only port that is forwarded through a firewall to the
|
only port that is forwarded through a firewall to the
|
||||||
server. Otherwise, \fBmosh\fP will choose a port between 60000 and
|
server. Otherwise, \fBmosh\fP will choose a port between 60000 and
|
||||||
61000.
|
61000.
|
||||||
|
|||||||
+18
-8
@@ -66,7 +66,8 @@ qq{Usage: $0 [options] [--] [user@]host [command...]
|
|||||||
-n --predict=never never use local echo
|
-n --predict=never never use local echo
|
||||||
--predict=experimental aggressively echo even when incorrect
|
--predict=experimental aggressively echo even when incorrect
|
||||||
|
|
||||||
-p NUM --port=NUM server-side UDP port
|
-p PORT[:PORT2]
|
||||||
|
--port=PORT[:PORT2] server-side UDP port or range
|
||||||
|
|
||||||
--ssh=COMMAND ssh command to run when setting up session
|
--ssh=COMMAND ssh command to run when setting up session
|
||||||
(example: "ssh -p 2222")
|
(example: "ssh -p 2222")
|
||||||
@@ -99,10 +100,10 @@ sub predict_check {
|
|||||||
GetOptions( 'client=s' => \$client,
|
GetOptions( 'client=s' => \$client,
|
||||||
'server=s' => \$server,
|
'server=s' => \$server,
|
||||||
'predict=s' => \$predict,
|
'predict=s' => \$predict,
|
||||||
'port=i' => \$port_request,
|
'port=s' => \$port_request,
|
||||||
'a' => sub { $predict = 'always' },
|
'a' => sub { $predict = 'always' },
|
||||||
'n' => sub { $predict = 'never' },
|
'n' => sub { $predict = 'never' },
|
||||||
'p=i' => \$port_request,
|
'p=s' => \$port_request,
|
||||||
'ssh=s' => \$ssh,
|
'ssh=s' => \$ssh,
|
||||||
'help' => \$help,
|
'help' => \$help,
|
||||||
'version' => \$version,
|
'version' => \$version,
|
||||||
@@ -122,12 +123,21 @@ if ( defined $predict ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( defined $port_request ) {
|
if ( defined $port_request ) {
|
||||||
if ( $port_request =~ m{^[0-9]+$}
|
if ( $port_request =~ m{^(?<low>\d+)(:(?<high>\d+))?$} ) {
|
||||||
and $port_request >= 0
|
# good port or port-range
|
||||||
and $port_request <= 65535 ) {
|
if ( $+{low} <= 0 or $+{low} >= 65535 ) {
|
||||||
# good port
|
die "$0: Server-side (low) port ($+{low}) must be within valid range [0..65535].\n";
|
||||||
|
}
|
||||||
|
if ( defined $+{high} ) {
|
||||||
|
if ( $+{high} <= 0 or $+{high} >= 65535 ) {
|
||||||
|
die "$0: Server-side high port ($+{high}) must be within valid range [0..65535].\n";
|
||||||
|
}
|
||||||
|
if ( $+{low} > $+{high} ) {
|
||||||
|
die "$0: Server-side port range ($port_request): low port greater than high port.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
die "$0: Server-side port ($port_request) must be within valid range [0..65535].\n";
|
die "$0: Server-side port ($port_request) not valid.\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ using namespace std;
|
|||||||
|
|
||||||
void print_usage( const char *argv0 )
|
void print_usage( const char *argv0 )
|
||||||
{
|
{
|
||||||
fprintf( stderr, "Usage: %s new [-s] [-v] [-i LOCALADDR] [-p PORT] [-c COLORS] [-l NAME=VALUE] [-- COMMAND...]\n", argv0 );
|
fprintf( stderr, "Usage: %s new [-s] [-v] [-i LOCALADDR] [-p PORT[:PORT2]] [-c COLORS] [-l NAME=VALUE] [-- COMMAND...]\n", argv0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_motd( void );
|
void print_motd( void );
|
||||||
@@ -235,9 +235,9 @@ int main( int argc, char *argv[] )
|
|||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( desired_port
|
int dpl, dph;
|
||||||
&& ( strspn( desired_port, "0123456789" ) != strlen( desired_port ) ) ) {
|
if ( desired_port && ! Connection::parse_portrange( desired_port, dpl, dph ) ) {
|
||||||
fprintf( stderr, "%s: Bad UDP port (%s)\n", argv[ 0 ], desired_port );
|
fprintf( stderr, "%s: Bad UDP port range (%s)\n", argv[ 0 ], desired_port );
|
||||||
print_usage( argv[ 0 ] );
|
print_usage( argv[ 0 ] );
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|||||||
+60
-18
@@ -223,20 +223,12 @@ Connection::Connection( const char *desired_ip, const char *desired_port ) /* se
|
|||||||
/* If an IP request is given, we try to bind to that IP, but we also
|
/* If an IP request is given, we try to bind to that IP, but we also
|
||||||
try INADDR_ANY. If a port request is given, we bind only to that port. */
|
try INADDR_ANY. If a port request is given, we bind only to that port. */
|
||||||
|
|
||||||
/* convert port number */
|
/* convert port numbers */
|
||||||
long int desired_port_no = 0;
|
int desired_port_low = 0;
|
||||||
|
int desired_port_high = 0;
|
||||||
|
|
||||||
if ( desired_port ) {
|
if ( desired_port && !parse_portrange( desired_port, desired_port_low, desired_port_high ) ) {
|
||||||
char *end;
|
throw NetworkException("Invalid port range", 0);
|
||||||
errno = 0;
|
|
||||||
desired_port_no = strtol( desired_port, &end, 10 );
|
|
||||||
if ( (errno != 0) || (end != desired_port + strlen( desired_port )) ) {
|
|
||||||
throw NetworkException( "Invalid port number", errno );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (desired_port_no < 0) || (desired_port_no > 65535) ) {
|
|
||||||
throw NetworkException( "Port number outside valid range [0..65535]", 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert desired IP */
|
/* convert desired IP */
|
||||||
@@ -253,7 +245,7 @@ Connection::Connection( const char *desired_ip, const char *desired_port ) /* se
|
|||||||
/* try to bind to desired IP first */
|
/* try to bind to desired IP first */
|
||||||
if ( desired_ip_addr != INADDR_ANY ) {
|
if ( desired_ip_addr != INADDR_ANY ) {
|
||||||
try {
|
try {
|
||||||
if ( try_bind( sock(), desired_ip_addr, desired_port_no ) ) { return; }
|
if ( try_bind( sock(), desired_ip_addr, desired_port_low, desired_port_high ) ) { return; }
|
||||||
} catch ( const NetworkException& e ) {
|
} catch ( const NetworkException& e ) {
|
||||||
struct in_addr sin_addr;
|
struct in_addr sin_addr;
|
||||||
sin_addr.s_addr = desired_ip_addr;
|
sin_addr.s_addr = desired_ip_addr;
|
||||||
@@ -265,7 +257,7 @@ Connection::Connection( const char *desired_ip, const char *desired_port ) /* se
|
|||||||
|
|
||||||
/* now try any local interface */
|
/* now try any local interface */
|
||||||
try {
|
try {
|
||||||
if ( try_bind( sock(), INADDR_ANY, desired_port_no ) ) { return; }
|
if ( try_bind( sock(), INADDR_ANY, desired_port_low, desired_port_high ) ) { return; }
|
||||||
} catch ( const NetworkException& e ) {
|
} catch ( const NetworkException& e ) {
|
||||||
fprintf( stderr, "Error binding to any interface: %s: %s\n",
|
fprintf( stderr, "Error binding to any interface: %s: %s\n",
|
||||||
e.function.c_str(), strerror( e.the_errno ) );
|
e.function.c_str(), strerror( e.the_errno ) );
|
||||||
@@ -276,7 +268,7 @@ Connection::Connection( const char *desired_ip, const char *desired_port ) /* se
|
|||||||
throw NetworkException( "Could not bind", errno );
|
throw NetworkException( "Could not bind", errno );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::try_bind( int socket, uint32_t addr, int port )
|
bool Connection::try_bind( int socket, uint32_t addr, int port_low, int port_high )
|
||||||
{
|
{
|
||||||
struct sockaddr_in local_addr;
|
struct sockaddr_in local_addr;
|
||||||
local_addr.sin_family = AF_INET;
|
local_addr.sin_family = AF_INET;
|
||||||
@@ -284,8 +276,11 @@ bool Connection::try_bind( int socket, uint32_t addr, int port )
|
|||||||
|
|
||||||
int search_low = PORT_RANGE_LOW, search_high = PORT_RANGE_HIGH;
|
int search_low = PORT_RANGE_LOW, search_high = PORT_RANGE_HIGH;
|
||||||
|
|
||||||
if ( port != 0 ) { /* port preference */
|
if ( port_low != 0 ) { /* low port preference */
|
||||||
search_low = search_high = port;
|
search_low = port_low;
|
||||||
|
}
|
||||||
|
if ( port_high != 0 ) { /* high port preference */
|
||||||
|
search_high = port_high;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = search_low; i <= search_high; i++ ) {
|
for ( int i = search_low; i <= search_high; i++ ) {
|
||||||
@@ -597,3 +592,50 @@ const Connection::Socket & Connection::Socket::operator=( const Socket & other )
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Connection::parse_portrange( const char * desired_port, int & desired_port_low, int & desired_port_high )
|
||||||
|
{
|
||||||
|
/* parse "port" or "portlow:porthigh" */
|
||||||
|
desired_port_low = desired_port_high = 0;
|
||||||
|
char *end;
|
||||||
|
long value;
|
||||||
|
|
||||||
|
/* parse first (only?) port */
|
||||||
|
errno = 0;
|
||||||
|
value = strtol( desired_port, &end, 10 );
|
||||||
|
if ( (errno != 0) || (*end != '\0' && *end != ':') ) {
|
||||||
|
fprintf( stderr, "Invalid (low) port number (%s)\n", desired_port );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( (value < 0) || (value > 65535) ) {
|
||||||
|
fprintf( stderr, "(Low) port number %ld outside valid range [0..65535]\n", value );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
desired_port_low = (int)value;
|
||||||
|
if (*end == '\0') { /* not a port range */
|
||||||
|
desired_port_high = desired_port_low;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* port range; parse high port */
|
||||||
|
const char * cp = end + 1;
|
||||||
|
errno = 0;
|
||||||
|
value = strtol( cp, &end, 10 );
|
||||||
|
if ( (errno != 0) || (*end != '\0') ) {
|
||||||
|
fprintf( stderr, "Invalid high port number (%s)\n", cp );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( (value < 0) || (value > 65535) ) {
|
||||||
|
fprintf( stderr, "High port number %ld outside valid range [0..65535]\n", value );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
desired_port_high = (int)value;
|
||||||
|
if ( desired_port_low > desired_port_high ) {
|
||||||
|
fprintf( stderr, "Low port %d greater than high port %d\n", desired_port_low, desired_port_high );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ namespace Network {
|
|||||||
|
|
||||||
static const int CONGESTION_TIMESTAMP_PENALTY = 500; /* ms */
|
static const int CONGESTION_TIMESTAMP_PENALTY = 500; /* ms */
|
||||||
|
|
||||||
static bool try_bind( int socket, uint32_t addr, int port );
|
static bool try_bind( int socket, uint32_t addr, int port_low, int port_high );
|
||||||
|
|
||||||
class Socket
|
class Socket
|
||||||
{
|
{
|
||||||
@@ -185,6 +185,8 @@ namespace Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void set_last_roundtrip_success( uint64_t s_success ) { last_roundtrip_success = s_success; }
|
void set_last_roundtrip_success( uint64_t s_success ) { last_roundtrip_success = s_success; }
|
||||||
|
|
||||||
|
static bool parse_portrange( const char * desired_port_range, int & desired_port_low, int & desired_port_high );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user