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 "UrlRewrite.h"
00025 #include "ProxyConfig.h"
00026 #include "ReverseProxy.h"
00027 #include "UrlMappingPathIndex.h"
00028 #include "RemapConfig.h"
00029 #include "I_Layout.h"
00030
00031 #define modulePrefix "[ReverseProxy]"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 static void
00043 SetHomePageRedirectFlag(url_mapping *new_mapping, URL &new_to_url)
00044 {
00045 int fromLen, toLen;
00046 const char *from_path = new_mapping->fromURL.path_get(&fromLen);
00047 const char *to_path = new_to_url.path_get(&toLen);
00048
00049 new_mapping->homePageRedirect = (from_path && !to_path) ? true : false;
00050 }
00051
00052
00053
00054
00055 UrlRewrite::UrlRewrite()
00056 : nohost_rules(0), reverse_proxy(0), backdoor_enabled(0),
00057 mgmt_autoconf_port(0), default_to_pac(0), default_to_pac_port(0), ts_name(NULL),
00058 http_default_redirect_url(NULL), num_rules_forward(0), num_rules_reverse(0), num_rules_redirect_permanent(0),
00059 num_rules_redirect_temporary(0), num_rules_forward_with_recv_port(0), _valid(false)
00060 {
00061
00062 forward_mappings.hash_lookup = reverse_mappings.hash_lookup =
00063 permanent_redirects.hash_lookup = temporary_redirects.hash_lookup =
00064 forward_mappings_with_recv_port.hash_lookup = NULL;
00065
00066 char * config_file = NULL;
00067 char * config_file_path = NULL;
00068
00069 REC_ReadConfigStringAlloc(config_file, "proxy.config.url_remap.filename");
00070 if (config_file == NULL) {
00071 pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, "Unable to find proxy.config.url_remap.filename");
00072 Warning("%s Unable to locate remap.config. No remappings in effect", modulePrefix);
00073 return;
00074 }
00075
00076 this->ts_name = NULL;
00077 REC_ReadConfigStringAlloc(this->ts_name, "proxy.config.proxy_name");
00078 if (this->ts_name == NULL) {
00079 pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, "Unable to read proxy.config.proxy_name");
00080 Warning("%s Unable to determine proxy name. Incorrect redirects could be generated", modulePrefix);
00081 this->ts_name = ats_strdup("");
00082 }
00083
00084 this->http_default_redirect_url = NULL;
00085 REC_ReadConfigStringAlloc(this->http_default_redirect_url, "proxy.config.http.referer_default_redirect");
00086 if (this->http_default_redirect_url == NULL) {
00087 pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, "Unable to read proxy.config.http.referer_default_redirect");
00088 Warning("%s Unable to determine default redirect url for \"referer\" filter.", modulePrefix);
00089 this->http_default_redirect_url = ats_strdup("http://www.apache.org");
00090 }
00091
00092 REC_ReadConfigInteger(reverse_proxy, "proxy.config.reverse_proxy.enabled");
00093 REC_ReadConfigInteger(mgmt_autoconf_port, "proxy.config.admin.autoconf_port");
00094 REC_ReadConfigInteger(default_to_pac, "proxy.config.url_remap.default_to_server_pac");
00095 REC_ReadConfigInteger(default_to_pac_port, "proxy.config.url_remap.default_to_server_pac_port");
00096 REC_ReadConfigInteger(url_remap_mode, "proxy.config.url_remap.url_remap_mode");
00097 REC_ReadConfigInteger(backdoor_enabled, "proxy.config.url_remap.handle_backdoor_urls");
00098
00099 config_file_path = Layout::relative_to(Layout::get()->sysconfdir, config_file);
00100
00101 if (0 == this->BuildTable(config_file_path)) {
00102 _valid = true;
00103 if (is_debug_tag_set("url_rewrite")) {
00104 Print();
00105 }
00106 } else {
00107 Warning("something failed during BuildTable() -- check your remap plugins!");
00108 }
00109
00110 ats_free(config_file_path);
00111 ats_free(config_file);
00112 }
00113
00114 UrlRewrite::~UrlRewrite()
00115 {
00116 ats_free(this->ts_name);
00117 ats_free(this->http_default_redirect_url);
00118
00119 DestroyStore(forward_mappings);
00120 DestroyStore(reverse_mappings);
00121 DestroyStore(permanent_redirects);
00122 DestroyStore(temporary_redirects);
00123 DestroyStore(forward_mappings_with_recv_port);
00124 _valid = false;
00125 }
00126
00127
00128 void
00129 UrlRewrite::SetReverseFlag(int flag)
00130 {
00131 reverse_proxy = flag;
00132 if (is_debug_tag_set("url_rewrite"))
00133 Print();
00134 }
00135
00136
00137
00138
00139
00140
00141 url_mapping *
00142 UrlRewrite::SetupPacMapping()
00143 {
00144 const char *from_url = "http:///";
00145 const char *local_url = "http://127.0.0.1/";
00146
00147 url_mapping *mapping;
00148 int pac_generator_port;
00149
00150 mapping = new url_mapping;
00151
00152 mapping->fromURL.create(NULL);
00153 mapping->fromURL.parse(from_url, strlen(from_url));
00154
00155 mapping->toUrl.create(NULL);
00156 mapping->toUrl.parse(local_url, strlen(local_url));
00157
00158 pac_generator_port = (default_to_pac_port < 0) ? mgmt_autoconf_port : default_to_pac_port;
00159
00160 mapping->toUrl.port_set(pac_generator_port);
00161
00162 return mapping;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 url_mapping *
00174 UrlRewrite::SetupBackdoorMapping()
00175 {
00176 const char from_url[] = "/ink/rh";
00177 const char to_url[] = "http://{backdoor}/ink/rh";
00178
00179 url_mapping *mapping = new url_mapping;
00180
00181 mapping->fromURL.create(NULL);
00182 mapping->fromURL.parse(from_url, sizeof(from_url) - 1);
00183 mapping->fromURL.scheme_set(URL_SCHEME_HTTP, URL_LEN_HTTP);
00184
00185 mapping->toUrl.create(NULL);
00186 mapping->toUrl.parse(to_url, sizeof(to_url) - 1);
00187
00188 return mapping;
00189 }
00190
00191
00192 void
00193 UrlRewrite::_destroyTable(InkHashTable *h_table)
00194 {
00195 InkHashTableEntry *ht_entry;
00196 InkHashTableIteratorState ht_iter;
00197 UrlMappingPathIndex *item;
00198
00199 if (h_table != NULL) {
00200
00201 for (ht_entry = ink_hash_table_iterator_first(h_table, &ht_iter); ht_entry != NULL;) {
00202 item = (UrlMappingPathIndex *)ink_hash_table_entry_value(h_table, ht_entry);
00203 delete item;
00204 ht_entry = ink_hash_table_iterator_next(h_table, &ht_iter);
00205 }
00206 ink_hash_table_destroy(h_table);
00207 }
00208 }
00209
00210
00211 void
00212 UrlRewrite::Print()
00213 {
00214 printf("URL Rewrite table with %d entries\n", num_rules_forward + num_rules_reverse +
00215 num_rules_redirect_temporary + num_rules_redirect_permanent + num_rules_forward_with_recv_port);
00216 printf(" Reverse Proxy is %s\n", (reverse_proxy == 0) ? "Off" : "On");
00217
00218 printf(" Forward Mapping Table with %d entries\n", num_rules_forward);
00219 PrintStore(forward_mappings);
00220
00221 printf(" Reverse Mapping Table with %d entries\n", num_rules_reverse);
00222 PrintStore(reverse_mappings);
00223
00224 printf(" Permanent Redirect Mapping Table with %d entries\n", num_rules_redirect_permanent);
00225 PrintStore(permanent_redirects);
00226
00227 printf(" Temporary Redirect Mapping Table with %d entries\n", num_rules_redirect_temporary);
00228 PrintStore(temporary_redirects);
00229
00230 printf(" Forward Mapping With Recv Port Table with %d entries\n", num_rules_forward_with_recv_port);
00231 PrintStore(forward_mappings_with_recv_port);
00232
00233 if (http_default_redirect_url != NULL) {
00234 printf(" Referer filter default redirect URL: \"%s\"\n", http_default_redirect_url);
00235 }
00236 }
00237
00238
00239 void
00240 UrlRewrite::PrintStore(MappingsStore &store)
00241 {
00242 if (store.hash_lookup != NULL) {
00243 InkHashTableEntry *ht_entry;
00244 InkHashTableIteratorState ht_iter;
00245 UrlMappingPathIndex *value;
00246
00247 for (ht_entry = ink_hash_table_iterator_first(store.hash_lookup, &ht_iter); ht_entry != NULL;) {
00248 value = (UrlMappingPathIndex *) ink_hash_table_entry_value(store.hash_lookup, ht_entry);
00249 value->Print();
00250 ht_entry = ink_hash_table_iterator_next(store.hash_lookup, &ht_iter);
00251 }
00252 }
00253
00254 if (!store.regex_list.empty()) {
00255 printf(" Regex mappings:\n");
00256 forl_LL(RegexMapping, list_iter, store.regex_list) {
00257 list_iter->url_map->Print();
00258 }
00259 }
00260 }
00261
00262
00263
00264
00265
00266
00267 url_mapping *
00268 UrlRewrite::_tableLookup(InkHashTable *h_table, URL *request_url,
00269 int request_port, char *request_host, int request_host_len)
00270 {
00271 UrlMappingPathIndex *ht_entry;
00272 url_mapping *um = NULL;
00273 int ht_result;
00274
00275 ht_result = ink_hash_table_lookup(h_table, request_host, (void **) &ht_entry);
00276
00277 if (likely(ht_result && ht_entry)) {
00278
00279 um = ht_entry->Search(request_url, request_port, request_host_len ? true : false);
00280 }
00281 return um;
00282 }
00283
00284
00285
00286 void
00287 url_rewrite_remap_request(const UrlMappingContainer& mapping_container, URL *request_url)
00288 {
00289 const char *requestPath;
00290 int requestPathLen = 0;
00291 int fromPathLen = 0;
00292
00293 URL *map_to = mapping_container.getToURL();
00294 URL *map_from = mapping_container.getFromURL();
00295 const char *toHost;
00296 const char *toPath;
00297 const char *toScheme;
00298 int toPathLen;
00299 int toHostLen;
00300 int toSchemeLen;
00301
00302 map_from->path_get(&fromPathLen);
00303
00304 toHost = map_to->host_get(&toHostLen);
00305 toPath = map_to->path_get(&toPathLen);
00306 toScheme = map_to->scheme_get(&toSchemeLen);
00307
00308 Debug("url_rewrite", "%s: Remapping rule id: %d matched", __func__, mapping_container.getMapping()->map_id);
00309
00310 request_url->host_set(toHost, toHostLen);
00311 request_url->port_set(map_to->port_get_raw());
00312 request_url->scheme_set(toScheme, toSchemeLen);
00313
00314 requestPath = request_url->path_get(&requestPathLen);
00315
00316
00317
00318
00319 char *newPath = static_cast<char*>(alloca(sizeof(char*)*((requestPathLen - fromPathLen) + toPathLen + 8)));
00320 int newPathLen = 0;
00321
00322 *newPath = 0;
00323 if (toPath) {
00324 memcpy(newPath, toPath, toPathLen);
00325 newPathLen += toPathLen;
00326 }
00327
00328
00329
00330 if (!fromPathLen && requestPathLen && newPathLen && toPathLen && *(newPath + newPathLen - 1) != '/') {
00331 *(newPath + newPathLen) = '/';
00332 newPathLen++;
00333 }
00334
00335 if (requestPath) {
00336
00337 if (requestPathLen < fromPathLen) {
00338 if (toPathLen && requestPath[requestPathLen - 1] == '/' && toPath[toPathLen - 1] == '/') {
00339 fromPathLen++;
00340 }
00341 } else {
00342 if (toPathLen && requestPath[fromPathLen] == '/' && toPath[toPathLen - 1] == '/') {
00343 fromPathLen++;
00344 }
00345 }
00346
00347
00348 if ((requestPathLen - fromPathLen) > 0) {
00349 memcpy(newPath + newPathLen, requestPath + fromPathLen, requestPathLen - fromPathLen);
00350 newPathLen += (requestPathLen - fromPathLen);
00351 }
00352 }
00353
00354
00355 if (*newPath == '/') {
00356 request_url->path_set(newPath + 1, newPathLen - 1);
00357 } else {
00358 request_url->path_set(newPath, newPathLen);
00359 }
00360 }
00361
00362
00363 #define N_URL_HEADERS 4
00364 bool
00365 UrlRewrite::ReverseMap(HTTPHdr *response_header)
00366 {
00367 const char *location_hdr;
00368 URL location_url;
00369 int loc_length;
00370 bool remap_found = false;
00371 const char *host;
00372 int host_len;
00373 char *new_loc_hdr;
00374 int new_loc_length;
00375 int i;
00376 const struct {
00377 const char *const field;
00378 const int len;
00379 } url_headers[N_URL_HEADERS] = {
00380 { MIME_FIELD_LOCATION, MIME_LEN_LOCATION } ,
00381 { MIME_FIELD_CONTENT_LOCATION, MIME_LEN_CONTENT_LOCATION } ,
00382 { "URI", 3 } ,
00383 { "Destination", 11 }
00384 };
00385
00386 if (unlikely(num_rules_reverse == 0)) {
00387 ink_assert(reverse_mappings.empty());
00388 return false;
00389 }
00390
00391 for (i = 0; i < N_URL_HEADERS; ++i) {
00392 location_hdr = response_header->value_get(url_headers[i].field, url_headers[i].len, &loc_length);
00393
00394 if (location_hdr == NULL) {
00395 continue;
00396 }
00397
00398 location_url.create(NULL);
00399 location_url.parse(location_hdr, loc_length);
00400
00401 host = location_url.host_get(&host_len);
00402
00403 UrlMappingContainer reverse_mapping(response_header->m_heap);
00404
00405 if (reverseMappingLookup(&location_url, location_url.port_get(), host, host_len, reverse_mapping)) {
00406 if (i == 0)
00407 remap_found = true;
00408 url_rewrite_remap_request(reverse_mapping, &location_url);
00409 new_loc_hdr = location_url.string_get_ref(&new_loc_length);
00410 response_header->value_set(url_headers[i].field, url_headers[i].len, new_loc_hdr, new_loc_length);
00411 }
00412
00413 location_url.destroy();
00414 }
00415 return remap_found;
00416 }
00417
00418
00419 void
00420 UrlRewrite::PerformACLFiltering(HttpTransact::State *s, url_mapping *map)
00421 {
00422 if (unlikely(!s || s->acl_filtering_performed || !s->client_connection_enabled))
00423 return;
00424
00425 s->acl_filtering_performed = true;
00426
00427 if (map->filter) {
00428 int res;
00429 int method = s->hdr_info.client_request.method_get_wksidx();
00430 int method_wksidx = (method != -1) ? (method - HTTP_WKSIDX_CONNECT) : -1;
00431 bool client_enabled_flag = true;
00432 ink_release_assert(ats_is_ip(&s->client_info.addr));
00433 for (acl_filter_rule * rp = map->filter; rp; rp = rp->next) {
00434 bool match = true;
00435 if (rp->method_restriction_enabled) {
00436 if (method_wksidx != -1) {
00437 match = rp->standard_method_lookup[method_wksidx];
00438 }
00439 else if (!rp->nonstandard_methods.empty()) {
00440 int method_str_len;
00441 const char *method_str = s->hdr_info.client_request.method_get(&method_str_len);
00442 match = rp->nonstandard_methods.count(std::string(method_str, method_str_len));
00443 }
00444 }
00445 if (match && rp->src_ip_valid) {
00446 match = false;
00447 for (int j = 0; j < rp->src_ip_cnt && !match; j++) {
00448 res = rp->src_ip_array[j].contains(s->client_info.addr) ? 1 : 0;
00449 if (rp->src_ip_array[j].invert) {
00450 if (res != 1)
00451 match = true;
00452 } else {
00453 if (res == 1)
00454 match = true;
00455 }
00456 }
00457 }
00458 if (match && client_enabled_flag) {
00459 Debug("url_rewrite", "matched ACL filter rule, %s request", rp->allow_flag ? "allowing" : "denying");
00460 client_enabled_flag = rp->allow_flag ? true : false;
00461 } else {
00462 if (!client_enabled_flag) {
00463 Debug("url_rewrite", "Previous ACL filter rule denied request, continuing to deny it");
00464 } else {
00465 Debug("url_rewrite", "did NOT match ACL filter rule, %s request", rp->allow_flag ? "denying" : "allowing");
00466 client_enabled_flag = rp->allow_flag ? false : true;
00467 }
00468 }
00469
00470 }
00471 s->client_connection_enabled = client_enabled_flag;
00472 }
00473 }
00474
00475
00476
00477
00478
00479
00480 mapping_type
00481 UrlRewrite::Remap_redirect(HTTPHdr *request_header, URL *redirect_url)
00482 {
00483 URL *request_url;
00484 mapping_type mappingType;
00485 const char *host = NULL;
00486 int host_len = 0, request_port = 0;
00487 bool prt, trt;
00488
00489 prt = (num_rules_redirect_permanent != 0);
00490 trt = (num_rules_redirect_temporary != 0);
00491
00492 if (prt + trt == 0)
00493 return NONE;
00494
00495
00496
00497
00498
00499 if (request_header == NULL) {
00500 Debug("url_rewrite", "request_header was invalid. UrlRewrite::Remap_redirect bailing out.");
00501 return NONE;
00502 }
00503 request_url = request_header->url_get();
00504 if (!request_url->valid()) {
00505 Debug("url_rewrite", "request_url was invalid. UrlRewrite::Remap_redirect bailing out.");
00506 return NONE;
00507 }
00508
00509 host = request_url->host_get(&host_len);
00510 request_port = request_url->port_get();
00511
00512 if (host_len == 0 && reverse_proxy != 0) {
00513
00514 int host_hdr_len;
00515 const char *host_hdr = request_header->value_get(MIME_FIELD_HOST, MIME_LEN_HOST, &host_hdr_len);
00516
00517 if (!host_hdr) {
00518 host_hdr = "";
00519 host_hdr_len = 0;
00520 }
00521
00522 const char *tmp = (const char *) memchr(host_hdr, ':', host_hdr_len);
00523
00524 if (tmp == NULL) {
00525 host_len = host_hdr_len;
00526 } else {
00527 host_len = tmp - host_hdr;
00528 request_port = ink_atoi(tmp + 1, host_hdr_len - host_len);
00529
00530
00531
00532 if (request_port == 0) {
00533 request_port = request_url->port_get();
00534 }
00535 }
00536
00537 host = host_hdr;
00538 }
00539
00540
00541
00542
00543 mappingType = NONE;
00544
00545 UrlMappingContainer redirect_mapping(request_header->m_heap);
00546
00547 if (trt) {
00548 if (temporaryRedirectLookup(request_url, request_port, host, host_len, redirect_mapping)) {
00549 mappingType = TEMPORARY_REDIRECT;
00550 }
00551 }
00552 if ((mappingType == NONE) && prt) {
00553 if (permanentRedirectLookup(request_url, request_port, host, host_len, redirect_mapping)) {
00554 mappingType = PERMANENT_REDIRECT;
00555 }
00556 }
00557
00558 if (mappingType != NONE) {
00559 ink_assert((mappingType == PERMANENT_REDIRECT) || (mappingType == TEMPORARY_REDIRECT));
00560
00561
00562
00563 redirect_url->create(NULL);
00564 redirect_url->copy(request_url);
00565
00566
00567 url_rewrite_remap_request(redirect_mapping, redirect_url);
00568
00569 return mappingType;
00570 }
00571 ink_assert(mappingType == NONE);
00572
00573 return NONE;
00574 }
00575
00576 bool
00577 UrlRewrite::_addToStore(MappingsStore &store, url_mapping *new_mapping, RegexMapping *reg_map,
00578 const char * src_host, bool is_cur_mapping_regex, int &count)
00579 {
00580 bool retval;
00581 if (is_cur_mapping_regex) {
00582 store.regex_list.enqueue(reg_map);
00583 retval = true;
00584 } else {
00585 retval = TableInsert(store.hash_lookup, new_mapping, src_host);
00586 }
00587 if (retval) {
00588 ++count;
00589 }
00590 return retval;
00591 }
00592
00593 bool
00594 UrlRewrite::InsertMapping(mapping_type maptype, url_mapping *new_mapping, RegexMapping *reg_map,
00595 const char * src_host, bool is_cur_mapping_regex)
00596 {
00597 bool success = false;
00598
00599
00600 switch (maptype) {
00601 case FORWARD_MAP:
00602 case FORWARD_MAP_REFERER:
00603 success = _addToStore(forward_mappings, new_mapping, reg_map, src_host,
00604 is_cur_mapping_regex, num_rules_forward);
00605 if (success) {
00606
00607 SetHomePageRedirectFlag(new_mapping, new_mapping->toUrl);
00608 }
00609 break;
00610 case REVERSE_MAP:
00611 success = _addToStore(reverse_mappings, new_mapping, reg_map, src_host,
00612 is_cur_mapping_regex, num_rules_reverse);
00613 new_mapping->homePageRedirect = false;
00614 break;
00615 case PERMANENT_REDIRECT:
00616 success = _addToStore(permanent_redirects, new_mapping, reg_map, src_host,
00617 is_cur_mapping_regex, num_rules_redirect_permanent);
00618 break;
00619 case TEMPORARY_REDIRECT:
00620 success = _addToStore(temporary_redirects, new_mapping, reg_map, src_host,
00621 is_cur_mapping_regex, num_rules_redirect_temporary);
00622 break;
00623 case FORWARD_MAP_WITH_RECV_PORT:
00624 success = _addToStore(forward_mappings_with_recv_port, new_mapping, reg_map, src_host,
00625 is_cur_mapping_regex, num_rules_forward_with_recv_port);
00626 break;
00627 default:
00628
00629
00630 return false;
00631 }
00632
00633 return success;
00634 }
00635
00636 bool
00637 UrlRewrite::InsertForwardMapping(mapping_type maptype, url_mapping * mapping, const char * src_host)
00638 {
00639 bool success;
00640
00641 if (maptype == FORWARD_MAP_WITH_RECV_PORT) {
00642 success = TableInsert(forward_mappings_with_recv_port.hash_lookup, mapping, src_host);
00643 } else {
00644 success = TableInsert(forward_mappings.hash_lookup, mapping, src_host);
00645 }
00646
00647 if (success) {
00648 switch (maptype) {
00649 case FORWARD_MAP:
00650 case FORWARD_MAP_REFERER:
00651 case FORWARD_MAP_WITH_RECV_PORT:
00652 SetHomePageRedirectFlag(mapping, mapping->toUrl);
00653 break;
00654 default:
00655 break;
00656 }
00657
00658 (maptype != FORWARD_MAP_WITH_RECV_PORT) ? ++num_rules_forward
00659 : ++num_rules_forward_with_recv_port;
00660 }
00661
00662 return success;
00663 }
00664
00665
00666
00667
00668
00669
00670
00671 int
00672 UrlRewrite::BuildTable(const char * path)
00673 {
00674 BUILD_TABLE_INFO bti;
00675 url_mapping * new_mapping = NULL;
00676
00677 ink_assert(forward_mappings.empty());
00678 ink_assert(reverse_mappings.empty());
00679 ink_assert(permanent_redirects.empty());
00680 ink_assert(temporary_redirects.empty());
00681 ink_assert(forward_mappings_with_recv_port.empty());
00682 ink_assert(num_rules_forward == 0);
00683 ink_assert(num_rules_reverse == 0);
00684 ink_assert(num_rules_redirect_permanent == 0);
00685 ink_assert(num_rules_redirect_temporary == 0);
00686 ink_assert(num_rules_forward_with_recv_port == 0);
00687
00688
00689 forward_mappings.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
00690 reverse_mappings.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
00691 permanent_redirects.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
00692 temporary_redirects.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
00693 forward_mappings_with_recv_port.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
00694
00695 if (!remap_parse_config(path, this)) {
00696
00697 return 3;
00698 }
00699
00700
00701
00702
00703 if (unlikely(backdoor_enabled)) {
00704 new_mapping = SetupBackdoorMapping();
00705 if (TableInsert(forward_mappings.hash_lookup, new_mapping, "")) {
00706 num_rules_forward++;
00707 } else {
00708 Warning("Could not insert backdoor mapping into store");
00709 delete new_mapping;
00710 return 3;
00711 }
00712 }
00713
00714
00715 if (default_to_pac) {
00716 new_mapping = SetupPacMapping();
00717 if (TableInsert(forward_mappings.hash_lookup, new_mapping, "")) {
00718 num_rules_forward++;
00719 } else {
00720 Warning("Could not insert pac mapping into store");
00721 delete new_mapping;
00722 return 3;
00723 }
00724 }
00725
00726 if (num_rules_forward == 0) {
00727 forward_mappings.hash_lookup = ink_hash_table_destroy(forward_mappings.hash_lookup);
00728 } else {
00729 if (ink_hash_table_isbound(forward_mappings.hash_lookup, "")) {
00730 nohost_rules = 1;
00731 }
00732 }
00733
00734 if (num_rules_reverse == 0) {
00735 reverse_mappings.hash_lookup = ink_hash_table_destroy(reverse_mappings.hash_lookup);
00736 }
00737
00738 if (num_rules_redirect_permanent == 0) {
00739 permanent_redirects.hash_lookup = ink_hash_table_destroy(permanent_redirects.hash_lookup);
00740 }
00741
00742 if (num_rules_redirect_temporary == 0) {
00743 temporary_redirects.hash_lookup = ink_hash_table_destroy(temporary_redirects.hash_lookup);
00744 }
00745
00746 if (num_rules_forward_with_recv_port == 0) {
00747 forward_mappings_with_recv_port.hash_lookup = ink_hash_table_destroy(
00748 forward_mappings_with_recv_port.hash_lookup);
00749 }
00750
00751 return 0;
00752 }
00753
00754
00755
00756
00757
00758
00759 bool
00760 UrlRewrite::TableInsert(InkHashTable *h_table, url_mapping *mapping, const char *src_host)
00761 {
00762 char src_host_tmp_buf[1];
00763 UrlMappingPathIndex *ht_contents;
00764
00765 if (!src_host) {
00766 src_host = &src_host_tmp_buf[0];
00767 src_host_tmp_buf[0] = 0;
00768 }
00769
00770 if (ink_hash_table_lookup(h_table, src_host, (void**) &ht_contents)) {
00771
00772 if (ht_contents == NULL) {
00773
00774 Warning("Found entry cannot be null!");
00775 return false;
00776 }
00777 } else {
00778 ht_contents = new UrlMappingPathIndex();
00779 ink_hash_table_insert(h_table, src_host, ht_contents);
00780 }
00781 if (!ht_contents->Insert(mapping)) {
00782 Warning("Could not insert new mapping");
00783 return false;
00784 }
00785 return true;
00786 }
00787
00788
00789
00790
00791
00792
00793
00794 bool
00795 UrlRewrite::_mappingLookup(MappingsStore &mappings, URL *request_url,
00796 int request_port, const char *request_host, int request_host_len,
00797 UrlMappingContainer &mapping_container)
00798 {
00799 char request_host_lower[TS_MAX_HOST_NAME_LEN];
00800
00801 if (!request_host || !request_url ||
00802 (request_host_len < 0) || (request_host_len >= TS_MAX_HOST_NAME_LEN)) {
00803 Debug("url_rewrite", "Invalid arguments!");
00804 return false;
00805 }
00806
00807
00808 for (int i = 0; i < request_host_len; ++i) {
00809 request_host_lower[i] = tolower(request_host[i]);
00810 }
00811 request_host_lower[request_host_len] = 0;
00812
00813 bool retval = false;
00814 int rank_ceiling = -1;
00815 url_mapping *mapping = _tableLookup(mappings.hash_lookup, request_url, request_port, request_host_lower,
00816 request_host_len);
00817 if (mapping != NULL) {
00818 rank_ceiling = mapping->getRank();
00819 Debug("url_rewrite", "Found 'simple' mapping with rank %d", rank_ceiling);
00820 mapping_container.set(mapping);
00821 retval = true;
00822 }
00823 if (_regexMappingLookup(mappings.regex_list, request_url, request_port, request_host_lower, request_host_len,
00824 rank_ceiling, mapping_container)) {
00825 Debug("url_rewrite", "Using regex mapping with rank %d", (mapping_container.getMapping())->getRank());
00826 retval = true;
00827 }
00828 return retval;
00829 }
00830
00831
00832 int
00833 UrlRewrite::_expandSubstitutions(int *matches_info, const RegexMapping *reg_map,
00834 const char *matched_string,
00835 char *dest_buf, int dest_buf_size)
00836 {
00837 int cur_buf_size = 0;
00838 int token_start = 0;
00839 int n_bytes_needed;
00840 int match_index;
00841 for (int i = 0; i < reg_map->n_substitutions; ++i) {
00842
00843 n_bytes_needed = reg_map->substitution_markers[i] - token_start;
00844 if ((cur_buf_size + n_bytes_needed) > dest_buf_size) {
00845 goto lOverFlow;
00846 }
00847 memcpy(dest_buf + cur_buf_size, reg_map->to_url_host_template + token_start, n_bytes_needed);
00848 cur_buf_size += n_bytes_needed;
00849
00850
00851 match_index = reg_map->substitution_ids[i] * 2;
00852 n_bytes_needed = matches_info[match_index + 1] - matches_info[match_index];
00853 if ((cur_buf_size + n_bytes_needed) > dest_buf_size) {
00854 goto lOverFlow;
00855 }
00856 memcpy(dest_buf + cur_buf_size, matched_string + matches_info[match_index], n_bytes_needed);
00857 cur_buf_size += n_bytes_needed;
00858
00859 token_start = reg_map->substitution_markers[i] + 2;
00860 }
00861
00862
00863 if (token_start < reg_map->to_url_host_template_len) {
00864 n_bytes_needed = reg_map->to_url_host_template_len - token_start;
00865 if ((cur_buf_size + n_bytes_needed) > dest_buf_size) {
00866 goto lOverFlow;
00867 }
00868 memcpy(dest_buf + cur_buf_size, reg_map->to_url_host_template + token_start, n_bytes_needed);
00869 cur_buf_size += n_bytes_needed;
00870 }
00871 Debug("url_rewrite_regex", "Expanded substitutions and returning string [%.*s] with length %d",
00872 cur_buf_size, dest_buf, cur_buf_size);
00873 return cur_buf_size;
00874
00875 lOverFlow:
00876 Warning("Overflow while expanding substitutions");
00877 return 0;
00878 }
00879
00880 bool
00881 UrlRewrite::_regexMappingLookup(RegexMappingList ®ex_mappings, URL *request_url, int request_port,
00882 const char *request_host, int request_host_len, int rank_ceiling,
00883 UrlMappingContainer &mapping_container)
00884 {
00885 bool retval = false;
00886
00887 if (rank_ceiling == -1) {
00888 rank_ceiling = INT_MAX;
00889 Debug("url_rewrite_regex", "Going to match all regexes");
00890 }
00891 else {
00892 Debug("url_rewrite_regex", "Going to match regexes with rank <= %d", rank_ceiling);
00893 }
00894
00895 int request_scheme_len, reg_map_scheme_len;
00896 const char *request_scheme = request_url->scheme_get(&request_scheme_len), *reg_map_scheme;
00897
00898 int request_path_len, reg_map_path_len;
00899 const char *request_path = request_url->path_get(&request_path_len), *reg_map_path;
00900
00901
00902 forl_LL(RegexMapping, list_iter, regex_mappings) {
00903 int reg_map_rank = list_iter->url_map->getRank();
00904
00905 if (reg_map_rank > rank_ceiling) {
00906 break;
00907 }
00908
00909 reg_map_scheme = list_iter->url_map->fromURL.scheme_get(®_map_scheme_len);
00910 if ((request_scheme_len != reg_map_scheme_len) ||
00911 strncmp(request_scheme, reg_map_scheme, request_scheme_len)) {
00912 Debug("url_rewrite_regex", "Skipping regex with rank %d as scheme does not match request scheme",
00913 reg_map_rank);
00914 continue;
00915 }
00916
00917 if (list_iter->url_map->fromURL.port_get() != request_port) {
00918 Debug("url_rewrite_regex", "Skipping regex with rank %d as regex map port does not match request port. "
00919 "regex map port: %d, request port %d",
00920 reg_map_rank, list_iter->url_map->fromURL.port_get(), request_port);
00921 continue;
00922 }
00923
00924 reg_map_path = list_iter->url_map->fromURL.path_get(®_map_path_len);
00925 if ((request_path_len < reg_map_path_len) ||
00926 strncmp(reg_map_path, request_path, reg_map_path_len)) {
00927 Debug("url_rewrite_regex", "Skipping regex with rank %d as path does not cover request path",
00928 reg_map_rank);
00929 continue;
00930 }
00931
00932 int matches_info[MAX_REGEX_SUBS * 3];
00933 int match_result = pcre_exec(list_iter->re, list_iter->re_extra, request_host, request_host_len,
00934 0, 0, matches_info, (sizeof(matches_info) / sizeof(int)));
00935 if (match_result > 0) {
00936 Debug("url_rewrite_regex", "Request URL host [%.*s] matched regex in mapping of rank %d "
00937 "with %d possible substitutions", request_host_len, request_host, reg_map_rank, match_result);
00938
00939 mapping_container.set(list_iter->url_map);
00940
00941 char buf[4096];
00942 int buf_len;
00943
00944
00945 buf_len = _expandSubstitutions(matches_info, list_iter, request_host, buf, sizeof(buf));
00946 URL *expanded_url = mapping_container.createNewToURL();
00947 expanded_url->copy(&((list_iter->url_map)->toUrl));
00948 expanded_url->host_set(buf, buf_len);
00949
00950 Debug("url_rewrite_regex", "Expanded toURL to [%.*s]",
00951 expanded_url->length_get(), expanded_url->string_get_ref());
00952 retval = true;
00953 break;
00954 } else if (match_result == PCRE_ERROR_NOMATCH) {
00955 Debug("url_rewrite_regex", "Request URL host [%.*s] did NOT match regex in mapping of rank %d",
00956 request_host_len, request_host, reg_map_rank);
00957 } else {
00958 Warning("pcre_exec() failed with error code %d", match_result);
00959 break;
00960 }
00961 }
00962
00963 return retval;
00964 }
00965
00966 void
00967 UrlRewrite::_destroyList(RegexMappingList &mappings)
00968 {
00969 RegexMapping *list_iter;
00970 while ((list_iter=mappings.pop()) != NULL) {
00971 delete list_iter->url_map;
00972 if (list_iter->re) {
00973 pcre_free(list_iter->re);
00974 }
00975 if (list_iter->re_extra) {
00976 pcre_free(list_iter->re_extra);
00977 }
00978 if (list_iter->to_url_host_template) {
00979 ats_free(list_iter->to_url_host_template);
00980 }
00981 delete list_iter;
00982 }
00983 mappings.clear();
00984 }