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(); }
   };
openSUSE Build Service is sponsored by