mirror of
https://github.com/apache/httpd.git
synced 2025-08-07 04:02:58 +03:00
This is the 1.3.x current proxy into 2.0 - first stage
PR: Obtained from: Sam Magnuson Submitted by: Chuck Murcko Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86923 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -58,7 +58,6 @@
|
|||||||
|
|
||||||
/* CONNECT method for Apache proxy */
|
/* CONNECT method for Apache proxy */
|
||||||
|
|
||||||
#include "apr_strings.h"
|
|
||||||
#include "mod_proxy.h"
|
#include "mod_proxy.h"
|
||||||
#include "http_log.h"
|
#include "http_log.h"
|
||||||
#include "http_main.h"
|
#include "http_main.h"
|
||||||
@@ -123,7 +122,7 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
int nbytes, i;
|
int nbytes, i;
|
||||||
|
|
||||||
BUFF *sock_buff;
|
BUFF *sock_buff;
|
||||||
apr_socket_t *client_sock=NULL;
|
apr_socket_t *client_sock = NULL;
|
||||||
apr_pollfd_t *pollfd;
|
apr_pollfd_t *pollfd;
|
||||||
apr_int32_t pollcnt;
|
apr_int32_t pollcnt;
|
||||||
apr_int16_t pollevent;
|
apr_int16_t pollevent;
|
||||||
@@ -144,7 +143,7 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if ProxyBlock directive on this host */
|
/* check if ProxyBlock directive on this host */
|
||||||
destaddr.s_addr = apr_inet_addr(host);
|
destaddr.s_addr = ap_inet_addr(host);
|
||||||
for (i = 0; i < conf->noproxies->nelts; i++) {
|
for (i = 0; i < conf->noproxies->nelts; i++) {
|
||||||
if ((npent[i].name != NULL && ap_strstr_c(host, npent[i].name) != NULL)
|
if ((npent[i].name != NULL && ap_strstr_c(host, npent[i].name) != NULL)
|
||||||
|| destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
|
|| destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
|
||||||
@@ -180,7 +179,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
return HTTP_INTERNAL_SERVER_ERROR;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ap_proxy_doconnect(sock, (char *)(proxyhost ? proxyhost : host), proxyport ? proxyport : port, r) == -1) {
|
if (ap_proxy_doconnect(sock, (char *)(proxyhost ? proxyhost : host),
|
||||||
|
proxyport ? proxyport : port, r) == -1) {
|
||||||
apr_close_socket(sock);
|
apr_close_socket(sock);
|
||||||
return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
|
return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
|
||||||
apr_pstrcat(r->pool, "Could not connect to remote machine:<br>",
|
apr_pstrcat(r->pool, "Could not connect to remote machine:<br>",
|
||||||
@@ -197,9 +197,11 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
*/
|
*/
|
||||||
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
|
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
|
||||||
"Sending the CONNECT request to the remote proxy");
|
"Sending the CONNECT request to the remote proxy");
|
||||||
nbytes = apr_snprintf(buffer, sizeof(buffer), "CONNECT %s HTTP/1.0" CRLF, r->uri);
|
nbytes = apr_snprintf(buffer, sizeof(buffer),
|
||||||
|
"CONNECT %s HTTP/1.0" CRLF, r->uri);
|
||||||
apr_send(sock, buffer, &nbytes);
|
apr_send(sock, buffer, &nbytes);
|
||||||
nbytes = apr_snprintf(buffer, sizeof(buffer),"Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
|
nbytes = apr_snprintf(buffer, sizeof(buffer),
|
||||||
|
"Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
|
||||||
apr_send(sock, buffer, &nbytes);
|
apr_send(sock, buffer, &nbytes);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -215,7 +217,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
|
|
||||||
if(apr_setup_poll(&pollfd, 2, r->pool) != APR_SUCCESS)
|
if(apr_setup_poll(&pollfd, 2, r->pool) != APR_SUCCESS)
|
||||||
{
|
{
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error apr_setup_poll()");
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||||
|
"proxy: error apr_setup_poll()");
|
||||||
return HTTP_INTERNAL_SERVER_ERROR;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,16 +229,17 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
just see if a recv gives us anything and do the same to sock (server) side, I'll leave this as TBD so
|
just see if a recv gives us anything and do the same to sock (server) side, I'll leave this as TBD so
|
||||||
one can decide the best path to take
|
one can decide the best path to take
|
||||||
*/
|
*/
|
||||||
if(apr_put_os_sock(&client_sock, (apr_os_sock_t *)get_socket(r->connection->client),
|
if(apr_put_os_sock(&client_sock,
|
||||||
|
(apr_os_sock_t *)get_socket(r->connection->client),
|
||||||
r->pool) != APR_SUCCESS)
|
r->pool) != APR_SUCCESS)
|
||||||
{
|
{
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error creating client apr_socket_t");
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||||
|
"proxy: error creating client apr_socket_t");
|
||||||
return HTTP_INTERNAL_SERVER_ERROR;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
apr_add_poll_socket(pollfd, client_sock, APR_POLLIN);
|
apr_add_poll_socket(pollfd, client_sock, APR_POLLIN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Add the server side to the poll */
|
/* Add the server side to the poll */
|
||||||
apr_add_poll_socket(pollfd, sock, APR_POLLIN);
|
apr_add_poll_socket(pollfd, sock, APR_POLLIN);
|
||||||
|
|
||||||
@@ -262,8 +266,7 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
o += i;
|
o += i;
|
||||||
nbytes -= i;
|
nbytes -= i;
|
||||||
}
|
}
|
||||||
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
|
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "Wrote %d bytes to client", nbytes);
|
||||||
"Wrote %d bytes to client", nbytes);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@@ -273,7 +276,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
if (pollevent & APR_POLLIN) {
|
if (pollevent & APR_POLLIN) {
|
||||||
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
|
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
|
||||||
"client was set");
|
"client was set");
|
||||||
if(ap_bread(r->connection->client, buffer, HUGE_STRING_LEN, &nbytes) == APR_SUCCESS) {
|
if(ap_bread(r->connection->client, buffer, HUGE_STRING_LEN,
|
||||||
|
&nbytes) == APR_SUCCESS) {
|
||||||
int o = 0;
|
int o = 0;
|
||||||
while(nbytes)
|
while(nbytes)
|
||||||
{
|
{
|
||||||
@@ -281,8 +285,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
o += i;
|
o += i;
|
||||||
nbytes -= i;
|
nbytes -= i;
|
||||||
}
|
}
|
||||||
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
|
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
|
||||||
"Wrote %d bytes to server", nbytes);
|
NULL, "Wrote %d bytes to server", nbytes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@@ -58,7 +58,6 @@
|
|||||||
|
|
||||||
/* HTTP routines for Apache proxy */
|
/* HTTP routines for Apache proxy */
|
||||||
|
|
||||||
#include "apr_strings.h"
|
|
||||||
#include "mod_proxy.h"
|
#include "mod_proxy.h"
|
||||||
#include "http_log.h"
|
#include "http_log.h"
|
||||||
#include "http_main.h"
|
#include "http_main.h"
|
||||||
@@ -135,7 +134,7 @@ static const char *proxy_location_reverse_map(request_rec *r, const char *url)
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear all connection-based headers from the incoming headers apr_table_t */
|
/* Clear all connection-based headers from the incoming headers table */
|
||||||
static void clear_connection(apr_pool_t *p, apr_table_t *headers)
|
static void clear_connection(apr_pool_t *p, apr_table_t *headers)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -174,23 +173,23 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
char *strp2;
|
char *strp2;
|
||||||
char *desthost;
|
char *desthost;
|
||||||
apr_socket_t *sock;
|
apr_socket_t *sock;
|
||||||
int i, len, backasswards, content_length=-1;
|
int i, len, backasswards, content_length = -1;
|
||||||
apr_array_header_t *reqhdrs_arr;
|
apr_array_header_t *reqhdrs_arr;
|
||||||
apr_table_t *resp_hdrs=NULL;
|
apr_table_t *resp_hdrs = NULL;
|
||||||
apr_table_entry_t *reqhdrs;
|
apr_table_entry_t *reqhdrs;
|
||||||
struct sockaddr_in server;
|
struct sockaddr_in server;
|
||||||
struct in_addr destaddr;
|
struct in_addr destaddr;
|
||||||
BUFF *f;
|
BUFF *f;
|
||||||
apr_file_t *cachefp=NULL;
|
|
||||||
char buffer[HUGE_STRING_LEN];
|
char buffer[HUGE_STRING_LEN];
|
||||||
char portstr[32];
|
char portstr[32];
|
||||||
apr_pool_t *p = r->pool;
|
apr_pool_t *p = r->pool;
|
||||||
const long int zero = 0L;
|
const long int zero = 0L;
|
||||||
int destport = 0;
|
int destport = 0;
|
||||||
apr_ssize_t cntr;
|
|
||||||
char *destportstr = NULL;
|
char *destportstr = NULL;
|
||||||
const char *urlptr = NULL;
|
const char *urlptr = NULL;
|
||||||
char *datestr, *clen;
|
char *datestr, *clen;
|
||||||
|
apr_ssize_t cntr;
|
||||||
|
apr_file_t *cachefp = NULL;
|
||||||
|
|
||||||
void *sconf = r->server->module_config;
|
void *sconf = r->server->module_config;
|
||||||
proxy_server_conf *conf =
|
proxy_server_conf *conf =
|
||||||
@@ -234,8 +233,10 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
/* check if ProxyBlock directive on this host */
|
/* check if ProxyBlock directive on this host */
|
||||||
destaddr.s_addr = apr_inet_addr(desthost);
|
destaddr.s_addr = apr_inet_addr(desthost);
|
||||||
for (i = 0; i < conf->noproxies->nelts; i++) {
|
for (i = 0; i < conf->noproxies->nelts; i++) {
|
||||||
if ((npent[i].name != NULL && ap_strstr_c(desthost, npent[i].name) != NULL)
|
if ((npent[i].name != NULL
|
||||||
|| destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
|
&& ap_strstr_c(desthost, npent[i].name) != NULL)
|
||||||
|
|| destaddr.s_addr == npent[i].addr.s_addr
|
||||||
|
|| npent[i].name[0] == '*')
|
||||||
return ap_proxyerror(r, HTTP_FORBIDDEN,
|
return ap_proxyerror(r, HTTP_FORBIDDEN,
|
||||||
"Connect to remote machine blocked");
|
"Connect to remote machine blocked");
|
||||||
}
|
}
|
||||||
@@ -246,10 +247,13 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
return HTTP_INTERNAL_SERVER_ERROR;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,conf->recv_buffer_size)) {
|
#if !defined(TPF) && !defined(BEOS)
|
||||||
|
if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,
|
||||||
|
conf->recv_buffer_size)) {
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||||
"setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
|
"setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (proxyhost != NULL) {
|
if (proxyhost != NULL) {
|
||||||
i = ap_proxy_doconnect(sock, (char *)proxyhost, proxyport, r);
|
i = ap_proxy_doconnect(sock, (char *)proxyhost, proxyport, r);
|
||||||
@@ -262,8 +266,8 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
if (proxyhost != NULL)
|
if (proxyhost != NULL)
|
||||||
return DECLINED; /* try again another way */
|
return DECLINED; /* try again another way */
|
||||||
else
|
else
|
||||||
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
|
return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(r->pool,
|
||||||
apr_pstrcat(r->pool, "Could not connect to remote machine: ",
|
"Could not connect to remote machine: ",
|
||||||
strerror(errno), NULL));
|
strerror(errno), NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +295,7 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
apr_snprintf(portstr, sizeof portstr, ":%d", i);
|
apr_snprintf(portstr, sizeof portstr, ":%d", i);
|
||||||
}
|
}
|
||||||
/* Generate outgoing Via: header with/without server comment: */
|
/* Generate outgoing Via: header with/without server comment: */
|
||||||
apr_table_mergen(r->headers_in, "Via",
|
ap_table_mergen(r->headers_in, "Via",
|
||||||
(conf->viaopt == via_full)
|
(conf->viaopt == via_full)
|
||||||
? apr_psprintf(p, "%d.%d %s%s (%s)",
|
? apr_psprintf(p, "%d.%d %s%s (%s)",
|
||||||
HTTP_VERSION_MAJOR(r->proto_num),
|
HTTP_VERSION_MAJOR(r->proto_num),
|
||||||
@@ -367,6 +371,7 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
/* read the headers. */
|
/* read the headers. */
|
||||||
/* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
|
/* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
|
||||||
/* Also, take care with headers with multiple occurences. */
|
/* Also, take care with headers with multiple occurences. */
|
||||||
|
|
||||||
resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f);
|
resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f);
|
||||||
if (resp_hdrs == NULL) {
|
if (resp_hdrs == NULL) {
|
||||||
ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
|
ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
|
||||||
@@ -391,8 +396,8 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
ap_cache_el_header_add(c, "Via", (conf->viaopt == via_full)
|
ap_cache_el_header_add(c, "Via", (conf->viaopt == via_full)
|
||||||
? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor,
|
? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor,
|
||||||
ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION)
|
ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION)
|
||||||
: apr_psprintf(p, "%d.%d %s%s", major, minor, ap_get_server_name(r), portstr)
|
: apr_psprintf(p, "%d.%d %s%s", major, minor,
|
||||||
);
|
ap_get_server_name(r), portstr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -436,7 +441,8 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
/* write status line */
|
/* write status line */
|
||||||
if (!r->assbackwards)
|
if (!r->assbackwards)
|
||||||
ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL);
|
ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL);
|
||||||
if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ", r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) {
|
if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ",
|
||||||
|
r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) {
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||||
"proxy: error writing status line to cache");
|
"proxy: error writing status line to cache");
|
||||||
ap_proxy_cache_error(&c);
|
ap_proxy_cache_error(&c);
|
||||||
@@ -451,14 +457,13 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
|
|
||||||
ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
|
ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
|
||||||
r->sent_bodyct = 1;
|
r->sent_bodyct = 1;
|
||||||
/* Is it an HTTP/0.9 respose? If so, send the extra data */
|
/* Is it an HTTP/0.9 response? If so, send the extra data */
|
||||||
if (backasswards) {
|
if (backasswards) {
|
||||||
ap_bwrite(r->connection->client, buffer, len, &cntr);
|
ap_bwrite(r->connection->client, buffer, len, &cntr);
|
||||||
cntr = len;
|
cntr = len;
|
||||||
if (cachefp && apr_write(cachefp, buffer, &cntr) != APR_SUCCESS) {
|
if (cachefp && apr_write(cachefp, buffer, &cntr) != APR_SUCCESS) {
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||||
"proxy: error writing extra data to cache %ld",
|
"proxy: error writing extra data to cache");
|
||||||
(long)cachefp);
|
|
||||||
ap_proxy_cache_error(&c);
|
ap_proxy_cache_error(&c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -57,21 +57,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Utility routines for Apache proxy */
|
/* Utility routines for Apache proxy */
|
||||||
#include "apr_strings.h"
|
|
||||||
#include "mod_proxy.h"
|
#include "mod_proxy.h"
|
||||||
#include "http_main.h"
|
#include "http_main.h"
|
||||||
#include "apr_md5.h"
|
|
||||||
#include "http_log.h"
|
#include "http_log.h"
|
||||||
#include "util_uri.h"
|
#include "util_uri.h"
|
||||||
#include "util_date.h" /* get ap_checkmask() decl. */
|
#include "util_date.h" /* get ap_checkmask() decl. */
|
||||||
|
#include "apr_md5.h"
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
|
static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
|
||||||
static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
|
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_hostname(struct dirconn_entry *This, request_rec *r);
|
||||||
static int proxy_match_word(struct dirconn_entry *This, request_rec *r);
|
static int proxy_match_word(struct dirconn_entry *This, request_rec *r);
|
||||||
|
static struct per_thread_data *get_per_thread_data(void);
|
||||||
/* already called in the knowledge that the characters are hex digits */
|
/* already called in the knowledge that the characters are hex digits */
|
||||||
int ap_proxy_hex2c(const char *x)
|
int ap_proxy_hex2c(const char *x)
|
||||||
{
|
{
|
||||||
@@ -137,8 +134,8 @@ void ap_proxy_c2hex(int ch, char *x)
|
|||||||
* and encodes those which must be encoded, and does not touch
|
* and encodes those which must be encoded, and does not touch
|
||||||
* those which must not be touched.
|
* those which must not be touched.
|
||||||
*/
|
*/
|
||||||
char *
|
char *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
|
||||||
ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t, int isenc)
|
int isenc)
|
||||||
{
|
{
|
||||||
int i, j, ch;
|
int i, j, ch;
|
||||||
char *y;
|
char *y;
|
||||||
@@ -181,7 +178,7 @@ char *
|
|||||||
}
|
}
|
||||||
/* decode it if not already done */
|
/* decode it if not already done */
|
||||||
if (isenc && ch == '%') {
|
if (isenc && ch == '%') {
|
||||||
if (!apr_isxdigit(x[i + 1]) || !apr_isxdigit(x[i + 2]))
|
if (!ap_isxdigit(x[i + 1]) || !ap_isxdigit(x[i + 2]))
|
||||||
return NULL;
|
return NULL;
|
||||||
ch = ap_proxy_hex2c(&x[i + 1]);
|
ch = ap_proxy_hex2c(&x[i + 1]);
|
||||||
i += 2;
|
i += 2;
|
||||||
@@ -275,7 +272,7 @@ char *
|
|||||||
return "Port number in URL > 65535";
|
return "Port number in URL > 65535";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ap_str_tolower(host); /* DNS names are case insensitive */
|
ap_str_tolower(host); /* DNS names are case-insensitive */
|
||||||
if (*host == '\0')
|
if (*host == '\0')
|
||||||
return "Missing host in URL";
|
return "Missing host in URL";
|
||||||
/* check hostname syntax */
|
/* check hostname syntax */
|
||||||
@@ -283,10 +280,10 @@ char *
|
|||||||
if (!apr_isdigit(host[i]) && host[i] != '.')
|
if (!apr_isdigit(host[i]) && host[i] != '.')
|
||||||
break;
|
break;
|
||||||
/* must be an IP address */
|
/* must be an IP address */
|
||||||
#ifdef WIN32
|
#if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
|
||||||
if (host[i] == '\0' && (inet_addr(host) == -1))
|
if (host[i] == '\0' && (inet_addr(host) == -1))
|
||||||
#else
|
#else
|
||||||
if (host[i] == '\0' && (apr_inet_addr(host) == -1 || inet_network(host) == -1))
|
if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return "Bad IP address in URL";
|
return "Bad IP address in URL";
|
||||||
@@ -348,7 +345,7 @@ const char *
|
|||||||
&min, &sec, &year) != 7)
|
&min, &sec, &year) != 7)
|
||||||
return x;
|
return x;
|
||||||
for (wk = 0; wk < 7; wk++)
|
for (wk = 0; wk < 7; wk++)
|
||||||
if (strcmp(week, apr_day_snames[wk]) == 0)
|
if (strcmp(week, ap_day_snames[wk]) == 0)
|
||||||
break;
|
break;
|
||||||
if (wk == 7)
|
if (wk == 7)
|
||||||
return x;
|
return x;
|
||||||
@@ -356,14 +353,14 @@ const char *
|
|||||||
|
|
||||||
/* check date */
|
/* check date */
|
||||||
for (mon = 0; mon < 12; mon++)
|
for (mon = 0; mon < 12; mon++)
|
||||||
if (strcmp(month, apr_month_snames[mon]) == 0)
|
if (strcmp(month, ap_month_snames[mon]) == 0)
|
||||||
break;
|
break;
|
||||||
if (mon == 12)
|
if (mon == 12)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
q = apr_palloc(p, 30);
|
q = apr_palloc(p, 30);
|
||||||
apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", apr_day_snames[wk], mday,
|
apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[wk],
|
||||||
apr_month_snames[mon], year, hour, min, sec);
|
mday, ap_month_snames[mon], year, hour, min, sec);
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +436,7 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF
|
|||||||
char *value, *end;
|
char *value, *end;
|
||||||
char field[MAX_STRING_LEN];
|
char field[MAX_STRING_LEN];
|
||||||
|
|
||||||
resp_hdrs = apr_make_table(r->pool, 20);
|
resp_hdrs = ap_make_table(r->pool, 20);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read header lines until we get the empty separator line, a read error,
|
* Read header lines until we get the empty separator line, a read error,
|
||||||
@@ -478,7 +475,7 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF
|
|||||||
for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
|
for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
|
||||||
*end = '\0';
|
*end = '\0';
|
||||||
|
|
||||||
apr_table_add(resp_hdrs, buffer, value);
|
ap_table_add(resp_hdrs, buffer, value);
|
||||||
|
|
||||||
/* the header was too long; at the least we should skip extra data */
|
/* the header was too long; at the least we should skip extra data */
|
||||||
if (len >= size - 1) {
|
if (len >= size - 1) {
|
||||||
@@ -521,17 +518,20 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
|
|||||||
* has its own timeout handler which can set both buffers to EOUT.
|
* has its own timeout handler which can set both buffers to EOUT.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef WIN32
|
#if defined(WIN32) || defined(TPF) || defined(NETWARE)
|
||||||
/* works fine under win32, so leave it */
|
/* works fine under win32, so leave it */
|
||||||
|
alternate_timeouts = 0;
|
||||||
#else
|
#else
|
||||||
/* CHECKME! Since hard_timeout won't work in unix on sends with partial
|
/* CHECKME! Since hard_timeout won't work in unix on sends with partial
|
||||||
* cache completion, we have to alternate between hard_timeout
|
* cache completion, we have to alternate between hard_timeout
|
||||||
* for reads, and soft_timeout for send. This is because we need
|
* for reads, and soft_timeout for send. This is because we need
|
||||||
* to get a return from ap_bwrite to be able to continue caching.
|
* to get a return from ap_bwrite to be able to continue caching.
|
||||||
* BUT, if we *can't* continue anyway, just use hard_timeout.
|
* BUT, if we *can't* continue anyway, just use hard_timeout.
|
||||||
|
* (Also, if no cache file is written, use hard timeouts)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!completion || completion->content_length > 0 || completion->cache_completion == 1.0) {
|
if (!completion || completion->content_length > 0
|
||||||
|
|| completion->cache_completion == 1.0) {
|
||||||
alternate_timeouts = 0;
|
alternate_timeouts = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -540,9 +540,9 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
|
|||||||
* or (after the client aborted) while we can successfully
|
* or (after the client aborted) while we can successfully
|
||||||
* read and finish the configured cache_completion.
|
* read and finish the configured cache_completion.
|
||||||
*/
|
*/
|
||||||
for (ok = 1; ok; cntr=0) {
|
for (ok = 1; ok; cntr = 0) {
|
||||||
/* Read block from server */
|
/* Read block from server */
|
||||||
if(ap_bread(f, buf, IOBUFSIZE, &cntr) != APR_SUCCESS && !cntr)
|
if (ap_bread(f, buf, IOBUFSIZE, &cntr) != APR_SUCCESS && !cntr)
|
||||||
{
|
{
|
||||||
if (c != NULL) {
|
if (c != NULL) {
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||||
@@ -553,7 +553,6 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
|
|||||||
}
|
}
|
||||||
else if(cntr == 0) break;
|
else if(cntr == 0) break;
|
||||||
|
|
||||||
|
|
||||||
/* Write to cache first. */
|
/* Write to cache first. */
|
||||||
/*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */
|
/*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */
|
||||||
wrote_to_cache = cntr;
|
wrote_to_cache = cntr;
|
||||||
@@ -561,7 +560,6 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
|
|||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||||
"proxy: error writing to cache");
|
"proxy: error writing to cache");
|
||||||
ap_proxy_cache_error(&c);
|
ap_proxy_cache_error(&c);
|
||||||
cachefp = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
written += n;
|
written += n;
|
||||||
}
|
}
|
||||||
@@ -614,7 +612,7 @@ void ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *t)
|
|||||||
|
|
||||||
ap_bvputs(fp, respline, CRLF, NULL);
|
ap_bvputs(fp, respline, CRLF, NULL);
|
||||||
|
|
||||||
for (i = 0; i < apr_table_elts(t)->nelts; ++i) {
|
for (i = 0; i < ap_table_elts(t)->nelts; ++i) {
|
||||||
if (elts[i].key != NULL) {
|
if (elts[i].key != NULL) {
|
||||||
ap_bvputs(fp, elts[i].key, ": ", elts[i].val, CRLF, NULL);
|
ap_bvputs(fp, elts[i].key, ": ", elts[i].val, CRLF, NULL);
|
||||||
apr_table_addn(r->headers_out, elts[i].key, elts[i].val);
|
apr_table_addn(r->headers_out, elts[i].key, elts[i].val);
|
||||||
@@ -626,7 +624,7 @@ void ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *t)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* list is a comma-separated list of case insensitive tokens, with
|
* list is a comma-separated list of case-insensitive tokens, with
|
||||||
* optional whitespace around the tokens.
|
* optional whitespace around the tokens.
|
||||||
* The return returns 1 if the token val is found in the list, or 0
|
* The return returns 1 if the token val is found in the list, or 0
|
||||||
* otherwise.
|
* otherwise.
|
||||||
@@ -658,7 +656,6 @@ int ap_proxy_liststr(const char *list, const char *val)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Converts 8 hex digits to a time integer
|
* Converts 8 hex digits to a time integer
|
||||||
*/
|
*/
|
||||||
@@ -740,11 +737,7 @@ const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
/* XXX - Either get rid of TLS, or use pthread/APR functions */
|
struct per_thread_data *ptd = get_per_thread_data();
|
||||||
#define APACHE_TLS
|
|
||||||
static APACHE_TLS struct hostent hpbuf;
|
|
||||||
static APACHE_TLS u_long ipaddr;
|
|
||||||
static APACHE_TLS char *charpbuf[2];
|
|
||||||
|
|
||||||
for (i = 0; host[i] != '\0'; i++)
|
for (i = 0; host[i] != '\0'; i++)
|
||||||
if (!apr_isdigit(host[i]) && host[i] != '.')
|
if (!apr_isdigit(host[i]) && host[i] != '.')
|
||||||
@@ -756,17 +749,17 @@ const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp)
|
|||||||
return "Host not found";
|
return "Host not found";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ipaddr = apr_inet_addr(host);
|
ptd->ipaddr = ap_inet_addr(host);
|
||||||
hp = gethostbyaddr((char *) &ipaddr, sizeof(u_long), AF_INET);
|
hp = gethostbyaddr((char *) &ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET);
|
||||||
if (hp == NULL) {
|
if (hp == NULL) {
|
||||||
memset(&hpbuf, 0, sizeof(hpbuf));
|
memset(&ptd->hpbuf, 0, sizeof(ptd->hpbuf));
|
||||||
hpbuf.h_name = 0;
|
ptd->hpbuf.h_name = 0;
|
||||||
hpbuf.h_addrtype = AF_INET;
|
ptd->hpbuf.h_addrtype = AF_INET;
|
||||||
hpbuf.h_length = sizeof(u_long);
|
ptd->hpbuf.h_length = sizeof(ptd->ipaddr);
|
||||||
hpbuf.h_addr_list = charpbuf;
|
ptd->hpbuf.h_addr_list = ptd->charpbuf;
|
||||||
hpbuf.h_addr_list[0] = (char *) &ipaddr;
|
ptd->hpbuf.h_addr_list[0] = (char *) &ptd->ipaddr;
|
||||||
hpbuf.h_addr_list[1] = 0;
|
ptd->hpbuf.h_addr_list[1] = 0;
|
||||||
hp = &hpbuf;
|
hp = &ptd->hpbuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*reqhp = *hp;
|
*reqhp = *hp;
|
||||||
@@ -809,7 +802,7 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
|
|||||||
long bits;
|
long bits;
|
||||||
|
|
||||||
/* if the address is given with an explicit netmask, use that */
|
/* if the address is given with an explicit netmask, use that */
|
||||||
/* Due to a deficiency in apr_inet_addr(), it is impossible to parse */
|
/* Due to a deficiency in ap_inet_addr(), it is impossible to parse */
|
||||||
/* "partial" addresses (with less than 4 quads) correctly, i.e. */
|
/* "partial" addresses (with less than 4 quads) correctly, i.e. */
|
||||||
/* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
|
/* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
|
||||||
/* I therefore have to parse the IP address manually: */
|
/* I therefore have to parse the IP address manually: */
|
||||||
@@ -881,18 +874,19 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
|
|||||||
|
|
||||||
if (bits != 32) /* no warning for fully qualified IP address */
|
if (bits != 32) /* no warning for fully qualified IP address */
|
||||||
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
|
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
|
||||||
"Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld",
|
"Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
|
||||||
inet_ntoa(This->addr), bits);
|
inet_ntoa(This->addr), bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits));
|
This->mask.s_addr = htonl(INADDR_NONE << (32 - bits));
|
||||||
|
|
||||||
if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
|
if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
|
||||||
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Warning: NetMask and IP-Addr disagree in %s/%ld",
|
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
|
||||||
|
"Warning: NetMask and IP-Addr disagree in %s/%ld\n",
|
||||||
inet_ntoa(This->addr), bits);
|
inet_ntoa(This->addr), bits);
|
||||||
This->addr.s_addr &= This->mask.s_addr;
|
This->addr.s_addr &= This->mask.s_addr;
|
||||||
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
|
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
|
||||||
" Set to %s/%ld",
|
" Set to %s/%ld\n",
|
||||||
inet_ntoa(This->addr), bits);
|
inet_ntoa(This->addr), bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1134,6 +1128,7 @@ static int proxy_match_word(struct dirconn_entry *This, request_rec *r)
|
|||||||
int ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t port, request_rec *r)
|
int ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t port, request_rec *r)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; host[i] != '\0'; i++)
|
for (i = 0; host[i] != '\0'; i++)
|
||||||
if (!apr_isdigit(host[i]) && host[i] != '.')
|
if (!apr_isdigit(host[i]) && host[i] != '.')
|
||||||
break;
|
break;
|
||||||
@@ -1151,14 +1146,15 @@ int ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t port, reques
|
|||||||
else if (rv == APR_SUCCESS)
|
else if (rv == APR_SUCCESS)
|
||||||
return 0;
|
return 0;
|
||||||
else {
|
else {
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy connect to %s port %d failed", host, port);
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
|
||||||
|
"proxy connect to %s port %d failed", host, port);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called by apr_table_do() for all header lines */
|
/* This function is called by ap_table_do() for all header lines */
|
||||||
/* (from proxy_http.c and proxy_ftp.c) */
|
/* (from proxy_http.c and proxy_ftp.c) */
|
||||||
/* It is passed a table_do_args struct pointer and a MIME field and value pair */
|
/* It is passed a table_do_args struct pointer and a MIME field and value pair */
|
||||||
int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
|
int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
|
||||||
@@ -1168,7 +1164,7 @@ int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
|
|||||||
return 1;
|
return 1;
|
||||||
if (!r->assbackwards)
|
if (!r->assbackwards)
|
||||||
ap_rvputs(r, key, ": ", value, CRLF, NULL);
|
ap_rvputs(r, key, ": ", value, CRLF, NULL);
|
||||||
return 1; /* tell apr_table_do() to continue calling us for more headers */
|
return 1; /* tell ap_table_do() to continue calling us for more headers */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send a text line to one or two BUFF's; return line length */
|
/* send a text line to one or two BUFF's; return line length */
|
||||||
@@ -1182,6 +1178,51 @@ unsigned ap_proxy_bputs2(const char *data, BUFF *client, ap_cache_el *cache)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined WIN32
|
||||||
|
|
||||||
|
static DWORD tls_index;
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
|
||||||
|
{
|
||||||
|
LPVOID memptr;
|
||||||
|
|
||||||
|
switch (reason) {
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
tls_index = TlsAlloc();
|
||||||
|
case DLL_THREAD_ATTACH: /* intentional no break */
|
||||||
|
TlsSetValue (tls_index, malloc (sizeof (struct per_thread_data)));
|
||||||
|
break;
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
memptr = TlsGetValue (tls_index);
|
||||||
|
if (memptr) {
|
||||||
|
free (memptr);
|
||||||
|
TlsSetValue (tls_index, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct per_thread_data *get_per_thread_data(void)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
#if defined(WIN32)
|
||||||
|
|
||||||
|
return (struct per_thread_data *) TlsGetValue (tls_index);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static APACHE_TLS struct per_thread_data sptd;
|
||||||
|
return &sptd;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int ap_proxy_cache_send(request_rec *r, ap_cache_el *c)
|
int ap_proxy_cache_send(request_rec *r, ap_cache_el *c)
|
||||||
{
|
{
|
||||||
apr_file_t *cachefp = NULL;
|
apr_file_t *cachefp = NULL;
|
||||||
|
Reference in New Issue
Block a user