File mosh-1.2.4-ipv6.patch of Package mosh
Index: configure.ac
===================================================================
--- configure.ac.orig
+++ configure.ac
@@ -170,7 +170,28 @@ AC_SEARCH_LIBS([socket], [socket])
AC_SEARCH_LIBS([inet_addr], [nsl])
# Checks for header files.
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h langinfo.h limits.h locale.h netinet/in.h stddef.h stdint.h inttypes.h stdlib.h string.h sys/ioctl.h sys/resource.h sys/socket.h sys/stat.h sys/time.h termios.h unistd.h wchar.h wctype.h], [], [AC_MSG_ERROR([Missing required header file.])])
+AC_CHECK_HEADERS([m4_normalize([
+ fcntl.h
+ langinfo.h
+ limits.h
+ locale.h
+ netdb.h
+ netinet/in.h
+ stddef.h
+ stdint.h
+ inttypes.h
+ stdlib.h
+ string.h
+ sys/ioctl.h
+ sys/resource.h
+ sys/socket.h
+ sys/stat.h
+ sys/time.h
+ termios.h
+ unistd.h
+ wchar.h
+ wctype.h
+ ])], [], [AC_MSG_ERROR([Missing required header file.])])
AC_CHECK_HEADERS([pty.h util.h libutil.h paths.h])
AC_CHECK_HEADERS([endian.h sys/endian.h])
Index: man/mosh.1
===================================================================
--- man/mosh.1.orig
+++ man/mosh.1
@@ -121,6 +121,19 @@ Synonym for \-\-predict=always
Synonym for \-\-predict=never
.TP
+.B --family=\fIFAMILY\fP
+Force the use of a particular address family, which defaults to `inet'
+(IPv4), and can also be `inet6' (IPv6; requires IO::Socket::IP).
+
+.TP
+.B -4
+Synonym for \-\-family=inet
+
+.TP
+.B -6
+Synonym for \-\-family=inet6
+
+.TP
.B \-p \fIPORT\fP[:\fIPORT2\fP], \-\-port=\fIPORT\fP[:\fIPORT2\fP]
Use a particular server-side UDP port or port range,
for example, if this is the
Index: scripts/mosh
===================================================================
--- scripts/mosh.orig
+++ scripts/mosh
@@ -34,8 +34,8 @@ my $MOSH_VERSION = '1.2.4';
use warnings;
use strict;
-use Socket;
use Getopt::Long;
+use IO::Socket::INET6;
$|=1;
@@ -44,6 +44,7 @@ my $server = 'mosh-server';
my $predict = undef;
+my $family = 'inet';
my $port_request = undef;
my $ssh = 'ssh';
@@ -67,6 +68,8 @@ qq{Usage: $0 [options] [--] [user@]host
-n --predict=never never use local echo
--predict=experimental aggressively echo even when incorrect
+-4 --family=inet use IPv4 only [default]
+-6 --family=inet6 use IPv6 only
-p PORT[:PORT2]
--port=PORT[:PORT2] server-side UDP port or range
@@ -106,6 +109,9 @@ GetOptions( 'client=s' => \$client,
'port=s' => \$port_request,
'a' => sub { $predict = 'always' },
'n' => sub { $predict = 'never' },
+ 'family=s' => \$family,
+ '4' => sub { $family = 'inet' },
+ '6' => sub { $family = 'inet6' },
'p=s' => \$port_request,
'ssh=s' => \$ssh,
'init!' => \$term_init,
@@ -150,25 +156,24 @@ delete $ENV{ 'MOSH_PREDICTION_DISPLAY' }
if ( defined $fake_proxy ) {
use Errno qw(EINTR);
- use IO::Socket::INET;
+ BEGIN { eval { require IO::Socket::IP; IO::Socket::IP->import('-register'); }; }
use POSIX qw(_exit);
my ( $host, $port ) = @ARGV;
- # Resolve hostname
- my $packed_ip = gethostbyname $host;
- if ( not defined $packed_ip ) {
- die "$0: Could not resolve hostname $host\n";
- }
- my $ip = inet_ntoa $packed_ip;
+ # Resolve hostname and connect
+ my $afstr = 'AF_' . uc( $family );
+ my $af = eval { IO::Socket->$afstr } or die "$0: Invalid family $family\n";
+ my $sock = IO::Socket->new( Domain => $af,
+ Family => $af,
+ PeerHost => $host,
+ PeerPort => $port,
+ Proto => "tcp" )
+ or die "$0: Could not connect to $host: $@\n";
- print STDERR "MOSH IP $ip\n";
+ print STDERR "MOSH IP ", $sock->peerhost, "\n";
# Act like netcat
- my $sock = IO::Socket::INET->new( PeerAddr => $ip,
- PeerPort => $port,
- Proto => "tcp" )
- or die "$0: connect to host $ip port $port: $!\n";
binmode($sock);
binmode(STDIN);
binmode(STDOUT);
@@ -243,7 +248,7 @@ if ( $pid == 0 ) { # child
push @server, '--', @command;
}
- my $quoted_self = shell_quote( $0 );
+ my $quoted_self = shell_quote( $0, "--family=$family" );
exec "$ssh " . shell_quote( '-S', 'none', '-o', "ProxyCommand=$quoted_self --fake-proxy -- %h %p", '-n', '-tt', $userhost, '--', "$server " . shell_quote( @server ) );
die "Cannot exec ssh: $!\n";
} else { # parent
Index: src/examples/ntester.cc
===================================================================
--- src/examples/ntester.cc.orig
+++ src/examples/ntester.cc
@@ -46,7 +46,7 @@ int main( int argc, char *argv[] )
bool server = true;
char *key;
char *ip;
- int port;
+ char *port;
UserStream me, remote;
@@ -59,7 +59,7 @@ int main( int argc, char *argv[] )
key = argv[ 1 ];
ip = argv[ 2 ];
- port = atoi( argv[ 3 ] );
+ port = argv[ 3 ];
n = new Transport<UserStream, UserStream>( me, remote, key, ip, port );
} else {
@@ -70,7 +70,7 @@ int main( int argc, char *argv[] )
exit( 1 );
}
- fprintf( stderr, "Port bound is %d, key is %s\n", n->port(), n->get_key().c_str() );
+ fprintf( stderr, "Port bound is %s, key is %s\n", n->port().c_str(), n->get_key().c_str() );
if ( server ) {
Select &sel = Select::get_instance();
Index: src/frontend/mosh-client.cc
===================================================================
--- src/frontend/mosh-client.cc.orig
+++ src/frontend/mosh-client.cc
@@ -117,7 +117,6 @@ int main( int argc, char *argv[] )
}
char *ip, *desired_port;
- int port;
if ( argc - optind != 2 ) {
usage( argv[ 0 ] );
@@ -128,13 +127,6 @@ int main( int argc, char *argv[] )
desired_port = argv[ optind + 1 ];
/* Sanity-check arguments */
- if ( ip
- && ( strspn( ip, "0123456789." ) != strlen( ip ) ) ) {
- fprintf( stderr, "%s: Bad IP address (%s)\n\n", argv[ 0 ], ip );
- usage( argv[ 0 ] );
- exit( 1 );
- }
-
if ( desired_port
&& ( strspn( desired_port, "0123456789" ) != strlen( desired_port ) ) ) {
fprintf( stderr, "%s: Bad UDP port (%s)\n\n", argv[ 0 ], desired_port );
@@ -142,8 +134,6 @@ int main( int argc, char *argv[] )
exit( 1 );
}
- port = myatoi( desired_port );
-
/* Read key from environment */
char *env_key = getenv( "MOSH_KEY" );
if ( env_key == NULL ) {
@@ -170,17 +160,17 @@ int main( int argc, char *argv[] )
set_native_locale();
try {
- STMClient client( ip, port, key, predict_mode );
+ STMClient client( ip, desired_port, key, predict_mode );
client.init();
try {
client.main();
} catch ( const Network::NetworkException &e ) {
- fprintf( stderr, "Network exception: %s: %s\r\n",
- e.function.c_str(), strerror( e.the_errno ) );
+ client.shutdown();
+ throw e;
} catch ( const Crypto::CryptoException &e ) {
- fprintf( stderr, "Crypto exception: %s\r\n",
- e.text.c_str() );
+ client.shutdown();
+ throw e;
}
client.shutdown();
Index: src/frontend/mosh-server.cc
===================================================================
--- src/frontend/mosh-server.cc.orig
+++ src/frontend/mosh-server.cc
@@ -50,8 +50,7 @@
#include <utempter.h>
#endif
#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+#include <netdb.h>
#include <time.h>
#include <sys/stat.h>
@@ -227,13 +226,6 @@ int main( int argc, char *argv[] )
}
/* Sanity-check arguments */
- if ( desired_ip
- && ( strspn( desired_ip, "0123456789." ) != strlen( desired_ip ) ) ) {
- fprintf( stderr, "%s: Bad IP address (%s)\n", argv[ 0 ], desired_ip );
- print_usage( argv[ 0 ] );
- exit( 1 );
- }
-
int dpl, dph;
if ( desired_port && ! Connection::parse_portrange( desired_port, dpl, dph ) ) {
fprintf( stderr, "%s: Bad UDP port range (%s)\n", argv[ 0 ], desired_port );
@@ -350,7 +342,7 @@ int run_server( const char *desired_ip,
network->set_verbose();
}
- printf( "\nMOSH CONNECT %d %s\n", network->port(), network->get_key().c_str() );
+ printf( "\nMOSH CONNECT %s %s\n", network->port().c_str(), network->get_key().c_str() );
fflush( stdout );
/* don't let signals kill us */
@@ -525,8 +517,8 @@ void serve( int host_fd, Terminal::Compl
#ifdef HAVE_UTEMPTER
bool connected_utmp = false;
- struct in_addr saved_addr;
- saved_addr.s_addr = 0;
+ Addr saved_addr;
+ socklen_t saved_addr_len = 0;
#endif
while ( 1 ) {
@@ -609,13 +601,24 @@ void serve( int host_fd, Terminal::Compl
#ifdef HAVE_UTEMPTER
/* update utmp entry if we have become "connected" */
if ( (!connected_utmp)
- || ( saved_addr.s_addr != network.get_remote_ip().s_addr ) ) {
+ || saved_addr_len != network.get_remote_addr_len()
+ || memcmp( &saved_addr, &network.get_remote_addr(),
+ saved_addr_len ) != 0 ) {
utempter_remove_record( host_fd );
- saved_addr = network.get_remote_ip();
+ saved_addr = network.get_remote_addr();
+ saved_addr_len = network.get_remote_addr_len();
+
+ char host[ NI_MAXHOST ];
+ int errcode = getnameinfo( &saved_addr.sa, saved_addr_len,
+ host, sizeof( host ), NULL, 0,
+ NI_NUMERICHOST );
+ if ( errcode != 0 ) {
+ throw NetworkException( std::string( "serve: getnameinfo: " ) + gai_strerror( errcode ), 0 );
+ }
char tmp[ 64 ];
- snprintf( tmp, 64, "%s via mosh [%d]", inet_ntoa( saved_addr ), getpid() );
+ snprintf( tmp, 64, "%s via mosh [%d]", host, getpid() );
utempter_add_record( host_fd, tmp );
connected_utmp = true;
Index: src/frontend/stmclient.cc
===================================================================
--- src/frontend/stmclient.cc.orig
+++ src/frontend/stmclient.cc
@@ -122,7 +122,7 @@ void STMClient::init( void )
}
wchar_t tmp[ 128 ];
- swprintf( tmp, 128, L"Nothing received from server on UDP port %d.", port );
+ swprintf( tmp, 128, L"Nothing received from server on UDP port %s.", port.c_str() );
connecting_notification = wstring( tmp );
}
@@ -143,8 +143,8 @@ void STMClient::shutdown( void )
}
if ( still_connecting() ) {
- fprintf( stderr, "\nmosh did not make a successful connection to %s:%d.\n", ip.c_str(), port );
- fprintf( stderr, "Please verify that UDP port %d is not firewalled and can reach the server.\n\n", port );
+ fprintf( stderr, "\nmosh did not make a successful connection to %s:%s.\n", ip.c_str(), port.c_str() );
+ fprintf( stderr, "Please verify that UDP port %s is not firewalled and can reach the server.\n\n", port.c_str() );
fprintf( stderr, "(By default, mosh uses a UDP port between 60000 and 61000. The -p option\nselects a specific UDP port number.)\n" );
} else if ( network ) {
if ( !clean_shutdown ) {
@@ -181,7 +181,7 @@ void STMClient::main_init( void )
Network::UserStream blank;
Terminal::Complete local_terminal( window_size.ws_col, window_size.ws_row );
network = new Network::Transport< Network::UserStream, Terminal::Complete >( blank, local_terminal,
- key.c_str(), ip.c_str(), port );
+ key.c_str(), ip.c_str(), port.c_str() );
network->set_send_delay( 1 ); /* minimal delay on outgoing keystrokes */
Index: src/frontend/stmclient.h
===================================================================
--- src/frontend/stmclient.h.orig
+++ src/frontend/stmclient.h
@@ -45,7 +45,7 @@
class STMClient {
private:
std::string ip;
- int port;
+ std::string port;
std::string key;
struct termios saved_termios, raw_termios;
@@ -77,7 +77,7 @@ private:
void resume( void ); /* restore state after SIGCONT */
public:
- STMClient( const char *s_ip, int s_port, const char *s_key, const char *predict_mode )
+ STMClient( const char *s_ip, const char *s_port, const char *s_key, const char *predict_mode )
: ip( s_ip ), port( s_port ), key( s_key ),
saved_termios(), raw_termios(),
window_size(),
Index: src/network/network.cc
===================================================================
--- src/network/network.cc.orig
+++ src/network/network.cc
@@ -37,13 +37,14 @@
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
+#include <netdb.h>
#include <netinet/in.h>
-#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include "dos_assert.h"
+#include "fatal_assert.h"
#include "byteorder.h"
#include "network.h"
#include "crypto.h"
@@ -119,6 +120,8 @@ void Connection::hop_port( void )
assert( !server );
setup();
+ assert( remote_addr_len != 0 );
+ socks.push_back( Socket( remote_addr.sa.sa_family ) );
prune_sockets();
}
@@ -146,8 +149,8 @@ void Connection::prune_sockets( void )
}
}
-Connection::Socket::Socket()
- : _fd( socket( AF_INET, SOCK_DGRAM, 0 ) )
+Connection::Socket::Socket( int family )
+ : _fd( socket( family, SOCK_DGRAM, 0 ) )
{
if ( _fd < 0 ) {
throw NetworkException( "socket", errno );
@@ -180,9 +183,6 @@ Connection::Socket::Socket()
void Connection::setup( void )
{
- /* create socket */
- socks.push_back( Socket() );
-
last_port_choice = timestamp();
}
@@ -199,10 +199,28 @@ const std::vector< int > Connection::fds
return ret;
}
+class AddrInfo {
+public:
+ struct addrinfo *res;
+ AddrInfo( const char *node, const char *service,
+ const struct addrinfo *hints ) :
+ res( NULL ) {
+ int errcode = getaddrinfo( node, service, hints, &res );
+ if ( errcode != 0 ) {
+ throw NetworkException( std::string( "Bad IP address (" ) + node + "): " + gai_strerror( errcode ), 0 );
+ }
+ }
+ ~AddrInfo() { freeaddrinfo(res); }
+private:
+ AddrInfo(const AddrInfo &);
+ AddrInfo &operator=(const AddrInfo &);
+};
+
Connection::Connection( const char *desired_ip, const char *desired_port ) /* server */
: socks(),
has_remote_addr( false ),
remote_addr(),
+ remote_addr_len( 0 ),
server( true ),
MTU( DEFAULT_SEND_MTU ),
key(),
@@ -237,33 +255,20 @@ Connection::Connection( const char *desi
throw NetworkException("Invalid port range", 0);
}
- /* convert desired IP */
- uint32_t desired_ip_addr = INADDR_ANY;
-
- if ( desired_ip ) {
- struct in_addr sin_addr;
- if ( inet_aton( desired_ip, &sin_addr ) == 0 ) {
- throw NetworkException( "Invalid IP address", errno );
- }
- desired_ip_addr = sin_addr.s_addr;
- }
-
/* try to bind to desired IP first */
- if ( desired_ip_addr != INADDR_ANY ) {
+ if ( desired_ip ) {
try {
- if ( try_bind( sock(), desired_ip_addr, desired_port_low, desired_port_high ) ) { return; }
+ if ( try_bind( desired_ip, desired_port_low, desired_port_high ) ) { return; }
} catch ( const NetworkException& e ) {
- struct in_addr sin_addr;
- sin_addr.s_addr = desired_ip_addr;
fprintf( stderr, "Error binding to IP %s: %s: %s\n",
- inet_ntoa( sin_addr ),
+ desired_ip,
e.function.c_str(), strerror( e.the_errno ) );
}
}
/* now try any local interface */
try {
- if ( try_bind( sock(), INADDR_ANY, desired_port_low, desired_port_high ) ) { return; }
+ if ( try_bind( NULL, desired_port_low, desired_port_high ) ) { return; }
} catch ( const NetworkException& e ) {
fprintf( stderr, "Error binding to any interface: %s: %s\n",
e.function.c_str(), strerror( e.the_errno ) );
@@ -274,11 +279,18 @@ Connection::Connection( const char *desi
throw NetworkException( "Could not bind", errno );
}
-bool Connection::try_bind( int socket, uint32_t addr, int port_low, int port_high )
+bool Connection::try_bind( const char *addr, int port_low, int port_high )
{
- struct sockaddr_in local_addr;
- local_addr.sin_family = AF_INET;
- local_addr.sin_addr.s_addr = addr;
+ struct addrinfo hints;
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV;
+ AddrInfo ai( addr, 0, &hints );
+
+ Addr local_addr;
+ socklen_t local_addr_len = ai.res->ai_addrlen;
+ memcpy( &local_addr.sa, ai.res->ai_addr, local_addr_len );
int search_low = PORT_RANGE_LOW, search_high = PORT_RANGE_HIGH;
@@ -289,16 +301,34 @@ bool Connection::try_bind( int socket, u
search_high = port_high;
}
+ socks.push_back( Socket( local_addr.sa.sa_family ) );
for ( int i = search_low; i <= search_high; i++ ) {
- local_addr.sin_port = htons( i );
+ switch (local_addr.sa.sa_family) {
+ case AF_INET:
+ local_addr.sin.sin_port = htons( i );
+ break;
+ case AF_INET6:
+ local_addr.sin6.sin6_port = htons( i );
+ break;
+ default:
+ throw NetworkException( "Unknown address family", 0 );
+ }
- if ( bind( socket, (sockaddr *)&local_addr, sizeof( local_addr ) ) == 0 ) {
+ if ( bind( sock(), &local_addr.sa, local_addr_len ) == 0 ) {
return true;
} else if ( i == search_high ) { /* last port to search */
- fprintf( stderr, "Failed binding to %s:%d\n",
- inet_ntoa( local_addr.sin_addr ),
- ntohs( local_addr.sin_port ) );
- throw NetworkException( "bind", errno );
+ int saved_errno = errno;
+ socks.pop_back();
+ char host[ NI_MAXHOST ], serv[ NI_MAXSERV ];
+ int errcode = getnameinfo( &local_addr.sa, local_addr_len,
+ host, sizeof( host ), serv, sizeof( serv ),
+ NI_DGRAM | NI_NUMERICHOST | NI_NUMERICSERV );
+ if ( errcode != 0 ) {
+ throw NetworkException( std::string( "bind: getnameinfo: " ) + gai_strerror( errcode ), 0 );
+ }
+ fprintf( stderr, "Failed binding to %s:%s\n",
+ host, serv );
+ throw NetworkException( "bind", saved_errno );
}
}
@@ -306,10 +336,11 @@ bool Connection::try_bind( int socket, u
return false;
}
-Connection::Connection( const char *key_str, const char *ip, int port ) /* client */
+Connection::Connection( const char *key_str, const char *ip, const char *port ) /* client */
: socks(),
has_remote_addr( false ),
remote_addr(),
+ remote_addr_len( 0 ),
server( false ),
MTU( DEFAULT_SEND_MTU ),
key( key_str ),
@@ -331,16 +362,19 @@ Connection::Connection( const char *key_
setup();
/* associate socket with remote host and port */
- remote_addr.sin_family = AF_INET;
- remote_addr.sin_port = htons( port );
- if ( !inet_aton( ip, &remote_addr.sin_addr ) ) {
- int saved_errno = errno;
- char buffer[ 2048 ];
- snprintf( buffer, 2048, "Bad IP address (%s)", ip );
- throw NetworkException( buffer, saved_errno );
- }
+ struct addrinfo hints;
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+ AddrInfo ai( ip, port, &hints );
+ fatal_assert( ai.res->ai_addrlen <= sizeof( remote_addr ) );
+ remote_addr_len = ai.res->ai_addrlen;
+ memcpy( &remote_addr.sa, ai.res->ai_addr, remote_addr_len );
has_remote_addr = true;
+
+ socks.push_back( Socket( remote_addr.sa.sa_family ) );
}
void Connection::send( string s )
@@ -354,7 +388,7 @@ void Connection::send( string s )
string p = px.tostring( &session );
ssize_t bytes_sent = sendto( sock(), p.data(), p.size(), MSG_DONTWAIT,
- (sockaddr *)&remote_addr, sizeof( remote_addr ) );
+ &remote_addr.sa, remote_addr_len );
if ( bytes_sent == static_cast<ssize_t>( p.size() ) ) {
have_send_exception = false;
@@ -415,7 +449,7 @@ string Connection::recv( void )
string Connection::recv_one( int sock_to_recv, bool nonblocking )
{
/* receive source address, ECN, and payload in msghdr structure */
- struct sockaddr_in packet_remote_addr;
+ Addr packet_remote_addr;
struct msghdr header;
struct iovec msg_iovec;
@@ -423,7 +457,7 @@ string Connection::recv_one( int sock_to
char msg_control[ Session::RECEIVE_MTU ];
/* receive source address */
- header.msg_name = &packet_remote_addr;
+ header.msg_name = &packet_remote_addr.sa;
header.msg_namelen = sizeof( packet_remote_addr );
/* receive payload */
@@ -511,12 +545,19 @@ string Connection::recv_one( int sock_to
last_heard = timestamp();
if ( server ) { /* only client can roam */
- if ( (remote_addr.sin_addr.s_addr != packet_remote_addr.sin_addr.s_addr)
- || (remote_addr.sin_port != packet_remote_addr.sin_port) ) {
+ if ( remote_addr_len != header.msg_namelen ||
+ memcmp( &remote_addr, &packet_remote_addr, remote_addr_len ) != 0 ) {
remote_addr = packet_remote_addr;
- fprintf( stderr, "Server now attached to client at %s:%d\n",
- inet_ntoa( remote_addr.sin_addr ),
- ntohs( remote_addr.sin_port ) );
+ remote_addr_len = header.msg_namelen;
+ char host[ NI_MAXHOST ], serv[ NI_MAXSERV ];
+ int errcode = getnameinfo( &remote_addr.sa, remote_addr_len,
+ host, sizeof( host ), serv, sizeof( serv ),
+ NI_DGRAM | NI_NUMERICHOST | NI_NUMERICSERV );
+ if ( errcode != 0 ) {
+ throw NetworkException( std::string( "recv_one: getnameinfo: " ) + gai_strerror( errcode ), 0 );
+ }
+ fprintf( stderr, "Server now attached to client at %s:%s\n",
+ host, serv );
}
}
}
@@ -524,16 +565,24 @@ string Connection::recv_one( int sock_to
return p.payload; /* we do return out-of-order or duplicated packets to caller */
}
-int Connection::port( void ) const
+std::string Connection::port( void ) const
{
- struct sockaddr_in local_addr;
+ Addr local_addr;
socklen_t addrlen = sizeof( local_addr );
- if ( getsockname( sock(), (sockaddr *)&local_addr, &addrlen ) < 0 ) {
+ if ( getsockname( sock(), &local_addr.sa, &addrlen ) < 0 ) {
throw NetworkException( "getsockname", errno );
}
- return ntohs( local_addr.sin_port );
+ char serv[ NI_MAXSERV ];
+ int errcode = getnameinfo( &local_addr.sa, addrlen,
+ NULL, 0, serv, sizeof( serv ),
+ NI_DGRAM | NI_NUMERICSERV );
+ if ( errcode != 0 ) {
+ throw NetworkException( std::string( "port: getnameinfo: " ) + gai_strerror( errcode ), 0 );
+ }
+
+ return std::string( serv );
}
uint64_t Network::timestamp( void )
Index: src/network/network.h
===================================================================
--- src/network/network.h.orig
+++ src/network/network.h
@@ -84,6 +84,13 @@ namespace Network {
string tostring( Session *session );
};
+ union Addr {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr_storage ss;
+ };
+
class Connection {
private:
static const int DEFAULT_SEND_MTU = 1300;
@@ -101,7 +108,7 @@ namespace Network {
static const int CONGESTION_TIMESTAMP_PENALTY = 500; /* ms */
- static bool try_bind( int socket, uint32_t addr, int port_low, int port_high );
+ bool try_bind( const char *addr, int port_low, int port_high );
class Socket
{
@@ -110,7 +117,7 @@ namespace Network {
public:
int fd( void ) const { return _fd; }
- Socket();
+ Socket( int family );
~Socket();
Socket( const Socket & other );
@@ -119,7 +126,8 @@ namespace Network {
std::deque< Socket > socks;
bool has_remote_addr;
- struct sockaddr_in remote_addr;
+ Addr remote_addr;
+ socklen_t remote_addr_len;
bool server;
@@ -161,21 +169,22 @@ namespace Network {
public:
Connection( const char *desired_ip, const char *desired_port ); /* server */
- Connection( const char *key_str, const char *ip, int port ); /* client */
+ Connection( const char *key_str, const char *ip, const char *port ); /* client */
void send( string s );
string recv( void );
const std::vector< int > fds( void ) const;
int get_MTU( void ) const { return MTU; }
- int port( void ) const;
+ std::string port( void ) const;
string get_key( void ) const { return key.printable_key(); }
bool get_has_remote_addr( void ) const { return has_remote_addr; }
uint64_t timeout( void ) const;
double get_SRTT( void ) const { return SRTT; }
- const struct in_addr & get_remote_ip( void ) const { return remote_addr.sin_addr; }
+ const Addr &get_remote_addr( void ) const { return remote_addr; }
+ socklen_t get_remote_addr_len( void ) const { return remote_addr_len; }
const NetworkException *get_send_exception( void ) const
{
Index: src/network/networktransport.cc
===================================================================
--- src/network/networktransport.cc.orig
+++ src/network/networktransport.cc
@@ -55,7 +55,7 @@ Transport<MyState, RemoteState>::Transpo
template <class MyState, class RemoteState>
Transport<MyState, RemoteState>::Transport( MyState &initial_state, RemoteState &initial_remote,
- const char *key_str, const char *ip, int port )
+ const char *key_str, const char *ip, const char *port )
: connection( key_str, ip, port ),
sender( &connection, initial_state ),
received_states( 1, TimestampedState<RemoteState>( timestamp(), 0, initial_remote ) ),
Index: src/network/networktransport.h
===================================================================
--- src/network/networktransport.h.orig
+++ src/network/networktransport.h
@@ -69,7 +69,7 @@ namespace Network {
Transport( MyState &initial_state, RemoteState &initial_remote,
const char *desired_ip, const char *desired_port );
Transport( MyState &initial_state, RemoteState &initial_remote,
- const char *key_str, const char *ip, int port );
+ const char *key_str, const char *ip, const char *port );
/* Send data or an ack if necessary. */
void tick( void ) { sender.tick(); }
@@ -94,7 +94,7 @@ namespace Network {
/* Other side has requested shutdown and we have sent one ACK */
bool counterparty_shutdown_ack_sent( void ) const { return sender.get_counterparty_shutdown_acknowledged(); }
- int port( void ) const { return connection.port(); }
+ std::string port( void ) const { return connection.port(); }
string get_key( void ) const { return connection.get_key(); }
MyState &get_current_state( void ) { return sender.get_current_state(); }
@@ -116,7 +116,8 @@ namespace Network {
unsigned int send_interval( void ) const { return sender.send_interval(); }
- const struct in_addr & get_remote_ip( void ) const { return connection.get_remote_ip(); }
+ const Addr &get_remote_addr( void ) const { return connection.get_remote_addr(); }
+ socklen_t get_remote_addr_len( void ) const { return connection.get_remote_addr_len(); }
const NetworkException *get_send_exception( void ) const { return connection.get_send_exception(); }
};