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 }