proxy_util.c revision 89225e8e84d38b07a8335922497997e83d872e75
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Licensed to the Apache Software Foundation (ASF) under one or more
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * contributor license agreements. See the NOTICE file distributed with
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * this work for additional information regarding copyright ownership.
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * The ASF licenses this file to You under the Apache License, Version 2.0
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * (the "License"); you may not use this file except in compliance with
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * the License. You may obtain a copy of the License at
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * Unless required by applicable law or agreed to in writing, software
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * distributed under the License is distributed on an "AS IS" BASIS,
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * See the License for the specific language governing permissions and
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * limitations under the License.
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen/* Utility routines for Apache proxy */
e8bdf1be00aec45d0c6dd72ad9c8be02a3dfc778Timo Sirainen * Opaque structure containing target server info when
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * using a forward proxy.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Up to now only used in combination with HTTP CONNECT.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainentypedef struct {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int use_http_connect; /* Use SSL Tunneling via HTTP CONNECT */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen const char *target_host; /* Target hostname */
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen const char *proxy_auth; /* Proxy authorization */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen/* Keep synced with mod_proxy.h! */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainenstatic struct wstat {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int bit;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen {PROXY_WORKER_INITIALIZED, PROXY_WORKER_INITIALIZED_FLAG, "Init "},
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen {PROXY_WORKER_IGNORE_ERRORS, PROXY_WORKER_IGNORE_ERRORS_FLAG, "Ign "},
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen {PROXY_WORKER_DRAIN, PROXY_WORKER_DRAIN_FLAG, "Drn "},
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen {PROXY_WORKER_IN_SHUTDOWN, PROXY_WORKER_IN_SHUTDOWN_FLAG, "Shut "},
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen {PROXY_WORKER_DISABLED, PROXY_WORKER_DISABLED_FLAG, "Dis "},
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen {PROXY_WORKER_STOPPED, PROXY_WORKER_STOPPED_FLAG, "Stop "},
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen {PROXY_WORKER_IN_ERROR, PROXY_WORKER_IN_ERROR_FLAG, "Err "},
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen {PROXY_WORKER_HOT_STANDBY, PROXY_WORKER_HOT_STANDBY_FLAG, "Stby "},
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen {PROXY_WORKER_FREE, PROXY_WORKER_FREE_FLAG, "Free "},
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen/* Global balancer counter */
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainenconst apr_strmatch_pattern PROXY_DECLARE_DATA *ap_proxy_strmatch_path;
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainenconst apr_strmatch_pattern PROXY_DECLARE_DATA *ap_proxy_strmatch_domain;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainenstatic int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainenstatic int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenstatic int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int proxy_match_word(struct dirconn_entry *This, request_rec *r);
de7611687432b9560bdd31a4969609e7b68a5b83Timo SirainenAPR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(proxy, PROXY, int, create_req,
678d0463849ba777106eb7875f27db07a5d8e3dfTimo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_strncpy(char *dst, const char *src,
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* Assume the typical case is smaller copying into bigger
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen so we have a fast return */
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen if ((thelen < dlen-1) || ((strlen(src)) == thelen)) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen /* XXX: APR_ENOSPACE would be better */
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen/* already called in the knowledge that the characters are hex digits */
0dffa25d211be541ee3c953b23566a1a990789dfTimo SirainenPROXY_DECLARE(int) ap_proxy_hex2c(const char *x)
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen#else /*APR_CHARSET_EBCDIC*/
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * we assume that the hex value refers to an ASCII character
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen * so convert to EBCDIC so that it makes sense locally;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen * client specifies %20 in URL to refer to a space char;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen * at this point we're called with EBCDIC "20"; after turning
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen * EBCDIC "20" into binary 0x20, we then need to assume that 0x20
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * represents an ASCII char and convert 0x20 to EBCDIC, yielding
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen#endif /*APR_CHARSET_EBCDIC*/
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo SirainenPROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (i >= 10) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (i >= 10) {
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen#else /*APR_CHARSET_EBCDIC*/
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen static const char ntoa[] = { "0123456789ABCDEF" };
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen#endif /*APR_CHARSET_EBCDIC*/
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * canonicalise a URL-encoded string
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * Convert a URL-encoded string to canonical form.
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * It decodes characters which need not be encoded,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * and encodes those which must be encoded, and does not touch
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen * those which must not be touched.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenPROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len,
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen char *allowed; /* characters which should not be encoded */
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen char *reserved; /* characters which much not be en/de-coded */
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen * N.B. in addition to :@&=, this allows ';' in an http path
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen * and '?' in an ftp path -- this may be revised
4673afe816ffbca769585e4518e9b3c3d72e95ddTimo Sirainen * Also, it makes a '+' character in a search string reserved, as
4673afe816ffbca769585e4518e9b3c3d72e95ddTimo Sirainen * it may be form-encoded. (Although RFC 1738 doesn't allow this -
4673afe816ffbca769585e4518e9b3c3d72e95ddTimo Sirainen * it only permits ; / ? : @ = & as reserved chars.)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen else if (t == enc_search) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen else if (t == enc_user) {
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen else if (t == enc_fpath) {
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen else { /* if (t == enc_parm) */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen else if (t == enc_search) {
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen for (i = 0, j = 0; i < len; i++, j++) {
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen/* always handle '/' first */
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen * decode it if not already done. do not decode reverse proxied URLs
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen * unless specifically forced
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if ((forcedec || (proxyreq && proxyreq != PROXYREQ_REVERSE)) && ch == '%') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!apr_isxdigit(x[i + 1]) || !apr_isxdigit(x[i + 2])) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (ch != 0 && strchr(reserved, ch)) { /* keep it encoded */
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen/* recode it, if necessary */
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * Parses network-location.
2e7e4804d8a88b10e00a3f9ec3726759ae0a6a13Timo Sirainen * urlp on input the URL; on output the path, after the leading /
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * user NULL if no user/password permitted
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen * password holder for password
2e7e4804d8a88b10e00a3f9ec3726759ae0a6a13Timo Sirainen * host holder for host
2e7e4804d8a88b10e00a3f9ec3726759ae0a6a13Timo Sirainen * port port number; only set if one is supplied.
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * Returns an error string.
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen char **passwordp, char **hostp, apr_port_t *port)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char *addr, *scope_id, *strp, *host, *url = *urlp;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen return "Malformed URL";
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen /* find _last_ '@' since it might occur in user/password part */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen/* find password */
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1, 0);
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen return "Bad %-escape in URL (password)";
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1, 0);
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen return "Bad %-escape in URL (username)";
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen * Parse the host string to separate host portion from optional port.
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen * Perform range checking on port.
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen rv = apr_parse_addr_port(&addr, &scope_id, &tmp_port, host, p);
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen if (rv != APR_SUCCESS || addr == NULL || scope_id != NULL) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen return "Invalid host/port";
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if (tmp_port != 0) { /* only update caller's port if port was specified */
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen ap_str_tolower(addr); /* DNS names are case-insensitive */
a6249a80d437771867cf654ae9d11f8418c9d07bTimo SirainenPROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message)
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen const char *uri = ap_escape_html(r->pool, r->uri);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen "The proxy server could not handle the request <em><a href=\"",
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen uri, "\">", ap_escape_html(r->pool, r->method), " ", uri,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen "</a></em>.<p>\n"
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen "Reason: <strong>", ap_escape_html(r->pool, message),
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen "</strong></p>",
bc89e663696ef6887c00a5a34c3361600304abe1Timo Sirainen /* Allow "error-notes" string to be printed by ap_send_error_response() */
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen apr_table_setn(r->notes, "verbose-error-to", "*");
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen r->status_line = apr_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00898) "%s returned by %s", message,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainenstatic const char *
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen char *url, *user = NULL, *password = NULL, *err, *host;
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen /* Set url to the first char after "scheme://" */
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen if ((url = strchr(r->uri, ':')) == NULL || url[1] != '/' || url[2] != '/') {
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen url = apr_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00899) "%s", err);
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen return host; /* ought to return the port, too */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen/* Return TRUE if addr represents an IP address (or an IP network address) */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo SirainenPROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * if the address is given with an explicit netmask, use that
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * Due to a deficiency in apr_inet_addr(), it is impossible to parse
df9169221169d9cd8d8f49fc51ad40bed0fb6f64Timo Sirainen * "partial" addresses (with less than 4 quads) correctly, i.e.
df9169221169d9cd8d8f49fc51ad40bed0fb6f64Timo Sirainen * 192.168.123 is parsed as 192.168.0.123, which is not what I want.
df9169221169d9cd8d8f49fc51ad40bed0fb6f64Timo Sirainen * I therefore have to parse the IP address manually:
df9169221169d9cd8d8f49fc51ad40bed0fb6f64Timo Sirainen * if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0)
df9169221169d9cd8d8f49fc51ad40bed0fb6f64Timo Sirainen * addr and mask were set by proxy_readmask()
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * Parse IP addr manually, optionally allowing
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * abbreviated net addresses like 192.168.
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* Iterate over up to 4 (dotted) quads. */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen for (quads = 0; quads < 4 && *addr != '\0'; ++quads) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (*addr == '/' && quads > 0) { /* netmask starts here. */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen return 0; /* no digit at start of quad */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (tmp == addr) { /* expected a digit, found something else */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen /* invalid octet */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ++addr; /* after the 4th quad, a dot would be illegal */
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen for (This->addr.s_addr = 0, i = 0; i < quads; ++i) {
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen if (addr[0] == '/' && apr_isdigit(addr[1])) { /* net mask follows: */
ebc973d8a29738c9b91e5c92a124375661df799bTimo Sirainen if (tmp == addr) { /* expected a digit, found something else */
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen if (bits < 0 || bits > 32) { /* netmask must be between 0 and 32 */
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen * Determine (i.e., "guess") netmask by counting the
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen * number of trailing .0's; reduce #quads appropriately
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen * (so that 192.168.0.0 is equivalent to 192.168.)
ce84075e7ad4aa67fd45d12e75feceaffc64e523Timo Sirainen while (quads > 0 && ip_addr[quads - 1] == 0) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* every zero-byte counts as 8 zero-bits */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen if (bits != 32) { /* no warning for fully qualified IP address */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00900)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld",
97c3cae5873e56c15357686eeeb3144896445e50Timo Sirainen This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00901)
658d3e1c4b58281c35241123973f5447f812764fTimo Sirainen "Warning: NetMask and IP-Addr disagree in %s/%ld",
658d3e1c4b58281c35241123973f5447f812764fTimo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00902)
10f216b59964b70548051d0a942ecea7d61c7a61Timo Sirainen " Set to %s/%ld", inet_ntoa(This->addr), bits);
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen return (*addr == '\0'); /* okay iff we've parsed the whole string */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen/* Return TRUE if addr represents an IP address (or an IP network address) */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainenstatic int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen const char *host = proxy_get_host_of_request(r);
f84e7cabe355c6416898b7ae82b7d59acc3c7fbdTimo Sirainen if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
f84e7cabe355c6416898b7ae82b7d59acc3c7fbdTimo Sirainen /* ap_proxy_is_ipaddr() already confirmed that we have
f84e7cabe355c6416898b7ae82b7d59acc3c7fbdTimo Sirainen * a valid octet in ip_addr[i]
f84e7cabe355c6416898b7ae82b7d59acc3c7fbdTimo Sirainen addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00903)
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00904)
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00905)
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00906)
c224fff79d18480a65e9b4504b891b8ea176f5b1Timo Sirainen "1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr));
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00907)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00908)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen if (apr_sockaddr_info_get(&reqaddr, host, APR_UNSPEC, 0, 0, r->pool)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00909)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen "2)IP-NoMatch: hostname=%s msg=Host not found", host);
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen /* Try to deal with multiple IP addr's for a host */
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen /* FIXME: This needs to be able to deal with IPv6 */
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (This->addr.s_addr == (ip->s_addr & This->mask.s_addr)) {
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00910)
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch "3)IP-Match: %s[%s] <-> ", host, inet_ntoa(*ip));
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00911)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00912)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00913)
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen "3)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(*ip));
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00914)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00915)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen/* Return TRUE if addr represents a domain name */
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo SirainenPROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen /* Domain name must start with a '.' */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen "@@@@ handle optional port in proxy_is_domainname()");
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen /* @@@@ handle optional port */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* Strip trailing dots */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen/* Return TRUE if host "host" is in domain "domain" */
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainenstatic int proxy_match_domainname(struct dirconn_entry *This, request_rec *r)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen const char *host = proxy_get_host_of_request(r);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen if (host == NULL) { /* some error was logged already */
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen /* @@@ do this within the setup? */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* Ignore trailing dots in domain comparison: */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen while (d_len > 0 && This->name[d_len - 1] == '.') {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen/* Return TRUE if host represents a host name */
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo SirainenPROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p)
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen /* Host names must not start with a '.' */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen for (i = 0; apr_isalnum(host[i]) || host[i] == '-' || host[i] == '.'; ++i);
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen if (host[i] != '\0' || apr_sockaddr_info_get(&addr, host, APR_UNSPEC, 0, 0, p) != APR_SUCCESS) {
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen /* Strip trailing dots */
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen for (i = strlen(host) - 1; i > 0 && host[i] == '.'; --i) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Return TRUE if host "host" is equal to host2 "host2" */
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainenstatic int proxy_match_hostname(struct dirconn_entry *This, request_rec *r)
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen const char *host2 = proxy_get_host_of_request(r);
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen return 0; /* oops! */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen struct apr_sockaddr_t *addr = *This->hostaddr;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen /* Try to deal with multiple IP addr's for a host */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (addr->ipaddr_ptr == ? ? ? ? ? ? ? ? ? ? ? ? ?)
5b237a9d400a434920c8fd77ae53e6b44c38d3fbTimo Sirainen /* Ignore trailing dots in host2 comparison: */
5b237a9d400a434920c8fd77ae53e6b44c38d3fbTimo Sirainen while (h2_len > 0 && host2[h2_len - 1] == '.') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (h1_len > 0 && host[h1_len - 1] == '.') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Return TRUE if addr is to be matched as a word */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenPROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen/* Return TRUE if string "str2" occurs literally in "str1" */
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainenstatic int proxy_match_word(struct dirconn_entry *This, request_rec *r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *host = proxy_get_host_of_request(r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return host != NULL && ap_strstr_c(host, This->name) != NULL;
3a282e21c69b9cad1b5f9359ec3aebd3c8b8e901Timo SirainenPROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf,
5d773f4692c09cb3e2d68a6a8ca7fd05f692ebb2Timo Sirainen /* XXX FIXME: conf->noproxies->elts is part of an opaque structure */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (j = 0; j < conf->noproxies->nelts; j++) {
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen "checking remote machine [%s] against [%s]",
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen if (ap_strstr_c(hostname, npent[j].name) || npent[j].name[0] == '*') {
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(00916)
b06bfeaa9bb367b72edd51672c33e24d33d8ff1bTimo Sirainen "connect to remote machine %s blocked: name %s "
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen /* No IP address checks if no IP address was passed in,
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen * i.e. the forward address proxy case, where this server does
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen * not resolve the hostname. */
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen for (conf_addr = npent[j].addr; conf_addr; conf_addr = conf_addr->next) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char caddr[MAX_IP_STR_LEN], uaddr[MAX_IP_STR_LEN];
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen if (apr_sockaddr_ip_getbuf(caddr, sizeof caddr, conf_addr))
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen for (uri_addr = addr; uri_addr; uri_addr = uri_addr->next) {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen if (apr_sockaddr_ip_getbuf(uaddr, sizeof uaddr, uri_addr))
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen "ProxyBlock comparing %s and %s", caddr, uaddr);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(00917)
430acc18d409c92da20be46ef35dc6f1d2a855d2Timo Sirainen "connect to remote machine %s blocked: "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* set up the minimal filter set */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenPROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r)
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo SirainenPROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen * XXX FIXME: Make sure this handled the ambiguous case of the :<PORT>
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen * after the hostname
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen * XXX FIXME: Ensure the /uri component is a case sensitive match
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rconf = ap_get_module_config(r->request_config, &proxy_module);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen ent = (struct proxy_alias *)rconf->raliases->elts;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen ent = (struct proxy_alias *)conf->raliases->elts;
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen proxy_server_conf *sconf = (proxy_server_conf *)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_get_module_config(r->server->module_config, &proxy_module);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * First check if mapping against a balancer and see
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen * if we have such a entity. If so, then we need to
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * find the particulars of the actual worker which may
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen * or may not be the right one... basically, we need
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen * to find which member actually handled this request.
4f44284b96302c0a18203e2ac1243aeb193c6840Timo Sirainen if (ap_proxy_valid_balancer_name((char *)real, 0) &&
4f44284b96302c0a18203e2ac1243aeb193c6840Timo Sirainen (balancer = ap_proxy_get_balancer(r->pool, sconf, real, 1))) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen proxy_worker **worker = (proxy_worker **)balancer->workers->elts;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen const char *urlpart = ap_strchr_c(real + sizeof(BALANCER_PREFIX) - 1, '/');
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen /* The balancer comparison is a bit trickier. Given the context
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * BalancerMember balancer://alias http://example.com/foo
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * ProxyPassReverse /bash balancer://alias/bar
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * translate url http://example.com/foo/bar/that to /bash/that
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen for (n = 0; n < balancer->workers->nelts; n++) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen /* urlpart (l3) assuredly starts with its own '/' */
6f1936d4f5424f2ce766b62ef41f4173ecf5e33bTimo Sirainen && strncasecmp((*worker)->s->name, url, l2) == 0
6f1936d4f5424f2ce766b62ef41f4173ecf5e33bTimo Sirainen u = apr_pstrcat(r->pool, ent[i].fake, &url[l2 + l3],
6f1936d4f5424f2ce766b62ef41f4173ecf5e33bTimo Sirainen return ap_is_url(u) ? u : ap_construct_url(r->pool, u, r);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen else if (l1 >= l2 && strncasecmp((*worker)->s->name, url, l2) == 0) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return ap_is_url(u) ? u : ap_construct_url(r->pool, u, r);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (l1 >= l2 && strncasecmp(real, part, l2) == 0) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen u = apr_pstrcat(r->pool, ent[i].fake, &part[l2], NULL);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return ap_is_url(u) ? u : ap_construct_url(r->pool, u, r);
4f44284b96302c0a18203e2ac1243aeb193c6840Timo Sirainen * Cookies are a bit trickier to match: we've got two substrings to worry
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen * about, and we can't just find them with strstr 'cos of case. Regexp
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen * matching would be an easy fix, but for better consistency with all the
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen * other matches we'll refrain and use apr_strmatch to find path=/domain=
221249518003d405ea16251a86d420dc5b921357Timo Sirainen * and stick to plain strings for the config values.
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo SirainenPROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r,
05f323615730bc20d5e9f2c85b01465f88af2092Timo Sirainen proxy_req_conf *rconf = ap_get_module_config(r->request_config,
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen * Find the match and replacement, but save replacing until we've done
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen * both path and domain so we know the new strlen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if ((pathp = apr_strmatch(ap_proxy_strmatch_path, str, len)) != NULL) {
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen ent = (struct proxy_alias *)rconf->cookie_paths->elts;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen ent = (struct proxy_alias *)conf->cookie_paths->elts;
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen for (i = 0; i < conf->cookie_paths->nelts; i++) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen if (l1 >= l2 && strncmp(ent[i].fake, pathp, l2) == 0) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if ((domainp = apr_strmatch(ap_proxy_strmatch_domain, str, len)) != NULL) {
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen l1 = domaine ? (domaine - domainp) : strlen(domainp);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen ent = (struct proxy_alias *)rconf->cookie_domains->elts;
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen ent = (struct proxy_alias *)conf->cookie_domains->elts;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen for (i = 0; i < conf->cookie_domains->nelts; i++) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if (l1 >= l2 && strncasecmp(ent[i].fake, domainp, l2) == 0) {
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen ret = apr_palloc(r->pool, len + pdiff + ddiff + 1);
fcadc92fa095335d1119b161584e7fa8568f9267Timo Sirainen memcpy(ret + poffs + l1, pathe, domainp - pathe);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen memcpy(ret + doffs + l2, domaine, pathp - domaine);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = apr_palloc(r->pool, len + pdiff + ddiff + 1);
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen * BALANCER related...
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen * verifies that the balancer name conforms to standards.
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo SirainenPROXY_DECLARE(int) ap_proxy_valid_balancer_name(char *name, int i)
fd1a173038402c968f82d6b19b8b2e029bbcee45Timo Sirainen return (!strncasecmp(name, BALANCER_PREFIX, i));
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo SirainenPROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen const char *url,
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* remove path from uri */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen hash.def = ap_proxy_hashfunc(uri, PROXY_HASHFUNC_DEFAULT);
4efba37e4f27b93832f6147c3a353d6d22c855c7Timo Sirainen hash.fnv = ap_proxy_hashfunc(uri, PROXY_HASHFUNC_FNV);
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen balancer = (proxy_balancer *)conf->balancers->elts;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen for (i = 0; i < conf->balancers->nelts; i++) {
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen if (balancer->hash.def == hash.def && balancer->hash.fnv == hash.fnv) {
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo SirainenPROXY_DECLARE(char *) ap_proxy_update_balancer(apr_pool_t *p,
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo Sirainen const char *url)
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen if (apr_uri_parse(p, url, &puri) != APR_SUCCESS) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen return apr_psprintf(p, "unable to parse: %s", url);
1a8b6bb75a7e10e0a44a98848f478f16972f13e7Timo Sirainen if (puri.path && PROXY_STRNCPY(balancer->s->vpath, puri.path) != APR_SUCCESS) {
1a8b6bb75a7e10e0a44a98848f478f16972f13e7Timo Sirainen return apr_psprintf(p, "balancer %s front-end virtual-path (%s) too long",
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen if (puri.hostname && PROXY_STRNCPY(balancer->s->vhost, puri.hostname) != APR_SUCCESS) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen return apr_psprintf(p, "balancer %s front-end vhost name (%s) too long",
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo SirainenPROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen const char *url,
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen /* We should never get here without a valid BALANCER_PREFIX... */
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0')
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return "Bad syntax for a balancer name";
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen /* remove path from uri */
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo Sirainen * NOTE: The default method is byrequests, which we assume
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen lbmethod = ap_lookup_provider(PROXY_LBMETHOD, "byrequests", "0");
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen return "Can't find 'byrequests' lb method";
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker *));
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen bshared = ap_malloc(sizeof(proxy_balancer_shared));
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen bshared = apr_palloc(p, sizeof(proxy_balancer_shared));
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen memset(bshared, 0, sizeof(proxy_balancer_shared));
ac1c79d03888e634d26914780f7a7bc9cf3bd4b6Timo Sirainen PROXY_STRNCPY(bshared->lbpname, "byrequests");
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen if (PROXY_STRNCPY(bshared->name, uri) != APR_SUCCESS) {
4efba37e4f27b93832f6147c3a353d6d22c855c7Timo Sirainen return apr_psprintf(p, "balancer name (%s) too long", uri);
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen ap_pstr2_alnum(p, bshared->name + sizeof(BALANCER_PREFIX) - 1,
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen sname = apr_pstrcat(p, conf->id, "_", sname, NULL);
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen if (PROXY_STRNCPY(bshared->sname, sname) != APR_SUCCESS) {
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen return apr_psprintf(p, "balancer safe-name (%s) too long", sname);
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen bshared->hash.def = ap_proxy_hashfunc(bshared->name, PROXY_HASHFUNC_DEFAULT);
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen bshared->hash.fnv = ap_proxy_hashfunc(bshared->name, PROXY_HASHFUNC_FNV);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen *bshared->nonce = PROXY_UNSET_NONCE; /* impossible valid input */
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen return ap_proxy_update_balancer(p, *balancer, alias);
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen * Create an already defined balancer and free up memory.
ac1c79d03888e634d26914780f7a7bc9cf3bd4b6Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_share_balancer(proxy_balancer *balancer,
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen memcpy(shm, balancer->s, sizeof(proxy_balancer_shared));
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen /* the below should always succeed */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen lbmethod = ap_lookup_provider(PROXY_LBMETHOD, balancer->s->lbpname, "0");
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (*balancer->s->nonce == PROXY_UNSET_NONCE) {
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen /* Retrieve a UUID and store the nonce for the lifetime of
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen * the process.
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen rv = PROXY_STRNCPY(balancer->s->nonce, nonce);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balancer, server_rec *s, apr_pool_t *p)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen ap_slotmem_provider_t *storage = balancer->storage;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen unsigned int num;
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(00918)
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * for each balancer we need to init the global
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen * mutex and then attach to the shared worker shm
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(00919)
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen /* Re-open the mutex for the child. */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen rv = apr_global_mutex_child_init(&(balancer->gmutex),
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(00920)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Failed to reopen mutex %s in child",
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainen /* now attach */
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen storage->attach(&(balancer->wslot), balancer->s->sname, &size, &num, p);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(00921) "slotmem_attach failed");
47025fa2781c7862957690e21fc9e1aa2f1b6f60Timo Sirainen if (balancer->lbmethod && balancer->lbmethod->reset)
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen rv = apr_thread_mutex_create(&(balancer->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(00922)
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen "can not create balancer thread mutex");
4cc8a792108e1c115c1c6c9eb61746b31f0205dbTimo Sirainen * CONNECTION related...
4cc8a792108e1c115c1c6c9eb61746b31f0205dbTimo Sirainenstatic apr_status_t conn_pool_cleanup(void *theworker)
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen proxy_worker *worker = (proxy_worker *)theworker;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void init_conn_pool(apr_pool_t *p, proxy_worker *worker)
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen * Create a connection pool's subpool.
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen * This pool is used for connection recycling.
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * Once the worker is added it is never removed but
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * it can be disabled.
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen * Alloc from the same pool as worker.
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen * proxy_conn_pool is permanently attached to the worker.
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen cp = (proxy_conn_pool *)apr_pcalloc(p, sizeof(proxy_conn_pool));
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainenstatic apr_status_t connection_cleanup(void *theconn)
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainen proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * If the connection pool is NULL the worker
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen * cleanup has been run. Just return.
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen /* Sanity check: Did we already return the pooled connection? */
73fd4a877d9d2517c2ba7438c79a4cf42c701352Timo Sirainen ap_log_perror(APLOG_MARK, APLOG_ERR, 0, conn->pool, APLOGNO(00923)
39344e449ff55820f8620c0fa943362f90ff9f6aTimo Sirainen "Pooled connection 0x%pp for worker %s has been"
39344e449ff55820f8620c0fa943362f90ff9f6aTimo Sirainen " already returned to the connection pool.", conn,
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen /* determine if the connection need to be closed */
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen if (conn->close || !worker->s->is_address_reusable || worker->s->disablereuse) {
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen conn = apr_pcalloc(p, sizeof(proxy_conn_rec));
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen apr_pool_tag(conn->scpool, "proxy_conn_scpool");
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen apr_reslist_release(worker->cp->res, (void *)conn);
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen /* Always return the SUCCESS */
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainenstatic void socket_cleanup(proxy_conn_rec *conn)
f63b54b0c5fa2717443fd3a96f37119fdceb39e9Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
f63b54b0c5fa2717443fd3a96f37119fdceb39e9Timo Sirainen * If we have an existing SSL connection it might be possible that the
f63b54b0c5fa2717443fd3a96f37119fdceb39e9Timo Sirainen * server sent some SSL message we have not read so far (e.g. an SSL
f63b54b0c5fa2717443fd3a96f37119fdceb39e9Timo Sirainen * shutdown message if the server closed the keepalive connection while
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen * the connection was held unused in our pool).
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen * So ensure that if present (=> APR_NONBLOCK_READ) it is read and
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen * processed. We don't expect any data to be in the returned brigade.
d55fb5fbf2dc0601fc34dbd26221369b0cedb5daTimo Sirainen bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen rv = ap_get_brigade(conn->connection->input_filters, bb,
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen if ((rv != APR_SUCCESS) && !APR_STATUS_IS_EAGAIN(rv)) {
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen ap_log_rerror(APLOG_MARK, APLOG_TRACE3, rv, r,
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen "SSL cleanup brigade contained %"
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen/* reslist constructor */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainenstatic apr_status_t connection_constructor(void **resource, void *params,
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen proxy_worker *worker = (proxy_worker *)params;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen * Create the subpool for each connection
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen * This keeps the memory consumption constant
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen * when disconnecting from backend.
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen * Create another subpool that manages the data for the
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen * socket and the connection member of the proxy_conn_rec struct as we
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen * destroy this data more frequently than other data in the proxy_conn_rec
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen * struct like hostname and addr (at least in the case where we have
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * keepalive connections that timed out).
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen conn = apr_pcalloc(ctx, sizeof(proxy_conn_rec));
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen/* reslist destructor */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainenstatic apr_status_t connection_destructor(void *resource, void *params,
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen proxy_conn_rec *conn = (proxy_conn_rec *)resource;
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen /* Destroy the pool only if not called from reslist_destroy */
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen * WORKER related...
de7611687432b9560bdd31a4969609e7b68a5b83Timo SirainenPROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
275cc4c040899c132b2acbe2fcac48ba4c1abbcfTimo Sirainen const char *url)
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen const char *c;
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen url_copy = apr_pstrmemdup(p, url, url_length);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * We need to find the start of the path and
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * therefore we know the length of the scheme://hostname/
3d962035558bec7ff88408a167c877b270138d25Timo Sirainen * part to we can force-lowercase everything up to
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen * the start of the path.
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen * Do a "longest match" on the worker name to find the worker that
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen * fits best to the URL, but keep in mind that we must have at least
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen * a minimum matching of length min_match such that
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen * scheme://hostname[:port] matches between worker and url.
d8b23843fb938c0a8f19f4abdb6c2a04b898a2b1Timo Sirainen proxy_worker **workers = (proxy_worker **)balancer->workers->elts;
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen for (i = 0; i < balancer->workers->nelts; i++, workers++) {
d8b23843fb938c0a8f19f4abdb6c2a04b898a2b1Timo Sirainen if ( ((worker_name_length = strlen(worker->s->name)) <= url_length)
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen && (strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) {
fcadc92fa095335d1119b161584e7fa8568f9267Timo Sirainen for (i = 0; i < conf->workers->nelts; i++, worker++) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if ( ((worker_name_length = strlen(worker->s->name)) <= url_length)
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen && (strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * To create a worker from scratch first we define the
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen * specifics of the worker; this is all local data.
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen * We then allocate space for it if data needs to be
b6ccb2a38287c42aa53f66a927a6ada9d324b0beTimo Sirainen * shared. This allows for dynamic addition during
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen * config and runtime.
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo SirainenPROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen const char *url,
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return "Unable to parse URL";
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return "URL must be absolute!";
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * Workers can be associated w/ balancers or on their
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * own; ie: the generic reverse-proxy or a worker
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * in a simple ProxyPass statement. eg:
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * in which case the worker goes in the conf slot.
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen /* recall that we get a ptr to the ptr here */
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen *worker = *runtime = apr_palloc(p, sizeof(proxy_worker)); /* right to left baby */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* we've updated the list of workers associated with
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen * this balancer *locally* */
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen } else if (conf) {
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen /* we need to allocate space here */
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen *worker = apr_palloc(p, sizeof(proxy_worker));
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen /* right here we just want to tuck away the worker info.
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen * if called during config, we don't have shm setup yet,
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen * so just note the info for later. */
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen wshared = ap_malloc(sizeof(proxy_worker_shared)); /* will be freed ap_proxy_share_worker */
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen wshared = apr_palloc(p, sizeof(proxy_worker_shared));
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen memset(wshared, 0, sizeof(proxy_worker_shared));
57a91f930a12d2cd1220da4f3f7cb2c47557cd37Timo Sirainen ptr = apr_uri_unparse(p, &uri, APR_URI_UNP_REVEALPASSWORD);
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen if (PROXY_STRNCPY(wshared->name, ptr) != APR_SUCCESS) {
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen return apr_psprintf(p, "worker name (%s) too long", ptr);
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen if (PROXY_STRNCPY(wshared->scheme, uri.scheme) != APR_SUCCESS) {
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen return apr_psprintf(p, "worker scheme (%s) too long", uri.scheme);
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen if (PROXY_STRNCPY(wshared->hostname, uri.hostname) != APR_SUCCESS) {
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen return apr_psprintf(p, "worker hostname (%s) too long", uri.hostname);
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen wshared->hash.def = ap_proxy_hashfunc(wshared->name, PROXY_HASHFUNC_DEFAULT);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen wshared->hash.fnv = ap_proxy_hashfunc(wshared->name, PROXY_HASHFUNC_FNV);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen * Create an already defined worker and free up memory
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_share_worker(proxy_worker *worker, proxy_worker_shared *shm,
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen memcpy(shm, worker->s, sizeof(proxy_worker_shared));
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen free(worker->s); /* was malloced in ap_proxy_define_worker */
57a91f930a12d2cd1220da4f3f7cb2c47557cd37Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, server_rec *s, apr_pool_t *p)
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen if (worker->s->status & PROXY_WORKER_INITIALIZED) {
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen /* The worker is already initialized */
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00924)
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen "worker %s shared already initialized", worker->s->name);
8925c5450daddcdd1834de2750b47fb6d192c6f6Timo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00925)
8925c5450daddcdd1834de2750b47fb6d192c6f6Timo Sirainen "initializing worker %s shared", worker->s->name);
8925c5450daddcdd1834de2750b47fb6d192c6f6Timo Sirainen /* Set default parameters */
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen worker->s->retry = apr_time_from_sec(PROXY_WORKER_DEFAULT_RETRY);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen /* By default address is reusable unless DisableReuse is set */
57a91f930a12d2cd1220da4f3f7cb2c47557cd37Timo Sirainen ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Set hard max to no more then mpm_threads */
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen if (worker->s->hmax == 0 || worker->s->hmax > mpm_threads) {
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (worker->s->smax == -1 || worker->s->smax > worker->s->hmax) {
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen /* Set min to be lower then smax */
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen /* This will supress the apr_reslist creation */
746a7ec64a09649ed3c96c88b97cdc370a7bbe2fTimo Sirainen worker->s->min = worker->s->smax = worker->s->hmax = 0;
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen /* What if local is init'ed and shm isn't?? Even possible? */
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen if (worker->local_status & PROXY_WORKER_INITIALIZED) {
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00926)
38da5c23b0a8b4012e79fcf647a8749786c83c51Timo Sirainen "worker %s local already initialized", worker->s->name);
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00927)
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen "initializing worker %s local", worker->s->name);
588f592a98fca95a10aaccdc76a589558e9ba125Timo Sirainen /* Now init local worker data */
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen rv = apr_thread_mutex_create(&(worker->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00928)
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen "can not create worker thread mutex");
042668c0cd5a7d35ce6373ae493695e8f12d3157Timo Sirainen ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00929)
38920bff33eaa2acef5c200df5ce7088fd61e673Timo Sirainen "can not create connection pool");
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen connection_constructor, connection_destructor,
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen apr_pool_cleanup_register(worker->cp->pool, (void *)worker,
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00930)
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen "initialized pool in child %" APR_PID_T_FMT " for (%s) min=%d max=%d smax=%d",
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen getpid(), worker->s->hostname, worker->s->min,
51335acfa1580c6f6b1aa1bdb915d2cb5e0e67a4Timo Sirainen /* Set the acquire timeout */
f6b317c4a91d72d5e0dcd14940ae023233845aa0Timo Sirainen if (rv == APR_SUCCESS && worker->s->acquire_set) {
51335acfa1580c6f6b1aa1bdb915d2cb5e0e67a4Timo Sirainen apr_reslist_timeout_set(worker->cp->res, worker->s->acquire);
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen rv = connection_constructor(&conn, worker, worker->cp->pool);
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00931)
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen "initialized single connection worker in child %" APR_PID_T_FMT " for (%s)",
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen worker->s->status |= (PROXY_WORKER_INITIALIZED);
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen worker->local_status |= (PROXY_WORKER_INITIALIZED);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainenstatic int ap_proxy_retry_worker(const char *proxy_function, proxy_worker *worker,
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen if (worker->s->status & PROXY_WORKER_IN_ERROR) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (apr_time_now() > worker->s->error_time + worker->s->retry) {
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00932)
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen "%s: worker for (%s) has been marked for retry",
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00933)
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen "%s: too soon to retry worker for (%s)",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenPROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
32147ee6bdea566e64139b77ad0ea89960200df9Timo Sirainen access_status = proxy_run_pre_request(worker, balancer, r, conf, url);
32147ee6bdea566e64139b77ad0ea89960200df9Timo Sirainen if (access_status == DECLINED && *balancer == NULL) {
32147ee6bdea566e64139b77ad0ea89960200df9Timo Sirainen *worker = ap_proxy_get_worker(r->pool, NULL, conf, *url);
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen "%s: found worker %s for %s",
f07762518db1e3771500a1a761ea0c06be23b8b5Timo Sirainen (*worker)->s->scheme, (*worker)->s->name, *url);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "*: found forward proxy worker for %s", *url);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen * The forward worker does not keep connections alive, so
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen * ensure that mod_proxy_http does the correct thing
38920bff33eaa2acef5c200df5ce7088fd61e673Timo Sirainen * regarding the Connection header in the request.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen apr_table_setn(r->subprocess_env, "proxy-nokeepalive", "1");
be6a511e672b84b1622f1875b2527827e20cbcb4Timo Sirainen "*: found reverse proxy worker for %s", *url);
38da5c23b0a8b4012e79fcf647a8749786c83c51Timo Sirainen * The reverse worker does not keep connections alive, so
38da5c23b0a8b4012e79fcf647a8749786c83c51Timo Sirainen * ensure that mod_proxy_http does the correct thing
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen * regarding the Connection header in the request.
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen apr_table_setn(r->subprocess_env, "proxy-nokeepalive", "1");
57a181d2ecd59039a4fc5c6bf0af72a7cd6a051fTimo Sirainen else if (access_status == DECLINED && *balancer != NULL) {
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen /* All the workers are busy */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00934)
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen "all workers are busy. Unable to serve %s", *url);
054fdbfc20f57cb4a386e088ec773d9980ac8b2cTimo SirainenPROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen access_status = proxy_run_post_request(worker, balancer, r, conf);
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen access_status = OK; /* no post_request handler available */
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen /* TODO: recycle direct worker */
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen/* DEPRECATED */
3ccab0bac68040f179a7de45c516cec258e28fdbTimo SirainenPROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **newsock,
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen if ((rv = apr_socket_create(newsock, backend_addr->family,
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen ap_log_rerror(APLOG_MARK, loglevel, rv, r, APLOGNO(00935)
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen "%s: error creating fam %d socket for target %s",
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen proxy_function, backend_addr->family, backend_name);
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen * this could be an IPv6 address from the DNS but the
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen * local machine won't give us an IPv6 socket; hopefully the
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen * DNS returned an additional address to try
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen (rv = apr_socket_opt_set(*newsock, APR_SO_RCVBUF,
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(00936)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen "apr_socket_opt_set(SO_RCVBUF): Failed to set "
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen "ProxyReceiveBufferSize, using default");
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen rv = apr_socket_opt_set(*newsock, APR_TCP_NODELAY, 1);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(00937)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen "apr_socket_opt_set(APR_TCP_NODELAY): "
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen "Failed to set");
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen /* Set a timeout on the socket */
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen apr_socket_timeout_set(*newsock, conf->timeout);
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen apr_socket_timeout_set(*newsock, r->server->timeout);
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen "%s: fam %d socket created to connect to %s",
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen proxy_function, backend_addr->family, backend_name);
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen rv = apr_socket_bind(*newsock, conf->source_address);
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(00938)
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen "%s: failed to bind socket to local address",
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen /* make the connection out of the socket */
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen rv = apr_socket_connect(*newsock, backend_addr);
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen /* if an error occurred, loop round and try again */
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen ap_log_rerror(APLOG_MARK, loglevel, rv, r, APLOGNO(00939)
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen "%s: attempt to connect to %pI (%s) failed",
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo SirainenPROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
bef19e231b696a2018fcb93d546a41fcf732c243Timo Sirainen /* Retry the worker */
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen ap_proxy_retry_worker(proxy_function, worker, s);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00940)
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen "%s: disabled connection for (%s)",
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen rv = apr_reslist_acquire(worker->cp->res, (void **)conn);
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen /* create the new connection if the previous was destroyed */
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen connection_constructor((void **)conn, worker, worker->cp->pool);
de83e0a4081e68172b66dd7fa9788effacdc1448Timo Sirainen ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00941)
f53a6e86c03f51ca7fb23a03751dfc88aa2d32f0Timo Sirainen "%s: failed to acquire connection for (%s)",
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00942)
bef19e231b696a2018fcb93d546a41fcf732c243Timo Sirainen "%s: has acquired connection for (%s)",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenPROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
8409959d66804dc963bc6fcdcc9a01da0d56a978Timo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00943)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "%s: has released connection for (%s)",
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainenap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
73c76fa7340a107229c530196d026aadeae979c7Timo Sirainen * Break up the URL to determine the host to connect to
73c76fa7340a107229c530196d026aadeae979c7Timo Sirainen /* we break the URL into host, port, uri */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (APR_SUCCESS != apr_uri_parse(p, *url, uri)) {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen uri->port = apr_uri_port_of_scheme(uri->scheme);
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00944)
82037d2bd997fef300025391353da4e085de9b4cTimo Sirainen "connecting %s to %s:%d", *url, uri->hostname, uri->port);
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * allocate these out of the specified connection pool
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen * The scheme handler decides if this is permanent or
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * short living pool.
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen /* are we connecting directly, or via a proxy? */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen *url = apr_pstrcat(p, uri->path, uri->query ? "?" : "",
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen * Figure out if our passed in proxy_conn_rec has a usable
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen * address cached.
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen * TODO: Handle this much better...
e05181d973025627ba08b631c12c07c3bbc99528Timo Sirainen * XXX: If generic workers are ever address-reusable, we need
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen * to check host and port on the conn and be careful about
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen * spilling the cached addr from the worker.
e05181d973025627ba08b631c12c07c3bbc99528Timo Sirainen if (!conn->hostname || !worker->s->is_address_reusable ||
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen conn->hostname = apr_pstrdup(conn->pool, proxyname);
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen * If we have a forward proxy and the protocol is HTTPS,
5375aa138868dc2c45eb1a4ff37a0b577c2814f8Timo Sirainen * then we need to prepend a HTTP CONNECT request before
5375aa138868dc2c45eb1a4ff37a0b577c2814f8Timo Sirainen * sending our actual HTTPS requests.
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen * Save our real backend data for using it later during HTTP CONNECT.
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen forward_info *forward = apr_pcalloc(conn->pool, sizeof(forward_info));
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen forward->target_host = apr_pstrdup(conn->pool, uri->hostname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Do we want to pass Proxy-Authorization along?
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * If we haven't used it, then YES
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * If we have used it then MAYBE: RFC2616 says we MAY propagate it.
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen * So let's make it configurable by env.
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen * The logic here is the same used in mod_proxy_http.
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization");
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen r->user == NULL && /* we haven't yet authenticated */
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen apr_table_get(r->subprocess_env, "Proxy-Chain-Auth")) {
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen forward->proxy_auth = apr_pstrdup(conn->pool, proxy_auth);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn->hostname = apr_pstrdup(conn->pool, uri->hostname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(00945) "lock");
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen * Worker can have the single constant backend adress.
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen * The single DNS lookup is used once per worker.
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen * If dynamic change is needed then set the addr to NULL
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen * inside dynamic config to force the lookup.
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen err = apr_sockaddr_info_get(&(worker->cp->addr),
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen if ((uerr = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(00946) "unlock");
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* Close a possible existing socket if we are told to do so */
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen /* Get the server port for the Via headers */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen apr_snprintf(server_portstr, server_portstr_size, ":%d",
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* check if ProxyBlock directive on this host */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (OK != ap_proxy_checkproxyblock(r, conf, uri->hostname,
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen "Connect to remote machine blocked");
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00947)
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen "connected %s to %s:%d", *url, conn->hostname, conn->port);
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen#if !defined(APR_MSG_PEEK) && defined(MSG_PEEK)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#if USE_ALTERNATE_IS_CONNECTED && defined(APR_MSG_PEEK)
server_rec *s)
int status;
int complete = 0;
int len = 0;
if (!complete) {
buffer);
code_str);
return(status);
server_rec *s)
int connected = 0;
int loglevel;
sizeof(apr_sockaddr_t));
conn_rec *c,
server_rec *s)
int rc;
return OK;
0, NULL,
return HTTP_INTERNAL_SERVER_ERROR;
return HTTP_INTERNAL_SERVER_ERROR;
return rc;
return OK;
int ap_proxy_lb_workers(void)
if (!lb_workers_limit)
return lb_workers_limit;
apr_bucket *e;
if (r->main)
c->bucket_alloc);
PROXY_DECLARE(unsigned int)
unsigned int hash;
return hash;
unsigned int hash;
return hash;
if (set)
return APR_SUCCESS;
pwt++;
return APR_EINVAL;
pwt++;
if (PROXY_WORKER_IS_USABLE(w))
return ret;
int index;
return APR_SUCCESS;
if (lbmethod) {
int found;
return APR_EGENERAL;
found = 0;
if (!found) {
return rv;
if (b->s->need_reset) {
b->s->need_reset = 0;
return APR_SUCCESS;