--- httpd-2.2.18-original/modules/proxy/mod_proxy.c 2010-10-07 20:51:18.000000000 +0200 +++ httpd-2.2.18-original/modules/proxy/mod_proxy.c 2011-05-19 13:08:18.012828504 +0200 @@ -101,6 +101,15 @@ return "TTL must be at least one second"; worker->ttl = apr_time_from_sec(ival); } + else if (!strcasecmp(key, "dnsto")) { + /* Time in seconds that will cause a new dns lookup + * for the connection + */ + ival = atoi(val); + if (ival < 1) + return "DNSTO must be at least one second"; + worker->dnsto = apr_time_from_sec(ival); + } else if (!strcasecmp(key, "min")) { /* Initial number of connections to remote */ --- httpd-2.2.18-original/modules/proxy/mod_proxy.h 2010-10-07 20:51:18.000000000 +0200 +++ httpd-2.2.18-original/modules/proxy/mod_proxy.h 2011-05-19 13:09:41.758940503 +0200 @@ -358,6 +358,7 @@ char disablereuse_set; apr_interval_time_t conn_timeout; char conn_timeout_set; + apr_interval_time_t dnsto; /* Timeout for the stored ip address to be looked up again */ }; /* --- httpd-2.2.18-original/modules/proxy/proxy_util.c 2010-08-25 16:10:14.000000000 +0200 +++ httpd-2.2.18-original/modules/proxy/proxy_util.c 2011-05-19 13:14:09.241028504 +0200 @@ -49,6 +49,7 @@ static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r); static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r); static int proxy_match_word(struct dirconn_entry *This, request_rec *r); +static char *get_addr(char *buf, apr_sockaddr_t *sa); APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr), (r, pr), @@ -2026,14 +2027,62 @@ proxy_conn_rec *conn, server_rec *s) { + char old_address[512]; + char new_address[512]; + int dnsto; + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: has released connection for (%s)", proxy_function, conn->worker->hostname); - connection_cleanup(conn); + + dnsto = apr_time_sec(conn->worker->dnsto); + if (dnsto) { + apr_status_t return_value; + const char *hostname = conn->worker->hostname; + const apr_port_t port = conn->worker->port; + apr_sockaddr_t *old_sock_addr = conn->addr; + apr_sockaddr_t *new_sock_addr; + apr_pool_t *pool; + return_value = apr_pool_create(&pool, conn->pool); + apr_sockaddr_info_get(&new_sock_addr, hostname, APR_UNSPEC, port, 0, pool); + get_addr(old_address, old_sock_addr); + get_addr(new_address, new_sock_addr); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "proxy: ip of connection is %pI, the current resolved ip is %pI", + old_sock_addr, new_sock_addr); + if (strcmp(old_address, new_address)) { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + "proxy: Invalidating the connection due to change in dns resolved address."); + /* + * If the address has changed, store the changed + * address in all relevant places and mark the + * connection as due to be closed. + */ + conn->worker->cp->addr = new_sock_addr; + conn->addr = new_sock_addr; + conn->connection->remote_addr = new_sock_addr; + conn->close = 1; + } + } + + connection_cleanup(conn, s); return OK; } +static char *get_addr(char *p, apr_sockaddr_t *sa) +{ + apr_size_t sub_len; + + if (apr_sockaddr_ip_getbuf(p, sa->addr_str_len, sa)) { + /* Should only fail if the buffer is too small, which it + * should not be; but fail safe anyway: */ + strcpy(p, "?"); + } + + return (p); +} + PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, proxy_server_conf *conf,