static int makesock_addrinfo(unsigned l4type, bool passive, struct addrinfo *ai,
struct flowopts *fo)
{
- struct addrinfo *local, *remote, *src = NULL, *dst = NULL;
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 */
-
- ret = socket(src ? src->ai_family : dst->ai_family,
- sock_type(l4type), l4type);
+ for (; ai; ai = ai->ai_next) {
+ ret = socket(ai->ai_family, sock_type(l4type), l4type);
if (ret < 0)
- goto get_next_dst;
+ continue;
sockfd = ret;
- /*
- * 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) {
- ret = -ERRNO_TO_PARA_ERROR(errno);
- close(sockfd);
- PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n",
- para_strerror(-ret));
- break;
- }
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);
+ PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n",
+ para_strerror(-ret));
+ return ret;
+ }
+ if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
close(sockfd);
- goto get_next_src;
+ continue;
}
- if (!dst) /* bind-only completed successfully */
- break;
+ return sockfd;
+ } else {
+ if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == 0)
+ return sockfd;
+ close(sockfd);
}
-
- 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)
- return ret < 0? ret : -E_MAKESOCK;
- return sockfd;
+ return -E_MAKESOCK;
}
/**