1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef MOD_PROXY_H 18#define MOD_PROXY_H 19 20/** 21 * @file mod_proxy.h 22 * @brief Proxy Extension Module for Apache 23 * 24 * @defgroup MOD_PROXY mod_proxy 25 * @ingroup APACHE_MODS 26 * @{ 27 */ 28 29#include "apr_hooks.h" 30#include "apr_optional.h" 31#include "apr.h" 32#include "apr_lib.h" 33#include "apr_strings.h" 34#include "apr_buckets.h" 35#include "apr_md5.h" 36#include "apr_network_io.h" 37#include "apr_pools.h" 38#include "apr_strings.h" 39#include "apr_uri.h" 40#include "apr_date.h" 41#include "apr_strmatch.h" 42#include "apr_fnmatch.h" 43#include "apr_reslist.h" 44#define APR_WANT_STRFUNC 45#include "apr_want.h" 46#include "apr_uuid.h" 47#include "util_mutex.h" 48#include "apr_global_mutex.h" 49#include "apr_thread_mutex.h" 50 51#include "httpd.h" 52#include "http_config.h" 53#include "ap_config.h" 54#include "http_core.h" 55#include "http_protocol.h" 56#include "http_request.h" 57#include "http_vhost.h" 58#include "http_main.h" 59#include "http_log.h" 60#include "http_connection.h" 61#include "util_filter.h" 62#include "util_ebcdic.h" 63#include "ap_provider.h" 64#include "ap_slotmem.h" 65 66#if APR_HAVE_NETINET_IN_H 67#include <netinet/in.h> 68#endif 69#if APR_HAVE_ARPA_INET_H 70#include <arpa/inet.h> 71#endif 72 73/* for proxy_canonenc() */ 74enum enctype { 75 enc_path, enc_search, enc_user, enc_fpath, enc_parm 76}; 77 78#define BALANCER_PREFIX "balancer://" 79 80#if APR_CHARSET_EBCDIC 81#define CRLF "\r\n" 82#else /*APR_CHARSET_EBCDIC*/ 83#define CRLF "\015\012" 84#endif /*APR_CHARSET_EBCDIC*/ 85 86/* default Max-Forwards header setting */ 87/* Set this to -1, which complies with RFC2616 by not setting 88 * max-forwards if the client didn't send it to us. 89 */ 90#define DEFAULT_MAX_FORWARDS -1 91 92typedef struct proxy_balancer proxy_balancer; 93typedef struct proxy_worker proxy_worker; 94typedef struct proxy_conn_pool proxy_conn_pool; 95typedef struct proxy_balancer_method proxy_balancer_method; 96 97/* static information about a remote proxy */ 98struct proxy_remote { 99 const char *scheme; /* the schemes handled by this proxy, or '*' */ 100 const char *protocol; /* the scheme used to talk to this proxy */ 101 const char *hostname; /* the hostname of this proxy */ 102 ap_regex_t *regexp; /* compiled regex (if any) for the remote */ 103 int use_regex; /* simple boolean. True if we have a regex pattern */ 104 apr_port_t port; /* the port for this proxy */ 105}; 106 107#define PROXYPASS_NOCANON 0x01 108#define PROXYPASS_INTERPOLATE 0x02 109#define PROXYPASS_NOQUERY 0x04 110struct proxy_alias { 111 const char *real; 112 const char *fake; 113 ap_regex_t *regex; 114 unsigned int flags; 115 proxy_balancer *balancer; /* only valid for reverse-proxys */ 116}; 117 118struct dirconn_entry { 119 char *name; 120 struct in_addr addr, mask; 121 struct apr_sockaddr_t *hostaddr; 122 int (*matcher) (struct dirconn_entry * This, request_rec *r); 123}; 124 125struct noproxy_entry { 126 const char *name; 127 struct apr_sockaddr_t *addr; 128}; 129 130typedef struct { 131 apr_array_header_t *proxies; 132 apr_array_header_t *sec_proxy; 133 apr_array_header_t *aliases; 134 apr_array_header_t *noproxies; 135 apr_array_header_t *dirconn; 136 apr_array_header_t *workers; /* non-balancer workers, eg ProxyPass http://example.com */ 137 apr_array_header_t *balancers; /* list of balancers @ config time */ 138 proxy_worker *forward; /* forward proxy worker */ 139 proxy_worker *reverse; /* reverse "module-driven" proxy worker */ 140 const char *domain; /* domain name to use in absence of a domain name in the request */ 141 const char *id; 142 apr_pool_t *pool; /* Pool used for allocating this struct */ 143 int req; /* true if proxy requests are enabled */ 144 int max_balancers; /* maximum number of allowed balancers */ 145 int bgrowth; /* number of post-config balancers can added */ 146 enum { 147 via_off, 148 via_on, 149 via_block, 150 via_full 151 } viaopt; /* how to deal with proxy Via: headers */ 152 apr_size_t recv_buffer_size; 153 apr_size_t io_buffer_size; 154 long maxfwd; 155 apr_interval_time_t timeout; 156 enum { 157 bad_error, 158 bad_ignore, 159 bad_body 160 } badopt; /* how to deal with bad headers */ 161 enum { 162 status_off, 163 status_on, 164 status_full 165 } proxy_status; /* Status display options */ 166 apr_sockaddr_t *source_address; 167 apr_global_mutex_t *mutex; /* global lock, for pool, etc */ 168 ap_slotmem_instance_t *bslot; /* balancers shm data - runtime */ 169 ap_slotmem_provider_t *storage; 170 171 unsigned int req_set:1; 172 unsigned int viaopt_set:1; 173 unsigned int recv_buffer_size_set:1; 174 unsigned int io_buffer_size_set:1; 175 unsigned int maxfwd_set:1; 176 unsigned int timeout_set:1; 177 unsigned int badopt_set:1; 178 unsigned int proxy_status_set:1; 179 unsigned int source_address_set:1; 180 unsigned int bgrowth_set:1; 181 unsigned int bal_persist:1; 182 unsigned int inherit:1; 183 unsigned int inherit_set:1; 184 unsigned int ppinherit:1; 185 unsigned int ppinherit_set:1; 186} proxy_server_conf; 187 188 189typedef struct { 190 const char *p; /* The path */ 191 ap_regex_t *r; /* Is this a regex? */ 192 193/* FIXME 194 * ProxyPassReverse and friends are documented as working inside 195 * <Location>. But in fact they never have done in the case of 196 * more than one <Location>, because the server_conf can't see it. 197 * We need to move them to the per-dir config. 198 * Discussed in February 2005: 199 * http://marc.theaimsgroup.com/?l=apache-httpd-dev&m=110726027118798&w=2 200 */ 201 apr_array_header_t *raliases; 202 apr_array_header_t* cookie_paths; 203 apr_array_header_t* cookie_domains; 204 signed char p_is_fnmatch; /* Is the path an fnmatch candidate? */ 205 signed char interpolate_env; 206 struct proxy_alias *alias; 207 208 /** 209 * the following setting masks the error page 210 * returned from the 'proxied server' and just 211 * forwards the status code upwards. 212 * This allows the main server (us) to generate 213 * the error page, (so it will look like a error 214 * returned from the rest of the system 215 */ 216 unsigned int error_override:1; 217 unsigned int preserve_host:1; 218 unsigned int preserve_host_set:1; 219 unsigned int error_override_set:1; 220 unsigned int alias_set:1; 221 unsigned int add_forwarded_headers:1; 222 223 /** Named back references */ 224 apr_array_header_t *refs; 225 226} proxy_dir_conf; 227 228/* if we interpolate env vars per-request, we'll need a per-request 229 * copy of the reverse proxy config 230 */ 231typedef struct { 232 apr_array_header_t *raliases; 233 apr_array_header_t* cookie_paths; 234 apr_array_header_t* cookie_domains; 235} proxy_req_conf; 236 237typedef struct { 238 conn_rec *connection; 239 request_rec *r; /* Request record of the backend request 240 * that is used over the backend connection. */ 241 proxy_worker *worker; /* Connection pool this connection belongs to */ 242 apr_pool_t *pool; /* Subpool for hostname and addr data */ 243 const char *hostname; 244 apr_sockaddr_t *addr; /* Preparsed remote address info */ 245 apr_pool_t *scpool; /* Subpool used for socket and connection data */ 246 apr_socket_t *sock; /* Connection socket */ 247 void *data; /* per scheme connection data */ 248 void *forward; /* opaque forward proxy data */ 249 apr_uint32_t flags; /* Connection flags */ 250 apr_port_t port; 251 unsigned int is_ssl:1; 252 unsigned int close:1; /* Close 'this' connection */ 253 unsigned int need_flush:1; /* Flag to decide whether we need to flush the 254 * filter chain or not */ 255 unsigned int inreslist:1; /* connection in apr_reslist? */ 256 const char *uds_path; /* Unix domain socket path */ 257} proxy_conn_rec; 258 259typedef struct { 260 float cache_completion; /* completion percentage */ 261 int content_length; /* length of the content */ 262} proxy_completion; 263 264/* Connection pool */ 265struct proxy_conn_pool { 266 apr_pool_t *pool; /* The pool used in constructor and destructor calls */ 267 apr_sockaddr_t *addr; /* Preparsed remote address info */ 268 apr_reslist_t *res; /* Connection resource list */ 269 proxy_conn_rec *conn; /* Single connection for prefork mpm */ 270}; 271 272/* Keep below in sync with proxy_util.c! */ 273/* worker status bits */ 274#define PROXY_WORKER_INITIALIZED 0x0001 275#define PROXY_WORKER_IGNORE_ERRORS 0x0002 276#define PROXY_WORKER_DRAIN 0x0004 277#define PROXY_WORKER_IN_SHUTDOWN 0x0010 278#define PROXY_WORKER_DISABLED 0x0020 279#define PROXY_WORKER_STOPPED 0x0040 280#define PROXY_WORKER_IN_ERROR 0x0080 281#define PROXY_WORKER_HOT_STANDBY 0x0100 282#define PROXY_WORKER_FREE 0x0200 283 284/* worker status flags */ 285#define PROXY_WORKER_INITIALIZED_FLAG 'O' 286#define PROXY_WORKER_IGNORE_ERRORS_FLAG 'I' 287#define PROXY_WORKER_DRAIN_FLAG 'N' 288#define PROXY_WORKER_IN_SHUTDOWN_FLAG 'U' 289#define PROXY_WORKER_DISABLED_FLAG 'D' 290#define PROXY_WORKER_STOPPED_FLAG 'S' 291#define PROXY_WORKER_IN_ERROR_FLAG 'E' 292#define PROXY_WORKER_HOT_STANDBY_FLAG 'H' 293#define PROXY_WORKER_FREE_FLAG 'F' 294 295#define PROXY_WORKER_NOT_USABLE_BITMAP ( PROXY_WORKER_IN_SHUTDOWN | \ 296PROXY_WORKER_DISABLED | PROXY_WORKER_STOPPED | PROXY_WORKER_IN_ERROR ) 297 298/* NOTE: these check the shared status */ 299#define PROXY_WORKER_IS_INITIALIZED(f) ( (f)->s->status & PROXY_WORKER_INITIALIZED ) 300 301#define PROXY_WORKER_IS_STANDBY(f) ( (f)->s->status & PROXY_WORKER_HOT_STANDBY ) 302 303#define PROXY_WORKER_IS_USABLE(f) ( ( !( (f)->s->status & PROXY_WORKER_NOT_USABLE_BITMAP) ) && \ 304 PROXY_WORKER_IS_INITIALIZED(f) ) 305 306#define PROXY_WORKER_IS_DRAINING(f) ( (f)->s->status & PROXY_WORKER_DRAIN ) 307 308/* default worker retry timeout in seconds */ 309#define PROXY_WORKER_DEFAULT_RETRY 60 310 311/* Some max char string sizes, for shm fields */ 312#define PROXY_WORKER_MAX_SCHEME_SIZE 16 313#define PROXY_WORKER_MAX_ROUTE_SIZE 64 314#define PROXY_BALANCER_MAX_ROUTE_SIZE PROXY_WORKER_MAX_ROUTE_SIZE 315#define PROXY_WORKER_MAX_NAME_SIZE 96 316#define PROXY_BALANCER_MAX_NAME_SIZE PROXY_WORKER_MAX_NAME_SIZE 317#define PROXY_WORKER_MAX_HOSTNAME_SIZE 64 318#define PROXY_BALANCER_MAX_HOSTNAME_SIZE PROXY_WORKER_MAX_HOSTNAME_SIZE 319#define PROXY_BALANCER_MAX_STICKY_SIZE 64 320 321#define PROXY_MAX_PROVIDER_NAME_SIZE 16 322 323#define PROXY_STRNCPY(dst, src) ap_proxy_strncpy((dst), (src), (sizeof(dst))) 324 325#define PROXY_COPY_CONF_PARAMS(w, c) \ 326do { \ 327(w)->s->timeout = (c)->timeout; \ 328(w)->s->timeout_set = (c)->timeout_set; \ 329(w)->s->recv_buffer_size = (c)->recv_buffer_size; \ 330(w)->s->recv_buffer_size_set = (c)->recv_buffer_size_set; \ 331(w)->s->io_buffer_size = (c)->io_buffer_size; \ 332(w)->s->io_buffer_size_set = (c)->io_buffer_size_set; \ 333} while (0) 334 335/* use 2 hashes */ 336typedef struct { 337 unsigned int def; 338 unsigned int fnv; 339} proxy_hashes ; 340 341/* Runtime worker status informations. Shared in scoreboard */ 342typedef struct { 343 char name[PROXY_WORKER_MAX_NAME_SIZE]; 344 char scheme[PROXY_WORKER_MAX_SCHEME_SIZE]; /* scheme to use ajp|http|https */ 345 char hostname[PROXY_WORKER_MAX_HOSTNAME_SIZE]; /* remote backend address */ 346 char route[PROXY_WORKER_MAX_ROUTE_SIZE]; /* balancing route */ 347 char redirect[PROXY_WORKER_MAX_ROUTE_SIZE]; /* temporary balancing redirection route */ 348 char flusher[PROXY_WORKER_MAX_SCHEME_SIZE]; /* flush provider used by mod_proxy_fdpass */ 349 char uds_path[PROXY_WORKER_MAX_NAME_SIZE]; /* path to worker's unix domain socket if applicable */ 350 int lbset; /* load balancer cluster set */ 351 int retries; /* number of retries on this worker */ 352 int lbstatus; /* Current lbstatus */ 353 int lbfactor; /* dynamic lbfactor */ 354 int min; /* Desired minimum number of available connections */ 355 int smax; /* Soft maximum on the total number of connections */ 356 int hmax; /* Hard maximum on the total number of connections */ 357 int flush_wait; /* poll wait time in microseconds if flush_auto */ 358 int index; /* shm array index */ 359 proxy_hashes hash; /* hash of worker name */ 360 unsigned int status; /* worker status bitfield */ 361 enum { 362 flush_off, 363 flush_on, 364 flush_auto 365 } flush_packets; /* control AJP flushing */ 366 apr_time_t updated; /* timestamp of last update */ 367 apr_time_t error_time; /* time of the last error */ 368 apr_interval_time_t ttl; /* maximum amount of time in seconds a connection 369 * may be available while exceeding the soft limit */ 370 apr_interval_time_t retry; /* retry interval */ 371 apr_interval_time_t timeout; /* connection timeout */ 372 apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */ 373 apr_interval_time_t ping_timeout; 374 apr_interval_time_t conn_timeout; 375 apr_size_t recv_buffer_size; 376 apr_size_t io_buffer_size; 377 apr_size_t elected; /* Number of times the worker was elected */ 378 apr_size_t busy; /* busyness factor */ 379 apr_port_t port; 380 apr_off_t transferred;/* Number of bytes transferred to remote */ 381 apr_off_t read; /* Number of bytes read from remote */ 382 void *context; /* general purpose storage */ 383 unsigned int keepalive:1; 384 unsigned int disablereuse:1; 385 unsigned int is_address_reusable:1; 386 unsigned int retry_set:1; 387 unsigned int timeout_set:1; 388 unsigned int acquire_set:1; 389 unsigned int ping_timeout_set:1; 390 unsigned int conn_timeout_set:1; 391 unsigned int recv_buffer_size_set:1; 392 unsigned int io_buffer_size_set:1; 393 unsigned int keepalive_set:1; 394 unsigned int disablereuse_set:1; 395 unsigned int was_malloced:1; 396} proxy_worker_shared; 397 398#define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared))) 399 400/* Worker configuration */ 401struct proxy_worker { 402 proxy_hashes hash; /* hash of worker name */ 403 unsigned int local_status; /* status of per-process worker */ 404 proxy_conn_pool *cp; /* Connection pool to use */ 405 proxy_worker_shared *s; /* Shared data */ 406 proxy_balancer *balancer; /* which balancer am I in? */ 407 apr_thread_mutex_t *tmutex; /* Thread lock for updating address cache */ 408 void *context; /* general purpose storage */ 409}; 410 411/* 412 * Time to wait (in microseconds) to find out if more data is currently 413 * available at the backend. 414 */ 415#define PROXY_FLUSH_WAIT 10000 416 417typedef struct { 418 char sticky_path[PROXY_BALANCER_MAX_STICKY_SIZE]; /* URL sticky session identifier */ 419 char sticky[PROXY_BALANCER_MAX_STICKY_SIZE]; /* sticky session identifier */ 420 char lbpname[PROXY_MAX_PROVIDER_NAME_SIZE]; /* lbmethod provider name */ 421 char nonce[APR_UUID_FORMATTED_LENGTH + 1]; 422 char name[PROXY_BALANCER_MAX_NAME_SIZE]; 423 char sname[PROXY_BALANCER_MAX_NAME_SIZE]; 424 char vpath[PROXY_BALANCER_MAX_ROUTE_SIZE]; 425 char vhost[PROXY_BALANCER_MAX_HOSTNAME_SIZE]; 426 apr_interval_time_t timeout; /* Timeout for waiting on free connection */ 427 apr_time_t wupdated; /* timestamp of last change to workers list */ 428 int max_attempts; /* Number of attempts before failing */ 429 int index; /* shm array index */ 430 proxy_hashes hash; 431 unsigned int sticky_force:1; /* Disable failover for sticky sessions */ 432 unsigned int scolonsep:1; /* true if ';' seps sticky session paths */ 433 unsigned int max_attempts_set:1; 434 unsigned int was_malloced:1; 435 unsigned int need_reset:1; 436 unsigned int vhosted:1; 437 unsigned int inactive:1; 438 unsigned int forcerecovery:1; 439 char sticky_separator; /* separator for sessionid/route */ 440} proxy_balancer_shared; 441 442#define ALIGNED_PROXY_BALANCER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_balancer_shared))) 443 444struct proxy_balancer { 445 apr_array_header_t *workers; /* initially configured workers */ 446 apr_array_header_t *errstatuses; /* statuses to force members into error */ 447 ap_slotmem_instance_t *wslot; /* worker shm data - runtime */ 448 ap_slotmem_provider_t *storage; 449 int growth; /* number of post-config workers can added */ 450 int max_workers; /* maximum number of allowed workers */ 451 proxy_hashes hash; 452 apr_time_t wupdated; /* timestamp of last change to workers list */ 453 proxy_balancer_method *lbmethod; 454 apr_global_mutex_t *gmutex; /* global lock for updating list of workers */ 455 apr_thread_mutex_t *tmutex; /* Thread lock for updating shm */ 456 proxy_server_conf *sconf; 457 void *context; /* general purpose storage */ 458 proxy_balancer_shared *s; /* Shared data */ 459 int failontimeout; /* Whether to mark a member in Err if IO timeout occurs */ 460}; 461 462struct proxy_balancer_method { 463 const char *name; /* name of the load balancer method*/ 464 proxy_worker *(*finder)(proxy_balancer *balancer, 465 request_rec *r); 466 void *context; /* general purpose storage */ 467 apr_status_t (*reset)(proxy_balancer *balancer, server_rec *s); 468 apr_status_t (*age)(proxy_balancer *balancer, server_rec *s); 469 apr_status_t (*updatelbstatus)(proxy_balancer *balancer, proxy_worker *elected, server_rec *s); 470}; 471 472#define PROXY_THREAD_LOCK(x) ( (x) && (x)->tmutex ? apr_thread_mutex_lock((x)->tmutex) : APR_SUCCESS) 473#define PROXY_THREAD_UNLOCK(x) ( (x) && (x)->tmutex ? apr_thread_mutex_unlock((x)->tmutex) : APR_SUCCESS) 474 475#define PROXY_GLOBAL_LOCK(x) ( (x) && (x)->gmutex ? apr_global_mutex_lock((x)->gmutex) : APR_SUCCESS) 476#define PROXY_GLOBAL_UNLOCK(x) ( (x) && (x)->gmutex ? apr_global_mutex_unlock((x)->gmutex) : APR_SUCCESS) 477 478/* hooks */ 479 480/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and 481 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform 482 */ 483#if !defined(WIN32) 484#define PROXY_DECLARE(type) type 485#define PROXY_DECLARE_NONSTD(type) type 486#define PROXY_DECLARE_DATA 487#elif defined(PROXY_DECLARE_STATIC) 488#define PROXY_DECLARE(type) type __stdcall 489#define PROXY_DECLARE_NONSTD(type) type 490#define PROXY_DECLARE_DATA 491#elif defined(PROXY_DECLARE_EXPORT) 492#define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall 493#define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type 494#define PROXY_DECLARE_DATA __declspec(dllexport) 495#else 496#define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall 497#define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type 498#define PROXY_DECLARE_DATA __declspec(dllimport) 499#endif 500 501APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r, 502 proxy_worker *worker, proxy_server_conf *conf, char *url, 503 const char *proxyhost, apr_port_t proxyport)) 504APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r, 505 char *url)) 506 507APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr)) 508APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r)) 509 510/** 511 * pre request hook. 512 * It will return the most suitable worker at the moment 513 * and coresponding balancer. 514 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri 515 * and then the scheme_handler is called. 516 * 517 */ 518APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker, 519 proxy_balancer **balancer, 520 request_rec *r, 521 proxy_server_conf *conf, char **url)) 522/** 523 * post request hook. 524 * It is called after request for updating runtime balancer status. 525 */ 526APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker, 527 proxy_balancer *balancer, request_rec *r, 528 proxy_server_conf *conf)) 529 530/** 531 * request status hook 532 * It is called after all proxy processing has been done. This gives other 533 * modules a chance to create default content on failure, for example 534 */ 535APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, request_status, 536 (int *status, request_rec *r)) 537 538/* proxy_util.c */ 539 540PROXY_DECLARE(apr_status_t) ap_proxy_strncpy(char *dst, const char *src, 541 apr_size_t dlen); 542PROXY_DECLARE(int) ap_proxy_hex2c(const char *x); 543PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x); 544PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t, 545 int forcedec, int proxyreq); 546PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp, 547 char **passwordp, char **hostp, apr_port_t *port); 548PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message); 549PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr); 550 551/** Test whether the hostname/address of the request are blocked by the ProxyBlock 552 * configuration. 553 * @param r request 554 * @param conf server configuration 555 * @param hostname hostname from request URI 556 * @param addr resolved address of hostname, or NULL if not known 557 * @return OK on success, or else an errro 558 */ 559PROXY_DECLARE(int) ap_proxy_checkproxyblock2(request_rec *r, proxy_server_conf *conf, 560 const char *hostname, apr_sockaddr_t *addr); 561 562PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r); 563/* DEPRECATED (will be replaced with ap_proxy_connect_backend */ 564PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, apr_sockaddr_t *, const char *, proxy_server_conf *, request_rec *); 565PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn, 566 request_rec *r); 567PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c); 568PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c); 569PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c); 570PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var); 571 572/* Header mapping functions, and a typedef of their signature */ 573PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *url); 574PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *str); 575 576#if !defined(WIN32) 577typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *, 578 proxy_dir_conf *, const char *); 579#elif defined(PROXY_DECLARE_STATIC) 580typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *, 581 proxy_dir_conf *, const char *); 582#elif defined(PROXY_DECLARE_EXPORT) 583typedef __declspec(dllexport) const char * 584 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *, 585 proxy_dir_conf *, const char *); 586#else 587typedef __declspec(dllimport) const char * 588 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *, 589 proxy_dir_conf *, const char *); 590#endif 591 592 593/* Connection pool API */ 594/** 595 * Return the user-land, UDS aware worker name 596 * @param p memory pool used for displaying worker name 597 * @param worker the worker 598 * @return name 599 */ 600 601PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p, 602 proxy_worker *worker); 603 604/** 605 * Get the worker from proxy configuration 606 * @param p memory pool used for finding worker 607 * @param balancer the balancer that the worker belongs to 608 * @param conf current proxy server configuration 609 * @param url url to find the worker from 610 * @return proxy_worker or NULL if not found 611 */ 612PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, 613 proxy_balancer *balancer, 614 proxy_server_conf *conf, 615 const char *url); 616/** 617 * Define and Allocate space for the worker to proxy configuration 618 * @param p memory pool to allocate worker from 619 * @param worker the new worker 620 * @param balancer the balancer that the worker belongs to 621 * @param conf current proxy server configuration 622 * @param url url containing worker name 623 * @param do_malloc true if shared struct should be malloced 624 * @return error message or NULL if successful (*worker is new worker) 625 */ 626PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p, 627 proxy_worker **worker, 628 proxy_balancer *balancer, 629 proxy_server_conf *conf, 630 const char *url, 631 int do_malloc); 632 633/** 634 * Share a defined proxy worker via shm 635 * @param worker worker to be shared 636 * @param shm location of shared info 637 * @param i index into shm 638 * @return APR_SUCCESS or error code 639 */ 640PROXY_DECLARE(apr_status_t) ap_proxy_share_worker(proxy_worker *worker, 641 proxy_worker_shared *shm, 642 int i); 643 644/** 645 * Initialize the worker by setting up worker connection pool and mutex 646 * @param worker worker to initialize 647 * @param s current server record 648 * @param p memory pool used for mutex and connection pool 649 * @return APR_SUCCESS or error code 650 */ 651PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, 652 server_rec *s, 653 apr_pool_t *p); 654 655/** 656 * Verifies valid balancer name (eg: balancer://foo) 657 * @param name name to test 658 * @param i number of chars to test; 0 for all. 659 * @return true/false 660 */ 661PROXY_DECLARE(int) ap_proxy_valid_balancer_name(char *name, int i); 662 663 664/** 665 * Get the balancer from proxy configuration 666 * @param p memory pool used for temporary storage while finding balancer 667 * @param conf current proxy server configuration 668 * @param url url to find the worker from; must have balancer:// prefix 669 * @param careactive true if we care if the balancer is active or not 670 * @return proxy_balancer or NULL if not found 671 */ 672PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p, 673 proxy_server_conf *conf, 674 const char *url, 675 int careactive); 676 677/** 678 * Update the balancer's vhost related fields 679 * @param p memory pool used for temporary storage while finding balancer 680 * @param balancer balancer to be updated 681 * @param url url to find vhost info 682 * @return error string or NULL if OK 683 */ 684PROXY_DECLARE(char *) ap_proxy_update_balancer(apr_pool_t *p, 685 proxy_balancer *balancer, 686 const char *url); 687 688/** 689 * Define and Allocate space for the balancer to proxy configuration 690 * @param p memory pool to allocate balancer from 691 * @param balancer the new balancer 692 * @param conf current proxy server configuration 693 * @param url url containing balancer name 694 * @param alias alias/fake-path to this balancer 695 * @param do_malloc true if shared struct should be malloced 696 * @return error message or NULL if successfull 697 */ 698PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p, 699 proxy_balancer **balancer, 700 proxy_server_conf *conf, 701 const char *url, 702 const char *alias, 703 int do_malloc); 704 705/** 706 * Share a defined proxy balancer via shm 707 * @param balancer balancer to be shared 708 * @param shm location of shared info 709 * @param i index into shm 710 * @return APR_SUCCESS or error code 711 */ 712PROXY_DECLARE(apr_status_t) ap_proxy_share_balancer(proxy_balancer *balancer, 713 proxy_balancer_shared *shm, 714 int i); 715 716/** 717 * Initialize the balancer as needed 718 * @param balancer balancer to initialize 719 * @param s current server record 720 * @param p memory pool used for mutex and connection pool 721 * @return APR_SUCCESS or error code 722 */ 723PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balancer, 724 server_rec *s, 725 apr_pool_t *p); 726 727/** 728 * Find the shm of the worker as needed 729 * @param storage slotmem provider 730 * @param slot slotmem instance 731 * @param worker worker to find 732 * @param index pointer to index within slotmem of worker 733 * @return pointer to shm of worker, or NULL 734 */ 735PROXY_DECLARE(proxy_worker_shared *) ap_proxy_find_workershm(ap_slotmem_provider_t *storage, 736 ap_slotmem_instance_t *slot, 737 proxy_worker *worker, 738 unsigned int *index); 739 740/** 741 * Find the shm of the balancer as needed 742 * @param storage slotmem provider 743 * @param slot slotmem instance 744 * @param balancer balancer of shm to find 745 * @param index pointer to index within slotmem of balancer 746 * @return pointer to shm of balancer, or NULL 747 */ 748PROXY_DECLARE(proxy_balancer_shared *) ap_proxy_find_balancershm(ap_slotmem_provider_t *storage, 749 ap_slotmem_instance_t *slot, 750 proxy_balancer *balancer, 751 unsigned int *index); 752 753/** 754 * Get the most suitable worker and/or balancer for the request 755 * @param worker worker used for processing request 756 * @param balancer balancer used for processing request 757 * @param r current request 758 * @param conf current proxy server configuration 759 * @param url request url that balancer can rewrite. 760 * @return OK or HTTP_XXX error 761 * @note It calls balancer pre_request hook if the url starts with balancer:// 762 * The balancer then rewrites the url to particular worker, like http://host:port 763 */ 764PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker, 765 proxy_balancer **balancer, 766 request_rec *r, 767 proxy_server_conf *conf, 768 char **url); 769/** 770 * Post request worker and balancer cleanup 771 * @param worker worker used for processing request 772 * @param balancer balancer used for processing request 773 * @param r current request 774 * @param conf current proxy server configuration 775 * @return OK or HTTP_XXX error 776 * @note Whenever the pre_request is called, the post_request has to be 777 * called too. 778 */ 779PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker, 780 proxy_balancer *balancer, 781 request_rec *r, 782 proxy_server_conf *conf); 783 784/** 785 * Determine backend hostname and port 786 * @param p memory pool used for processing 787 * @param r current request 788 * @param conf current proxy server configuration 789 * @param worker worker used for processing request 790 * @param conn proxy connection struct 791 * @param uri processed uri 792 * @param url request url 793 * @param proxyname are we connecting directly or via a proxy 794 * @param proxyport proxy host port 795 * @param server_portstr Via headers server port 796 * @param server_portstr_size size of the server_portstr buffer 797 * @return OK or HTTP_XXX error 798 */ 799PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, 800 proxy_server_conf *conf, 801 proxy_worker *worker, 802 proxy_conn_rec *conn, 803 apr_uri_t *uri, 804 char **url, 805 const char *proxyname, 806 apr_port_t proxyport, 807 char *server_portstr, 808 int server_portstr_size); 809 810/** 811 * Mark a worker for retry 812 * @param proxy_function calling proxy scheme (http, ajp, ...) 813 * @param worker worker used for retrying 814 * @param s current server record 815 * @return OK if marked for retry, DECLINED otherwise 816 * @note The error status of the worker will cleared if the retry interval has 817 * elapsed since the last error. 818 */ 819APR_DECLARE_OPTIONAL_FN(int, ap_proxy_retry_worker, 820 (const char *proxy_function, proxy_worker *worker, server_rec *s)); 821 822/** 823 * Acquire a connection from worker connection pool 824 * @param proxy_function calling proxy scheme (http, ajp, ...) 825 * @param conn acquired connection 826 * @param worker worker used for obtaining connection 827 * @param s current server record 828 * @return OK or HTTP_XXX error 829 * @note If the connection limit has been reached, the function will 830 * block until a connection becomes available or the timeout has 831 * elapsed. 832 */ 833PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function, 834 proxy_conn_rec **conn, 835 proxy_worker *worker, 836 server_rec *s); 837/** 838 * Release a connection back to worker connection pool 839 * @param proxy_function calling proxy scheme (http, ajp, ...) 840 * @param conn acquired connection 841 * @param s current server record 842 * @return OK or HTTP_XXX error 843 * @note The connection will be closed if conn->close_on_release is set 844 */ 845PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function, 846 proxy_conn_rec *conn, 847 server_rec *s); 848/** 849 * Make a connection to the backend 850 * @param proxy_function calling proxy scheme (http, ajp, ...) 851 * @param conn acquired connection 852 * @param worker connection worker 853 * @param s current server record 854 * @return OK or HTTP_XXX error 855 * @note In case the socket already exists for conn, just check the link 856 * status. 857 */ 858PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, 859 proxy_conn_rec *conn, 860 proxy_worker *worker, 861 server_rec *s); 862/** 863 * Make a connection record for backend connection 864 * @param proxy_function calling proxy scheme (http, ajp, ...) 865 * @param conn acquired connection 866 * @param c client connection record 867 * @param s current server record 868 * @return OK or HTTP_XXX error 869 * @note The function will return immediately if conn->connection 870 * is already set, 871 */ 872PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, 873 proxy_conn_rec *conn, 874 conn_rec *c, server_rec *s); 875/** 876 * Signal the upstream chain that the connection to the backend broke in the 877 * middle of the response. This is done by sending an error bucket with 878 * status HTTP_BAD_GATEWAY and an EOS bucket up the filter chain. 879 * @param r current request record of client request 880 * @param brigade The brigade that is sent through the output filter chain 881 */ 882PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r, 883 apr_bucket_brigade *brigade); 884 885/** 886 * Return a hash based on the passed string 887 * @param str string to produce hash from 888 * @param method hashing method to use 889 * @return hash as unsigned int 890 */ 891 892typedef enum { PROXY_HASHFUNC_DEFAULT, PROXY_HASHFUNC_APR, PROXY_HASHFUNC_FNV } proxy_hash_t; 893 894PROXY_DECLARE(unsigned int) ap_proxy_hashfunc(const char *str, proxy_hash_t method); 895 896 897/** 898 * Set/unset the worker status bitfield depending on flag 899 * @param c flag 900 * @param set set or unset bit 901 * @param w worker to use 902 * @return APR_SUCCESS if valid flag 903 */ 904PROXY_DECLARE(apr_status_t) ap_proxy_set_wstatus(char c, int set, proxy_worker *w); 905 906 907/** 908 * Create readable representation of worker status bitfield 909 * @param p pool 910 * @param w worker to use 911 * @return string representation of status 912 */ 913PROXY_DECLARE(char *) ap_proxy_parse_wstatus(apr_pool_t *p, proxy_worker *w); 914 915 916/** 917 * Sync balancer and workers based on any updates w/i shm 918 * @param b balancer to check/update member list of 919 * @param s server rec 920 * @param conf config 921 * @return APR_SUCCESS if all goes well 922 */ 923PROXY_DECLARE(apr_status_t) ap_proxy_sync_balancer(proxy_balancer *b, 924 server_rec *s, 925 proxy_server_conf *conf); 926 927 928/** 929 * Find the matched alias for this request and setup for proxy handler 930 * @param r request 931 * @param ent proxy_alias record 932 * @param dconf per-dir config or NULL 933 * @return DECLINED, DONE or OK if matched 934 */ 935PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, 936 struct proxy_alias *ent, 937 proxy_dir_conf *dconf); 938 939/** 940 * Create a HTTP request header brigade, old_cl_val and old_te_val as required. 941 * @param p pool 942 * @param header_brigade header brigade to use/fill 943 * @param r request 944 * @param p_conn proxy connection rec 945 * @param worker selected worker 946 * @param conf per-server proxy config 947 * @param uri uri 948 * @param url url 949 * @param server_portstr port as string 950 * @param old_cl_val stored old content-len val 951 * @param old_te_val stored old TE val 952 * @return OK or HTTP_EXPECTATION_FAILED 953 */ 954PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, 955 apr_bucket_brigade *header_brigade, 956 request_rec *r, 957 proxy_conn_rec *p_conn, 958 proxy_worker *worker, 959 proxy_server_conf *conf, 960 apr_uri_t *uri, 961 char *url, char *server_portstr, 962 char **old_cl_val, 963 char **old_te_val); 964 965/** 966 * @param bucket_alloc bucket allocator 967 * @param r request 968 * @param p_conn proxy connection 969 * @param origin connection rec of origin 970 * @param bb brigade to send to origin 971 * @param flush flush 972 * @return status (OK) 973 */ 974PROXY_DECLARE(int) ap_proxy_pass_brigade(apr_bucket_alloc_t *bucket_alloc, 975 request_rec *r, proxy_conn_rec *p_conn, 976 conn_rec *origin, apr_bucket_brigade *bb, 977 int flush); 978 979/** 980 * Clear the headers referenced by the Connection header from the given 981 * table, and remove the Connection header. 982 * @param r request 983 * @param headers table of headers to clear 984 * @return 1 if "close" was present, 0 otherwise. 985 */ 986APR_DECLARE_OPTIONAL_FN(int, ap_proxy_clear_connection, 987 (request_rec *r, apr_table_t *headers)); 988 989#define PROXY_LBMETHOD "proxylbmethod" 990 991/* The number of dynamic workers that can be added when reconfiguring. 992 * If this limit is reached you must stop and restart the server. 993 */ 994#define PROXY_DYNAMIC_BALANCER_LIMIT 16 995 996/** 997 * Calculate maximum number of workers in scoreboard. 998 * @return number of workers to allocate in the scoreboard 999 */ 1000int ap_proxy_lb_workers(void); 1001 1002/** 1003 * Return the port number of a known scheme (eg: http -> 80). 1004 * @param scheme scheme to test 1005 * @return port number or 0 if unknown 1006 */ 1007PROXY_DECLARE(apr_port_t) ap_proxy_port_of_scheme(const char *scheme); 1008 1009extern module PROXY_DECLARE_DATA proxy_module; 1010 1011#endif /*MOD_PROXY_H*/ 1012/** @} */ 1013