X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=net.c;h=94610a84e2a3aa6b42ad9d5c11dbc03bc69cb306;hb=8d47a8cea663cc9c1c01cdba23b0531caa5c8d9c;hp=2d0c9e22e1a69adeae2759209bbf56f77128b1b7;hpb=82f292e24ec2b252f56d2720797d3348b0512b07;p=paraslash.git diff --git a/net.c b/net.c index 2d0c9e22..94610a84 100644 --- a/net.c +++ b/net.c @@ -12,6 +12,11 @@ */ #define _GNU_SOURCE +#include +#include +#include +#include +#include #include /* At least NetBSD needs these. */ @@ -417,68 +422,43 @@ static int lookup_address(unsigned l4type, bool passive, const char *host, static int makesock_addrinfo(unsigned l4type, bool passive, struct addrinfo *ai, struct flowopts *fo) { - struct addrinfo *local, *remote, *src = NULL, *dst = NULL; - int rc = -E_MAKESOCK, on = 1, sockfd = -1; + int ret = -E_MAKESOCK, on = 1, sockfd = -1; - if (passive) { - local = ai; - remote = NULL; - } else { - local = NULL; - remote = ai; - } - - /* Iterate over all src/dst combination, exhausting dst first */ - for (src = local, dst = remote; src != NULL || dst != NULL; /* no op */ ) { - if (src && dst && src->ai_family == AF_INET - && dst->ai_family == AF_INET6) - goto get_next_dst; /* v4 -> v6 is not possible */ - - sockfd = socket(src ? src->ai_family : dst->ai_family, - sock_type(l4type), l4type); - if (sockfd < 0) - goto get_next_dst; - - /* - * Reuse the address on passive sockets to avoid failure on - * restart (protocols using listen()) and when creating - * multiple listener instances (UDP multicast). - */ - if (passive && setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)) == -1) { - rc = errno; - close(sockfd); - PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n", - strerror(rc)); - rc = -ERRNO_TO_PARA_ERROR(rc); - break; - } + for (; ai; ai = ai->ai_next) { + ret = socket(ai->ai_family, sock_type(l4type), l4type); + if (ret < 0) + continue; + sockfd = ret; flowopt_setopts(sockfd, fo); - - if (src) { - if (bind(sockfd, src->ai_addr, src->ai_addrlen) < 0) { + if (passive) { + /* + * Reuse the address on passive sockets to avoid + * failure on restart (protocols using listen()) and + * when creating multiple listener instances (UDP + * multicast). + */ + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, + sizeof(on)) == -1) { + ret = -ERRNO_TO_PARA_ERROR(errno); close(sockfd); - goto get_next_src; - } - if (!dst) /* bind-only completed successfully */ + PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n", + para_strerror(-ret)); break; + } + if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { + close(sockfd); + continue; + } + /* bind completed successfully */ + break; + } else { + if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == 0) + break; /* connection completed successfully */ } - - if (dst && connect(sockfd, dst->ai_addr, dst->ai_addrlen) == 0) - break; /* connection completed successfully */ close(sockfd); -get_next_dst: - if (dst && (dst = dst->ai_next)) - continue; -get_next_src: - if (src && (src = src->ai_next)) /* restart inner loop */ - dst = remote; - } - if (src == NULL && dst == NULL) { - if (rc >= 0) - rc = -E_MAKESOCK; - return rc; } + if (!ai) + return ret < 0? ret : -E_MAKESOCK; return sockfd; }