#ifndef MOD_PROXY_H
#define MOD_PROXY_H
#define CORE_PRIVATE
#include "apr_hooks.h"
#include "apr.h"
#include "apr_lib.h"
#include "apr_strings.h"
#include "apr_buckets.h"
#include "apr_md5.h"
#include "apr_network_io.h"
#include "apr_pools.h"
#include "apr_strings.h"
#include "apr_uri.h"
#include "apr_date.h"
#include "apr_strmatch.h"
#include "apr_fnmatch.h"
#include "apr_reslist.h"
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "httpd.h"
#include "http_config.h"
#include "ap_config.h"
#include "http_core.h"
#include "http_protocol.h"
#include "http_request.h"
#include "http_vhost.h"
#include "http_main.h"
#include "http_log.h"
#include "http_connection.h"
#include "util_filter.h"
#include "util_ebcdic.h"
#include "ap_provider.h"
#if APR_HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#if APR_HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
enum enctype {
enc_path, enc_search, enc_user, enc_fpath, enc_parm
};
#if APR_CHARSET_EBCDIC
#define CRLF "\r\n"
#else
#define CRLF "\015\012"
#endif
#define DEFAULT_MAX_FORWARDS -1
struct proxy_remote {
const char *scheme;
const char *protocol;
const char *hostname;
apr_port_t port;
ap_regex_t *regexp;
int use_regex;
};
#define PROXYPASS_NOCANON 0x01
#define PROXYPASS_INTERPOLATE 0x02
struct proxy_alias {
const char *real;
const char *fake;
ap_regex_t *regex;
unsigned int flags;
};
struct dirconn_entry {
char *name;
struct in_addr addr, mask;
struct apr_sockaddr_t *hostaddr;
int (*matcher) (struct dirconn_entry * This, request_rec *r);
};
struct noproxy_entry {
const char *name;
struct apr_sockaddr_t *addr;
};
typedef struct proxy_balancer proxy_balancer;
typedef struct proxy_worker proxy_worker;
typedef struct proxy_conn_pool proxy_conn_pool;
typedef struct proxy_balancer_method proxy_balancer_method;
typedef struct {
apr_array_header_t *proxies;
apr_array_header_t *sec_proxy;
apr_array_header_t *aliases;
apr_array_header_t *noproxies;
apr_array_header_t *dirconn;
apr_array_header_t *allowed_connect_ports;
apr_array_header_t *workers;
apr_array_header_t *balancers;
proxy_worker *forward;
proxy_worker *reverse;
const char *domain;
int req;
char req_set;
enum {
via_off,
via_on,
via_block,
via_full
} viaopt;
char viaopt_set;
apr_size_t recv_buffer_size;
char recv_buffer_size_set;
apr_size_t io_buffer_size;
char io_buffer_size_set;
long maxfwd;
char maxfwd_set;
int error_override;
int error_override_set;
int preserve_host;
int preserve_host_set;
apr_interval_time_t timeout;
char timeout_set;
enum {
bad_error,
bad_ignore,
bad_body
} badopt;
char badopt_set;
enum {
status_off,
status_on,
status_full
} proxy_status;
char proxy_status_set;
apr_pool_t *pool;
} proxy_server_conf;
typedef struct {
const char *p;
int p_is_fnmatch;
ap_regex_t *r;
apr_array_header_t *raliases;
apr_array_header_t* cookie_paths;
apr_array_header_t* cookie_domains;
const apr_strmatch_pattern* cookie_path_str;
const apr_strmatch_pattern* cookie_domain_str;
const char *ftp_directory_charset;
int interpolate_env;
} proxy_dir_conf;
typedef struct {
apr_array_header_t *raliases;
apr_array_header_t* cookie_paths;
apr_array_header_t* cookie_domains;
} proxy_req_conf;
typedef struct {
conn_rec *connection;
const char *hostname;
apr_port_t port;
int is_ssl;
apr_pool_t *pool;
apr_socket_t *sock;
apr_sockaddr_t *addr;
apr_uint32_t flags;
int close;
int close_on_recycle;
proxy_worker *worker;
void *data;
#if APR_HAS_THREADS
int inreslist;
#endif
apr_pool_t *scpool;
request_rec *r;
int need_flush;
void *forward;
} proxy_conn_rec;
typedef struct {
float cache_completion;
int content_length;
} proxy_completion;
struct proxy_conn_pool {
apr_pool_t *pool;
apr_sockaddr_t *addr;
#if APR_HAS_THREADS
apr_reslist_t *res;
#endif
proxy_conn_rec *conn;
};
#define PROXY_WORKER_INITIALIZED 0x0001
#define PROXY_WORKER_IGNORE_ERRORS 0x0002
#define PROXY_WORKER_IN_SHUTDOWN 0x0010
#define PROXY_WORKER_DISABLED 0x0020
#define PROXY_WORKER_STOPPED 0x0040
#define PROXY_WORKER_IN_ERROR 0x0080
#define PROXY_WORKER_HOT_STANDBY 0x0100
#define PROXY_WORKER_NOT_USABLE_BITMAP ( PROXY_WORKER_IN_SHUTDOWN | \
PROXY_WORKER_DISABLED | PROXY_WORKER_STOPPED | PROXY_WORKER_IN_ERROR )
#define PROXY_WORKER_IS_INITIALIZED(f) ( (f)->s && \
( (f)->s->status & PROXY_WORKER_INITIALIZED ) )
#define PROXY_WORKER_IS_STANDBY(f) ( (f)->s && \
( (f)->s->status & PROXY_WORKER_HOT_STANDBY ) )
#define PROXY_WORKER_IS_USABLE(f) ( (f)->s && \
( !( (f)->s->status & PROXY_WORKER_NOT_USABLE_BITMAP) ) && \
PROXY_WORKER_IS_INITIALIZED(f) )
#define PROXY_WORKER_DEFAULT_RETRY 60
#define PROXY_WORKER_MAX_ROUTE_SIZ 63
typedef struct {
int status;
apr_time_t error_time;
int retries;
int lbstatus;
int lbfactor;
apr_off_t transferred;
apr_off_t read;
apr_size_t elected;
char route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
void *context;
apr_size_t busy;
int lbset;
} proxy_worker_stat;
struct proxy_worker {
int id;
apr_interval_time_t retry;
int lbfactor;
const char *name;
const char *scheme;
const char *hostname;
const char *route;
const char *redirect;
int status;
apr_port_t port;
int min;
int smax;
int hmax;
apr_interval_time_t ttl;
apr_interval_time_t timeout;
char timeout_set;
apr_interval_time_t acquire;
char acquire_set;
apr_size_t recv_buffer_size;
char recv_buffer_size_set;
apr_size_t io_buffer_size;
char io_buffer_size_set;
char keepalive;
char keepalive_set;
proxy_conn_pool *cp;
proxy_worker_stat *s;
void *opaque;
int is_address_reusable;
#if APR_HAS_THREADS
apr_thread_mutex_t *mutex;
#endif
void *context;
enum {
flush_off,
flush_on,
flush_auto
} flush_packets;
int flush_wait;
int lbset;
apr_interval_time_t ping_timeout;
char ping_timeout_set;
char retry_set;
char disablereuse;
char disablereuse_set;
apr_interval_time_t conn_timeout;
char conn_timeout_set;
};
#define PROXY_FLUSH_WAIT 10000
struct proxy_balancer {
apr_array_header_t *workers;
const char *name;
const char *sticky;
int sticky_force;
apr_interval_time_t timeout;
int max_attempts;
char max_attempts_set;
proxy_balancer_method *lbmethod;
#if APR_HAS_THREADS
apr_thread_mutex_t *mutex;
#endif
void *context;
int scolonsep;
apr_array_header_t *errstatuses;
};
struct proxy_balancer_method {
const char *name;
proxy_worker *(*finder)(proxy_balancer *balancer,
request_rec *r);
void *context;
};
#if APR_HAS_THREADS
#define PROXY_THREAD_LOCK(x) apr_thread_mutex_lock((x)->mutex)
#define PROXY_THREAD_UNLOCK(x) apr_thread_mutex_unlock((x)->mutex)
#else
#define PROXY_THREAD_LOCK(x) APR_SUCCESS
#define PROXY_THREAD_UNLOCK(x) APR_SUCCESS
#endif
#if !defined(WIN32)
#define PROXY_DECLARE(type) type
#define PROXY_DECLARE_NONSTD(type) type
#define PROXY_DECLARE_DATA
#elif defined(PROXY_DECLARE_STATIC)
#define PROXY_DECLARE(type) type __stdcall
#define PROXY_DECLARE_NONSTD(type) type
#define PROXY_DECLARE_DATA
#elif defined(PROXY_DECLARE_EXPORT)
#define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
#define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
#define PROXY_DECLARE_DATA __declspec(dllexport)
#else
#define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
#define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
#define PROXY_DECLARE_DATA __declspec(dllimport)
#endif
#define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
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, canon_handler, (request_rec *r,
char *url))
APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
proxy_balancer **balancer,
request_rec *r,
proxy_server_conf *conf, char **url))
APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
proxy_balancer *balancer, request_rec *r,
proxy_server_conf *conf))
APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, request_status,
(int *status, request_rec *r))
PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
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(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,
char **passwordp, char **hostp, apr_port_t *port);
PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, apr_sockaddr_t *, const char *, proxy_server_conf *, server_rec *, apr_pool_t *);
PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
request_rec *r);
PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c);
PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var);
PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *url);
PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *str);
#if !defined(WIN32)
typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *,
proxy_dir_conf *, const char *);
#elif defined(PROXY_DECLARE_STATIC)
typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
proxy_dir_conf *, const char *);
#elif defined(PROXY_DECLARE_EXPORT)
typedef __declspec(dllexport) const char *
(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
proxy_dir_conf *, const char *);
#else
typedef __declspec(dllimport) const char *
(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
proxy_dir_conf *, const char *);
#endif
PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
proxy_server_conf *conf,
const char *url);
PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
apr_pool_t *p,
proxy_server_conf *conf,
const char *url);
PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
proxy_worker *worker,
server_rec *s);
PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
server_rec *s);
PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
proxy_server_conf *conf,
const char *url);
PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
apr_pool_t *p,
proxy_server_conf *conf,
const char *url);
PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
proxy_balancer *balancer,
proxy_worker *worker);
PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
proxy_balancer **balancer,
request_rec *r,
proxy_server_conf *conf,
char **url);
PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
proxy_balancer *balancer,
request_rec *r,
proxy_server_conf *conf);
PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
proxy_server_conf *conf,
proxy_worker *worker,
proxy_conn_rec *conn,
apr_uri_t *uri,
char **url,
const char *proxyname,
apr_port_t proxyport,
char *server_portstr,
int server_portstr_size);
PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
proxy_worker *worker,
server_rec *s);
PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
proxy_conn_rec **conn,
proxy_worker *worker,
server_rec *s);
PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
proxy_conn_rec *conn,
server_rec *s);
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
proxy_conn_rec *conn,
proxy_worker *worker,
server_rec *s);
PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
proxy_conn_rec *conn,
conn_rec *c, server_rec *s);
PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
apr_bucket_brigade *brigade);
#if MODULE_MAGIC_NUMBER_MAJOR > 20020903
#define PROXY_HAS_SCOREBOARD 1
#else
#define PROXY_HAS_SCOREBOARD 0
#endif
PROXY_DECLARE(apr_status_t)
ap_proxy_buckets_lifetime_transform(request_rec *r, apr_bucket_brigade *from,
apr_bucket_brigade *to);
#define PROXY_LBMETHOD "proxylbmethod"
#define PROXY_DYNAMIC_BALANCER_LIMIT 16
int ap_proxy_lb_workers(void);
extern module PROXY_DECLARE_DATA proxy_module;
extern int PROXY_DECLARE_DATA proxy_lb_workers;
#endif