예제 #1
0
ret_t
cherokee_socket_pton (cherokee_socket_t *socket, cherokee_buffer_t *host)
{
	int re;

	switch (SOCKET_AF(socket)) {
	case AF_INET:
#ifdef HAVE_INET_PTON
		re = inet_pton (AF_INET, host->buf, &SOCKET_SIN_ADDR(socket));
		if (re <= 0) return ret_error;
#else
		re = inet_aton (host->buf, &SOCKET_SIN_ADDR(socket));
		if (re == 0) return ret_error;
#endif
		break;
#ifdef HAVE_IPV6
	case AF_INET6:
		re = inet_pton (AF_INET6, host->buf, &SOCKET_SIN6_ADDR(socket));
		if (re <= 0) return ret_error;
		break;
#endif
	default:
		LOG_CRITICAL (CHEROKEE_ERROR_SOCKET_BAD_FAMILY, SOCKET_AF(socket));
		return ret_error;
	}

	return ret_ok;
}
예제 #2
0
ret_t
cherokee_socket_ntop (cherokee_socket_t *socket, char *dst, size_t cnt)
{
	if (unlikely (SOCKET_FD(socket) < 0)) {
		return ret_error;
	}

	return cherokee_ntop (SOCKET_AF(socket),
			      (struct sockaddr *) &SOCKET_ADDR(socket),
			      dst, cnt);
}
예제 #3
0
ret_t
cherokee_socket_create_fd (cherokee_socket_t *sock, unsigned short int family)
{
	/* Create the socket
	 */
	do {
		sock->socket = socket (family, SOCK_STREAM, 0);
	} while ((sock->socket == -1) && (errno == EINTR));

	if (sock->socket < 0) {
#ifdef HAVE_IPV6
		if ((family == AF_INET6) &&
		    (errno == EAFNOSUPPORT))
		{
			LOG_WARNING (CHEROKEE_ERROR_SOCKET_NO_IPV6);
		} else
#endif
		{
			LOG_ERRNO (errno, cherokee_err_error, CHEROKEE_ERROR_SOCKET_NEW_SOCKET);
			return ret_error;
		}
	}

	/* Set the family length
	 */
	switch (family) {
	case AF_INET:
		sock->client_addr_len = sizeof (struct sockaddr_in);
		memset (&sock->client_addr, 0, sock->client_addr_len);
		break;
#ifdef HAVE_IPV6
	case AF_INET6:
		sock->client_addr_len = sizeof (struct sockaddr_in6);
		memset (&sock->client_addr, 0, sock->client_addr_len);
		break;
#endif
#ifdef HAVE_SOCKADDR_UN
	case AF_UNIX:
		memset (&sock->client_addr, 0, sizeof (struct sockaddr_un));
		break;
#endif
	default:
		SHOULDNT_HAPPEN;
		return ret_error;
	}

	/* Set the family
	 */
	SOCKET_AF(sock) = family;
	return ret_ok;
}
예제 #4
0
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
}
예제 #5
0
ret_t
cherokee_socket_update_from_addrinfo (cherokee_socket_t     *socket,
                                      const struct addrinfo *addr,
                                      cuint_t                num)
{
	const struct addrinfo *ai;

	if (unlikely (addr == NULL))
		return ret_error;

	/* Find the right address
	 */
	ai = addr;
	while (num > 0) {
		num -= 1;
		ai   = ai->ai_next;
		if (ai == NULL) {
			return ret_not_found;
		}
	}

	/* Copy the information
	 */
	SOCKET_AF(socket)       = addr->ai_family;
	socket->client_addr_len = addr->ai_addrlen;

	switch (addr->ai_family) {
	case AF_INET:
		memcpy (&SOCKET_SIN_ADDR(socket), &((struct sockaddr_in *) ai->ai_addr)->sin_addr, sizeof(struct in_addr));
		break;
	case AF_INET6:
		memcpy (&SOCKET_SIN6_ADDR(socket), &((struct sockaddr_in6 *) ai->ai_addr)->sin6_addr, sizeof(struct in6_addr));
		break;
	default:
		SHOULDNT_HAPPEN;
		return ret_error;
	}

	return ret_ok;
}
예제 #6
0
ret_t
cherokee_socket_gethostbyname (cherokee_socket_t *socket, cherokee_buffer_t *hostname)
{
	if (SOCKET_AF(socket) == AF_UNIX) {
#ifdef _WIN32
		SHOULDNT_HAPPEN;
		return ret_no_sys;
#else
		memset ((char*) SOCKET_SUN_PATH(socket), 0,
			sizeof (SOCKET_ADDR_UNIX(socket)));

		SOCKET_ADDR_UNIX(socket)->sun_family = AF_UNIX;

		strncpy (SOCKET_SUN_PATH (socket), hostname->buf,
			 sizeof (SOCKET_ADDR_UNIX(socket)->sun_path) - sizeof(short));

		return ret_ok;
#endif
	}

	return cherokee_gethostbyname (hostname->buf, &SOCKET_SIN_ADDR(socket));
}
예제 #7
0
ret_t
cherokee_socket_bind (cherokee_socket_t *sock, cuint_t port, cherokee_buffer_t *listen_to)
{
	/* Bind
	 */
	switch (SOCKET_AF(sock)) {
	case AF_INET:
		return cherokee_bind_v4 (sock, port, listen_to);
#ifdef HAVE_IPV6
	case AF_INET6:
		return cherokee_bind_v6 (sock, port, listen_to);
#endif
#ifdef HAVE_SOCKADDR_UN
	case AF_UNIX:
		return cherokee_bind_local (sock, listen_to);
#endif
	default:
		break;
	}

	SHOULDNT_HAPPEN;
	return ret_error;
}
예제 #8
0
ret_t
cherokee_socket_connect (cherokee_socket_t *sock)
{
	int r;
	int err;

	TRACE (ENTRIES",connect", "connect type=%s\n",
	       SOCKET_AF(sock) == AF_INET  ? "AF_INET"  :
	       SOCKET_AF(sock) == AF_INET6 ? "AF_INET6" :
	       SOCKET_AF(sock) == AF_UNIX  ? "AF_UNIX"  : "Unknown");

	do {
		switch (SOCKET_AF(sock)) {
		case AF_INET:
			r = connect (SOCKET_FD(sock),
			             (struct sockaddr *) &SOCKET_ADDR(sock),
			             sizeof(struct sockaddr_in));
			break;
#ifdef HAVE_IPV6
		case AF_INET6:
			r = connect (SOCKET_FD(sock),
			             (struct sockaddr *) &SOCKET_ADDR(sock),
			             sizeof(struct sockaddr_in6));
			break;
#endif
#ifdef HAVE_SOCKADDR_UN
		case AF_UNIX:
			if (SOCKET_SUN_PATH (socket)[0] != 0) {
				r = connect (SOCKET_FD(sock),
				             (struct sockaddr *) &SOCKET_ADDR(sock),
				             SUN_LEN (SOCKET_ADDR_UNIX(sock)));
			}
			else {
				r = connect (SOCKET_FD(sock),
				             (struct sockaddr *) &SOCKET_ADDR(sock),
				             SUN_ABSTRACT_LEN (SOCKET_ADDR_UNIX(sock)));
			}
			break;
#endif
		default:
			SHOULDNT_HAPPEN;
			return ret_no_sys;
		}
	} while ((r == -1) && (errno == EINTR));

	if (r < 0) {
		err = SOCK_ERRNO();
		TRACE (ENTRIES",connect", "connect error=%d '%s'\n", err, strerror(err));

		switch (err) {
		case EISCONN:
			break;
		case EINVAL:
		case ENOENT:
		case ECONNRESET:
		case ECONNREFUSED:
		case EADDRNOTAVAIL:
			return ret_deny;
		case ETIMEDOUT:
			return ret_error;
		case EAGAIN:
		case EALREADY:
		case EINPROGRESS:
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
		case EWOULDBLOCK:
#endif
			return ret_eagain;
		default:
			LOG_ERRNO_S (errno, cherokee_err_error, CHEROKEE_ERROR_SOCKET_CONNECT);
			return ret_error;
		}
	}

	TRACE (ENTRIES",connect", "succeed. fd=%d\n", SOCKET_FD(sock));

	sock->status = socket_reading;
	return ret_ok;
}