]> git.ipfire.org Git - thirdparty/squid.git/blame - src/redirect.cc
Author: D Kazarov <d.y.kazarov@mail.ru>
[thirdparty/squid.git] / src / redirect.cc
CommitLineData
be335c22 1
30a4f2a8 2/*
262a0e14 3 * $Id$
30a4f2a8 4 *
17bb3486 5 * DEBUG: section 61 Redirector
30a4f2a8 6 * AUTHOR: Duane Wessels
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
30a4f2a8 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
30a4f2a8 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
26ac0430 24 *
30a4f2a8 25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
26ac0430 29 *
30a4f2a8 30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
30a4f2a8 34 */
35
36#include "squid.h"
2d2b0bb7 37#include "auth/UserRequest.h"
8822ebee 38#include "mgr/Registration.h"
e6ccf245 39#include "Store.h"
472adb2f 40#include "fde.h"
528b2c61 41#include "client_side_request.h"
3ad63615 42#include "acl/Checklist.h"
8000a965 43#include "HttpRequest.h"
a46d2c0e 44#include "client_side.h"
7561850e 45#include "client_side_reply.h"
aa839030 46#include "helper.h"
1fa9b1a7 47#include "rfc1738.h"
4db984be
CT
48#if USE_SSL
49#include "ssl/support.h"
50#endif
30a4f2a8 51
7561850e
AJ
52/// url maximum lengh + extra informations passed to redirector
53#define MAX_REDIRECTOR_REQUEST_STRLEN (MAX_URL + 1024)
54
26ac0430 55typedef struct {
d2af9477 56 void *data;
30a4f2a8 57 char *orig_url;
62e76326 58
b7ac5457 59 Ip::Address client_addr;
0ee4272b 60 const char *client_ident;
61 const char *method_s;
582b6456 62 RH *handler;
2fadd50d 63} redirectStateData;
30a4f2a8 64
74addf6c 65static HLPCB redirectHandleReply;
f5b8bbc4 66static void redirectStateFree(redirectStateData * r);
74addf6c 67static helper *redirectors = NULL;
68static OBJH redirectStats;
07476a7f 69static int n_bypassed = 0;
28c60158 70CBDATA_TYPE(redirectStateData);
30a4f2a8 71
582b6456 72static void
74addf6c 73redirectHandleReply(void *data, char *reply)
30a4f2a8 74{
e6ccf245 75 redirectStateData *r = static_cast<redirectStateData *>(data);
74addf6c 76 char *t;
fa80a8ef 77 void *cbdata;
58523b80 78 debugs(61, 5, "redirectHandleRead: {" << (reply && *reply != '\0' ? reply : "<NULL>") << "}");
62e76326 79
c68e9c6b 80 if (reply) {
62e76326 81 if ((t = strchr(reply, ' ')))
82 *t = '\0';
83
84 if (*reply == '\0')
85 reply = NULL;
c68e9c6b 86 }
62e76326 87
fa80a8ef 88 if (cbdataReferenceValidDone(r->data, &cbdata))
62e76326 89 r->handler(cbdata, reply);
90
74addf6c 91 redirectStateFree(r);
30a4f2a8 92}
93
e7a22b88 94static void
95redirectStateFree(redirectStateData * r)
96{
97 safe_free(r->orig_url);
74addf6c 98 cbdataFree(r);
e7a22b88 99}
100
b8d8561b 101static void
74addf6c 102redirectStats(StoreEntry * sentry)
30a4f2a8 103{
587609e9 104 if (redirectors == NULL) {
105 storeAppendPrintf(sentry, "No redirectors defined\n");
106 return;
107 }
108
9522b380 109 helperStats(sentry, redirectors, "Redirector Statistics");
62e76326 110
07476a7f 111 if (Config.onoff.redirector_bypass)
62e76326 112 storeAppendPrintf(sentry, "\nNumber of requests bypassed "
113 "because all redirectors were busy: %d\n", n_bypassed);
30a4f2a8 114}
115
d2af9477 116/**** PUBLIC FUNCTIONS ****/
117
b8d8561b 118void
59a1efb2 119redirectStart(ClientHttpRequest * http, RH * handler, void *data)
d2af9477 120{
9512de47 121 ConnStateData * conn = http->getConn();
d2af9477 122 redirectStateData *r = NULL;
74addf6c 123 const char *fqdn;
7561850e
AJ
124 char buf[MAX_REDIRECTOR_REQUEST_STRLEN];
125 int sz;
126 http_status status;
cc192b50 127 char claddr[MAX_IPSTRLEN];
128 char myaddr[MAX_IPSTRLEN];
74addf6c 129 assert(http);
130 assert(handler);
bf8fe701 131 debugs(61, 5, "redirectStart: '" << http->uri << "'");
62e76326 132
07476a7f 133 if (Config.onoff.redirector_bypass && redirectors->stats.queue_size) {
62e76326 134 /* Skip redirector if there is one request queued */
135 n_bypassed++;
136 handler(data, NULL);
137 return;
07476a7f 138 }
62e76326 139
72711e31 140 r = cbdataAlloc(redirectStateData);
23d92c64 141 r->orig_url = xstrdup(http->uri);
26ac0430 142 if (conn != NULL)
cc192b50 143 r->client_addr = conn->log_addr;
144 else
145 r->client_addr.SetNoAddr();
472adb2f 146 r->client_ident = NULL;
62e76326 147
a33a428a 148 if (http->request->auth_user_request != NULL)
f5691f9c 149 r->client_ident = http->request->auth_user_request->username();
b4f2886c
FC
150 else if (http->request->extacl_user.defined()) {
151 r->client_ident = http->request->extacl_user.termedBuf();
472adb2f 152 }
153
85a4b153 154 if (!r->client_ident && (conn != NULL && conn->rfc931[0]))
62e76326 155 r->client_ident = conn->rfc931;
472adb2f 156
157#if USE_SSL
158
85a4b153 159 if (!r->client_ident && conn != NULL)
472adb2f 160 r->client_ident = sslGetUserEmail(fd_table[conn->fd].ssl);
161
162#endif
163
164 if (!r->client_ident)
62e76326 165 r->client_ident = dash_str;
62e76326 166
60745f24 167 r->method_s = RequestMethodStr(http->request->method);
472adb2f 168
d2af9477 169 r->handler = handler;
472adb2f 170
fa80a8ef 171 r->data = cbdataReference(data);
62e76326 172
74addf6c 173 if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL)
62e76326 174 fqdn = dash_str;
175
7561850e 176 sz = snprintf(buf, MAX_REDIRECTOR_REQUEST_STRLEN, "%s %s/%s %s %s myip=%s myport=%d\n",
e9f8ec2d
A
177 r->orig_url,
178 r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
179 fqdn,
180 r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
181 r->method_s,
182 http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
183 http->request->my_addr.GetPort());
7561850e
AJ
184
185 if ((sz<=0) || (sz>=MAX_REDIRECTOR_REQUEST_STRLEN)) {
e9f8ec2d
A
186 if (sz<=0) {
187 status = HTTP_INTERNAL_SERVER_ERROR;
188 debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Can not build request to be passed to redirector. Request ABORTED.");
189 } else {
190 status = HTTP_REQUEST_URI_TOO_LARGE;
191 debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Request passed to redirector exceeds MAX_REDIRECTOR_REQUEST_STRLEN (" << MAX_REDIRECTOR_REQUEST_STRLEN << "). Request ABORTED.");
192 }
193
194 clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data;
195 clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
196 assert (repContext);
197 Ip::Address tmpnoaddr;
198 tmpnoaddr.SetNoAddr();
199 repContext->setReplyToError(ERR_GATEWAY_FAILURE, status,
200 http->request->method, NULL,
201 http->getConn() != NULL ? http->getConn()->peer : tmpnoaddr,
202 http->request,
203 NULL,
204 http->getConn() != NULL && http->getConn()->auth_user_request != NULL ?
205 http->getConn()->auth_user_request : http->request->auth_user_request);
206
207 node = (clientStreamNode *)http->client_stream.tail->data;
208 clientStreamRead(node, http, node->readBuffer);
209 return;
7561850e 210 }
62e76326 211
74addf6c 212 helperSubmit(redirectors, buf, redirectHandleReply, r);
0a21bd84 213}
214
5f5e883f
FC
215static void
216redirectRegisterWithCacheManager(void)
217{
8822ebee 218 Mgr::RegisterAction("redirector", "URL Redirector Stats", redirectStats, 0, 1);
5f5e883f
FC
219}
220
b8d8561b 221void
74addf6c 222redirectInit(void)
30a4f2a8 223{
74addf6c 224 static int init = 0;
62e76326 225
d120ed12
FC
226 redirectRegisterWithCacheManager();
227
74addf6c 228 if (!Config.Program.redirect)
62e76326 229 return;
230
838b993c 231 if (redirectors == NULL)
48d54e4d 232 redirectors = new helper("redirector");
62e76326 233
c6d5b87b 234 redirectors->cmdline = Config.Program.redirect;
62e76326 235
48d54e4d 236 redirectors->childs = Config.redirectChildren;
07eca7e0 237
1ccc0d40 238 redirectors->ipc_type = IPC_STREAM;
62e76326 239
74addf6c 240 helperOpenServers(redirectors);
62e76326 241
74addf6c 242 if (!init) {
62e76326 243 init = 1;
244 CBDATA_INIT_TYPE(redirectStateData);
d2af9477 245 }
30a4f2a8 246}
247
16d3fe0d 248void
74addf6c 249redirectShutdown(void)
30a4f2a8 250{
74addf6c 251 if (!redirectors)
62e76326 252 return;
253
74addf6c 254 helperShutdown(redirectors);
62e76326 255
838b993c 256 if (!shutting_down)
62e76326 257 return;
258
48d54e4d 259 delete redirectors;
1f5f60dd 260 redirectors = NULL;
30a4f2a8 261}