00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "RemapProcessor.h"
00025
00026 RemapProcessor remapProcessor;
00027 extern ClassAllocator<RemapPlugins> pluginAllocator;
00028
00029 int
00030 RemapProcessor::start(int num_threads, size_t stacksize)
00031 {
00032 if (_use_separate_remap_thread)
00033 ET_REMAP = eventProcessor.spawn_event_threads(num_threads, "ET_REMAP", stacksize);
00034
00035 return 0;
00036 }
00037
00038
00039
00040
00041
00042
00043
00044
00045 bool
00046 RemapProcessor::setup_for_remap(HttpTransact::State *s)
00047 {
00048 Debug("url_rewrite", "setting up for remap: %p", s);
00049 URL *request_url = NULL;
00050 bool mapping_found = false;
00051 HTTPHdr *request_header = &s->hdr_info.client_request;
00052 char **redirect_url = &s->remap_redirect;
00053 const char *request_host;
00054 int request_host_len;
00055 int request_port;
00056 bool proxy_request = false;
00057
00058 s->reverse_proxy = rewrite_table->reverse_proxy;
00059 s->url_map.set(s->hdr_info.client_request.m_heap);
00060
00061 ink_assert(redirect_url != NULL);
00062
00063 if (unlikely((rewrite_table->num_rules_forward == 0) &&
00064 (rewrite_table->num_rules_forward_with_recv_port == 0))) {
00065 ink_assert(rewrite_table->forward_mappings.empty() &&
00066 rewrite_table->forward_mappings_with_recv_port.empty());
00067 Debug("url_rewrite", "[lookup] No forward mappings found; Skipping...");
00068 return false;
00069 }
00070
00071
00072
00073
00074 if (unlikely(!request_header || (request_url = request_header->url_get()) == NULL || !request_url->valid())) {
00075 Error("NULL or invalid request data");
00076 return false;
00077 }
00078
00079 request_host = request_header->host_get(&request_host_len);
00080 request_port = request_header->port_get();
00081 proxy_request = request_header->is_target_in_url() || ! s->reverse_proxy;
00082
00083
00084 if (!request_host) {
00085 request_host = "";
00086 request_host_len = 0;
00087 }
00088
00089 Debug("url_rewrite", "[lookup] attempting %s lookup", proxy_request ? "proxy" : "normal");
00090
00091 if (rewrite_table->num_rules_forward_with_recv_port) {
00092 Debug("url_rewrite", "[lookup] forward mappings with recv port found; Using recv port %d",
00093 s->client_info.port);
00094 if (rewrite_table->forwardMappingWithRecvPortLookup(request_url, s->client_info.port,
00095 request_host, request_host_len, s->url_map)) {
00096 Debug("url_rewrite", "Found forward mapping with recv port");
00097 mapping_found = true;
00098 } else if (rewrite_table->num_rules_forward == 0) {
00099 ink_assert(rewrite_table->forward_mappings.empty());
00100 Debug("url_rewrite", "No forward mappings left");
00101 return false;
00102 }
00103 }
00104
00105 if (!mapping_found) {
00106 mapping_found = rewrite_table->forwardMappingLookup(request_url, request_port, request_host, request_host_len, s->url_map);
00107 }
00108
00109
00110
00111
00112 if (!mapping_found && rewrite_table->nohost_rules && request_host_len) {
00113 Debug("url_rewrite", "[lookup] nothing matched");
00114 mapping_found = rewrite_table->forwardMappingLookup(request_url, 0, "", 0, s->url_map);
00115 }
00116
00117 if (!proxy_request) {
00118
00119
00120
00121 s->hh_info.host_len = request_host_len;
00122 s->hh_info.request_host = request_host;
00123 s->hh_info.request_port = request_port;
00124
00125 if (mapping_found) {
00126
00127
00128
00129
00130 request_header->set_url_target_from_host_field();
00131 }
00132 }
00133
00134 if (mapping_found) {
00135 request_header->mark_target_dirty();
00136 } else {
00137 Debug("url_rewrite", "RemapProcessor::setup_for_remap did not find a mapping");
00138 }
00139
00140 return mapping_found;
00141 }
00142
00143 bool
00144 RemapProcessor::finish_remap(HttpTransact::State *s)
00145 {
00146 url_mapping *map = NULL;
00147 HTTPHdr *request_header = &s->hdr_info.client_request;
00148 URL *request_url = request_header->url_get();
00149 char **redirect_url = &s->remap_redirect;
00150 char host_hdr_buf[TS_MAX_HOST_NAME_LEN], tmp_referer_buf[4096], tmp_redirect_buf[4096], tmp_buf[2048], *c;
00151 const char *remapped_host;
00152 int remapped_host_len, remapped_port, tmp;
00153 int from_len;
00154 bool remap_found = false;
00155 referer_info *ri;
00156
00157 map = s->url_map.getMapping();
00158 if (!map) {
00159 return false;
00160 }
00161
00162 rewrite_table->PerformACLFiltering(s, map);
00163
00164
00165 if ((s->filter_mask & URL_REMAP_FILTER_REFERER) != 0 && (ri = map->referer_list) != 0) {
00166 const char *referer_hdr = 0;
00167 int referer_len = 0;
00168 bool enabled_flag = map->optional_referer ? true : false;
00169
00170 if (request_header->presence(MIME_PRESENCE_REFERER) &&
00171 (referer_hdr = request_header->value_get(MIME_FIELD_REFERER, MIME_LEN_REFERER, &referer_len)) != NULL) {
00172 if (referer_len >= (int) sizeof(tmp_referer_buf))
00173 referer_len = (int) (sizeof(tmp_referer_buf) - 1);
00174 memcpy(tmp_referer_buf, referer_hdr, referer_len);
00175 tmp_referer_buf[referer_len] = 0;
00176 for (enabled_flag = false; ri; ri = ri->next) {
00177 if (ri->any) {
00178 enabled_flag = true;
00179 if (!map->negative_referer)
00180 break;
00181 } else if (ri->regx_valid && (pcre_exec(ri->regx, NULL, tmp_referer_buf, referer_len, 0, 0, NULL, 0) != -1)) {
00182 enabled_flag = ri->negative ? false : true;
00183 break;
00184 }
00185 }
00186 }
00187
00188 if (!enabled_flag) {
00189 if (!map->default_redirect_url) {
00190 if ((s->filter_mask & URL_REMAP_FILTER_REDIRECT_FMT) != 0 && map->redir_chunk_list) {
00191 redirect_tag_str *rc;
00192 tmp_redirect_buf[(tmp = 0)] = 0;
00193 for (rc = map->redir_chunk_list; rc; rc = rc->next) {
00194 c = 0;
00195 switch (rc->type) {
00196 case 's':
00197 c = rc->chunk_str;
00198 break;
00199 case 'r':
00200 c = (referer_len && referer_hdr) ? &tmp_referer_buf[0] : 0;
00201 break;
00202 case 'f':
00203 case 't':
00204 remapped_host = (rc->type == 'f') ?
00205 map->fromURL.string_get_buf(tmp_buf, (int) sizeof(tmp_buf), &from_len) :
00206 ((s->url_map).getToURL())->string_get_buf(tmp_buf, (int)sizeof(tmp_buf), &from_len);
00207 if (remapped_host && from_len > 0) {
00208 c = &tmp_buf[0];
00209 }
00210 break;
00211 case 'o':
00212 c = s->pristine_url.string_get_ref(NULL);
00213 break;
00214 };
00215
00216 if (c && tmp < (int) (sizeof(tmp_redirect_buf) - 1)) {
00217 tmp += snprintf(&tmp_redirect_buf[tmp], sizeof(tmp_redirect_buf) - tmp, "%s", c);
00218 }
00219 }
00220 tmp_redirect_buf[sizeof(tmp_redirect_buf) - 1] = 0;
00221 *redirect_url = ats_strdup(tmp_redirect_buf);
00222 }
00223 } else {
00224 *redirect_url = ats_strdup(rewrite_table->http_default_redirect_url);
00225 }
00226
00227 if (*redirect_url == NULL) {
00228 *redirect_url = ats_strdup(map->filter_redirect_url ? map->filter_redirect_url :
00229 rewrite_table->http_default_redirect_url);
00230 }
00231
00232 return false;
00233 }
00234 }
00235
00236 remap_found = true;
00237
00238
00239
00240 int host_len;
00241 const char *host_hdr = request_header->value_get(MIME_FIELD_HOST, MIME_LEN_HOST, &host_len);
00242
00243 if (request_url && host_hdr != NULL && s->txn_conf->maintain_pristine_host_hdr == 0) {
00244
00245
00246
00247 if (is_debug_tag_set("url_rewrite")) {
00248 int old_host_hdr_len;
00249 char *old_host_hdr = (char *) request_header->value_get(MIME_FIELD_HOST, MIME_LEN_HOST, &old_host_hdr_len);
00250
00251 if (old_host_hdr) {
00252 old_host_hdr = ats_strndup(old_host_hdr, old_host_hdr_len);
00253 Debug("url_rewrite", "Host: Header before rewrite %.*s", old_host_hdr_len, old_host_hdr);
00254 ats_free(old_host_hdr);
00255 }
00256 }
00257
00258
00259
00260
00261 remapped_host = request_url->host_get(&remapped_host_len);
00262 remapped_port = request_url->port_get_raw();
00263
00264 if (TS_MAX_HOST_NAME_LEN > remapped_host_len) {
00265 tmp = remapped_host_len;
00266 memcpy(host_hdr_buf, remapped_host, remapped_host_len);
00267 if (remapped_port) {
00268 tmp += snprintf(host_hdr_buf + remapped_host_len, TS_MAX_HOST_NAME_LEN - remapped_host_len - 1,
00269 ":%d", remapped_port);
00270 }
00271 } else {
00272 tmp = TS_MAX_HOST_NAME_LEN;
00273 }
00274
00275
00276
00277
00278
00279 if (tmp >= TS_MAX_HOST_NAME_LEN) {
00280 request_header->field_delete(MIME_FIELD_HOST, MIME_LEN_HOST);
00281 Debug("url_rewrite", "Host: Header too long after rewrite");
00282 } else {
00283 Debug("url_rewrite", "Host: Header after rewrite %.*s", tmp, host_hdr_buf);
00284 request_header->value_set(MIME_FIELD_HOST, MIME_LEN_HOST, host_hdr_buf, tmp);
00285 }
00286 }
00287
00288 request_header->mark_target_dirty();
00289
00290 return remap_found;
00291 }
00292
00293 Action *
00294 RemapProcessor::perform_remap(Continuation *cont, HttpTransact::State *s)
00295 {
00296 Debug("url_rewrite", "Beginning RemapProcessor::perform_remap");
00297 HTTPHdr *request_header = &s->hdr_info.client_request;
00298 URL *request_url = request_header->url_get();
00299 url_mapping *map = s->url_map.getMapping();
00300 host_hdr_info *hh_info = &(s->hh_info);
00301
00302 if (!map) {
00303 Error("Could not find corresponding url_mapping for this transaction %p", s);
00304 Debug("url_rewrite", "Could not find corresponding url_mapping for this transaction");
00305 ink_assert(!"this should never happen -- call setup_for_remap first");
00306 cont->handleEvent(EVENT_REMAP_ERROR, NULL);
00307 return ACTION_RESULT_DONE;
00308 }
00309
00310 if (_use_separate_remap_thread) {
00311 RemapPlugins *plugins = pluginAllocator.alloc();
00312
00313 plugins->setState(s);
00314 plugins->setRequestUrl(request_url);
00315 plugins->setRequestHeader(request_header);
00316 plugins->setHostHeaderInfo(hh_info);
00317
00318
00319 ink_assert(cont->mutex->thread_holding == this_ethread());
00320 plugins->mutex = cont->mutex;
00321 plugins->action = cont;
00322 SET_CONTINUATION_HANDLER(plugins, &RemapPlugins::run_remap);
00323 eventProcessor.schedule_imm(plugins, ET_REMAP);
00324
00325 return &plugins->action;
00326 } else {
00327 RemapPlugins plugins(s, request_url, request_header, hh_info);
00328 int ret = 0;
00329
00330 do {
00331 ret = plugins.run_single_remap();
00332 } while (ret == 0);
00333
00334 return ACTION_RESULT_DONE;
00335 }
00336 }