Exemple #1
0
static ret_t
match (cherokee_rule_request_t *rule,
       cherokee_connection_t   *conn,
       cherokee_config_entry_t *ret_conf)
{
	int                     re;
	ret_t                   ret;
	cherokee_regex_table_t *regexs = CONN_SRV(conn)->regexs;

	UNUSED(ret_conf);

	/* Sanity checks
	 */
	if (unlikely (regexs == NULL)) {
		LOG_ERROR_S (CHEROKEE_ERROR_RULE_REQUEST_NO_TABLE);
		return ret_error;
	}

	if (unlikely (rule->pcre == NULL)) {
		LOG_ERROR_S (CHEROKEE_ERROR_RULE_REQUEST_NO_PCRE_PTR);
		return ret_error;
	}

        /* Build the request string
         */
        if (! cherokee_buffer_is_empty (&conn->query_string)) {
                cherokee_buffer_add_str (&conn->request, "?");
                cherokee_buffer_add_buffer (&conn->request, &conn->query_string);
        }

	/* Evaluate the pcre
	 */
	re = pcre_exec (rule->pcre, NULL,
			conn->request.buf,
			conn->request.len,
			0, 0,
			conn->regex_ovector, OVECTOR_LEN);

	if (re < 0) {
		TRACE (ENTRIES, "Request \"%s\" didn't match with \"%s\"\n",
		       conn->request.buf, rule->pattern.buf);

		ret = ret_not_found;
		goto restore;
	}

	conn->regex_ovecsize = re;

	TRACE (ENTRIES, "Request \"%s\" matches with \"%s\", ovecsize=%d\n",
	       conn->request.buf, rule->pattern.buf, conn->regex_ovecsize);

	ret = ret_ok;

restore:
        if (! cherokee_buffer_is_empty (&conn->query_string)) {
                cherokee_buffer_drop_ending (&conn->request, conn->query_string.len + 1);
        }

	return ret;
}
Exemple #2
0
ret_t
cherokee_validator_digest_response (cherokee_validator_t  *validator,
				    char                  *A1,
				    cherokee_buffer_t     *buf,
				    cherokee_connection_t *conn)
{
	ret_t              ret;
	cherokee_buffer_t a2 = CHEROKEE_BUF_INIT;

	/* A1 has to be in string of length 32:
	 * MD5_digest(user":"******":"passwd)
	 */

	/* Sanity checks
	 */
	if (A1 == NULL)
		return ret_deny;

	if (cherokee_buffer_is_empty (&validator->nonce))
		return ret_deny;

	/* Build A2
	 */
	ret = digest_HA2 (validator, &a2, conn);
	if (ret != ret_ok)
		goto error;

	/* Build the final string
	 */
	cherokee_buffer_ensure_size (buf, 32 + a2.len + validator->nonce.len + 4);

	cherokee_buffer_add (buf, A1, 32);
	cherokee_buffer_add_str (buf, ":");
	cherokee_buffer_add_buffer (buf, &validator->nonce);
	cherokee_buffer_add_str (buf, ":");

	if (!cherokee_buffer_is_empty (&validator->qop)) {
		if (!cherokee_buffer_is_empty (&validator->nc))
			cherokee_buffer_add_buffer (buf, &validator->nc);
		cherokee_buffer_add_str (buf, ":");
		if (!cherokee_buffer_is_empty (&validator->cnonce))
			cherokee_buffer_add_buffer (buf, &validator->cnonce);
		cherokee_buffer_add_str (buf, ":");
		cherokee_buffer_add_buffer (buf, &validator->qop);
		cherokee_buffer_add_str (buf, ":");
	}

	cherokee_buffer_add_buffer (buf, &a2);
	cherokee_buffer_encode_md5_digest (buf);
	cherokee_buffer_mrproper (&a2);

	return ret_ok;

error:
	cherokee_buffer_mrproper (&a2);
	return ret;
}
Exemple #3
0
static ret_t
do_send_socket (cherokee_socket_t        *sock,
		cherokee_buffer_t        *buffer,
		cherokee_socket_status_t *blocking)
{
	ret_t  ret;
	size_t written = 0;

	ret = cherokee_socket_bufwrite (sock, buffer, &written);
	switch (ret) {
	case ret_ok:
		break;
	case ret_eagain:
		if (written > 0) {
			break;
		}

		TRACE (ENTRIES, "Post write: EAGAIN, wrote nothing of %d\n", buffer->len);
		*blocking = socket_writing;
		return ret_eagain;
	default:
		return ret_error;
	}

	cherokee_buffer_move_to_begin (buffer, written);
	TRACE (ENTRIES, "sent=%d, remaining=%d\n", written, buffer->len);

	if (! cherokee_buffer_is_empty (buffer)) {
		return ret_eagain;
	}

	return ret_ok;
}
Exemple #4
0
static ret_t
downloader_send_buffer (cherokee_downloader_t *downloader, cherokee_buffer_t *buf)
{
	ret_t              ret;
	size_t             written = 0;
	cherokee_socket_t *sock    = &downloader->socket;;

	ret = cherokee_socket_bufwrite (sock, buf, &written);
	switch (ret) {
	case ret_ok:
		/* Drop the header that has been sent
		 */
		cherokee_buffer_drop_ending (buf, written);
		if (cherokee_buffer_is_empty (buf)) {
			return ret_ok;
		}

		return ret_eagain;

	case ret_eagain:
		return ret;

	default:
		return ret_error;
	}
}
ret_t
cherokee_handler_ssi_init (cherokee_handler_ssi_t *hdl)
{
	ret_t                  ret;
	cherokee_connection_t *conn = HANDLER_CONN(hdl);

	/* Build the local directory
	 */
	cherokee_buffer_add_buffer (&hdl->dir, &conn->local_directory);
	cherokee_buffer_add_buffer (&hdl->dir, &conn->request);

	while (true) {
		if (cherokee_buffer_is_empty (&hdl->dir))
			return ret_error;

		if (cherokee_buffer_is_ending (&hdl->dir, '/'))
			break;

		cherokee_buffer_drop_ending (&hdl->dir, 1);
	}


	/* Real init function
	 */
	cherokee_buffer_add_buffer (&conn->local_directory, &conn->request);
	ret = init (hdl, &conn->local_directory);
	cherokee_buffer_drop_ending (&conn->local_directory, conn->request.len);

	return ret;
}
int
cherokee_post_has_buffered_info (cherokee_post_t   *post,
				 cherokee_buffer_t *tmp)
{
	cherokee_buffer_t *buffer = tmp ? tmp : &post->send.buffer;
	return (! cherokee_buffer_is_empty (buffer));
}
Exemple #7
0
ret_t
cherokee_downloader_connect (cherokee_downloader_t *downloader)
{
	ret_t               ret;
	cherokee_boolean_t  uses_proxy;
	cherokee_url_t     *url  = &downloader->request.url;

	/* Does it use a proxy?
	 */
	uses_proxy = ! cherokee_buffer_is_empty (&downloader->proxy);
	ret = cherokee_request_header_uses_proxy (&downloader->request, uses_proxy);
	if (ret != ret_ok) return ret;

	/* Connect
	 */
	if (uses_proxy) {
		ret = connect_to (downloader, &downloader->proxy, downloader->proxy_port, http);
		if (ret != ret_ok) return ret;
	} else {
		ret = connect_to (downloader, &url->host, url->port, url->protocol);
		if (ret != ret_ok) return ret;
	}

	return ret_ok;
}
static ret_t
send_query (cherokee_handler_dbslayer_t *hdl)
{
	int                    re;
	cuint_t                len;
	cherokee_connection_t *conn = HANDLER_CONN(hdl);
	cherokee_buffer_t     *tmp  = &HANDLER_THREAD(hdl)->tmp_buf1;

	/* Extract the SQL query
	 */
	if ((cherokee_buffer_is_empty (&conn->web_directory)) ||
	    (cherokee_buffer_is_ending (&conn->web_directory, '/')))
	{
		len = conn->web_directory.len;
	} else {
		len = conn->web_directory.len + 1;
	}

	cherokee_buffer_clean (tmp);
	cherokee_buffer_add   (tmp,
			       conn->request.buf + len,
			       conn->request.len - len);

	cherokee_buffer_unescape_uri (tmp);

	/* Send the query
	 */
	re = mysql_real_query (hdl->conn, tmp->buf, tmp->len);
	if (re != 0)
		return ret_error;

	return ret_ok;
}
Exemple #9
0
static ret_t
digest_HA2 (cherokee_validator_t *validator, cherokee_buffer_t *buf, cherokee_connection_t *conn)
{
	ret_t       ret;
	const char *method;
	cuint_t     method_len;

	/* Sanity check
	 */
	if (cherokee_buffer_is_empty (&validator->uri))
		return ret_deny;

	ret = cherokee_http_method_to_string (conn->header.method, &method, &method_len);
	if (unlikely (ret != ret_ok))
		return ret;

	cherokee_buffer_ensure_size (buf, method_len + 1 + validator->uri.len);

	cherokee_buffer_add        (buf, method, method_len);
	cherokee_buffer_add_str    (buf, ":");
	cherokee_buffer_add_buffer (buf, &validator->uri);

	cherokee_buffer_encode_md5_digest (buf);

	return ret_ok;
}
Exemple #10
0
static ret_t
configure (cherokee_rule_header_t    *rule,
	   cherokee_config_node_t    *conf,
	   cherokee_virtual_server_t *vsrv)
{
	ret_t                   ret;
	cherokee_buffer_t      *type     = NULL;
	cherokee_buffer_t      *header   = NULL;
	cherokee_regex_table_t *regexs   = VSERVER_SRV(vsrv)->regexs;

	/* Read the header
	 */
	ret = cherokee_config_node_read (conf, "header", &header);
	if (ret != ret_ok) {
		LOG_ERROR (CHEROKEE_ERROR_RULE_NO_PROPERTY,
			   RULE(rule)->priority, "header");
		return ret_error;
	}

	ret = header_str_to_type (header, &rule->header);
	if (ret != ret_ok) {
		return ret;
	}

	/* Type
	 */
	ret = cherokee_config_node_read (conf, "type", &type);
	if (ret == ret_ok) {
		ret = type_str_to_type (type, &rule->type);
		if (ret != ret_ok) {
			return ret;
		}
	}

	/* Read the match
	 */
	ret = cherokee_config_node_copy (conf, "match", &rule->match);
	if (ret != ret_ok) {
		if (equal_buf_str (type, "regex")) {
			LOG_ERROR (CHEROKEE_ERROR_RULE_NO_PROPERTY,
				   RULE(rule)->priority, "match");
			return ret_error;
		}
	}

	/* Compile the regular expression
	 */
	if (! cherokee_buffer_is_empty (&rule->match)) {
		ret = cherokee_regex_table_add (regexs, rule->match.buf);
		if (ret != ret_ok)
			return ret;

		ret = cherokee_regex_table_get (regexs, rule->match.buf, &rule->pcre);
		if (ret != ret_ok)
			return ret;
	}

	return ret_ok;
}
Exemple #11
0
int
cherokee_buffer_is_ending (cherokee_buffer_t *buf, char c)
{
	if (cherokee_buffer_is_empty(buf))
		return 0;

	return (buf->buf[buf->len - 1] == c);
}
Exemple #12
0
crc_t
cherokee_buffer_crc32 (cherokee_buffer_t *buf)
{
	if (cherokee_buffer_is_empty (buf))
		return 0;

	return crc32_sz (buf->buf, buf->len);
}
Exemple #13
0
ret_t
cherokee_validator_digest_check (cherokee_validator_t *validator, cherokee_buffer_t *passwd, cherokee_connection_t *conn)
{
	ret_t             ret;
	int               re   = -1;
	cherokee_buffer_t a1   = CHEROKEE_BUF_INIT;
	cherokee_buffer_t buf  = CHEROKEE_BUF_INIT;

	/* Sanity check
	 */
	if (cherokee_buffer_is_empty (&validator->user) ||
	    cherokee_buffer_is_empty (&validator->realm))
		return ret_deny;

	/* Build A1
	 */
	cherokee_buffer_ensure_size (&a1,
				     validator->user.len  + 1 +
				     validator->realm.len + 1 +
				     passwd->len);

	cherokee_buffer_add_buffer (&a1, &validator->user);
	cherokee_buffer_add_str    (&a1, ":");
	cherokee_buffer_add_buffer (&a1, &validator->realm);
	cherokee_buffer_add_str    (&a1, ":");
	cherokee_buffer_add_buffer (&a1, passwd);

	cherokee_buffer_encode_md5_digest (&a1);

	/* Build a possible response
	 */
	ret = cherokee_validator_digest_response (validator, a1.buf, &buf, conn);
	if (unlikely(ret != ret_ok))
		goto go_out;

	/* Compare and return
	 */
	re = cherokee_buffer_cmp_buf (&conn->validator->response, &buf);

go_out:
	cherokee_buffer_mrproper (&a1);
	cherokee_buffer_mrproper (&buf);

	return (re == 0) ? ret_ok : ret_deny;
}
Exemple #14
0
ret_t
cherokee_url_parse (cherokee_url_t    *url,
		    cherokee_buffer_t *string,
		    cherokee_buffer_t *user_ret,
		    cherokee_buffer_t *password_ret)
{
	if (cherokee_buffer_is_empty (string)) {
		return ret_error;
	}

	return cherokee_url_parse_guts (url, string, user_ret, password_ret);
}
Exemple #15
0
static ret_t
load_theme (cherokee_buffer_t *theme_path, cherokee_handler_dirlist_props_t *props)
{
    load_theme_load_file (theme_path, "header.html", &props->header);
    load_theme_load_file (theme_path, "footer.html", &props->footer);
    load_theme_load_file (theme_path, "entry.html", &props->entry);
    load_theme_load_file (theme_path, "theme.css", &props->css);

    /* Check it
     */
    if ((cherokee_buffer_is_empty (&props->header) ||
            cherokee_buffer_is_empty (&props->entry) ||
            cherokee_buffer_is_empty (&props->footer)))
        return ret_error;

    /* Parse conditional blocks
     */
    parse_macros_in_buffer (&props->header, props);
    parse_macros_in_buffer (&props->footer, props);
    parse_macros_in_buffer (&props->entry,  props);

    return ret_ok;
}
static ret_t
process_buffer (cherokee_handler_fcgi_t *hdl, cherokee_buffer_t *inbuf, cherokee_buffer_t *outbuf)
{
	ret_t ret;

	do {
		ret = process_package (hdl, inbuf, outbuf);
	} while (ret == ret_eagain);

	if (ret == ret_ok) {
		if (cherokee_buffer_is_empty (outbuf))
			return (HDL_CGI_BASE(hdl)->got_eof) ? ret_eof : ret_eagain;
	}

	return ret;
}
ret_t
cherokee_validator_htdigest_check (cherokee_validator_htdigest_t *htdigest,
				   cherokee_connection_t         *conn)
{
	ret_t              ret;
	cherokee_buffer_t *fpass;
	cherokee_buffer_t  file = CHEROKEE_BUF_INIT;

	/* Ensure that we have all what we need
	 */
	if ((conn->validator == NULL) ||
	    cherokee_buffer_is_empty (&conn->validator->user))
		return ret_error;

	/* Get the full path to the file
	 */
	ret = cherokee_validator_file_get_full_path (VFILE(htdigest), conn, &fpass,
						     &CONN_THREAD(conn)->tmp_buf1);
	if (ret != ret_ok) {
		ret = ret_error;
		goto out;
	}

	/* Read the whole file
	 */
	ret = cherokee_buffer_read_file (&file, fpass->buf);
	if (ret != ret_ok) {
		ret = ret_error;
		goto out;
	}

	/* Authenticate
	 */
	if (conn->req_auth_type & http_auth_basic) {
		ret = validate_basic (htdigest, conn, &file);

	} else if (conn->req_auth_type & http_auth_digest) {
		ret = validate_digest (htdigest, conn, &file);

	} else {
		SHOULDNT_HAPPEN;
	}

out:
	cherokee_buffer_mrproper (&file);
	return ret;
}
static void
print_connection_info (void)
{
	printf ("\n");

	if (! cherokee_buffer_is_empty (&password)) {
		printf ("Login:\n"
			"  User:              admin\n"
			"  One-time Password: %s\n\n", password.buf);
	}

	printf ("Web Interface:\n"
		"  URL:               http://%s:%d/\n\n",
		(bind_to) ? bind_to : "localhost", port);

	fflush(stdout);
}
Exemple #19
0
ret_t
cherokee_handler_cgi_init (cherokee_handler_cgi_t *cgi)
{
	ret_t                        ret;
	cherokee_handler_cgi_base_t *cgi_base = HDL_CGI_BASE(cgi);
	cherokee_connection_t       *conn     = HANDLER_CONN(cgi);

	switch (cgi_base->init_phase) {
	case hcgi_phase_build_headers:

		/* Extracts PATH_INFO and filename from request uri
		 */
		if (cherokee_buffer_is_empty (&cgi_base->executable)) {
			ret = cherokee_handler_cgi_base_extract_path (cgi_base, true);
			if (unlikely (ret < ret_ok)) {
				return ret;
			}
		}

		/* It has to update the timeout of the connection,
		 * otherwhise the server will drop it for the CGI
		 * isn't fast enough
		 */
		conn->timeout = cherokee_bogonow_now + CGI_TIMEOUT;
		cgi_base->init_phase = hcgi_phase_connect;

	case hcgi_phase_connect:
		/* Launch the CGI
		 */
		ret = fork_and_execute_cgi_via_spawner(cgi);
		if (unlikely (ret != ret_ok)) {
			ret = fork_and_execute_cgi(cgi);
			if (unlikely (ret != ret_ok)) {
				return ret;
			}
		}

	default:
		break;
	}

	TRACE (ENTRIES, "finishing %s\n", "ret_ok");
	return ret_ok;
}
Exemple #20
0
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;
}
Exemple #21
0
ret_t
cherokee_validator_file_configure (cherokee_config_node_t     *conf,
				   cherokee_server_t          *srv,
				   cherokee_module_props_t  **_props)
{
	ret_t                            ret;
	cherokee_config_node_t          *subconf;
	cherokee_validator_file_props_t *props    = PROP_VFILE(*_props);

	UNUSED (srv);

	/* Password file
	 */
	ret = cherokee_config_node_get (conf, "passwdfile", &subconf);
	if (ret == ret_ok) {
		cherokee_buffer_add_buffer (&props->password_file, &subconf->val);
	}

	/* Path type
	 */
	ret = cherokee_config_node_get (conf, "passwdfile_path", &subconf);
	if (ret == ret_ok) {
		if (equal_buf_str (&subconf->val, "full")) {
			props->password_path_type = val_path_full;
		} else if (equal_buf_str (&subconf->val, "local_dir")) {
			props->password_path_type = val_path_local_dir;
		} else {
			LOG_ERROR (CHEROKEE_ERROR_VALIDATOR_FILE, subconf->val.buf);
			return ret_error;
		}
	}

	/* Final checks
	 */
	if (cherokee_buffer_is_empty (&props->password_file)) {
		LOG_CRITICAL_S (CHEROKEE_ERROR_VALIDATOR_FILE_NO_FILE);
		return ret_error;
	}

	return ret_ok;
}
Exemple #22
0
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;
}
Exemple #23
0
static ret_t
do_read_plain (cherokee_post_t   *post,
	       cherokee_socket_t *sock_in,
	       cherokee_buffer_t *buffer,
	       off_t              to_read)
{
	ret_t  ret;
	size_t len;

	/* Surplus from header read
	 */
	if (! cherokee_buffer_is_empty (&post->header_surplus)) {
		TRACE (ENTRIES, "Post appending %d surplus bytes\n", post->header_surplus.len);
		post->send.read += post->header_surplus.len;

		cherokee_buffer_add_buffer (buffer, &post->header_surplus);
		cherokee_buffer_clean (&post->header_surplus);

		return ret_ok;
	}

	/* Read
	 */
	if (to_read <= 0) {
		return ret_ok;
	}

	TRACE (ENTRIES, "Post reading from client (to_read=%d)\n", to_read);
	ret = cherokee_socket_bufread (sock_in, buffer, to_read, &len);
	TRACE (ENTRIES, "Post read from client: ret=%d len=%d\n", ret, len);

	if (ret != ret_ok) {
		return ret;
	}

	post->send.read += len;
	return ret_ok;
}
static ret_t
validate_digest (cherokee_validator_htdigest_t *htdigest, cherokee_connection_t *conn, cherokee_buffer_t *file)
{
	int                re;
	ret_t              ret;
	char              *user   = NULL;
	char              *realm  = NULL;
	char              *passwd = NULL;
	cherokee_buffer_t  buf    = CHEROKEE_BUF_INIT;

	/* Sanity check
	 */
	if (cherokee_buffer_is_empty (&conn->validator->response))
		return ret_error;

	/* Extact the right entry information
	 */
	ret = extract_user_entry (file, conn->validator->user.buf, &user, &realm, &passwd);
	if (unlikely(ret != ret_ok))
		return ret;

	/* Build the hash:
	 * In this case passwd is the HA1 hash: md5(user:realm:passwd)
	 */
	ret = cherokee_validator_digest_response (VALIDATOR(htdigest), passwd, &buf, conn);
	if (unlikely(ret != ret_ok))
		goto go_out;

	/* Compare and return
	 */
	re = cherokee_buffer_cmp_buf (&conn->validator->response, &buf);

go_out:
	cherokee_buffer_mrproper (&buf);
	return (re == 0) ? ret_ok : ret_deny;
}
ret_t
cherokee_handler_zeromq_read_post (cherokee_handler_zeromq_t *hdl)
{
	zmq_msg_t				message;
	int						re;
	ret_t					ret;
	cherokee_buffer_t	   *post = &HANDLER_THREAD(hdl)->tmp_buf1;
	cherokee_buffer_t	   *out  = &HANDLER_THREAD(hdl)->tmp_buf2;
	cherokee_connection_t  *conn = HANDLER_CONN(hdl);

	/* Check for the post info
	 */
	if (! conn->post.has_info) {
		conn->error_code = http_bad_request;
		return ret_error;
	}

	cherokee_buffer_clean (post);
	ret = cherokee_post_read (&conn->post, &conn->socket, post);
	switch (ret) {
	case ret_ok:
		cherokee_connection_update_timeout (conn);
		break;
	case ret_eagain:
		ret = cherokee_thread_deactive_to_polling (HANDLER_THREAD(hdl),
												   HANDLER_CONN(hdl),
												   conn->socket.socket,
												   FDPOLL_MODE_READ, false);
		if (ret != ret_ok) {
			return ret_error;
		} else {
			return ret_eagain;
		}
	default:
		conn->error_code = http_bad_request;
		return ret_error;
	}

	TRACE (ENTRIES, "Post contains: '%s'\n", post->buf);

	re = cherokee_post_read_finished (&conn->post);
	ret = re ? ret_ok : ret_eagain;

	if (hdl->encoder != NULL) {
		cherokee_buffer_clean(out);
		if (ret == ret_ok) {
			cherokee_encoder_flush(hdl->encoder, post, out);
		} else {
			cherokee_encoder_encode(hdl->encoder, post, out);
		}

		post = out;
	}
	
	cherokee_buffer_add_buffer(&hdl->output, post);
	
	if (ret == ret_ok) {
		cherokee_buffer_t	 			*tmp   = &HANDLER_THREAD(hdl)->tmp_buf1;
		cherokee_handler_zeromq_props_t *props = HANDLER_ZEROMQ_PROPS(hdl);
		zmq_msg_t envelope;
		zmq_msg_t message;
		cuint_t len;

		if ((cherokee_buffer_is_empty (&conn->web_directory)) ||
			(cherokee_buffer_is_ending (&conn->web_directory, '/'))) {
			len = conn->web_directory.len;
		} else {
			len = conn->web_directory.len + 1;
		}

		cherokee_buffer_clean (tmp);
		cherokee_buffer_add   (tmp, conn->request.buf + len,
									conn->request.len - len);

		TRACE(ENTRIES, "ZeroMQ: incomming path '%s'\n", tmp->buf);

		zmq_msg_init_size (&envelope, tmp->len);
		memcpy (zmq_msg_data (&envelope), tmp->buf, tmp->len);
		zmq_msg_init_size (&message, hdl->output.len);
		memcpy (zmq_msg_data (&message), hdl->output.buf, hdl->output.len);

		/* Atomic Section */
		CHEROKEE_MUTEX_LOCK (&props->mutex);
		zmq_msg_send (&envelope, props->socket, ZMQ_DONTWAIT | ZMQ_SNDMORE);
		zmq_msg_send (&message, props->socket, ZMQ_DONTWAIT);
		CHEROKEE_MUTEX_UNLOCK (&props->mutex);

		zmq_msg_close (&envelope);
		zmq_msg_close (&message);
	}

	return ret;
}
static ret_t
parse (cherokee_handler_ssi_t *hdl,
       cherokee_buffer_t      *in,
       cherokee_buffer_t      *out)
{
	ret_t              ret;
	char              *p, *q;
	char              *begin;
	int                re;
	cuint_t            len;
	operations_t       op;
	path_type_t        path;
	struct stat        info;
	cherokee_boolean_t ignore;
	cherokee_buffer_t  key     = CHEROKEE_BUF_INIT;
	cherokee_buffer_t  val     = CHEROKEE_BUF_INIT;
	cherokee_buffer_t  pair    = CHEROKEE_BUF_INIT;
	cherokee_buffer_t  fpath   = CHEROKEE_BUF_INIT;

	q = in->buf;

	while (true) {
		begin = q;

		/* Check the end
		 */
		if (q >= in->buf + in->len)
			break;

		/* Find next SSI tag
		 */
		p = strstr (q, "<!--#");
		if (p == NULL) {
			cherokee_buffer_add (out, begin, (in->buf + in->len) - begin);
			ret = ret_ok;
			goto out;
		}

		q = strstr (p + 5, "-->");
		if (q == NULL) {
			ret = ret_error;
			goto out;
		}

		len = q - p;
		len -= 5;

		cherokee_buffer_clean (&key);
		cherokee_buffer_add (&key, p+5, len);
		cherokee_buffer_trim (&key);

		q += 3;
		TRACE(ENTRIES, "Found key '%s'\n", key.buf);

		/* Add the previous chunk
		 */
		cherokee_buffer_add (out, begin, p - begin);

		/* Check element
		 */
		op     = op_none;
		ignore = false;

		if (strncmp (key.buf, "include", 7) == 0) {
			op  = op_include;
			len = 7;
		} else if (strncmp (key.buf, "fsize", 5) == 0) {
			op  = op_size;
			len = 5;
		} else if (strncmp (key.buf, "flastmod", 8) == 0) {
			op  = op_lastmod;
			len = 8;
		} else {
			LOG_ERROR (CHEROKEE_ERROR_HANDLER_SSI_PROPERTY, key.buf);
		}

		/* Deeper parsing
		 */
		path = path_none;

		switch (op) {
		case op_size:
		case op_include:
		case op_lastmod:
			/* Read a property key
			 */
			cherokee_buffer_move_to_begin (&key, len);
			cherokee_buffer_trim (&key);

			cherokee_buffer_clean (&pair);
			get_pair (&key, &pair);

			cherokee_buffer_drop_ending (&key, pair.len);
			cherokee_buffer_trim (&key);

			/* Parse the property
			 */
			if (strncmp (pair.buf, "file=", 5) == 0) {
				path = path_file;
				len  = 5;
			} else if (strncmp (pair.buf, "virtual=", 8) == 0) {
				path = path_virtual;
				len  = 8;
			}

			cherokee_buffer_clean (&val);
			get_val (pair.buf + len, &val);

			cherokee_buffer_clean (&fpath);

			switch (path) {
			case path_file:
				cherokee_buffer_add_buffer (&fpath, &hdl->dir);
				cherokee_buffer_add_char   (&fpath, '/');
				cherokee_buffer_add_buffer (&fpath, &val);

				TRACE(ENTRIES, "Path: file '%s'\n", fpath.buf);
				break;
			case path_virtual:
				cherokee_buffer_add_buffer (&fpath, &HANDLER_VSRV(hdl)->root);
				cherokee_buffer_add_char   (&fpath, '/');
				cherokee_buffer_add_buffer (&fpath, &val);

				TRACE(ENTRIES, "Path: virtual '%s'\n", fpath.buf);
				break;
			default:
				ignore = true;
				SHOULDNT_HAPPEN;
			}

			/* Path security check: ensure that the file
			 * to include is inside the document root.
			 */
			if (! cherokee_buffer_is_empty (&fpath)) {
				cherokee_path_short (&fpath);

				if (fpath.len < HANDLER_VSRV(hdl)->root.len) {
					ignore = true;

				}  else {
					re = strncmp (fpath.buf,
					              HANDLER_VSRV(hdl)->root.buf,
					              HANDLER_VSRV(hdl)->root.len);
					if (re != 0) {
						ignore = true;
					}
				}
			}

			/* Perform the operation
			 */
			if (! ignore) {
				switch (op) {
				case op_include: {
					cherokee_buffer_t file_content = CHEROKEE_BUF_INIT;

					ret = cherokee_buffer_read_file (&file_content, fpath.buf);
					if (unlikely (ret != ret_ok)) {
						cherokee_buffer_mrproper (&file_content);
						ret = ret_error;
						goto out;
					}

					TRACE(ENTRIES, "Including file '%s'\n", fpath.buf);

					ret = parse (hdl, &file_content, out);
					if (unlikely (ret != ret_ok)) {
						cherokee_buffer_mrproper (&file_content);
						ret = ret_error;
						goto out;
					}

					cherokee_buffer_mrproper (&file_content);
					break;
				}

				case op_size:
					TRACE(ENTRIES, "Including file size '%s'\n", fpath.buf);
					re = cherokee_stat (fpath.buf, &info);
					if (re >=0) {
						cherokee_buffer_add_ullong10 (out, info.st_size);
					}
					break;

				case op_lastmod:
					TRACE(ENTRIES, "Including file modification date '%s'\n", fpath.buf);
					re = cherokee_stat (fpath.buf, &info);
					if (re >= 0) {
						struct tm *ltime;
						struct tm  ltime_buf;
						char       tmp[50];

						ltime = cherokee_localtime (&info.st_mtime, &ltime_buf);
						if (ltime != NULL) {
							strftime (tmp, sizeof(tmp), "%d-%b-%Y %H:%M", ltime);
							cherokee_buffer_add (out, tmp, strlen(tmp));
						}
					}
					break;
				default:
					SHOULDNT_HAPPEN;
				}
			} /* !ignore */

			break;
		default:
			SHOULDNT_HAPPEN;
		} /* switch(op) */
	} /* while */

	ret = ret_ok;

out:
	cherokee_buffer_mrproper (&key);
	cherokee_buffer_mrproper (&val);
	cherokee_buffer_mrproper (&pair);
	cherokee_buffer_mrproper (&fpath);

	return ret;
}
static ret_t
config_server (cherokee_server_t *srv)
{
	ret_t                  ret;
	cherokee_config_node_t conf;
	cherokee_buffer_t      buf       = CHEROKEE_BUF_INIT;
	cherokee_buffer_t      rrd_dir   = CHEROKEE_BUF_INIT;
	cherokee_buffer_t      rrd_bin   = CHEROKEE_BUF_INIT;
	cherokee_buffer_t      fake;

	/* Generate the password
	 */
	if (unsecure == 0) {
		ret = generate_admin_password (&password);
		if (ret != ret_ok)
			return ret;
	}

	/* Configure the embedded server
	 */
	if (scgi_port > 0) {
		ret = find_empty_port (scgi_port, &scgi_port);
	} else {
		ret = remove_old_socket (DEFAULT_UNIX_SOCKET);
	}
	if (ret != ret_ok) {
		return ret_error;
	}

	cherokee_buffer_add_va  (&buf, "server!bind!1!port = %d\n", port);
	cherokee_buffer_add_str (&buf, "server!ipv6 = 1\n");
	cherokee_buffer_add_str (&buf, "server!max_connection_reuse = 0\n");
	cherokee_buffer_add_va  (&buf, "server!iocache = %d\n", iocache);

	if (bind_to) {
		cherokee_buffer_add_va (&buf, "server!bind!1!interface = %s\n", bind_to);
	}

	if (thread_num != -1) {
		cherokee_buffer_add_va (&buf, "server!thread_number = %d\n", thread_num);
	}

	cherokee_buffer_add_str (&buf, "vserver!1!nick = default\n");
	cherokee_buffer_add_va  (&buf, "vserver!1!document_root = %s\n", document_root);

	if (scgi_port <= 0) {
		cherokee_buffer_add_va  (&buf,
					 "source!1!nick = app-logic\n"
					 "source!1!type = interpreter\n"
					 "source!1!timeout = " TIMEOUT "\n"
					 "source!1!host = %s\n"
					 "source!1!interpreter = %s/server.py %s %s %s\n"
					 "source!1!env_inherited = 1\n",
					 DEFAULT_UNIX_SOCKET, document_root,
					 DEFAULT_UNIX_SOCKET, config_file,
					 (debug) ? "-x" : "");

	} else {
		cherokee_buffer_add_va  (&buf,
					 "source!1!nick = app-logic\n"
					 "source!1!type = interpreter\n"
					 "source!1!timeout = " TIMEOUT "\n"
					 "source!1!host = localhost:%d\n"
					 "source!1!interpreter = %s/server.py %d %s %s\n"
					 "source!1!env_inherited = 1\n",
					 scgi_port, document_root,
					 scgi_port, config_file,
					 (debug) ? "-x" : "");
	}

	if (debug) {
		cherokee_buffer_add_str  (&buf, "source!1!debug = 1\n");
	}

	cherokee_buffer_add_str  (&buf,
				  RULE_PRE "1!match = default\n"
				  RULE_PRE "1!handler = scgi\n"
				  RULE_PRE "1!timeout = " TIMEOUT "\n"
				  RULE_PRE "1!handler!balancer = round_robin\n"
				  RULE_PRE "1!handler!balancer!source!1 = 1\n");

	cherokee_buffer_add_str  (&buf, RULE_PRE "1!handler!env!CTK_COOKIE = ");
	generate_admin_password  (&buf);
	cherokee_buffer_add_char (&buf, '\n');

	if (! debug) {
		cherokee_buffer_add_str (&buf, RULE_PRE "1!encoder!gzip = 1\n");
	}

	if ((unsecure == 0) &&
	    (!cherokee_buffer_is_empty (&password)))
	{
		cherokee_buffer_add_va (&buf,
					RULE_PRE "1!auth = authlist\n"
					RULE_PRE "1!auth!methods = digest\n"
					RULE_PRE "1!auth!realm = Cherokee-admin\n"
					RULE_PRE "1!auth!list!1!user = admin\n"
					RULE_PRE "1!auth!list!1!password = %s\n",
					password.buf);
	}

	cherokee_buffer_add_str (&buf,
				 RULE_PRE "2!match = directory\n"
				 RULE_PRE "2!match!directory = /about\n"
				 RULE_PRE "2!handler = server_info\n");

	cherokee_buffer_add_str (&buf,
				 RULE_PRE "3!match = directory\n"
				 RULE_PRE "3!match!directory = /static\n"
				 RULE_PRE "3!handler = file\n"
				 RULE_PRE "3!expiration = time\n"
				 RULE_PRE "3!expiration!time = 30d\n");

	cherokee_buffer_add_va  (&buf,
				 RULE_PRE "4!match = request\n"
				 RULE_PRE "4!match!request = ^/favicon.ico$\n"
				 RULE_PRE "4!document_root = %s/static/images\n"
				 RULE_PRE "4!handler = file\n"
				 RULE_PRE "4!expiration = time\n"
				 RULE_PRE "4!expiration!time = 30d\n",
				 document_root);

	cherokee_buffer_add_va  (&buf,
				 RULE_PRE "5!match = directory\n"
				 RULE_PRE "5!match!directory = /icons_local\n"
				 RULE_PRE "5!handler = file\n"
				 RULE_PRE "5!document_root = %s\n"
				 RULE_PRE "5!expiration = time\n"
				 RULE_PRE "5!expiration!time = 30d\n",
				 CHEROKEE_ICONSDIR);

	cherokee_buffer_add_va  (&buf,
				 RULE_PRE "6!match = directory\n"
				 RULE_PRE "6!match!directory = /CTK\n"
				 RULE_PRE "6!handler = file\n"
				 RULE_PRE "6!document_root = %s/CTK/static\n"
				 RULE_PRE "6!expiration = time\n"
				 RULE_PRE "6!expiration!time = 30d\n",
				 document_root);

	/* Embedded help
	 */
	cherokee_buffer_add_va  (&buf,
				 RULE_PRE "7!match = and\n"
				 RULE_PRE "7!match!left = directory\n"
				 RULE_PRE "7!match!left!directory = /help\n"
				 RULE_PRE "7!match!right = not\n"
				 RULE_PRE "7!match!right!right = extensions\n"
				 RULE_PRE "7!match!right!right!extensions = html\n"
				 RULE_PRE "7!handler = file\n");

	cherokee_buffer_add_va  (&buf,
				 RULE_PRE "8!match = fullpath\n"
				 RULE_PRE "8!match!fullpath!1 = /static/help_404.html\n"
				 RULE_PRE "8!handler = file\n"
				 RULE_PRE "8!document_root = %s\n", document_root);

	cherokee_buffer_add_va  (&buf,
				 RULE_PRE "9!match = and\n"
				 RULE_PRE "9!match!left = directory\n"
				 RULE_PRE "9!match!left!directory = /help\n"
				 RULE_PRE "9!match!right = not\n"
				 RULE_PRE "9!match!right!right = exists\n"
				 RULE_PRE "9!match!right!right!match_any = 1\n"
				 RULE_PRE "9!handler = redir\n"
				 RULE_PRE "9!handler!rewrite!1!show = 1\n"
				 RULE_PRE "9!handler!rewrite!1!substring = /static/help_404.html\n");

	cherokee_buffer_add_va  (&buf,
				 RULE_PRE "10!match = directory\n"
				 RULE_PRE "10!match!directory = /help\n"
				 RULE_PRE "10!match!final = 0\n"
				 RULE_PRE "10!document_root = %s\n", CHEROKEE_DOCDIR);

	/* GZip
	 */
	if (! debug) {
		cherokee_buffer_add_va (&buf,
					RULE_PRE "15!match = extensions\n"
					RULE_PRE "15!match!extensions = css,js,html\n"
					RULE_PRE "15!match!final = 0\n"
					RULE_PRE "15!encoder!gzip = 1\n");
	}

	/* RRDtool graphs
	 */
	cherokee_config_node_init (&conf);
	cherokee_buffer_fake (&fake, config_file, strlen(config_file));

	ret = cherokee_config_reader_parse (&conf, &fake);
	if (ret == ret_ok) {
		cherokee_config_node_copy (&conf, "server!collector!rrdtool_path", &rrd_bin);
		cherokee_config_node_copy (&conf, "server!collector!database_dir", &rrd_dir);
	}

	if (! cherokee_buffer_is_empty (&rrd_bin)) {
		cherokee_buffer_add_va  (&buf,
					 RULE_PRE "20!handler!rrdtool_path = %s\n", rrd_bin.buf);
	}

	if (! cherokee_buffer_is_empty (&rrd_dir)) {
		cherokee_buffer_add_va  (&buf,
					 RULE_PRE "20!handler!database_dir = %s\n", rrd_dir.buf);
	}

	cherokee_buffer_add_str (&buf,
				 RULE_PRE "20!match = directory\n"
				 RULE_PRE "20!match!directory = /graphs\n"
				 RULE_PRE "20!handler = render_rrd\n"
				 RULE_PRE "20!expiration = epoch\n"
				 RULE_PRE "20!expiration!caching = no-cache\n"
				 RULE_PRE "20!expiration!caching!no-store = 1\n");

	cherokee_buffer_add_str (&buf, RULE_PRE "20!document_root = ");
	cherokee_tmp_dir_copy   (&buf);
	cherokee_buffer_add_va  (&buf, "/cherokee/rrd-cache\n");

	/* MIME types
	 */
	cherokee_buffer_add_str (&buf,
				 "mime!text/javascript!extensions = js\n"
				 "mime!text/css!extensions = css\n"
				 "mime!image/png!extensions = png\n"
				 "mime!image/jpeg!extensions = jpeg,jpg\n"
				 "mime!image/svg+xml!extensions = svg,svgz\n"
				 "mime!image/gif!extensions = gif\n");

	ret = cherokee_server_read_config_string (srv, &buf);
	if (ret != ret_ok) {
		PRINT_ERROR_S ("Could not initialize the server\n");
		return ret;
	}

	cherokee_config_node_mrproper (&conf);

	cherokee_buffer_mrproper (&rrd_bin);
	cherokee_buffer_mrproper (&rrd_dir);
	cherokee_buffer_mrproper (&buf);

	return ret_ok;
}
Exemple #28
0
ret_t
cherokee_buffer_add_buffer_slice (cherokee_buffer_t *buf,
				  cherokee_buffer_t *buf2,
				  ssize_t            begin,
				  ssize_t            end)
{
	ssize_t pos_end;
	ssize_t pos_begin;

	/* Ensure there's something to copy
	 */
	if (unlikely (cherokee_buffer_is_empty (buf2)))
		return ret_ok;

	/* Check the end
	 */
	if (end == CHEROKEE_BUF_SLIDE_NONE) {
		/* [__:] */
		pos_end = buf2->len;
	} else {
		if (end > 0) {
			/* [__:x] */
			pos_end = end;
		} else {
			if ((-end) > buf2->len) {
				/* [__:-x] */
				pos_end = buf2->len - (-end);
			} else {
				/* [__:-xxxxx] */
				return ret_ok;
			}
		}
	}

	/* Check the beginning
	 */
	if (begin == CHEROKEE_BUF_SLIDE_NONE) {
		/* [:__] */
		pos_begin = 0;
	} else {
		if (begin >= 0) {
			if (begin > buf2->len) {
				/* [xxxx:__]  */
				pos_begin = buf2->len;
			} else {
				/* [x:__] */
				pos_begin = begin;
			}
		} else {
			if ((-begin) < buf2->len) {
				/* [-x:__] */
				pos_begin = buf2->len - begin;
			} else {
				/* [-xxxx:__] */
				pos_begin = 0;
			}
		}
	}

	/* Sanity check
	 */
	if (unlikely ((pos_begin < 0)       ||
		      (pos_end < 0)         ||
		      (pos_end > buf2->len) ||
		      (pos_end < pos_begin)))
	{
		return ret_ok;
	}

	/* Copy the substring
	 */
	return cherokee_buffer_add (buf, buf2->buf + pos_begin, pos_end - pos_begin);
}
Exemple #29
0
int
main (int argc, char **argv)
{
    int                    re;
    ret_t                  ret;
    cint_t                 val;
    cint_t                 param_num;
    cint_t                 long_index;
    cherokee_downloader_t *downloader;
    cherokee_buffer_t      proxy       = CHEROKEE_BUF_INIT;
    cuint_t                proxy_port;

    struct option long_options[] = {
        /* Options without arguments */
        {"help",          no_argument,       NULL, 'h'},
        {"version",       no_argument,       NULL, 'V'},
        {"quiet",         no_argument,       NULL, 'q'},
        {"save-headers",  no_argument,       NULL, 's'},
        {"header",        required_argument, NULL,  0 },
        {NULL, 0, NULL, 0}
    };

    /* Parse known parameters
     */
    while ((val = getopt_long (argc, argv, "VshqO:", long_options, &long_index)) != -1) {
        switch (val) {
        case 'V':
            printf ("Cherokee Downloader %s\n"
                    "Written by Alvaro Lopez Ortega <*****@*****.**>\n\n"
                    "Copyright (C) 2001-2014 Alvaro Lopez Ortega.\n"
                    "This is free software; see the source for copying conditions.  There is NO\n"
                    "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
                    PACKAGE_VERSION);
            return EXIT_OK;

        case 'O':
            if (global_fd != UNSET_FD) {
                close (global_fd);
            }

            if ((strlen(optarg) == 1) && (optarg[0] == '-')) {
                global_fd = fileno(stdout);
            } else {
                global_fd = open (optarg, O_WRONLY | O_CREAT, 0644);
            }

            if (global_fd < 0) {
                PRINT_MSG ("ERROR: Can not open %s\n", optarg);
                return EXIT_ERROR;
            }
            break;

        case 0:
            break;

        case 'q':
            quiet = true;
            break;

        case 's':
            save_headers = true;
            break;

        case 'h':
        case '?':
        default:
            print_help();
            return EXIT_OK;
        }
    }

    /* The rest..
     */
    param_num = argc - optind;

    if (param_num <= 0) {
        print_usage();
        return EXIT_OK;
    }

    /* Tracing and proxy discovering..
     */
    cherokee_init();
    cget_find_proxy (&proxy, &proxy_port);

    for (val=optind; val<optind+param_num; val++) {
        cherokee_buffer_t url = CHEROKEE_BUF_INIT;

        /* Build the url buffer
         */
        ret = cherokee_buffer_add_va (&url, "%s", argv[val]);
        if (ret != ret_ok)
            exit (EXIT_ERROR);

        /* Create the downloader object..
         */
        ret = cherokee_downloader_new (&downloader);
        if (ret != ret_ok)
            exit (EXIT_ERROR);

        ret = cherokee_downloader_init(downloader);
        if (ret != ret_ok)
            exit (EXIT_ERROR);

        if (! cherokee_buffer_is_empty (&proxy)) {
            ret = cherokee_downloader_set_proxy (downloader, &proxy, proxy_port);
            if (ret != ret_ok)
                exit (EXIT_ERROR);
        }

        ret = cherokee_downloader_set_url (downloader, &url);
        if (ret != ret_ok)
            exit (EXIT_ERROR);

        ret = cherokee_downloader_connect (downloader);
        if (ret != ret_ok)
            exit (EXIT_ERROR);

        /* Download it!
         */
        ret = do_download (downloader);
        if ((ret != ret_ok) && (ret != ret_eof)) {
            exit (EXIT_ERROR);
        }

        /* Free the objects..
         */
        cherokee_buffer_mrproper (&url);
        cherokee_downloader_free (downloader);
    }

    /* Close the output file
     */
    re = close (output_fd);
    if (re != 0)
        exit (EXIT_ERROR);

    cherokee_mrproper();
    return EXIT_OK;
}
Exemple #30
0
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);
}