]>
Commit | Line | Data |
---|---|---|
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 | 55 | typedef 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 | 65 | static HLPCB redirectHandleReply; |
f5b8bbc4 | 66 | static void redirectStateFree(redirectStateData * r); |
74addf6c | 67 | static helper *redirectors = NULL; |
68 | static OBJH redirectStats; | |
07476a7f | 69 | static int n_bypassed = 0; |
28c60158 | 70 | CBDATA_TYPE(redirectStateData); |
30a4f2a8 | 71 | |
582b6456 | 72 | static void |
74addf6c | 73 | redirectHandleReply(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 | 94 | static void |
95 | redirectStateFree(redirectStateData * r) | |
96 | { | |
97 | safe_free(r->orig_url); | |
74addf6c | 98 | cbdataFree(r); |
e7a22b88 | 99 | } |
100 | ||
b8d8561b | 101 | static void |
74addf6c | 102 | redirectStats(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 | 118 | void |
59a1efb2 | 119 | redirectStart(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 |
215 | static void |
216 | redirectRegisterWithCacheManager(void) | |
217 | { | |
8822ebee | 218 | Mgr::RegisterAction("redirector", "URL Redirector Stats", redirectStats, 0, 1); |
5f5e883f FC |
219 | } |
220 | ||
b8d8561b | 221 | void |
74addf6c | 222 | redirectInit(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 | 248 | void |
74addf6c | 249 | redirectShutdown(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 | } |