static ret_t cherokee_bind_v6 (cherokee_socket_t *sock, cuint_t port, cherokee_buffer_t *listen_to) { int re; ret_t ret; SOCKET_ADDR_IPv6(sock)->sin6_port = htons(port); if (cherokee_buffer_is_empty (listen_to)) { SOCKET_ADDR_IPv6(sock)->sin6_addr = in6addr_any; } else{ ret = cherokee_socket_pton (sock, listen_to); if (ret != ret_ok) return ret; } re = bind (SOCKET_FD(sock), (struct sockaddr *)&SOCKET_ADDR(sock), sock->client_addr_len); if (re != 0) return ret_error; return ret_ok; }
ret_t cherokee_source_connect (cherokee_source_t *src, cherokee_socket_t *sock) { ret_t ret; cherokee_resolv_cache_t *resolv; /* Short path: it's already connecting */ if (sock->socket >= 0) { return cherokee_socket_connect (sock); } /* Create the new socket and set the target IP info */ if (! cherokee_buffer_is_empty (&src->unix_socket)) { /* Create the socket descriptor */ ret = cherokee_socket_create_fd (sock, AF_UNIX); if (unlikely (ret != ret_ok)) { return ret; } ret = cherokee_socket_gethostbyname (sock, &src->unix_socket); if (unlikely (ret != ret_ok)) { return ret; } } else { cherokee_boolean_t tested_all; const struct addrinfo *addr; const struct addrinfo *addr_info = NULL; /* Query the resolv cache */ ret = cherokee_resolv_cache_get_default (&resolv); if (unlikely (ret!=ret_ok)) { return ret; } ret = cherokee_resolv_cache_get_addrinfo (resolv, &src->host, &addr_info); if ((ret != ret_ok) || (addr_info == NULL)) { return ret_error; } /* Current address */ if (src->addr_current) { tested_all = false; addr = src->addr_current; } else { tested_all = true; addr = addr_info; } /* Create the fd for the address family * * Iterates through the different addresses of the * host and stores a pointer to the first one with * a supported family. */ while (addr != NULL) { ret = cherokee_socket_create_fd (sock, addr->ai_family); #ifdef TRACE_ENABLED if (cherokee_trace_is_tracing()) { ret_t ret2; char ip[46]; ret2 = cherokee_ntop (addr->ai_family, addr->ai_addr, ip, sizeof(ip)); if (ret2 == ret_ok) { TRACE (ENTRIES, "Connecting to %s, ret=%d\n", ip, ret); } } #endif if (ret == ret_ok) { src->addr_current = addr; break; } addr = addr->ai_next; if (addr == NULL) { if (tested_all) { return ret_error; } tested_all = true; src->addr_current = NULL; addr = addr_info; continue; } cherokee_socket_close(sock); } /* Update the new socket with the address info */ switch (src->addr_current->ai_family) { case AF_INET: SOCKET_ADDR_IPv4(sock)->sin_port = htons(src->port); break; case AF_INET6: SOCKET_ADDR_IPv6(sock)->sin6_port = htons(src->port); break; default: SHOULDNT_HAPPEN; return ret_error; } ret = cherokee_socket_update_from_addrinfo (sock, src->addr_current, 0); if (unlikely (ret != ret_ok)) { return ret_error; } } /* Set non-blocking */ ret = cherokee_fd_set_nonblocking (sock->socket, true); if (unlikely (ret != ret_ok)) { LOG_ERRNO (errno, cherokee_err_error, CHEROKEE_ERROR_SOURCE_NONBLOCK, sock->socket); } /* Set close-on-exec and reuse-address */ cherokee_fd_set_closexec (sock->socket); cherokee_fd_set_reuseaddr (sock->socket); return cherokee_socket_connect (sock); }