diff options
Diffstat (limited to 'modules/proxy/mod_proxy.h')
-rw-r--r-- | modules/proxy/mod_proxy.h | 296 |
1 files changed, 284 insertions, 12 deletions
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index aabd09f..51a55f8 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -58,6 +58,7 @@ #include "http_main.h" #include "http_log.h" #include "http_connection.h" +#include "http_ssl.h" #include "util_filter.h" #include "util_ebcdic.h" #include "ap_provider.h" @@ -75,8 +76,12 @@ enum enctype { enc_path, enc_search, enc_user, enc_fpath, enc_parm }; +/* Flags for ap_proxy_canonenc_ex */ +#define PROXY_CANONENC_FORCEDEC 0x01 +#define PROXY_CANONENC_NOENCODEDSLASHENCODING 0x02 + typedef enum { - NONE, TCP, OPTIONS, HEAD, GET, CPING, PROVIDER, EOT + NONE, TCP, OPTIONS, HEAD, GET, CPING, PROVIDER, OPTIONS11, HEAD11, GET11, EOT } hcmethod_t; typedef struct { @@ -116,6 +121,7 @@ struct proxy_remote { const char *protocol; /* the scheme used to talk to this proxy */ const char *hostname; /* the hostname of this proxy */ ap_regex_t *regexp; /* compiled regex (if any) for the remote */ + const char *creds; /* auth credentials (if any) for the proxy */ int use_regex; /* simple boolean. True if we have a regex pattern */ apr_port_t port; /* the port for this proxy */ }; @@ -123,6 +129,8 @@ struct proxy_remote { #define PROXYPASS_NOCANON 0x01 #define PROXYPASS_INTERPOLATE 0x02 #define PROXYPASS_NOQUERY 0x04 +#define PROXYPASS_MAP_ENCODED 0x08 +#define PROXYPASS_MAP_SERVLET 0x18 /* + MAP_ENCODED */ struct proxy_alias { const char *real; const char *fake; @@ -199,9 +207,10 @@ typedef struct { unsigned int inherit_set:1; unsigned int ppinherit:1; unsigned int ppinherit_set:1; + unsigned int map_encoded_one:1; + unsigned int map_encoded_all:1; } proxy_server_conf; - typedef struct { const char *p; /* The path */ ap_regex_t *r; /* Is this a regex? */ @@ -240,6 +249,10 @@ typedef struct { /** Named back references */ apr_array_header_t *refs; + unsigned int forward_100_continue:1; + unsigned int forward_100_continue_set:1; + + apr_array_header_t *error_override_codes; } proxy_dir_conf; /* if we interpolate env vars per-request, we'll need a per-request @@ -251,6 +264,8 @@ typedef struct { apr_array_header_t* cookie_domains; } proxy_req_conf; +struct proxy_address; /* opaque TTL'ed and refcount'ed address */ + typedef struct { conn_rec *connection; request_rec *r; /* Request record of the backend request @@ -276,6 +291,9 @@ typedef struct { * and its scpool/bucket_alloc (NULL before), * must be left cleaned when used (locally). */ + apr_pool_t *uds_pool; /* Subpool for reusing UDS paths */ + apr_pool_t *fwd_pool; /* Subpool for reusing ProxyRemote infos */ + struct proxy_address *address; /* Current remote address */ } proxy_conn_rec; typedef struct { @@ -285,12 +303,15 @@ typedef struct { /* Connection pool */ struct proxy_conn_pool { - apr_pool_t *pool; /* The pool used in constructor and destructor calls */ - apr_sockaddr_t *addr; /* Preparsed remote address info */ - apr_reslist_t *res; /* Connection resource list */ - proxy_conn_rec *conn; /* Single connection for prefork mpm */ + apr_pool_t *pool; /* The pool used in constructor and destructor calls */ + apr_sockaddr_t *addr; /* Preparsed remote address info */ + apr_reslist_t *res; /* Connection resource list */ + proxy_conn_rec *conn; /* Single connection for prefork mpm */ + apr_pool_t *dns_pool; /* The pool used for worker scoped DNS resolutions */ }; +#define AP_VOLATILIZE_T(T, x) (*(T volatile *)&(x)) + /* worker status bits */ /* * NOTE: Keep up-to-date w/ proxy_wstat_tbl[] @@ -343,6 +364,8 @@ PROXY_WORKER_HC_FAIL ) #define PROXY_WORKER_IS_HCFAILED(f) ( (f)->s->status & PROXY_WORKER_HC_FAIL ) +#define PROXY_WORKER_IS_ERROR(f) ( (f)->s->status & PROXY_WORKER_IN_ERROR ) + #define PROXY_WORKER_IS(f, b) ( (f)->s->status & (b) ) /* default worker retry timeout in seconds */ @@ -357,8 +380,10 @@ PROXY_WORKER_HC_FAIL ) #define PROXY_WORKER_MAX_HOSTNAME_SIZE 64 #define PROXY_BALANCER_MAX_HOSTNAME_SIZE PROXY_WORKER_MAX_HOSTNAME_SIZE #define PROXY_BALANCER_MAX_STICKY_SIZE 64 +#define PROXY_WORKER_MAX_SECRET_SIZE 64 #define PROXY_RFC1035_HOSTNAME_SIZE 256 +#define PROXY_WORKER_EXT_NAME_SIZE 384 /* RFC-1035 mentions limits of 255 for host-names and 253 for domain-names, * dotted together(?) this would fit the below size (+ trailing NUL). @@ -379,6 +404,15 @@ do { \ (w)->s->io_buffer_size_set = (c)->io_buffer_size_set; \ } while (0) +#define PROXY_SHOULD_PING_100_CONTINUE(w, r) \ + ((w)->s->ping_timeout_set \ + && (PROXYREQ_REVERSE == (r)->proxyreq) \ + && ap_request_has_body((r))) + +#define PROXY_DO_100_CONTINUE(w, r) \ + (PROXY_SHOULD_PING_100_CONTINUE(w, r) \ + && !apr_table_get((r)->subprocess_env, "force-proxy-request-1.0")) + /* use 2 hashes */ typedef struct { unsigned int def; @@ -441,6 +475,7 @@ typedef struct { unsigned int keepalive_set:1; unsigned int disablereuse_set:1; unsigned int was_malloced:1; + unsigned int is_name_matchable:1; char hcuri[PROXY_WORKER_MAX_ROUTE_SIZE]; /* health check uri */ char hcexpr[PROXY_WORKER_MAX_SCHEME_SIZE]; /* name of condition expr for health check */ int passes; /* number of successes for check to pass */ @@ -453,6 +488,11 @@ typedef struct { char hostname_ex[PROXY_RFC1035_HOSTNAME_SIZE]; /* RFC1035 compliant version of the remote backend address */ apr_size_t response_field_size; /* Size of proxy response buffer in bytes. */ unsigned int response_field_size_set:1; + char secret[PROXY_WORKER_MAX_SECRET_SIZE]; /* authentication secret (e.g. AJP13) */ + char name_ex[PROXY_WORKER_EXT_NAME_SIZE]; /* Extended name (>96 chars for 2.4.x) */ + unsigned int address_ttl_set:1; + apr_int32_t address_ttl; /* backend address' TTL (seconds) */ + apr_uint32_t address_expiry; /* backend address' next expiry time */ } proxy_worker_shared; #define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared))) @@ -464,9 +504,12 @@ struct proxy_worker { proxy_conn_pool *cp; /* Connection pool to use */ proxy_worker_shared *s; /* Shared data */ proxy_balancer *balancer; /* which balancer am I in? */ +#if APR_HAS_THREADS apr_thread_mutex_t *tmutex; /* Thread lock for updating address cache */ +#endif void *context; /* general purpose storage */ ap_conf_vector_t *section_config; /* <Proxy>-section wherein defined */ + struct proxy_address *volatile address; /* current worker address (if reusable) */ }; /* default to health check every 30 seconds */ @@ -523,7 +566,9 @@ struct proxy_balancer { apr_time_t wupdated; /* timestamp of last change to workers list */ proxy_balancer_method *lbmethod; apr_global_mutex_t *gmutex; /* global lock for updating list of workers */ +#if APR_HAS_THREADS apr_thread_mutex_t *tmutex; /* Thread lock for updating shm */ +#endif proxy_server_conf *sconf; void *context; /* general purpose storage */ proxy_balancer_shared *s; /* Shared data */ @@ -602,6 +647,8 @@ APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r, proxy_worker *worker, proxy_server_conf *conf, char *url, const char *proxyhost, apr_port_t proxyport)) +APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, check_trans, + (request_rec *r, const char *url)) APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r, char *url)) @@ -643,6 +690,8 @@ PROXY_DECLARE(apr_status_t) ap_proxy_strncpy(char *dst, const char *src, apr_size_t dlen); PROXY_DECLARE(int) ap_proxy_hex2c(const char *x); PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x); +PROXY_DECLARE(char *)ap_proxy_canonenc_ex(apr_pool_t *p, const char *x, int len, enum enctype t, + int flags, int proxyreq); PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t, int forcedec, int proxyreq); PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp, @@ -656,7 +705,7 @@ PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *c * @param conf server configuration * @param hostname hostname from request URI * @param addr resolved address of hostname, or NULL if not known - * @return OK on success, or else an errro + * @return OK on success, or else an error */ PROXY_DECLARE(int) ap_proxy_checkproxyblock2(request_rec *r, proxy_server_conf *conf, const char *hostname, apr_sockaddr_t *addr); @@ -708,7 +757,42 @@ PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p, proxy_worker *worker); /** - * Get the worker from proxy configuration + * Return whether a worker upgrade configuration matches Upgrade header + * @param p memory pool used for displaying worker name + * @param worker the worker + * @param upgrade the Upgrade header to match + * @param dflt default protocol (NULL for none) + * @return 1 (true) or 0 (false) + */ +PROXY_DECLARE(int) ap_proxy_worker_can_upgrade(apr_pool_t *p, + const proxy_worker *worker, + const char *upgrade, + const char *dflt); + +/* Bitmask for ap_proxy_{define,get}_worker_ex(). */ +#define AP_PROXY_WORKER_IS_PREFIX (1u << 0) +#define AP_PROXY_WORKER_IS_MATCH (1u << 1) +#define AP_PROXY_WORKER_IS_MALLOCED (1u << 2) +#define AP_PROXY_WORKER_NO_UDS (1u << 3) + +/** + * Get the worker from proxy configuration, looking for either PREFIXED or + * MATCHED or both types of workers according to given mask + * @param p memory pool used for finding worker + * @param balancer the balancer that the worker belongs to + * @param conf current proxy server configuration + * @param url url to find the worker from + * @param mask bitmask of AP_PROXY_WORKER_IS_* + * @return proxy_worker or NULL if not found + */ +PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url, + unsigned int mask); + +/** + * Get the worker from proxy configuration, both types * @param p memory pool used for finding worker * @param balancer the balancer that the worker belongs to * @param conf current proxy server configuration @@ -719,7 +803,26 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, proxy_balancer *balancer, proxy_server_conf *conf, const char *url); + /** + * Define and Allocate space for the worker to proxy configuration, of either + * PREFIXED or MATCHED type according to given mask + * @param p memory pool to allocate worker from + * @param worker the new worker + * @param balancer the balancer that the worker belongs to + * @param conf current proxy server configuration + * @param url url containing worker name + * @param mask bitmask of AP_PROXY_WORKER_IS_* + * @return error message or NULL if successful (*worker is new worker) + */ +PROXY_DECLARE(char *) ap_proxy_define_worker_ex(apr_pool_t *p, + proxy_worker **worker, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url, + unsigned int mask); + + /** * Define and Allocate space for the worker to proxy configuration * @param p memory pool to allocate worker from * @param worker the new worker @@ -737,6 +840,25 @@ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p, int do_malloc); /** + * Define and Allocate space for the ap_strcmp_match()able worker to proxy + * configuration. + * @param p memory pool to allocate worker from + * @param worker the new worker + * @param balancer the balancer that the worker belongs to + * @param conf current proxy server configuration + * @param url url containing worker name (produces match pattern) + * @param do_malloc true if shared struct should be malloced + * @return error message or NULL if successful (*worker is new worker) + * @deprecated Replaced by ap_proxy_define_worker_ex() + */ +PROXY_DECLARE(char *) ap_proxy_define_match_worker(apr_pool_t *p, + proxy_worker **worker, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url, + int do_malloc); + +/** * Share a defined proxy worker via shm * @param worker worker to be shared * @param shm location of shared info @@ -912,6 +1034,29 @@ PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker, request_rec *r, proxy_server_conf *conf); +/* Bitmask for ap_proxy_determine_address() */ +#define PROXY_DETERMINE_ADDRESS_CHECK (1u << 0) +/** + * Resolve an address, reusing the one of the worker if any. + * @param proxy_function calling proxy scheme (http, ajp, ...) + * @param conn proxy connection the address is used for + * @param hostname host to resolve (should be the worker's if reusable) + * @param hostport port to resolve (should be the worker's if reusable) + * @param flags bitmask of PROXY_DETERMINE_ADDRESS_* + * @param r current request (if any) + * @param s current server (or NULL if r != NULL and ap_proxyerror() + * should be called on error) + * @return APR_SUCCESS or an error, APR_EEXIST if the address is still + * the same and PROXY_DETERMINE_ADDRESS_CHECK is asked + */ +PROXY_DECLARE(apr_status_t) ap_proxy_determine_address(const char *proxy_function, + proxy_conn_rec *conn, + const char *hostname, + apr_port_t hostport, + unsigned int flags, + request_rec *r, + server_rec *s); + /** * Determine backend hostname and port * @param p memory pool used for processing @@ -1112,13 +1257,27 @@ PROXY_DECLARE(apr_status_t) ap_proxy_sync_balancer(proxy_balancer *b, server_rec *s, proxy_server_conf *conf); +/** + * Configure and create workers (and balancer) in mod_balancer. + * @param r request + * @param params table with the parameters like b=mycluster etc. + * @return 404 when the worker/balancer doesn't exist, + * 400 if something is invalid + * 200 for success. + */ +APR_DECLARE_OPTIONAL_FN(apr_status_t, balancer_manage, + (request_rec *, apr_table_t *params)); /** * Find the matched alias for this request and setup for proxy handler * @param r request * @param ent proxy_alias record * @param dconf per-dir config or NULL - * @return DECLINED, DONE or OK if matched + * @return OK if the alias matched, + * DONE if the alias matched and r->uri was normalized so + * no further transformation should happen on it, + * DECLINED if proxying is disabled for this alias, + * HTTP_CONTINUE if the alias did not match */ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent, @@ -1151,6 +1310,55 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, char **old_te_val); /** + * Prefetch the client request body (in memory), up to a limit. + * Read what's in the client pipe. If nonblocking is set and read is EAGAIN, + * pass a FLUSH bucket to the backend and read again in blocking mode. + * @param r client request + * @param backend backend connection + * @param input_brigade input brigade to use/fill + * @param block blocking or non-blocking mode + * @param bytes_read number of bytes read + * @param max_read maximum number of bytes to read + * @return OK or HTTP_* error code + * @note max_read is rounded up to APR_BUCKET_BUFF_SIZE + */ +PROXY_DECLARE(int) ap_proxy_prefetch_input(request_rec *r, + proxy_conn_rec *backend, + apr_bucket_brigade *input_brigade, + apr_read_type_e block, + apr_off_t *bytes_read, + apr_off_t max_read); + +/** + * Spool the client request body to memory, or disk above given limit. + * @param r client request + * @param backend backend connection + * @param input_brigade input brigade to use/fill + * @param bytes_spooled number of bytes spooled + * @param max_mem_spool maximum number of in-memory bytes + * @return OK or HTTP_* error code + */ +PROXY_DECLARE(int) ap_proxy_spool_input(request_rec *r, + proxy_conn_rec *backend, + apr_bucket_brigade *input_brigade, + apr_off_t *bytes_spooled, + apr_off_t max_mem_spool); + +/** + * Read what's in the client pipe. If the read would block (EAGAIN), + * pass a FLUSH bucket to the backend and read again in blocking mode. + * @param r client request + * @param backend backend connection + * @param input_brigade brigade to use/fill + * @param max_read maximum number of bytes to read + * @return OK or HTTP_* error code + */ +PROXY_DECLARE(int) ap_proxy_read_input(request_rec *r, + proxy_conn_rec *backend, + apr_bucket_brigade *input_brigade, + apr_off_t max_read); + +/** * @param bucket_alloc bucket allocator * @param r request * @param p_conn proxy connection @@ -1164,6 +1372,41 @@ PROXY_DECLARE(int) ap_proxy_pass_brigade(apr_bucket_alloc_t *bucket_alloc, conn_rec *origin, apr_bucket_brigade *bb, int flush); +struct proxy_tunnel_conn; /* opaque */ +typedef struct { + request_rec *r; + const char *scheme; + apr_pollset_t *pollset; + apr_array_header_t *pfds; + apr_interval_time_t timeout; + struct proxy_tunnel_conn *client, + *origin; + apr_size_t read_buf_size; + int replied; /* TODO 2.5+: one bit to merge in below bitmask */ + unsigned int nohalfclose :1; +} proxy_tunnel_rec; + +/** + * Create a tunnel, to be activated by ap_proxy_tunnel_run(). + * @param tunnel tunnel created + * @param r client request + * @param c_o connection to origin + * @param scheme caller proxy scheme (connect, ws(s), http(s), ...) + * @return APR_SUCCESS or error status + */ +PROXY_DECLARE(apr_status_t) ap_proxy_tunnel_create(proxy_tunnel_rec **tunnel, + request_rec *r, conn_rec *c_o, + const char *scheme); + +/** + * Forward anything from either side of the tunnel to the other, + * until one end aborts or a polling timeout/error occurs. + * @param tunnel tunnel to run + * @return OK if completion is full, HTTP_GATEWAY_TIME_OUT on timeout + * or another HTTP_ error otherwise. + */ +PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel); + /** * Clear the headers referenced by the Connection header from the given * table, and remove the Connection header. @@ -1175,6 +1418,15 @@ APR_DECLARE_OPTIONAL_FN(int, ap_proxy_clear_connection, (request_rec *r, apr_table_t *headers)); /** + * Do a AJP CPING and wait for CPONG on the socket + * + */ +APR_DECLARE_OPTIONAL_FN(apr_status_t, ajp_handle_cping_cpong, + (apr_socket_t *sock, request_rec *r, + apr_interval_time_t timeout)); + + +/** * @param socket socket to test * @return TRUE if socket is connected/active */ @@ -1194,6 +1446,15 @@ PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket); int ap_proxy_lb_workers(void); /** + * Returns 1 if a response with the given status should be overridden. + * + * @param conf proxy directory configuration + * @param code http status code + * @return 1 if code is considered an error-code, 0 otherwise + */ +PROXY_DECLARE(int) ap_proxy_should_override(proxy_dir_conf *conf, int code); + +/** * Return the port number of a known scheme (eg: http -> 80). * @param scheme scheme to test * @return port number or 0 if unknown @@ -1238,6 +1499,15 @@ PROXY_DECLARE(apr_status_t) ap_proxy_buckets_lifetime_transform(request_rec *r, apr_bucket_brigade *from, apr_bucket_brigade *to); +/* + * The flags for ap_proxy_transfer_between_connections(), where for legacy and + * compatibility reasons FLUSH_EACH and FLUSH_AFTER are boolean values. + */ +#define AP_PROXY_TRANSFER_FLUSH_EACH (0x00) +#define AP_PROXY_TRANSFER_FLUSH_AFTER (0x01) +#define AP_PROXY_TRANSFER_YIELD_PENDING (0x02) +#define AP_PROXY_TRANSFER_YIELD_MAX_READS (0x04) + /* * Sends all data that can be read non blocking from the input filter chain of * c_i and send it down the output filter chain of c_o. For reading it uses @@ -1255,10 +1525,12 @@ PROXY_DECLARE(apr_status_t) ap_proxy_buckets_lifetime_transform(request_rec *r, * @param name string for logging from where data was pulled * @param sent if not NULL will be set to 1 if data was sent through c_o * @param bsize maximum amount of data pulled in one iteration from c_i - * @param after if set flush data on c_o only once after the loop + * @param flags AP_PROXY_TRANSFER_* bitmask * @return apr_status_t of the operation. Could be any error returned from * either the input filter chain of c_i or the output filter chain - * of c_o. APR_EPIPE if the outgoing connection was aborted. + * of c_o, APR_EPIPE if the outgoing connection was aborted, or + * APR_INCOMPLETE if AP_PROXY_TRANSFER_YIELD_PENDING was set and + * the output stack gets full before the input stack is exhausted. */ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( request_rec *r, @@ -1269,7 +1541,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( const char *name, int *sent, apr_off_t bsize, - int after); + int flags); extern module PROXY_DECLARE_DATA proxy_module; |