ret_t cherokee_socket_gethostbyname (cherokee_socket_t *socket, cherokee_buffer_t *hostname) { #ifndef _WIN32 ret_t ret; cherokee_resolv_cache_t *resolv = NULL; /* Unix sockets */ if (SOCKET_AF(socket) == AF_UNIX) { memset ((char*) SOCKET_SUN_PATH(socket), 0, sizeof (SOCKET_ADDR_UNIX(socket))); SOCKET_ADDR_UNIX(socket)->sun_family = AF_UNIX; if (hostname->buf[0] == '@') { strncpy (SOCKET_SUN_PATH (socket) + 1, hostname->buf + 1, (sizeof (SOCKET_ADDR_UNIX(socket)->sun_path) - 1) - sizeof(short)); SOCKET_SUN_PATH (socket)[0] = 0; } else { strncpy (SOCKET_SUN_PATH (socket), hostname->buf, sizeof (SOCKET_ADDR_UNIX(socket)->sun_path) - sizeof(short)); } return ret_ok; } /* TCP sockets */ ret = cherokee_resolv_cache_get_default (&resolv); if (ret != ret_ok) { return ret_error; } ret = cherokee_resolv_cache_get_host (resolv, hostname, socket); if (ret != ret_ok) { return ret_error; } return ret_ok; #else SHOULDNT_HAPPEN; return ret_no_sys; #endif }
ret_t cherokee_proxy_util_init_socket (cherokee_socket_t *socket, cherokee_source_t *src) { ret_t ret; cherokee_resolv_cache_t *resolv; TRACE (ENTRIES, "Initializing proxy socket: %s\n", cherokee_string_is_ipv6 (&src->host) ? "IPv6": "IPv4"); /* Family */ if (cherokee_string_is_ipv6 (&src->host)) { ret = cherokee_socket_set_client (socket, AF_INET6); } else { ret = cherokee_socket_set_client (socket, AF_INET); } if (unlikely(ret != ret_ok)) return ret_error; /* TCP port */ SOCKET_SIN_PORT(socket) = htons (src->port); /* IP host */ ret = cherokee_resolv_cache_get_default (&resolv); if (unlikely (ret != ret_ok)) { return ret_error; } ret = cherokee_resolv_cache_get_host (resolv, &src->host, socket); if (ret != ret_ok) { return ret_error; } /* Set a few properties */ cherokee_fd_set_closexec (socket->socket); cherokee_fd_set_nonblocking (socket->socket, true); cherokee_fd_set_nodelay (socket->socket, true); return ret_ok; }
static ret_t set_host (cherokee_source_t *src, cherokee_buffer_t *host) { ret_t ret; cherokee_resolv_cache_t *resolv; if (cherokee_buffer_is_empty (host)) return ret_error; TRACE (ENTRIES, "Configuring source, setting host '%s'\n", host->buf); /* Original */ cherokee_buffer_add_buffer (&src->original, host); /* Unix socket */ if (host->buf[0] == '/' || host->buf[0] == '@') { cherokee_buffer_add_buffer (&src->unix_socket, host); return ret_ok; } /* Host name */ ret = cherokee_parse_host (host, &src->host, (cuint_t *)&src->port); if (unlikely (ret != ret_ok)) { return ret_error; } /* Resolve and cache it */ ret = cherokee_resolv_cache_get_default (&resolv); if (unlikely (ret!=ret_ok)) { return ret_error; } cherokee_resolv_cache_get_ipstr (resolv, &src->host, NULL); 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); }