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 *
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * http://www.apache.org/licenses/LICENSE-2.0
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen *
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 */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen/* Utility routines for Apache proxy */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen#include "mod_proxy.h"
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen#include "ap_mpm.h"
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen#include "scoreboard.h"
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen#include "apr_version.h"
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen#include "apr_hash.h"
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen#include "proxy_util.h"
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen#if APR_HAVE_UNISTD_H
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen#include <unistd.h> /* for getpid() */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#if (APR_MAJOR_VERSION < 1)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#undef apr_socket_create
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen#define apr_socket_create apr_socket_create_ex
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
89b548af722113acb5d63dfffb44423cb60f91e4Timo SirainenAPLOG_USE_MODULE(proxy);
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
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 Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainentypedef struct {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int use_http_connect; /* Use SSL Tunneling via HTTP CONNECT */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen const char *target_host; /* Target hostname */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen apr_port_t target_port; /* Target port */
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen const char *proxy_auth; /* Proxy authorization */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen} forward_info;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen/* Keep synced with mod_proxy.h! */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainenstatic struct wstat {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int bit;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen char flag;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *name;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen} wstat_tbl[] = {
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 "},
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen {0x0, '\0', NULL}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen/* Global balancer counter */
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainenint PROXY_DECLARE_DATA proxy_lb_workers = 0;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenstatic int lb_workers_limit = 0;
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainenconst apr_strmatch_pattern PROXY_DECLARE_DATA *ap_proxy_strmatch_path;
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainenconst apr_strmatch_pattern PROXY_DECLARE_DATA *ap_proxy_strmatch_domain;
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen
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 Sirainen
de7611687432b9560bdd31a4969609e7b68a5b83Timo SirainenAPR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(proxy, PROXY, int, create_req,
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen (request_rec *r, request_rec *pr), (r, pr),
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen OK, DECLINED)
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_strncpy(char *dst, const char *src,
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen apr_size_t dlen)
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char *thenil;
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen apr_size_t thelen;
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen thenil = apr_cpystrn(dst, src, dlen);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen thelen = thenil - dst;
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)) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen return APR_SUCCESS;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen }
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen /* XXX: APR_ENOSPACE would be better */
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen return APR_EGENERAL;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen}
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen/* already called in the knowledge that the characters are hex digits */
0dffa25d211be541ee3c953b23566a1a990789dfTimo SirainenPROXY_DECLARE(int) ap_proxy_hex2c(const char *x)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen{
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#if !APR_CHARSET_EBCDIC
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ch = x[0];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e32cf1b4430c4a5f28c9b5bb8b1366e7b06ed68dTimo Sirainen if (apr_isdigit(ch)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i = ch - '0';
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen }
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen else if (apr_isupper(ch)) {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen i = ch - ('A' - 10);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen else {
38da5c23b0a8b4012e79fcf647a8749786c83c51Timo Sirainen i = ch - ('a' - 10);
bb592fc58fe5c3e81ad941637fbb30d1d1cd8694Timo Sirainen }
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen i <<= 4;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen ch = x[1];
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (apr_isdigit(ch)) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen i += ch - '0';
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (apr_isupper(ch)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i += ch - ('A' - 10);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen else {
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen i += ch - ('a' - 10);
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen }
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen return i;
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen#else /*APR_CHARSET_EBCDIC*/
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /*
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;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen *
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * example:
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen *
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
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * 0x40
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen char buf[1];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (1 == sscanf(x, "%2x", &i)) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen buf[0] = i & 0xFF;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen ap_xlate_proto_from_ascii(buf, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return buf[0];
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen else {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen return 0;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen }
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen#endif /*APR_CHARSET_EBCDIC*/
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo SirainenPROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
feaa6a3d82ea61496ced1f83a726ff33047c7da2Timo Sirainen#if !APR_CHARSET_EBCDIC
eb99fc24b7d1b2abb6b9217e2b732595069c908eTimo Sirainen int i;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen x[0] = '%';
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen i = (ch & 0xF0) >> 4;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (i >= 10) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen x[1] = ('A' - 10) + i;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen }
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen else {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen x[1] = '0' + i;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen }
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen i = ch & 0x0F;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (i >= 10) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen x[2] = ('A' - 10) + i;
d67ac5f76cc02c227f4997878bb4aef48ee298faTimo Sirainen }
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen else {
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen x[2] = '0' + i;
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen }
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen#else /*APR_CHARSET_EBCDIC*/
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen static const char ntoa[] = { "0123456789ABCDEF" };
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen char buf[1];
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen ch &= 0xFF;
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen buf[0] = ch;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen ap_xlate_proto_to_ascii(buf, 1);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen x[0] = '%';
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen x[1] = ntoa[(buf[0] >> 4) & 0x0F];
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen x[2] = ntoa[buf[0] & 0x0F];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen x[3] = '\0';
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen#endif /*APR_CHARSET_EBCDIC*/
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen}
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen
8a6fc472a12c5ec09e2bd19f1b3acd553d75ff91Timo Sirainen/*
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * canonicalise a URL-encoded string
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen */
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen/*
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 Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenPROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum enctype t, int forcedec,
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen int proxyreq)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen{
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen int i, j, ch;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen char *y;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen char *allowed; /* characters which should not be encoded */
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen char *reserved; /* characters which much not be en/de-coded */
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen/*
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 *
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.)
4673afe816ffbca769585e4518e9b3c3d72e95ddTimo Sirainen */
4673afe816ffbca769585e4518e9b3c3d72e95ddTimo Sirainen if (t == enc_path) {
4673afe816ffbca769585e4518e9b3c3d72e95ddTimo Sirainen allowed = "~$-_.+!*'(),;:@&=";
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen else if (t == enc_search) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen allowed = "$-_.!*'(),;:@&=";
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen else if (t == enc_user) {
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen allowed = "$-_.+!*'(),;@&=";
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen }
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen else if (t == enc_fpath) {
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen allowed = "$-_.+!*'(),?:@&=";
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen }
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen else { /* if (t == enc_parm) */
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen allowed = "$-_.+!*'(),?/:@&=";
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen }
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen if (t == enc_path) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen reserved = "/";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen else if (t == enc_search) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen reserved = "+";
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen reserved = "";
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen }
6cb2c6ecddcdbeac9e6c73a292244747e12a793eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen y = apr_palloc(p, 3 * len + 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen for (i = 0, j = 0; i < len; i++, j++) {
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen/* always handle '/' first */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ch = x[i];
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen if (strchr(reserved, ch)) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen y[j] = ch;
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen continue;
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen }
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen/*
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen * decode it if not already done. do not decode reverse proxied URLs
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen * unless specifically forced
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if ((forcedec || (proxyreq && proxyreq != PROXYREQ_REVERSE)) && ch == '%') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!apr_isxdigit(x[i + 1]) || !apr_isxdigit(x[i + 2])) {
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen ch = ap_proxy_hex2c(&x[i + 1]);
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen i += 2;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (ch != 0 && strchr(reserved, ch)) { /* keep it encoded */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ap_proxy_c2hex(ch, &y[j]);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen j += 2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen continue;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen }
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen/* recode it, if necessary */
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen ap_proxy_c2hex(ch, &y[j]);
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen j += 2;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen }
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen else {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen y[j] = ch;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen y[j] = '\0';
fdcb22a688c4676face8db865736b217d9c07d19Timo Sirainen return y;
6e1e9e341ffe21a69a23229c2b896d03066a071eTimo Sirainen}
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen
8da095519878426b012058e6f331a669f327f47fTimo Sirainen/*
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.
075086f56fdcc480b0e87aabde63128e30b49002Timo Sirainen *
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * Returns an error string.
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen */
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo SirainenPROXY_DECLARE(char *)
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)
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char *addr, *scope_id, *strp, *host, *url = *urlp;
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen char *user = NULL, *password = NULL;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen apr_port_t tmp_port;
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen apr_status_t rv;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen if (url[0] != '/' || url[1] != '/') {
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen return "Malformed URL";
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen }
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen host = url + 2;
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen url = strchr(host, '/');
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen if (url == NULL) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen url = "";
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen }
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen else {
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen *(url++) = '\0'; /* skip seperating '/' */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen }
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen /* find _last_ '@' since it might occur in user/password part */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen strp = strrchr(host, '@');
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen
950a4789af247d57874d99a09ed7a67be5ddc2dcTimo Sirainen if (strp != NULL) {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen *strp = '\0';
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen user = host;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen host = strp + 1;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen/* find password */
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen strp = strchr(user, ':');
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen if (strp != NULL) {
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen *strp = '\0';
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1, 0);
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen if (password == NULL) {
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen return "Bad %-escape in URL (password)";
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen }
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen }
85452efe6f9edd85e2ce45bfc4f198e9cb9b82bdTimo Sirainen
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1, 0);
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen if (user == NULL) {
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen return "Bad %-escape in URL (username)";
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen if (userp != NULL) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen *userp = user;
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (passwordp != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *passwordp = password;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen /*
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen * Parse the host string to separate host portion from optional port.
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen * Perform range checking on port.
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen */
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 }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if (tmp_port != 0) { /* only update caller's port if port was specified */
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen *port = tmp_port;
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen ap_str_tolower(addr); /* DNS names are case-insensitive */
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen *urlp = url;
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen *hostp = addr;
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen return NULL;
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen}
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen
a6249a80d437771867cf654ae9d11f8418c9d07bTimo SirainenPROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message)
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen{
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen const char *uri = ap_escape_html(r->pool, r->uri);
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen apr_table_setn(r->notes, "error-notes",
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen apr_pstrcat(r->pool,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen "The proxy server could not handle the request <em><a href=\"",
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen uri, "\">", ap_escape_html(r->pool, r->method), "&nbsp;", uri,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen "</a></em>.<p>\n"
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen "Reason: <strong>", ap_escape_html(r->pool, message),
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen "</strong></p>",
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen NULL));
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen
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
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,
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen r->uri);
9e9763d04764f094c2f1bd6f36f2d83a89bd699dTimo Sirainen return statuscode;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen}
14c3da8abe2e666ecdb2900c8000478ef303161bTimo Sirainen
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainenstatic const char *
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen proxy_get_host_of_request(request_rec *r)
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen{
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen char *url, *user = NULL, *password = NULL, *err, *host;
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen apr_port_t port;
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen if (r->hostname != NULL) {
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen return r->hostname;
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen }
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen /* Set url to the first char after "scheme://" */
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen if ((url = strchr(r->uri, ':')) == NULL || url[1] != '/' || url[2] != '/') {
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen return NULL;
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen }
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen url = apr_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen if (err != NULL) {
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00899) "%s", err);
0dab9ad19ae7b1e3afe74d3ace2882fabb264a41Timo Sirainen }
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen r->hostname = host;
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen return host; /* ought to return the port, too */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen}
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
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{
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen const char *addr = This->name;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen long ip_addr[4];
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen int i, quads;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen long bits;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /*
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()
df9169221169d9cd8d8f49fc51ad40bed0fb6f64Timo Sirainen * return 1;
df9169221169d9cd8d8f49fc51ad40bed0fb6f64Timo Sirainen */
df9169221169d9cd8d8f49fc51ad40bed0fb6f64Timo Sirainen
df9169221169d9cd8d8f49fc51ad40bed0fb6f64Timo Sirainen /*
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * Parse IP addr manually, optionally allowing
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen * abbreviated net addresses like 192.168.
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* Iterate over up to 4 (dotted) quads. */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen for (quads = 0; quads < 4 && *addr != '\0'; ++quads) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen char *tmp;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (*addr == '/' && quads > 0) { /* netmask starts here. */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen break;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (!apr_isdigit(*addr)) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen return 0; /* no digit at start of quad */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen ip_addr[quads] = strtol(addr, &tmp, 0);
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (tmp == addr) { /* expected a digit, found something else */
97c3cae5873e56c15357686eeeb3144896445e50Timo Sirainen return 0;
97c3cae5873e56c15357686eeeb3144896445e50Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen /* invalid octet */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen addr = tmp;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*addr == '.' && quads != 3) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ++addr; /* after the 4th quad, a dot would be illegal */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
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));
97c3cae5873e56c15357686eeeb3144896445e50Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen if (addr[0] == '/' && apr_isdigit(addr[1])) { /* net mask follows: */
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen char *tmp;
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen ++addr;
97c3cae5873e56c15357686eeeb3144896445e50Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bits = strtol(addr, &tmp, 0);
ebc973d8a29738c9b91e5c92a124375661df799bTimo Sirainen
ebc973d8a29738c9b91e5c92a124375661df799bTimo Sirainen if (tmp == addr) { /* expected a digit, found something else */
ebc973d8a29738c9b91e5c92a124375661df799bTimo Sirainen return 0;
ebc973d8a29738c9b91e5c92a124375661df799bTimo Sirainen }
ebc973d8a29738c9b91e5c92a124375661df799bTimo Sirainen
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen addr = tmp;
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen if (bits < 0 || bits > 32) { /* netmask must be between 0 and 32 */
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen return 0;
97c3cae5873e56c15357686eeeb3144896445e50Timo Sirainen }
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen }
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen else {
ce84075e7ad4aa67fd45d12e75feceaffc64e523Timo Sirainen /*
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.)
97c3cae5873e56c15357686eeeb3144896445e50Timo Sirainen */
ce84075e7ad4aa67fd45d12e75feceaffc64e523Timo Sirainen while (quads > 0 && ip_addr[quads - 1] == 0) {
ce84075e7ad4aa67fd45d12e75feceaffc64e523Timo Sirainen --quads;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
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 if (quads < 1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* every zero-byte counts as 8 zero-bits */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen bits = 8 * quads;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
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",
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen inet_ntoa(This->addr), bits);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen }
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen
97c3cae5873e56c15357686eeeb3144896445e50Timo Sirainen This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits));
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
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 inet_ntoa(This->addr), bits);
658d3e1c4b58281c35241123973f5447f812764fTimo Sirainen This->addr.s_addr &= This->mask.s_addr;
658d3e1c4b58281c35241123973f5447f812764fTimo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00902)
10f216b59964b70548051d0a942ecea7d61c7a61Timo Sirainen " Set to %s/%ld", inet_ntoa(This->addr), bits);
658d3e1c4b58281c35241123973f5447f812764fTimo Sirainen }
658d3e1c4b58281c35241123973f5447f812764fTimo Sirainen
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen if (*addr == '\0') {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen This->matcher = proxy_match_ipaddr;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen return 1;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen }
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen else {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen return (*addr == '\0'); /* okay iff we've parsed the whole string */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen }
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen}
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen
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{
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen int i, ip_addr[4];
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen struct in_addr addr, *ip;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen const char *host = proxy_get_host_of_request(r);
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen
c224fff79d18480a65e9b4504b891b8ea176f5b1Timo Sirainen if (host == NULL) { /* oops! */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen return 0;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen }
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen memset(&addr, '\0', sizeof addr);
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen memset(ip_addr, '\0', sizeof ip_addr);
3dbc59409d19dbcd3f47c041fdd2fe342647e331Timo Sirainen
f84e7cabe355c6416898b7ae82b7d59acc3c7fbdTimo Sirainen if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
3dbc59409d19dbcd3f47c041fdd2fe342647e331Timo Sirainen for (addr.s_addr = 0, i = 0; i < 4; ++i) {
f84e7cabe355c6416898b7ae82b7d59acc3c7fbdTimo Sirainen /* ap_proxy_is_ipaddr() already confirmed that we have
f84e7cabe355c6416898b7ae82b7d59acc3c7fbdTimo Sirainen * a valid octet in ip_addr[i]
f84e7cabe355c6416898b7ae82b7d59acc3c7fbdTimo Sirainen */
f84e7cabe355c6416898b7ae82b7d59acc3c7fbdTimo Sirainen addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen }
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen#if DEBUGGING
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)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "%s/", inet_ntoa(This->addr));
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00905)
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen "%s", inet_ntoa(This->mask));
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen#endif
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen return 1;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen }
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen#if DEBUGGING
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen else {
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)
97c3cae5873e56c15357686eeeb3144896445e50Timo Sirainen "%s/", inet_ntoa(This->addr));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00908)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "%s", inet_ntoa(This->mask));
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen#endif
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen else {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen struct apr_sockaddr_t *reqaddr;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen if (apr_sockaddr_info_get(&reqaddr, host, APR_UNSPEC, 0, 0, r->pool)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen != APR_SUCCESS) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen#if DEBUGGING
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#endif
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen return 0;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen
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 */
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen while (reqaddr) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen ip = (struct in_addr *) reqaddr->ipaddr_ptr;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (This->addr.s_addr == (ip->s_addr & This->mask.s_addr)) {
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch#if DEBUGGING
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 "%s/", inet_ntoa(This->addr));
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00912)
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch "%s", inet_ntoa(This->mask));
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch#endif
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return 1;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch }
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch#if DEBUGGING
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen else {
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 "%s/", inet_ntoa(This->addr));
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00915)
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen "%s", inet_ntoa(This->mask));
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen#endif
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen reqaddr = reqaddr->next;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen return 0;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen}
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen
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{
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen char *addr = This->name;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen int i;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen /* Domain name must start with a '.' */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (addr[0] != '.') {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return 0;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen
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 continue;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen#if 0
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (addr[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 }
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen#endif
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (addr[i] != '\0') {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return 0;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* Strip trailing dots */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen addr[i] = '\0';
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen This->matcher = proxy_match_domainname;
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen return 1;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen}
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
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{
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen const char *host = proxy_get_host_of_request(r);
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen int d_len = strlen(This->name), h_len;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen if (host == NULL) { /* some error was logged already */
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen return 0;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen h_len = strlen(host);
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen
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] == '.') {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen --d_len;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen while (h_len > 0 && host[h_len - 1] == '.') {
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen --h_len;
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return h_len > d_len
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen}
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen
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)
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen{
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen struct apr_sockaddr_t *addr;
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen char *host = This->name;
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen int i;
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen /* Host names must not start with a '.' */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (host[0] == '.') {
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen return 0;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
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
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen if (host[i] != '\0' || apr_sockaddr_info_get(&addr, host, APR_UNSPEC, 0, 0, p) != APR_SUCCESS) {
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen return 0;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen }
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen This->hostaddr = addr;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen /* Strip trailing dots */
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen for (i = strlen(host) - 1; i > 0 && host[i] == '.'; --i) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen host[i] = '\0';
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen This->matcher = proxy_match_hostname;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
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)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen char *host = This->name;
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen const char *host2 = proxy_get_host_of_request(r);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen int h2_len;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen int h1_len;
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen if (host == NULL || host2 == NULL) {
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen return 0; /* oops! */
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen h2_len = strlen(host2);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen h1_len = strlen(host);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen#if 0
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen struct apr_sockaddr_t *addr = *This->hostaddr;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen /* Try to deal with multiple IP addr's for a host */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen while (addr) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (addr->ipaddr_ptr == ? ? ? ? ? ? ? ? ? ? ? ? ?)
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return 1;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen addr = addr->next;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
5b237a9d400a434920c8fd77ae53e6b44c38d3fbTimo Sirainen#endif
5b237a9d400a434920c8fd77ae53e6b44c38d3fbTimo Sirainen
5b237a9d400a434920c8fd77ae53e6b44c38d3fbTimo Sirainen /* Ignore trailing dots in host2 comparison: */
5b237a9d400a434920c8fd77ae53e6b44c38d3fbTimo Sirainen while (h2_len > 0 && host2[h2_len - 1] == '.') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen --h2_len;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (h1_len > 0 && host[h1_len - 1] == '.') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen --h1_len;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return h1_len == h2_len
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen && strncasecmp(host, host2, h1_len) == 0;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
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)
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen{
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen This->matcher = proxy_match_word;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return 1;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen}
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
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{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *host = proxy_get_host_of_request(r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return host != NULL && ap_strstr_c(host, This->name) != NULL;
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen}
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen
588f592a98fca95a10aaccdc76a589558e9ba125Timo Sirainen#define MAX_IP_STR_LEN (46)
588f592a98fca95a10aaccdc76a589558e9ba125Timo Sirainen
3a282e21c69b9cad1b5f9359ec3aebd3c8b8e901Timo SirainenPROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf,
3a282e21c69b9cad1b5f9359ec3aebd3c8b8e901Timo Sirainen const char *hostname, apr_sockaddr_t *addr)
3a282e21c69b9cad1b5f9359ec3aebd3c8b8e901Timo Sirainen{
3a282e21c69b9cad1b5f9359ec3aebd3c8b8e901Timo Sirainen int j;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi
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 struct apr_sockaddr_t *conf_addr;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen "checking remote machine [%s] against [%s]",
0360636eced27e96661f210828d1203871e6c47cTimo Sirainen hostname, npent[j].name);
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 "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "matched", hostname, npent[j].name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return HTTP_FORBIDDEN;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
819e20e6f108db20751e19784ee5a091b3f50046Timo Sirainen
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 if (!addr)
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen continue;
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen
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];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen apr_sockaddr_t *uri_addr;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen if (apr_sockaddr_ip_getbuf(caddr, sizeof caddr, conf_addr))
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen continue;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
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))
b6ccb2a38287c42aa53f66a927a6ada9d324b0beTimo Sirainen continue;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen "ProxyBlock comparing %s and %s", caddr, uaddr);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (!strcmp(caddr, uaddr)) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(00917)
430acc18d409c92da20be46ef35dc6f1d2a855d2Timo Sirainen "connect to remote machine %s blocked: "
430acc18d409c92da20be46ef35dc6f1d2a855d2Timo Sirainen "IP %s matched", hostname, caddr);
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen return HTTP_FORBIDDEN;
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
5b440b4d921cb1a36d74b4082599ccd3bb0f0401Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return OK;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen}
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* set up the minimal filter set */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenPROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen ap_add_input_filter("HTTP_IN", NULL, r, c);
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen return OK;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen}
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo SirainenPROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen proxy_dir_conf *conf, const char *url)
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen{
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen proxy_req_conf *rconf;
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen struct proxy_alias *ent;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen int i, l1, l2;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen char *u;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
a6249a80d437771867cf654ae9d11f8418c9d07bTimo Sirainen /*
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
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen */
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen if (r->proxyreq != PROXYREQ_REVERSE) {
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen return url;
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen }
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen l1 = strlen(url);
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen if (conf->interpolate_env == 1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rconf = ap_get_module_config(r->request_config, &proxy_module);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen ent = (struct proxy_alias *)rconf->raliases->elts;
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen }
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen else {
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen ent = (struct proxy_alias *)conf->raliases->elts;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen }
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen for (i = 0; i < conf->raliases->nelts; i++) {
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen proxy_server_conf *sconf = (proxy_server_conf *)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_get_module_config(r->server->module_config, &proxy_module);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_balancer *balancer;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *real = ent[i].real;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen /*
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 */
4f44284b96302c0a18203e2ac1243aeb193c6840Timo Sirainen if (ap_proxy_valid_balancer_name((char *)real, 0) &&
4f44284b96302c0a18203e2ac1243aeb193c6840Timo Sirainen (balancer = ap_proxy_get_balancer(r->pool, sconf, real, 1))) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen int n, l3 = 0;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen proxy_worker **worker = (proxy_worker **)balancer->workers->elts;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen const char *urlpart = ap_strchr_c(real + sizeof(BALANCER_PREFIX) - 1, '/');
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (urlpart) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (!urlpart[1])
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen urlpart = NULL;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen else
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen l3 = strlen(urlpart);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
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
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen */
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen for (n = 0; n < balancer->workers->nelts; n++) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen l2 = strlen((*worker)->s->name);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if (urlpart) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen /* urlpart (l3) assuredly starts with its own '/' */
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if ((*worker)->s->name[l2 - 1] == '/')
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen --l2;
6f1936d4f5424f2ce766b62ef41f4173ecf5e33bTimo Sirainen if (l1 >= l2 + l3
6f1936d4f5424f2ce766b62ef41f4173ecf5e33bTimo Sirainen && strncasecmp((*worker)->s->name, url, l2) == 0
6f1936d4f5424f2ce766b62ef41f4173ecf5e33bTimo Sirainen && strncmp(urlpart, url + l2, l3) == 0) {
6f1936d4f5424f2ce766b62ef41f4173ecf5e33bTimo Sirainen u = apr_pstrcat(r->pool, ent[i].fake, &url[l2 + l3],
6f1936d4f5424f2ce766b62ef41f4173ecf5e33bTimo Sirainen NULL);
6f1936d4f5424f2ce766b62ef41f4173ecf5e33bTimo Sirainen return ap_is_url(u) ? u : ap_construct_url(r->pool, u, r);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
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 }
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen worker++;
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
54cb36f32da0f2b1225a62e9e5717d521e21aa99Timo Sirainen else {
54cb36f32da0f2b1225a62e9e5717d521e21aa99Timo Sirainen const char *part = url;
54cb36f32da0f2b1225a62e9e5717d521e21aa99Timo Sirainen l2 = strlen(real);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen if (real[0] == '/') {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen part = ap_strstr_c(url, "://");
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen if (part) {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen part = ap_strchr_c(part+3, '/');
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen if (part) {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen l1 = strlen(part);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen }
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen else {
54cb36f32da0f2b1225a62e9e5717d521e21aa99Timo Sirainen part = url;
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen }
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen }
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen else {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen part = url;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
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);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen return url;
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen}
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen/*
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.
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo SirainenPROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r,
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen proxy_dir_conf *conf, const char *str)
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen{
05f323615730bc20d5e9f2c85b01465f88af2092Timo Sirainen proxy_req_conf *rconf = ap_get_module_config(r->request_config,
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen &proxy_module);
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen struct proxy_alias *ent;
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen apr_size_t len = strlen(str);
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen const char *newpath = NULL;
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen const char *newdomain = NULL;
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen const char *pathp;
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen const char *domainp;
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen const char *pathe = NULL;
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen const char *domaine = NULL;
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen apr_size_t l1, l2, poffs = 0, doffs = 0;
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen int i;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen int ddiff = 0;
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen int pdiff = 0;
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen char *ret;
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen if (r->proxyreq != PROXYREQ_REVERSE) {
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen return str;
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen }
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen /*
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
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if ((pathp = apr_strmatch(ap_proxy_strmatch_path, str, len)) != NULL) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen pathp += 5;
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen poffs = pathp - str;
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen pathe = ap_strchr_c(pathp, ';');
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen l1 = pathe ? (pathe - pathp) : strlen(pathp);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen pathe = pathp + l1 ;
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen if (conf->interpolate_env == 1) {
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen ent = (struct proxy_alias *)rconf->cookie_paths->elts;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen else {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen ent = (struct proxy_alias *)conf->cookie_paths->elts;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen for (i = 0; i < conf->cookie_paths->nelts; i++) {
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen l2 = strlen(ent[i].fake);
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen if (l1 >= l2 && strncmp(ent[i].fake, pathp, l2) == 0) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen newpath = ent[i].real;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen pdiff = strlen(newpath) - l1;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen break;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if ((domainp = apr_strmatch(ap_proxy_strmatch_domain, str, len)) != NULL) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen domainp += 7;
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen doffs = domainp - str;
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen domaine = ap_strchr_c(domainp, ';');
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen l1 = domaine ? (domaine - domainp) : strlen(domainp);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen domaine = domainp + l1;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if (conf->interpolate_env == 1) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen ent = (struct proxy_alias *)rconf->cookie_domains->elts;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen else {
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen ent = (struct proxy_alias *)conf->cookie_domains->elts;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen for (i = 0; i < conf->cookie_domains->nelts; i++) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen l2 = strlen(ent[i].fake);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if (l1 >= l2 && strncasecmp(ent[i].fake, domainp, l2) == 0) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen newdomain = ent[i].real;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen ddiff = strlen(newdomain) - l1;
8c94614f795530b2cbe70e5e828da121f2ddbee2Timo Sirainen break;
003dcf6f58919f7c64d9307b6de829b0259bb592Timo Sirainen }
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen }
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen }
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen if (newpath) {
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen ret = apr_palloc(r->pool, len + pdiff + ddiff + 1);
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen l1 = strlen(newpath);
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen if (newdomain) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen l2 = strlen(newdomain);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if (doffs > poffs) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen memcpy(ret, str, poffs);
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen memcpy(ret + poffs, newpath, l1);
fcadc92fa095335d1119b161584e7fa8568f9267Timo Sirainen memcpy(ret + poffs + l1, pathe, domainp - pathe);
fcadc92fa095335d1119b161584e7fa8568f9267Timo Sirainen memcpy(ret + doffs + pdiff, newdomain, l2);
fcadc92fa095335d1119b161584e7fa8568f9267Timo Sirainen strcpy(ret + doffs + pdiff + l2, domaine);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen else {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen memcpy(ret, str, doffs) ;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen memcpy(ret + doffs, newdomain, l2);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen memcpy(ret + doffs + l2, domaine, pathp - domaine);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen memcpy(ret + poffs + ddiff, newpath, l1);
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen strcpy(ret + poffs + ddiff + l1, pathe);
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen }
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen }
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen else {
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen memcpy(ret, str, poffs);
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen memcpy(ret + poffs, newpath, l1);
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen strcpy(ret + poffs + l1, pathe);
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen }
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen }
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen else {
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen if (newdomain) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = apr_palloc(r->pool, len + pdiff + ddiff + 1);
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen l2 = strlen(newdomain);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(ret, str, doffs);
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen memcpy(ret + doffs, newdomain, l2);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen strcpy(ret + doffs+l2, domaine);
4f44284b96302c0a18203e2ac1243aeb193c6840Timo Sirainen }
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen else {
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen ret = (char *)str; /* no change */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen }
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen return ret;
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen}
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen * BALANCER related...
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen * verifies that the balancer name conforms to standards.
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen */
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo SirainenPROXY_DECLARE(int) ap_proxy_valid_balancer_name(char *name, int i)
fd1a173038402c968f82d6b19b8b2e029bbcee45Timo Sirainen{
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen if (!i)
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen i = sizeof(BALANCER_PREFIX)-1;
fd1a173038402c968f82d6b19b8b2e029bbcee45Timo Sirainen return (!strncasecmp(name, BALANCER_PREFIX, i));
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen}
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen
fd1a173038402c968f82d6b19b8b2e029bbcee45Timo Sirainen
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo SirainenPROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen proxy_server_conf *conf,
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen const char *url,
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen int care)
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen{
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen proxy_balancer *balancer;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen char *c, *uri = apr_pstrdup(p, url);
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen int i;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen proxy_hashes hash;
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen ap_str_tolower(uri);
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen c = strchr(uri, ':');
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
e7912167935f67b3dc68c80bf80d719bb1cdc533Timo Sirainen return NULL;
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* remove path from uri */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if ((c = strchr(c + 3, '/'))) {
c31661baf87b506c2a90a1fca02968cf82e448bbTimo Sirainen *c = '\0';
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
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) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (!care || !balancer->s->inactive) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen return balancer;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen balancer++;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return NULL;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo Sirainen
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo SirainenPROXY_DECLARE(char *) ap_proxy_update_balancer(apr_pool_t *p,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen proxy_balancer *balancer,
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo Sirainen const char *url)
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo Sirainen{
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen apr_uri_t puri;
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen if (apr_uri_parse(p, url, &puri) != APR_SUCCESS) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen return apr_psprintf(p, "unable to parse: %s", url);
1a8b6bb75a7e10e0a44a98848f478f16972f13e7Timo Sirainen }
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",
1a8b6bb75a7e10e0a44a98848f478f16972f13e7Timo Sirainen balancer->s->name, puri.path);
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
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",
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen balancer->s->name, puri.hostname);
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen return NULL;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen}
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen#define PROXY_UNSET_NONCE '\n'
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo SirainenPROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen proxy_balancer **balancer,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen proxy_server_conf *conf,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen const char *url,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen const char *alias,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen int do_malloc)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen{
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen proxy_balancer_method *lbmethod;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen proxy_balancer_shared *bshared;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen char *c, *q, *uri = apr_pstrdup(p, url);
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen const char *sname;
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo Sirainen
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen /* We should never get here without a valid BALANCER_PREFIX... */
223e07c3178289fe7e8ec62af7655657ee236dcfTimo Sirainen
223e07c3178289fe7e8ec62af7655657ee236dcfTimo Sirainen c = strchr(uri, ':');
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 */
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if ((q = strchr(c + 3, '/')))
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen *q = '\0';
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo Sirainen ap_str_tolower(uri);
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo Sirainen *balancer = apr_array_push(conf->balancers);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen memset(*balancer, 0, sizeof(proxy_balancer));
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
ebc973d8a29738c9b91e5c92a124375661df799bTimo Sirainen /*
6b77095184aeb8a9976a74fa9ba1a06740f40d0eTimo Sirainen * NOTE: The default method is byrequests, which we assume
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen * exists!
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen lbmethod = ap_lookup_provider(PROXY_LBMETHOD, "byrequests", "0");
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (!lbmethod) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen return "Can't find 'byrequests' lb method";
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen }
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker *));
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen (*balancer)->gmutex = NULL;
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen (*balancer)->tmutex = NULL;
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen (*balancer)->lbmethod = lbmethod;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen if (do_malloc)
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen bshared = ap_malloc(sizeof(proxy_balancer_shared));
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen else
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen bshared = apr_palloc(p, sizeof(proxy_balancer_shared));
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen memset(bshared, 0, sizeof(proxy_balancer_shared));
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen
ac1c79d03888e634d26914780f7a7bc9cf3bd4b6Timo Sirainen bshared->was_malloced = (do_malloc != 0);
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 }
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen ap_pstr2_alnum(p, bshared->name + sizeof(BALANCER_PREFIX) - 1,
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen &sname);
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 }
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);
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen (*balancer)->hash = bshared->hash;
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen bshared->forcerecovery = 1;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen *bshared->nonce = PROXY_UNSET_NONCE; /* impossible valid input */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen (*balancer)->s = bshared;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen (*balancer)->sconf = conf;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen return ap_proxy_update_balancer(p, *balancer, alias);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen/*
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen * Create an already defined balancer and free up memory.
ac1c79d03888e634d26914780f7a7bc9cf3bd4b6Timo Sirainen */
ac1c79d03888e634d26914780f7a7bc9cf3bd4b6Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_share_balancer(proxy_balancer *balancer,
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen proxy_balancer_shared *shm,
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen int i)
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen{
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen apr_status_t rv = APR_SUCCESS;
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen proxy_balancer_method *lbmethod;
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (!shm || !balancer->s)
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen return APR_EINVAL;
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen memcpy(shm, balancer->s, sizeof(proxy_balancer_shared));
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (balancer->s->was_malloced)
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen free(balancer->s);
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen balancer->s = shm;
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen balancer->s->index = i;
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen /* the below should always succeed */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen lbmethod = ap_lookup_provider(PROXY_LBMETHOD, balancer->s->lbpname, "0");
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (lbmethod)
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen balancer->lbmethod = lbmethod;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (*balancer->s->nonce == PROXY_UNSET_NONCE) {
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen char nonce[APR_UUID_FORMATTED_LENGTH + 1];
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen apr_uuid_t uuid;
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen /* Retrieve a UUID and store the nonce for the lifetime of
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen * the process.
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen */
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen apr_uuid_get(&uuid);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen apr_uuid_format(nonce, &uuid);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen rv = PROXY_STRNCPY(balancer->s->nonce, nonce);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen }
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen return rv;
90814c0276d9f7bd6650e430b8cb64a8918ad4b3Timo Sirainen}
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balancer, server_rec *s, apr_pool_t *p)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen{
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen apr_status_t rv = APR_SUCCESS;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen ap_slotmem_provider_t *storage = balancer->storage;
90814c0276d9f7bd6650e430b8cb64a8918ad4b3Timo Sirainen apr_size_t size;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen unsigned int num;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen if (!storage) {
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(00918)
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen "no provider for %s", balancer->s->name);
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen return APR_EGENERAL;
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen }
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen /*
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen * for each balancer we need to init the global
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen * mutex and then attach to the shared worker shm
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen */
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (!balancer->gmutex) {
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(00919)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen "no mutex %s", balancer->s->name);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return APR_EGENERAL;
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen }
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen /* Re-open the mutex for the child. */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen rv = apr_global_mutex_child_init(&(balancer->gmutex),
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen apr_global_mutex_lockfile(balancer->gmutex),
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen p);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (rv != APR_SUCCESS) {
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(00920)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Failed to reopen mutex %s in child",
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen balancer->s->name);
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen return rv;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainen /* now attach */
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen storage->attach(&(balancer->wslot), balancer->s->sname, &size, &num, p);
d67ac5f76cc02c227f4997878bb4aef48ee298faTimo Sirainen if (!balancer->wslot) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(00921) "slotmem_attach failed");
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return APR_EGENERAL;
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen }
47025fa2781c7862957690e21fc9e1aa2f1b6f60Timo Sirainen if (balancer->lbmethod && balancer->lbmethod->reset)
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen balancer->lbmethod->reset(balancer, s);
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (balancer->tmutex == NULL) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen rv = apr_thread_mutex_create(&(balancer->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if (rv != APR_SUCCESS) {
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(00922)
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen "can not create balancer thread mutex");
ec9161e5061a34f0262ccbbf7760ee933d409167Timo Sirainen return rv;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen }
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen return APR_SUCCESS;
223e07c3178289fe7e8ec62af7655657ee236dcfTimo Sirainen}
4cc8a792108e1c115c1c6c9eb61746b31f0205dbTimo Sirainen
4cc8a792108e1c115c1c6c9eb61746b31f0205dbTimo Sirainen/*
4cc8a792108e1c115c1c6c9eb61746b31f0205dbTimo Sirainen * CONNECTION related...
4cc8a792108e1c115c1c6c9eb61746b31f0205dbTimo Sirainen */
4cc8a792108e1c115c1c6c9eb61746b31f0205dbTimo Sirainen
4cc8a792108e1c115c1c6c9eb61746b31f0205dbTimo Sirainenstatic apr_status_t conn_pool_cleanup(void *theworker)
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen{
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen proxy_worker *worker = (proxy_worker *)theworker;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (worker->cp->res) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen worker->cp->pool = NULL;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen return APR_SUCCESS;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen}
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void init_conn_pool(apr_pool_t *p, proxy_worker *worker)
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen{
bb592fc58fe5c3e81ad941637fbb30d1d1cd8694Timo Sirainen apr_pool_t *pool;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen proxy_conn_pool *cp;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /*
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.
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen */
ac1c79d03888e634d26914780f7a7bc9cf3bd4b6Timo Sirainen apr_pool_create(&pool, p);
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen apr_pool_tag(pool, "proxy_worker_cp");
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /*
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen * Alloc from the same pool as worker.
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen * proxy_conn_pool is permanently attached to the worker.
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen cp = (proxy_conn_pool *)apr_pcalloc(p, sizeof(proxy_conn_pool));
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainen cp->pool = pool;
db5fdf605555d43ca7abeaeb9cba0dcb178f2688Aki Tuomi worker->cp = cp;
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainen}
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainen
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainenstatic apr_status_t connection_cleanup(void *theconn)
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainen{
6af9d209ee997d624aecbaf4a0bcd0ca7d60c31aTimo Sirainen proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen proxy_worker *worker = conn->worker;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen /*
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * If the connection pool is NULL the worker
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen * cleanup has been run. Just return.
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen */
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen if (!worker->cp) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return APR_SUCCESS;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (conn->r) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen apr_pool_destroy(conn->r->pool);
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen conn->r = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen /* Sanity check: Did we already return the pooled connection? */
39344e449ff55820f8620c0fa943362f90ff9f6aTimo Sirainen if (conn->inreslist) {
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,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen worker->s->name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return APR_SUCCESS;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
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 apr_pool_t *p = conn->pool;
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen apr_pool_clear(p);
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen conn = apr_pcalloc(p, sizeof(proxy_conn_rec));
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen conn->pool = p;
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen conn->worker = worker;
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen apr_pool_create(&(conn->scpool), p);
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen apr_pool_tag(conn->scpool, "proxy_conn_scpool");
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen }
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen
67b328e6950f41c8d680af4775639c2c689f43cdTimo Sirainen if (worker->s->hmax && worker->cp->res) {
67b328e6950f41c8d680af4775639c2c689f43cdTimo Sirainen conn->inreslist = 1;
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen apr_reslist_release(worker->cp->res, (void *)conn);
67b328e6950f41c8d680af4775639c2c689f43cdTimo Sirainen }
67b328e6950f41c8d680af4775639c2c689f43cdTimo Sirainen else
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen {
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen worker->cp->conn = conn;
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen }
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen /* Always return the SUCCESS */
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen return APR_SUCCESS;
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen}
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainenstatic void socket_cleanup(proxy_conn_rec *conn)
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen{
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen conn->sock = NULL;
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen conn->connection = NULL;
f63b54b0c5fa2717443fd3a96f37119fdceb39e9Timo Sirainen apr_pool_clear(conn->scpool);
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen}
f63b54b0c5fa2717443fd3a96f37119fdceb39e9Timo Sirainen
f63b54b0c5fa2717443fd3a96f37119fdceb39e9Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
d55fb5fbf2dc0601fc34dbd26221369b0cedb5daTimo Sirainen request_rec *r)
f63b54b0c5fa2717443fd3a96f37119fdceb39e9Timo Sirainen{
f63b54b0c5fa2717443fd3a96f37119fdceb39e9Timo Sirainen apr_bucket_brigade *bb;
95c8129d63a2e243402d67f9c93e532beebee394Timo Sirainen apr_status_t rv;
95c8129d63a2e243402d67f9c93e532beebee394Timo Sirainen
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen /*
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.
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen */
d55fb5fbf2dc0601fc34dbd26221369b0cedb5daTimo Sirainen if (conn->sock && conn->connection) {
d55fb5fbf2dc0601fc34dbd26221369b0cedb5daTimo Sirainen bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen rv = ap_get_brigade(conn->connection->input_filters, bb,
d55fb5fbf2dc0601fc34dbd26221369b0cedb5daTimo Sirainen AP_MODE_READBYTES, APR_NONBLOCK_READ,
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen HUGE_STRING_LEN);
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen if ((rv != APR_SUCCESS) && !APR_STATUS_IS_EAGAIN(rv)) {
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen socket_cleanup(conn);
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen }
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen if (!APR_BRIGADE_EMPTY(bb)) {
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen apr_off_t len;
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen rv = apr_brigade_length(bb, 0, &len);
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen ap_log_rerror(APLOG_MARK, APLOG_TRACE3, rv, r,
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen "SSL cleanup brigade contained %"
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen APR_OFF_T_FMT " bytes of data.", len);
0441036bcde07d0ee015f06967a6579e3e1d5b9bTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen apr_brigade_destroy(bb);
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen }
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return APR_SUCCESS;
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen}
ee1681a053a515048d82fb57c366c26696fa0a33Timo Sirainen
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen/* reslist constructor */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainenstatic apr_status_t connection_constructor(void **resource, void *params,
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen apr_pool_t *pool)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen apr_pool_t *ctx;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen apr_pool_t *scpool;
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen proxy_conn_rec *conn;
9405e52abbd62fa7f57fbd86943743e1959fe7acTimo Sirainen proxy_worker *worker = (proxy_worker *)params;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen /*
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen * Create the subpool for each connection
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen * This keeps the memory consumption constant
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen * when disconnecting from backend.
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen apr_pool_create(&ctx, pool);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen apr_pool_tag(ctx, "proxy_conn_pool");
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen /*
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 */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen apr_pool_create(&scpool, ctx);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen apr_pool_tag(scpool, "proxy_conn_scpool");
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen conn = apr_pcalloc(ctx, sizeof(proxy_conn_rec));
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen conn->pool = ctx;
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen conn->scpool = scpool;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen conn->worker = worker;
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen conn->inreslist = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *resource = conn;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return APR_SUCCESS;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen}
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen/* reslist destructor */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainenstatic apr_status_t connection_destructor(void *resource, void *params,
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen apr_pool_t *pool)
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen{
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen proxy_conn_rec *conn = (proxy_conn_rec *)resource;
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen /* Destroy the pool only if not called from reslist_destroy */
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen if (conn->worker->cp->pool) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen apr_pool_destroy(conn->pool);
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen return APR_SUCCESS;
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen}
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen/*
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen * WORKER related...
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
de7611687432b9560bdd31a4969609e7b68a5b83Timo SirainenPROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen proxy_balancer *balancer,
275cc4c040899c132b2acbe2fcac48ba4c1abbcfTimo Sirainen proxy_server_conf *conf,
275cc4c040899c132b2acbe2fcac48ba4c1abbcfTimo Sirainen const char *url)
275cc4c040899c132b2acbe2fcac48ba4c1abbcfTimo Sirainen{
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen proxy_worker *worker;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen proxy_worker *max_worker = NULL;
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen int max_match = 0;
ac432b21f61d8c97f3459134b180ed13b90704e5Timo Sirainen int url_length;
ac432b21f61d8c97f3459134b180ed13b90704e5Timo Sirainen int min_match;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen int worker_name_length;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen const char *c;
ac432b21f61d8c97f3459134b180ed13b90704e5Timo Sirainen char *url_copy;
ac432b21f61d8c97f3459134b180ed13b90704e5Timo Sirainen int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
3f88671f6d3d54d1e5fd090c2d1cbd602df0d09bTimo Sirainen c = ap_strchr_c(url, ':');
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen return NULL;
de7611687432b9560bdd31a4969609e7b68a5b83Timo Sirainen }
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen url_length = strlen(url);
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen url_copy = apr_pstrmemdup(p, url, url_length);
b6ccb2a38287c42aa53f66a927a6ada9d324b0beTimo Sirainen
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen /*
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.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen c = ap_strchr_c(c+3, '/');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (c) {
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen char *pathstart;
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen pathstart = url_copy + (c - url);
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen *pathstart = '\0';
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen ap_str_tolower(url_copy);
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen min_match = strlen(url_copy);
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen *pathstart = '/';
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen }
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen else {
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen ap_str_tolower(url_copy);
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen min_match = strlen(url_copy);
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen }
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen /*
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.
7133574ad9c46d79a6b741adfc5b0ecc04cd9298Timo Sirainen */
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen if (balancer) {
d8b23843fb938c0a8f19f4abdb6c2a04b898a2b1Timo Sirainen proxy_worker **workers = (proxy_worker **)balancer->workers->elts;
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen for (i = 0; i < balancer->workers->nelts; i++, workers++) {
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen worker = *workers;
d8b23843fb938c0a8f19f4abdb6c2a04b898a2b1Timo Sirainen if ( ((worker_name_length = strlen(worker->s->name)) <= url_length)
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen && (worker_name_length >= min_match)
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen && (worker_name_length > max_match)
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen && (strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) {
7133574ad9c46d79a6b741adfc5b0ecc04cd9298Timo Sirainen max_worker = worker;
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen max_match = worker_name_length;
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen } else {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen worker = (proxy_worker *)conf->workers->elts;
fcadc92fa095335d1119b161584e7fa8568f9267Timo Sirainen for (i = 0; i < conf->workers->nelts; i++, worker++) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if ( ((worker_name_length = strlen(worker->s->name)) <= url_length)
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen && (worker_name_length >= min_match)
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen && (worker_name_length > max_match)
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen && (strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen max_worker = worker;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen max_match = worker_name_length;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
fe761f466e2c0c49445115aa123c77097c0eaf5cTimo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
81c7a6e414a6d1c31f65cc977feda823b586d263Timo Sirainen return max_worker;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen}
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen/*
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.
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen */
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo SirainenPROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p,
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen proxy_worker **worker,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen proxy_balancer *balancer,
aba2f05e938a7f635b3f114d56c7c3413ee858feTimo Sirainen proxy_server_conf *conf,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen const char *url,
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen int do_malloc)
a0b92d47480ac4135b5dec900c4358defbb3e0e6Timo Sirainen{
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen int rv;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen apr_uri_t uri;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen proxy_worker_shared *wshared;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen char *ptr;
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen rv = apr_uri_parse(p, url, &uri);
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen if (rv != APR_SUCCESS) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return "Unable to parse URL";
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen if (!uri.hostname || !uri.scheme) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen return "URL must be absolute!";
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen ap_str_tolower(uri.hostname);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen ap_str_tolower(uri.scheme);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen /*
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 *
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen * ProxyPass / http://www.example.com
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen *
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen * in which case the worker goes in the conf slot.
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen */
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen if (balancer) {
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen proxy_worker **runtime;
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen /* recall that we get a ptr to the ptr here */
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen runtime = apr_array_push(balancer->workers);
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 balancer->wupdated = apr_time_now();
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen } else if (conf) {
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen *worker = apr_array_push(conf->workers);
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen } else {
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen /* we need to allocate space here */
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen *worker = apr_palloc(p, sizeof(proxy_worker));
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen }
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen memset(*worker, 0, 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. */
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen if (do_malloc)
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen wshared = ap_malloc(sizeof(proxy_worker_shared)); /* will be freed ap_proxy_share_worker */
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen else
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen wshared = apr_palloc(p, sizeof(proxy_worker_shared));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen memset(wshared, 0, sizeof(proxy_worker_shared));
57a91f930a12d2cd1220da4f3f7cb2c47557cd37Timo Sirainen
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 }
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 }
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen if (PROXY_STRNCPY(wshared->hostname, uri.hostname) != APR_SUCCESS) {
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen return apr_psprintf(p, "worker hostname (%s) too long", uri.hostname);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen }
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen wshared->port = uri.port;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen wshared->flush_packets = flush_off;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen wshared->flush_wait = PROXY_FLUSH_WAIT;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen wshared->is_address_reusable = 1;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen wshared->lbfactor = 1;
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen wshared->smax = -1;
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);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen wshared->was_malloced = (do_malloc != 0);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen (*worker)->hash = wshared->hash;
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen (*worker)->context = NULL;
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen (*worker)->cp = NULL;
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen (*worker)->balancer = balancer;
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen (*worker)->s = wshared;
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen return NULL;
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen}
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen/*
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen * Create an already defined worker and free up memory
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen */
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_share_worker(proxy_worker *worker, proxy_worker_shared *shm,
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen int i)
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen{
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen if (!shm || !worker->s)
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen return APR_EINVAL;
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen memcpy(shm, worker->s, sizeof(proxy_worker_shared));
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen if (worker->s->was_malloced)
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen free(worker->s); /* was malloced in ap_proxy_define_worker */
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen worker->s = shm;
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen worker->s->index = i;
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen return APR_SUCCESS;
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
57a91f930a12d2cd1220da4f3f7cb2c47557cd37Timo SirainenPROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, server_rec *s, apr_pool_t *p)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
e32cf1b4430c4a5f28c9b5bb8b1366e7b06ed68dTimo Sirainen apr_status_t rv = APR_SUCCESS;
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen int mpm_threads;
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen
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);
e32cf1b4430c4a5f28c9b5bb8b1366e7b06ed68dTimo Sirainen }
8925c5450daddcdd1834de2750b47fb6d192c6f6Timo Sirainen else {
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 */
57a91f930a12d2cd1220da4f3f7cb2c47557cd37Timo Sirainen if (!worker->s->retry_set) {
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen worker->s->retry = apr_time_from_sec(PROXY_WORKER_DEFAULT_RETRY);
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen }
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen /* By default address is reusable unless DisableReuse is set */
588f592a98fca95a10aaccdc76a589558e9ba125Timo Sirainen if (worker->s->disablereuse) {
588f592a98fca95a10aaccdc76a589558e9ba125Timo Sirainen worker->s->is_address_reusable = 0;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen }
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen else {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen worker->s->is_address_reusable = 1;
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen }
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen
57a91f930a12d2cd1220da4f3f7cb2c47557cd37Timo Sirainen ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen if (mpm_threads > 1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Set hard max to no more then mpm_threads */
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen if (worker->s->hmax == 0 || worker->s->hmax > mpm_threads) {
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen worker->s->hmax = mpm_threads;
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen }
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (worker->s->smax == -1 || worker->s->smax > worker->s->hmax) {
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen worker->s->smax = worker->s->hmax;
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen }
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen /* Set min to be lower then smax */
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (worker->s->min > worker->s->smax) {
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen worker->s->min = worker->s->smax;
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen }
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen }
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen else {
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen /* This will supress the apr_reslist creation */
746a7ec64a09649ed3c96c88b97cdc370a7bbe2fTimo Sirainen worker->s->min = worker->s->smax = worker->s->hmax = 0;
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen }
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen }
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen
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);
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen }
edf8c636e80ad4cfe5dd29525c718898685fc2c3Timo Sirainen else {
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 */
588f592a98fca95a10aaccdc76a589558e9ba125Timo Sirainen if (worker->tmutex == NULL) {
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen rv = apr_thread_mutex_create(&(worker->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen if (rv != APR_SUCCESS) {
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00928)
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen "can not create worker thread mutex");
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen return rv;
38da5c23b0a8b4012e79fcf647a8749786c83c51Timo Sirainen }
042668c0cd5a7d35ce6373ae493695e8f12d3157Timo Sirainen }
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen if (worker->cp == NULL)
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen init_conn_pool(p, worker);
042668c0cd5a7d35ce6373ae493695e8f12d3157Timo Sirainen if (worker->cp == NULL) {
042668c0cd5a7d35ce6373ae493695e8f12d3157Timo Sirainen ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00929)
38920bff33eaa2acef5c200df5ce7088fd61e673Timo Sirainen "can not create connection pool");
38920bff33eaa2acef5c200df5ce7088fd61e673Timo Sirainen return APR_EGENERAL;
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen }
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen if (worker->s->hmax) {
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen rv = apr_reslist_create(&(worker->cp->res),
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen worker->s->min, worker->s->smax,
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen worker->s->hmax, worker->s->ttl,
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen connection_constructor, connection_destructor,
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen worker, worker->cp->pool);
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen apr_pool_cleanup_register(worker->cp->pool, (void *)worker,
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen conn_pool_cleanup,
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen apr_pool_cleanup_null);
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen
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,
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen worker->s->hmax, worker->s->smax);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen
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);
bef19e231b696a2018fcb93d546a41fcf732c243Timo Sirainen }
bef19e231b696a2018fcb93d546a41fcf732c243Timo Sirainen
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen }
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen void *conn;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen rv = connection_constructor(&conn, worker, worker->cp->pool);
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen worker->cp->conn = conn;
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen
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 getpid(), worker->s->hostname);
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen }
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen }
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen if (rv == APR_SUCCESS) {
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen worker->s->status |= (PROXY_WORKER_INITIALIZED);
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen worker->local_status |= (PROXY_WORKER_INITIALIZED);
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen }
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen return rv;
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen}
1930b9fae508a90de5f08fcd74602cbe3a5a5964Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainenstatic int ap_proxy_retry_worker(const char *proxy_function, proxy_worker *worker,
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen server_rec *s)
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen{
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen if (worker->s->status & PROXY_WORKER_IN_ERROR) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (apr_time_now() > worker->s->error_time + worker->s->retry) {
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen ++worker->s->retries;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen worker->s->status &= ~PROXY_WORKER_IN_ERROR;
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00932)
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen "%s: worker for (%s) has been marked for retry",
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen proxy_function, worker->s->hostname);
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen return OK;
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen }
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen else {
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00933)
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen "%s: too soon to retry worker for (%s)",
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen proxy_function, worker->s->hostname);
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen return DECLINED;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
edf8c636e80ad4cfe5dd29525c718898685fc2c3Timo Sirainen }
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen else {
feaa6a3d82ea61496ced1f83a726ff33047c7da2Timo Sirainen return OK;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen}
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenPROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_balancer **balancer,
32147ee6bdea566e64139b77ad0ea89960200df9Timo Sirainen request_rec *r,
32147ee6bdea566e64139b77ad0ea89960200df9Timo Sirainen proxy_server_conf *conf, char **url)
32147ee6bdea566e64139b77ad0ea89960200df9Timo Sirainen{
feaa6a3d82ea61496ced1f83a726ff33047c7da2Timo Sirainen int access_status;
32147ee6bdea566e64139b77ad0ea89960200df9Timo Sirainen
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);
f07762518db1e3771500a1a761ea0c06be23b8b5Timo Sirainen if (*worker) {
056bbae2011f2d93570e59c0618702d835d7e244Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen "%s: found worker %s for %s",
f07762518db1e3771500a1a761ea0c06be23b8b5Timo Sirainen (*worker)->s->scheme, (*worker)->s->name, *url);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen *balancer = NULL;
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen access_status = OK;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen }
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen else if (r->proxyreq == PROXYREQ_PROXY) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (conf->forward) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "*: found forward proxy worker for %s", *url);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *balancer = NULL;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen *worker = conf->forward;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen access_status = OK;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen /*
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.
38920bff33eaa2acef5c200df5ce7088fd61e673Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen apr_table_setn(r->subprocess_env, "proxy-nokeepalive", "1");
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen }
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (r->proxyreq == PROXYREQ_REVERSE) {
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen if (conf->reverse) {
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
be6a511e672b84b1622f1875b2527827e20cbcb4Timo Sirainen "*: found reverse proxy worker for %s", *url);
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen *balancer = NULL;
be6a511e672b84b1622f1875b2527827e20cbcb4Timo Sirainen *worker = conf->reverse;
8e1c66e6f43698fbd5ae8b00863cbe10581aa9fdTimo Sirainen access_status = OK;
be6a511e672b84b1622f1875b2527827e20cbcb4Timo Sirainen /*
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 */
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen apr_table_setn(r->subprocess_env, "proxy-nokeepalive", "1");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
042668c0cd5a7d35ce6373ae493695e8f12d3157Timo Sirainen }
042668c0cd5a7d35ce6373ae493695e8f12d3157Timo Sirainen }
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);
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen access_status = HTTP_SERVICE_UNAVAILABLE;
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen }
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen return access_status;
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
054fdbfc20f57cb4a386e088ec773d9980ac8b2cTimo SirainenPROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen proxy_balancer *balancer,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen request_rec *r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_server_conf *conf)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen int access_status = OK;
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen if (balancer) {
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen access_status = proxy_run_post_request(worker, balancer, r, conf);
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen if (access_status == DECLINED) {
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen access_status = OK; /* no post_request handler available */
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen /* TODO: recycle direct worker */
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen }
da8115ebacf055f87ec71ae1155a421452f2e0d5Timo Sirainen }
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen return access_status;
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen}
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen/* DEPRECATED */
3ccab0bac68040f179a7de45c516cec258e28fdbTimo SirainenPROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **newsock,
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen const char *proxy_function,
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen apr_sockaddr_t *backend_addr,
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen const char *backend_name,
dc40ce1dda503f114e9505c2da9371fd3cb34096Timo Sirainen proxy_server_conf *conf,
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen request_rec *r)
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen{
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen apr_status_t rv;
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen int connected = 0;
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen int loglevel;
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen while (backend_addr && !connected) {
2087637d10ad94ea029fe055f8ee55cd594955a8Timo Sirainen if ((rv = apr_socket_create(newsock, backend_addr->family,
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen SOCK_STREAM, 0, r->pool)) != APR_SUCCESS) {
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 /*
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 */
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen backend_addr = backend_addr->next;
ac1c79d03888e634d26914780f7a7bc9cf3bd4b6Timo Sirainen continue;
ac1c79d03888e634d26914780f7a7bc9cf3bd4b6Timo Sirainen }
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (conf->recv_buffer_size > 0 &&
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen (rv = apr_socket_opt_set(*newsock, APR_SO_RCVBUF,
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen conf->recv_buffer_size))) {
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");
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen }
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen
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 }
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen /* Set a timeout on the socket */
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen if (conf->timeout_set) {
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen apr_socket_timeout_set(*newsock, conf->timeout);
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen }
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen else {
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen apr_socket_timeout_set(*newsock, r->server->timeout);
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen }
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
228edfb38d7f1a0bfe36f74e7c521006ea48fbdfTimo Sirainen "%s: fam %d socket created to connect to %s",
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen proxy_function, backend_addr->family, backend_name);
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen if (conf->source_address) {
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen rv = apr_socket_bind(*newsock, conf->source_address);
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen if (rv != APR_SUCCESS) {
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 proxy_function);
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen }
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen }
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen /* make the connection out of the socket */
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen rv = apr_socket_connect(*newsock, backend_addr);
2bde8972f2dcec46d96543407cc5b56954054359Timo Sirainen
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen /* if an error occurred, loop round and try again */
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen if (rv != APR_SUCCESS) {
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen apr_socket_close(*newsock);
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",
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen proxy_function, backend_addr, backend_name);
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen backend_addr = backend_addr->next;
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen continue;
0f506139b4c95589a09a81a5d51636aee994cd1eTimo Sirainen }
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen connected = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen return connected ? 0 : 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo SirainenPROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen proxy_conn_rec **conn,
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen proxy_worker *worker,
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen server_rec *s)
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen{
65d89650662f7f1681a3431c585bfc9721a85149Timo Sirainen apr_status_t rv;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!PROXY_WORKER_IS_USABLE(worker)) {
bef19e231b696a2018fcb93d546a41fcf732c243Timo Sirainen /* Retry the worker */
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen ap_proxy_retry_worker(proxy_function, worker, s);
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen if (!PROXY_WORKER_IS_USABLE(worker)) {
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00940)
d656ea23231ca1232b2dae327cea83bb44c6f6ffTimo Sirainen "%s: disabled connection for (%s)",
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen proxy_function, worker->s->hostname);
b06bfeaa9bb367b72edd51672c33e24d33d8ff1bTimo Sirainen return HTTP_SERVICE_UNAVAILABLE;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen }
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen }
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen if (worker->s->hmax && worker->cp->res) {
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen rv = apr_reslist_acquire(worker->cp->res, (void **)conn);
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen }
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen else {
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen /* create the new connection if the previous was destroyed */
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen if (!worker->cp->conn) {
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen connection_constructor((void **)conn, worker, worker->cp->pool);
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen }
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen else {
12e145323c63ecf3d3522bf1381012a985caa844Timo Sirainen *conn = worker->cp->conn;
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen worker->cp->conn = NULL;
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen }
ebc973d8a29738c9b91e5c92a124375661df799bTimo Sirainen rv = APR_SUCCESS;
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen }
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen if (rv != APR_SUCCESS) {
de83e0a4081e68172b66dd7fa9788effacdc1448Timo Sirainen ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00941)
f53a6e86c03f51ca7fb23a03751dfc88aa2d32f0Timo Sirainen "%s: failed to acquire connection for (%s)",
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen proxy_function, worker->s->hostname);
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen return HTTP_SERVICE_UNAVAILABLE;
bef19e231b696a2018fcb93d546a41fcf732c243Timo Sirainen }
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00942)
bef19e231b696a2018fcb93d546a41fcf732c243Timo Sirainen "%s: has acquired connection for (%s)",
bb592fc58fe5c3e81ad941637fbb30d1d1cd8694Timo Sirainen proxy_function, worker->s->hostname);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen (*conn)->worker = worker;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (*conn)->close = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (*conn)->inreslist = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return OK;
b06bfeaa9bb367b72edd51672c33e24d33d8ff1bTimo Sirainen}
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenPROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen proxy_conn_rec *conn,
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen server_rec *s)
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen{
8409959d66804dc963bc6fcdcc9a01da0d56a978Timo Sirainen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00943)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "%s: has released connection for (%s)",
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen proxy_function, conn->worker->s->hostname);
3a282e21c69b9cad1b5f9359ec3aebd3c8b8e901Timo Sirainen connection_cleanup(conn);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch
3a282e21c69b9cad1b5f9359ec3aebd3c8b8e901Timo Sirainen return OK;
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen}
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen
033557e1c8ebec5ae31f2f24fab90226a1945168Timo SirainenPROXY_DECLARE(int)
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainenap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen proxy_server_conf *conf,
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen proxy_worker *worker,
3054cbf69a94ca08123ca3a8d6a2c19a1784e11dTimo Sirainen proxy_conn_rec *conn,
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen apr_uri_t *uri,
bef19e231b696a2018fcb93d546a41fcf732c243Timo Sirainen char **url,
bb592fc58fe5c3e81ad941637fbb30d1d1cd8694Timo Sirainen const char *proxyname,
bb592fc58fe5c3e81ad941637fbb30d1d1cd8694Timo Sirainen apr_port_t proxyport,
d5bae4060a1ba3fe663991169de7102f81039304Timo Sirainen char *server_portstr,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int server_portstr_size)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen int server_port;
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen apr_status_t err = APR_SUCCESS;
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen apr_status_t uerr = APR_SUCCESS;
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen /*
73c76fa7340a107229c530196d026aadeae979c7Timo Sirainen * Break up the URL to determine the host to connect to
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
73c76fa7340a107229c530196d026aadeae979c7Timo Sirainen /* we break the URL into host, port, uri */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (APR_SUCCESS != apr_uri_parse(p, *url, uri)) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return ap_proxyerror(r, HTTP_BAD_REQUEST,
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen apr_pstrcat(p,"URI cannot be parsed: ", *url,
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen NULL));
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen }
bef19e231b696a2018fcb93d546a41fcf732c243Timo Sirainen if (!uri->port) {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen uri->port = apr_uri_port_of_scheme(uri->scheme);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
b06bfeaa9bb367b72edd51672c33e24d33d8ff1bTimo Sirainen
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);
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen /*
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.
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen /* are we connecting directly, or via a proxy? */
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen if (!proxyname) {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen *url = apr_pstrcat(p, uri->path, uri->query ? "?" : "",
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen uri->query ? uri->query : "",
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen uri->fragment ? "#" : "",
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen uri->fragment ? uri->fragment : "", NULL);
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen }
777ff25e82e0305e2696bcbe3c6e0274e3e8ce10Timo Sirainen /*
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen * Figure out if our passed in proxy_conn_rec has a usable
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen * address cached.
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen *
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen * TODO: Handle this much better...
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen *
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 */
e05181d973025627ba08b631c12c07c3bbc99528Timo Sirainen if (!conn->hostname || !worker->s->is_address_reusable ||
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen worker->s->disablereuse) {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen if (proxyname) {
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen conn->hostname = apr_pstrdup(conn->pool, proxyname);
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen conn->port = proxyport;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen /*
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.
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen */
0add8c99ca65e56dbf613595fc37c41aafff3f7fTimo Sirainen if (conn->is_ssl) {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen const char *proxy_auth;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen
033557e1c8ebec5ae31f2f24fab90226a1945168Timo Sirainen forward_info *forward = apr_pcalloc(conn->pool, sizeof(forward_info));
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen conn->forward = forward;
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen forward->use_http_connect = 1;
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen forward->target_host = apr_pstrdup(conn->pool, uri->hostname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen forward->target_port = uri->port;
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 */
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization");
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen if (proxy_auth != NULL &&
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen proxy_auth[0] != '\0' &&
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);
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen }
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen }
316689d0ef55e2fa4e2fb4ac5b1ea35ce65688d3Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn->hostname = apr_pstrdup(conn->pool, uri->hostname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn->port = uri->port;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen socket_cleanup(conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen err = apr_sockaddr_info_get(&(conn->addr),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn->hostname, APR_UNSPEC,
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen conn->port, 0,
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen conn->pool);
43f6755bda8c834bf7a7120e6b485c35e27ee8bdTimo Sirainen }
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen else if (!worker->cp->addr) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(00945) "lock");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return HTTP_INTERNAL_SERVER_ERROR;
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen }
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen /*
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 */
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen err = apr_sockaddr_info_get(&(worker->cp->addr),
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen conn->hostname, APR_UNSPEC,
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen conn->port, 0,
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen worker->cp->pool);
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen conn->addr = 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");
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen }
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen }
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen else {
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen conn->addr = worker->cp->addr;
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* Close a possible existing socket if we are told to do so */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (conn->close) {
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen socket_cleanup(conn);
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen conn->close = 0;
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen }
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen
dc4e0821e709d93c8504e50b4ba0aaeb5ce9e032Timo Sirainen if (err != APR_SUCCESS) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ap_proxyerror(r, HTTP_BAD_GATEWAY,
1302f472805684b42ead4be8e4d5cbd95dfdc29bTimo Sirainen apr_pstrcat(p, "DNS lookup failure for: ",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn->hostname, NULL));
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen }
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen /* Get the server port for the Via headers */
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen server_port = ap_get_server_port(r);
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen if (ap_is_default_port(server_port, r)) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen strcpy(server_portstr,"");
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen else {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen apr_snprintf(server_portstr, server_portstr_size, ":%d",
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen server_port);
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen /* check if ProxyBlock directive on this host */
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen if (OK != ap_proxy_checkproxyblock(r, conf, uri->hostname,
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen proxyname ? NULL : conn->addr)) {
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen return ap_proxyerror(r, HTTP_FORBIDDEN,
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen "Connect to remote machine blocked");
621e8c0767de486db8d4ebb317d441b3f3a0434fTimo Sirainen }
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);
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen return OK;
6681a083b7e8c552d3a6bccb32bbbdb7e7987bf6Timo Sirainen}
1302f472805684b42ead4be8e4d5cbd95dfdc29bTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define USE_ALTERNATE_IS_CONNECTED 1
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen#if !defined(APR_MSG_PEEK) && defined(MSG_PEEK)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define APR_MSG_PEEK MSG_PEEK
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen#endif
9740d55b228a670047c854484d5cc979a056a9afTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#if USE_ALTERNATE_IS_CONNECTED && defined(APR_MSG_PEEK)
static int is_socket_connected(apr_socket_t *socket)
{
apr_pollfd_t pfds[1];
apr_status_t status;
apr_int32_t nfds;
pfds[0].reqevents = APR_POLLIN;
pfds[0].desc_type = APR_POLL_SOCKET;
pfds[0].desc.s = socket;
do {
status = apr_poll(&pfds[0], 1, &nfds, 0);
} while (APR_STATUS_IS_EINTR(status));
if (status == APR_SUCCESS && nfds == 1 &&
pfds[0].rtnevents == APR_POLLIN) {
apr_sockaddr_t unused;
apr_size_t len = 1;
char buf[1];
/* The socket might be closed in which case
* the poll will return POLLIN.
* If there is no data available the socket
* is closed.
*/
status = apr_socket_recvfrom(&unused, socket, APR_MSG_PEEK,
&buf[0], &len);
if (status == APR_SUCCESS && len)
return 1;
else
return 0;
}
else if (APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status)) {
return 1;
}
return 0;
}
#else
static int is_socket_connected(apr_socket_t *sock)
{
apr_size_t buffer_len = 1;
char test_buffer[1];
apr_status_t socket_status;
apr_interval_time_t current_timeout;
/* save timeout */
apr_socket_timeout_get(sock, &current_timeout);
/* set no timeout */
apr_socket_timeout_set(sock, 0);
socket_status = apr_socket_recv(sock, test_buffer, &buffer_len);
/* put back old timeout */
apr_socket_timeout_set(sock, current_timeout);
if (APR_STATUS_IS_EOF(socket_status)
|| APR_STATUS_IS_ECONNRESET(socket_status)) {
return 0;
}
else {
return 1;
}
}
#endif /* USE_ALTERNATE_IS_CONNECTED */
/*
* Send a HTTP CONNECT request to a forward proxy.
* The proxy is given by "backend", the target server
* is contained in the "forward" member of "backend".
*/
static apr_status_t send_http_connect(proxy_conn_rec *backend,
server_rec *s)
{
int status;
apr_size_t nbytes;
apr_size_t left;
int complete = 0;
char buffer[HUGE_STRING_LEN];
char drain_buffer[HUGE_STRING_LEN];
forward_info *forward = (forward_info *)backend->forward;
int len = 0;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00948)
"CONNECT: sending the CONNECT request for %s:%d "
"to the remote proxy %pI (%s)",
forward->target_host, forward->target_port,
backend->addr, backend->hostname);
/* Create the CONNECT request */
nbytes = apr_snprintf(buffer, sizeof(buffer),
"CONNECT %s:%d HTTP/1.0" CRLF,
forward->target_host, forward->target_port);
/* Add proxy authorization from the initial request if necessary */
if (forward->proxy_auth != NULL) {
nbytes += apr_snprintf(buffer + nbytes, sizeof(buffer) - nbytes,
"Proxy-Authorization: %s" CRLF,
forward->proxy_auth);
}
/* Set a reasonable agent and send everything */
nbytes += apr_snprintf(buffer + nbytes, sizeof(buffer) - nbytes,
"Proxy-agent: %s" CRLF CRLF,
ap_get_server_banner());
apr_socket_send(backend->sock, buffer, &nbytes);
/* Receive the whole CONNECT response */
left = sizeof(buffer) - 1;
/* Read until we find the end of the headers or run out of buffer */
do {
nbytes = left;
status = apr_socket_recv(backend->sock, buffer + len, &nbytes);
len += nbytes;
left -= nbytes;
buffer[len] = '\0';
if (strstr(buffer + len - nbytes, "\r\n\r\n") != NULL) {
complete = 1;
break;
}
} while (status == APR_SUCCESS && left > 0);
/* Drain what's left */
if (!complete) {
nbytes = sizeof(drain_buffer) - 1;
while (status == APR_SUCCESS && nbytes) {
status = apr_socket_recv(backend->sock, drain_buffer, &nbytes);
buffer[nbytes] = '\0';
nbytes = sizeof(drain_buffer) - 1;
if (strstr(drain_buffer, "\r\n\r\n") != NULL) {
break;
}
}
}
/* Check for HTTP_OK response status */
if (status == APR_SUCCESS) {
int major, minor;
/* Only scan for three character status code */
char code_str[4];
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00949)
"send_http_connect: response from the forward proxy: %s",
buffer);
/* Extract the returned code */
if (sscanf(buffer, "HTTP/%u.%u %3s", &major, &minor, code_str) == 3) {
status = atoi(code_str);
if (status == HTTP_OK) {
status = APR_SUCCESS;
}
else {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00950)
"send_http_connect: the forward proxy returned code is '%s'",
code_str);
status = APR_INCOMPLETE;
}
}
}
return(status);
}
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
proxy_conn_rec *conn,
proxy_worker *worker,
server_rec *s)
{
apr_status_t rv;
int connected = 0;
int loglevel;
apr_sockaddr_t *backend_addr = conn->addr;
/* the local address to use for the outgoing connection */
apr_sockaddr_t *local_addr;
apr_socket_t *newsock;
void *sconf = s->module_config;
proxy_server_conf *conf =
(proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
if (conn->sock) {
if (!(connected = is_socket_connected(conn->sock))) {
socket_cleanup(conn);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00951)
"%s: backend socket is disconnected.",
proxy_function);
}
}
while (backend_addr && !connected) {
if ((rv = apr_socket_create(&newsock, backend_addr->family,
SOCK_STREAM, APR_PROTO_TCP,
conn->scpool)) != APR_SUCCESS) {
loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00952)
"%s: error creating fam %d socket for target %s",
proxy_function,
backend_addr->family,
worker->s->hostname);
/*
* this could be an IPv6 address from the DNS but the
* local machine won't give us an IPv6 socket; hopefully the
* DNS returned an additional address to try
*/
backend_addr = backend_addr->next;
continue;
}
conn->connection = NULL;
if (worker->s->recv_buffer_size > 0 &&
(rv = apr_socket_opt_set(newsock, APR_SO_RCVBUF,
worker->s->recv_buffer_size))) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00953)
"apr_socket_opt_set(SO_RCVBUF): Failed to set "
"ProxyReceiveBufferSize, using default");
}
rv = apr_socket_opt_set(newsock, APR_TCP_NODELAY, 1);
if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00954)
"apr_socket_opt_set(APR_TCP_NODELAY): "
"Failed to set");
}
/* Set a timeout for connecting to the backend on the socket */
if (worker->s->conn_timeout_set) {
apr_socket_timeout_set(newsock, worker->s->conn_timeout);
}
else if (worker->s->timeout_set) {
apr_socket_timeout_set(newsock, worker->s->timeout);
}
else if (conf->timeout_set) {
apr_socket_timeout_set(newsock, conf->timeout);
}
else {
apr_socket_timeout_set(newsock, s->timeout);
}
/* Set a keepalive option */
if (worker->s->keepalive) {
if ((rv = apr_socket_opt_set(newsock,
APR_SO_KEEPALIVE, 1)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00955)
"apr_socket_opt_set(SO_KEEPALIVE): Failed to set"
" Keepalive");
}
}
ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, s,
"%s: fam %d socket created to connect to %s",
proxy_function, backend_addr->family, worker->s->hostname);
if (conf->source_address_set) {
local_addr = apr_pmemdup(conn->pool, conf->source_address,
sizeof(apr_sockaddr_t));
local_addr->pool = conn->pool;
rv = apr_socket_bind(newsock, local_addr);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00956)
"%s: failed to bind socket to local address",
proxy_function);
}
}
/* make the connection out of the socket */
rv = apr_socket_connect(newsock, backend_addr);
/* if an error occurred, loop round and try again */
if (rv != APR_SUCCESS) {
apr_socket_close(newsock);
loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00957)
"%s: attempt to connect to %pI (%s) failed",
proxy_function,
backend_addr,
worker->s->hostname);
backend_addr = backend_addr->next;
continue;
}
/* Set a timeout on the socket */
if (worker->s->timeout_set) {
apr_socket_timeout_set(newsock, worker->s->timeout);
}
else if (conf->timeout_set) {
apr_socket_timeout_set(newsock, conf->timeout);
}
else {
apr_socket_timeout_set(newsock, s->timeout);
}
conn->sock = newsock;
if (conn->forward) {
forward_info *forward = (forward_info *)conn->forward;
/*
* For HTTP CONNECT we need to prepend CONNECT request before
* sending our actual HTTPS requests.
*/
if (forward->use_http_connect) {
rv = send_http_connect(conn, s);
/* If an error occurred, loop round and try again */
if (rv != APR_SUCCESS) {
conn->sock = NULL;
apr_socket_close(newsock);
loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00958)
"%s: attempt to connect to %s:%d "
"via http CONNECT through %pI (%s) failed",
proxy_function,
forward->target_host, forward->target_port,
backend_addr, worker->s->hostname);
backend_addr = backend_addr->next;
continue;
}
}
}
connected = 1;
}
/*
* Put the entire worker to error state if
* the PROXY_WORKER_IGNORE_ERRORS flag is not set.
* Altrough some connections may be alive
* no further connections to the worker could be made
*/
if (!connected && PROXY_WORKER_IS_USABLE(worker) &&
!(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
worker->s->error_time = apr_time_now();
worker->s->status |= PROXY_WORKER_IN_ERROR;
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00959)
"ap_proxy_connect_backend disabling worker for (%s) for %"
APR_TIME_T_FMT "s",
worker->s->hostname, apr_time_sec(worker->s->retry));
}
else {
if (worker->s->retries) {
/*
* A worker came back. So here is where we need to
* either reset all params to initial conditions or
* apply some sort of aging
*/
}
worker->s->error_time = 0;
worker->s->retries = 0;
}
return connected ? OK : DECLINED;
}
PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
proxy_conn_rec *conn,
conn_rec *c,
server_rec *s)
{
apr_sockaddr_t *backend_addr = conn->addr;
int rc;
apr_interval_time_t current_timeout;
apr_bucket_alloc_t *bucket_alloc;
if (conn->connection) {
return OK;
}
bucket_alloc = apr_bucket_alloc_create(conn->scpool);
/*
* The socket is now open, create a new backend server connection
*/
conn->connection = ap_run_create_connection(conn->scpool, s, conn->sock,
0, NULL,
bucket_alloc);
if (!conn->connection) {
/*
* the peer reset the connection already; ap_run_create_connection()
* closed the socket
*/
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
s, APLOGNO(00960) "%s: an error occurred creating a "
"new connection to %pI (%s)", proxy_function,
backend_addr, conn->hostname);
/* XXX: Will be closed when proxy_conn is closed */
socket_cleanup(conn);
return HTTP_INTERNAL_SERVER_ERROR;
}
/* For ssl connection to backend */
if (conn->is_ssl) {
if (!ap_proxy_ssl_enable(conn->connection)) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
s, APLOGNO(00961) "%s: failed to enable ssl support "
"for %pI (%s)", proxy_function,
backend_addr, conn->hostname);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
else {
/* TODO: See if this will break FTP */
ap_proxy_ssl_disable(conn->connection);
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00962)
"%s: connection complete to %pI (%s)",
proxy_function, backend_addr, conn->hostname);
/*
* save the timeout of the socket because core_pre_connection
* will set it to base_server->timeout
* (core TimeOut directive).
*/
apr_socket_timeout_get(conn->sock, &current_timeout);
/* set up the connection filters */
rc = ap_run_pre_connection(conn->connection, conn->sock);
if (rc != OK && rc != DONE) {
conn->connection->aborted = 1;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00963)
"%s: pre_connection setup failed (%d)",
proxy_function, rc);
return rc;
}
apr_socket_timeout_set(conn->sock, current_timeout);
return OK;
}
int ap_proxy_lb_workers(void)
{
/*
* Since we can't resize the scoreboard when reconfiguring, we
* have to impose a limit on the number of workers, we are
* able to reconfigure to.
*/
if (!lb_workers_limit)
lb_workers_limit = proxy_lb_workers + PROXY_DYNAMIC_BALANCER_LIMIT;
return lb_workers_limit;
}
PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
apr_bucket_brigade *brigade)
{
apr_bucket *e;
conn_rec *c = r->connection;
r->no_cache = 1;
/*
* If this is a subrequest, then prevent also caching of the main
* request.
*/
if (r->main)
r->main->no_cache = 1;
e = ap_bucket_error_create(HTTP_BAD_GATEWAY, NULL, c->pool,
c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(brigade, e);
e = apr_bucket_eos_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(brigade, e);
}
/*
* Provide a string hashing function for the proxy.
* We offer 2 methods: one is the APR model but we
* also provide our own, based on either FNV or SDBM.
* The reason is in case we want to use both to ensure no
* collisions.
*/
PROXY_DECLARE(unsigned int)
ap_proxy_hashfunc(const char *str, proxy_hash_t method)
{
if (method == PROXY_HASHFUNC_APR) {
apr_ssize_t slen = strlen(str);
return apr_hashfunc_default(str, &slen);
}
else if (method == PROXY_HASHFUNC_FNV) {
/* FNV model */
unsigned int hash;
const unsigned int fnv_prime = 0x811C9DC5;
for (hash = 0; *str; str++) {
hash *= fnv_prime;
hash ^= (*str);
}
return hash;
}
else { /* method == PROXY_HASHFUNC_DEFAULT */
/* SDBM model */
unsigned int hash;
for (hash = 0; *str; str++) {
hash = (*str) + (hash << 6) + (hash << 16) - hash;
}
return hash;
}
}
PROXY_DECLARE(apr_status_t) ap_proxy_set_wstatus(char c, int set, proxy_worker *w)
{
unsigned int *status = &w->s->status;
char flag = toupper(c);
struct wstat *pwt = wstat_tbl;
while (pwt->bit) {
if (flag == pwt->flag) {
if (set)
*status |= pwt->bit;
else
*status &= ~(pwt->bit);
return APR_SUCCESS;
}
pwt++;
}
return APR_EINVAL;
}
PROXY_DECLARE(char *) ap_proxy_parse_wstatus(apr_pool_t *p, proxy_worker *w)
{
char *ret = "";
unsigned int status = w->s->status;
struct wstat *pwt = wstat_tbl;
while (pwt->bit) {
if (status & pwt->bit)
ret = apr_pstrcat(p, ret, pwt->name, NULL);
pwt++;
}
if (PROXY_WORKER_IS_USABLE(w))
ret = apr_pstrcat(p, ret, "Ok ", NULL);
return ret;
}
PROXY_DECLARE(apr_status_t) ap_proxy_sync_balancer(proxy_balancer *b, server_rec *s,
proxy_server_conf *conf)
{
proxy_worker **workers;
int i;
int index;
proxy_worker_shared *shm;
proxy_balancer_method *lbmethod;
ap_slotmem_provider_t *storage = b->storage;
if (b->s->wupdated <= b->wupdated)
return APR_SUCCESS;
/* balancer sync */
lbmethod = ap_lookup_provider(PROXY_LBMETHOD, b->s->lbpname, "0");
if (lbmethod) {
b->lbmethod = lbmethod;
}
/* worker sync */
/*
* Look thru the list of workers in shm
* and see which one(s) we are lacking...
* again, the cast to unsigned int is safe
* since our upper limit is always max_workers
* which is int.
*/
for (index = 0; index < b->max_workers; index++) {
int found;
apr_status_t rv;
if ((rv = storage->dptr(b->wslot, (unsigned int)index, (void *)&shm)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(00965) "worker slotmem_dptr failed");
return APR_EGENERAL;
}
/* account for possible "holes" in the slotmem
* (eg: slots 0-2 are used, but 3 isn't, but 4-5 is)
*/
if (!shm->hash.def || !shm->hash.fnv)
continue;
found = 0;
workers = (proxy_worker **)b->workers->elts;
for (i = 0; i < b->workers->nelts; i++, workers++) {
proxy_worker *worker = *workers;
if (worker->hash.def == shm->hash.def && worker->hash.fnv == shm->hash.fnv) {
found = 1;
break;
}
}
if (!found) {
proxy_worker **runtime;
runtime = apr_array_push(b->workers);
*runtime = apr_palloc(conf->pool, sizeof(proxy_worker));
(*runtime)->hash = shm->hash;
(*runtime)->context = NULL;
(*runtime)->cp = NULL;
(*runtime)->balancer = b;
(*runtime)->s = shm;
(*runtime)->tmutex = NULL;
if ((rv = ap_proxy_initialize_worker(*runtime, s, conf->pool)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(00966) "Cannot init worker");
return rv;
}
}
}
if (b->s->need_reset) {
if (b->lbmethod && b->lbmethod->reset)
b->lbmethod->reset(b, s);
b->s->need_reset = 0;
}
b->wupdated = b->s->wupdated;
return APR_SUCCESS;
}
void proxy_util_register_hooks(apr_pool_t *p)
{
APR_REGISTER_OPTIONAL_FN(ap_proxy_retry_worker);
}