From 10406b4ad2ce68ff32128ff398cffcd3df1353a9 Mon Sep 17 00:00:00 2001 From: Jeff Trawick Date: Fri, 4 Jan 2002 01:47:55 +0000 Subject: [PATCH] Fix a couple of mod_proxy problems forwarding HTTP connections: (1) PR #9190 It failed to connect to IPv6 hosts. (2) It failed to connect when the first IP address returned by the resolver was unreachable but a secondary IP address was. PR: 9190 (partly) git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@92727 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 6 ++++ modules/proxy/proxy_http.c | 62 +++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/CHANGES b/CHANGES index 01dfbdd392..7d710a0eef 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,11 @@ Changes with Apache 2.0.30-dev + *) Fix a couple of mod_proxy problems forwarding HTTP connections: + (1) PR #9190 It failed to connect to IPv6 hosts. + (2) It failed to connect when the first IP address returned by + the resolver was unreachable but a secondary IP address was. + [Jeff Trawick] + *) Fix the module identifer as shown in the docs for various core modules (e.g., the identifer for mod_log_config was previously listed as config_log_module). PR #9338 diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c index af5c8ce4b2..2fe038126b 100644 --- a/modules/proxy/proxy_http.c +++ b/modules/proxy/proxy_http.c @@ -344,31 +344,6 @@ apr_status_t ap_proxy_http_create_connection(apr_pool_t *p, request_rec *r, /* create a new socket */ backend->connection = NULL; - /* see memory note above */ - if ((rv = apr_socket_create(&p_conn->sock, APR_INET, SOCK_STREAM, - c->pool)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, - "proxy: error creating socket"); - return HTTP_INTERNAL_SERVER_ERROR; - } - -#if !defined(TPF) && !defined(BEOS) - if (conf->recv_buffer_size > 0 && - (rv = apr_setsocketopt(p_conn->sock, APR_SO_RCVBUF, - conf->recv_buffer_size))) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, - "setsockopt(SO_RCVBUF): Failed to set " - "ProxyReceiveBufferSize, using default"); - } -#endif - - /* Set a timeout on the socket */ - apr_setsocketopt(p_conn->sock, APR_SO_TIMEOUT, - (int)(r->server->timeout * APR_USEC_PER_SEC)); - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: socket has been created"); - /* * At this point we have a list of one or more IP addresses of * the machine to connect to. If configured, reorder this @@ -378,17 +353,50 @@ apr_status_t ap_proxy_http_create_connection(apr_pool_t *p, request_rec *r, * * For now we do nothing, ie we get DNS round robin. * XXX FIXME + * + * We have to create a new socket each time through the loop because + * + * (1) On most stacks, connect() fails with EINVAL or similar if + * we previously failed connect() on the socket in the past + * (2) The address family of the socket needs to match that of the + * address we're trying to connect to. */ /* try each IP address until we connect successfully */ failed = 1; while (p_conn->addr) { + /* see memory note above */ + if ((rv = apr_socket_create(&p_conn->sock, p_conn->addr->family, + SOCK_STREAM, c->pool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, + "proxy: error creating socket"); + return HTTP_INTERNAL_SERVER_ERROR; + } + +#if !defined(TPF) && !defined(BEOS) + if (conf->recv_buffer_size > 0 && + (rv = apr_setsocketopt(p_conn->sock, APR_SO_RCVBUF, + conf->recv_buffer_size))) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "setsockopt(SO_RCVBUF): Failed to set " + "ProxyReceiveBufferSize, using default"); + } +#endif + + /* Set a timeout on the socket */ + apr_setsocketopt(p_conn->sock, APR_SO_TIMEOUT, + (int)(r->server->timeout * APR_USEC_PER_SEC)); + + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, + "proxy: socket has been created"); + /* make the connection out of the socket */ rv = apr_connect(p_conn->sock, p_conn->addr); /* if an error occurred, loop round and try again */ if (rv != APR_SUCCESS) { + apr_socket_close(p_conn->sock); ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, "proxy: attempt to connect to %pI (%s) failed", p_conn->addr, p_conn->name); @@ -403,7 +411,6 @@ apr_status_t ap_proxy_http_create_connection(apr_pool_t *p, request_rec *r, /* handle a permanent error from the above loop */ if (failed) { - apr_socket_close(p_conn->sock); if (proxyname) { return DECLINED; } else { @@ -433,7 +440,8 @@ apr_status_t ap_proxy_http_create_connection(apr_pool_t *p, request_rec *r, backend->port = p_conn->port; ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: connection complete"); + "proxy: connection complete to %pI (%s)", + p_conn->addr, p_conn->name); /* set up the connection filters */ ap_proxy_pre_http_connection(*origin); -- 2.50.1