commit 56515abe9498cbeac4cd9b690171fcc99a18f352
Author:     Patrick Steinhardt <p...@pks.im>
AuthorDate: Wed Jun 21 09:33:20 2017 +0200
Commit:     Oswald Buddenhagen <o...@users.sf.net>
CommitDate: Thu Jun 22 09:23:56 2017 +0200

    socket: use next addrinfo if opening socket fails
    
    The `socket_connect_one` function previously did an `exit(1)` when
    encountering any errors with opening the socket. This would break
    connecting to a host where multiple possible addrinfos are returned,
    where the leading addrinfos are in fact impossible to connect to. E.g.
    with a kernel configured without support for IPv6, the `getaddrinfo`
    call may still return a hint containing an IPv6 address alongside
    another hint with an IPv4 address. Creating the socket with the IPv6
    address, which will cause an error, lead us to exiting early without
    even trying remaining hints.
    
    While one can argue that the user should have compiled without HAVE_IPV6
    or used an appropriate DNS configuration, we can do better by simply
    skipping over the current addrinfo causing an error. To do so, we split
    out a new function `socket_connect_next`, which selects the next
    available address info and subsequently calls `socket_connect_one`
    again. When no hints remain, `sock_connect_one` will error out at that
    point.

 src/socket.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/socket.c b/src/socket.c
index 3736fd5..c806e2e 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -329,6 +329,7 @@ static void socket_fd_cb( int, void * );
 static void socket_fake_cb( void * );
 
 static void socket_connect_one( conn_t * );
+static void socket_connect_next( conn_t * );
 static void socket_connect_failed( conn_t * );
 static void socket_connected( conn_t * );
 static void socket_connect_bail( conn_t * );
@@ -469,8 +470,8 @@ socket_connect_one( conn_t *sock )
        s = socket( PF_INET, SOCK_STREAM, 0 );
 #endif
        if (s < 0) {
-               perror( "socket" );
-               exit( 1 );
+               socket_connect_next( sock );
+               return;
        }
        socket_open_internal( sock, s );
 
@@ -494,10 +495,9 @@ socket_connect_one( conn_t *sock )
 }
 
 static void
-socket_connect_failed( conn_t *conn )
+socket_connect_next( conn_t *conn )
 {
        sys_error( "Cannot connect to %s", conn->name );
-       socket_close_internal( conn );
        free( conn->name );
        conn->name = 0;
 #ifdef HAVE_IPV6
@@ -509,6 +509,13 @@ socket_connect_failed( conn_t *conn )
 }
 
 static void
+socket_connect_failed( conn_t *conn )
+{
+       socket_close_internal( conn );
+       socket_connect_next( conn );
+}
+
+static void
 socket_connected( conn_t *conn )
 {
 #ifdef HAVE_IPV6

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to