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 "RemapConfig.h"
00025 #include "UrlRewrite.h"
00026 #include "ReverseProxy.h"
00027 #include "I_Layout.h"
00028 #include "HTTP.h"
00029 #include "libts.h"
00030 #include "ink_cap.h"
00031
00032 #define modulePrefix "[ReverseProxy]"
00033
00034 static bool remap_parse_config_bti(const char * path, BUILD_TABLE_INFO * bti);
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 static int
00045 UrlWhack(char *toWhack, int *origLength)
00046 {
00047 int length = strlen(toWhack);
00048 char *tmp;
00049 *origLength = length;
00050
00051
00052 tmp = strstr(toWhack, "://");
00053 if (tmp != NULL) {
00054 if (strchr(tmp + 3, '/') == NULL) {
00055 toWhack[length] = '/';
00056 length++;
00057 }
00058 }
00059 return length;
00060 }
00061
00062
00063
00064
00065
00066
00067 static void
00068 clear_xstr_array(char *v[], size_t vsize)
00069 {
00070 for (unsigned i = 0; i < vsize; i++) {
00071 v[i] = (char *)ats_free_null(v[i]);
00072 }
00073 }
00074
00075 BUILD_TABLE_INFO::BUILD_TABLE_INFO()
00076 : remap_optflg(0), paramc(0), argc(0), rules_list(NULL), rewrite(NULL)
00077 {
00078 memset(this->paramv, 0, sizeof(this->paramv));
00079 memset(this->argv, 0, sizeof(this->argv));
00080 }
00081
00082 BUILD_TABLE_INFO::~BUILD_TABLE_INFO()
00083 {
00084 this->reset();
00085 }
00086
00087 void
00088 BUILD_TABLE_INFO::reset()
00089 {
00090 this->paramc = this->argc = 0;
00091 clear_xstr_array(this->paramv, sizeof(this->paramv) / sizeof(char *));
00092 clear_xstr_array(this->argv, sizeof(this->argv) / sizeof(char *));
00093 }
00094
00095 static const char *
00096 process_filter_opt(url_mapping * mp, const BUILD_TABLE_INFO * bti, char * errStrBuf, int errStrBufSize)
00097 {
00098 acl_filter_rule *rp, **rpp;
00099 const char *errStr = NULL;
00100
00101 if (unlikely(!mp || !bti || !errStrBuf || errStrBufSize <= 0)) {
00102 Debug("url_rewrite", "[process_filter_opt] Invalid argument(s)");
00103 return (const char *) "[process_filter_opt] Invalid argument(s)";
00104 }
00105 for (rp = bti->rules_list; rp; rp = rp->next) {
00106 if (rp->active_queue_flag) {
00107 Debug("url_rewrite", "[process_filter_opt] Add active main filter \"%s\" (argc=%d)",
00108 rp->filter_name ? rp->filter_name : "<NULL>", rp->argc);
00109 for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next));
00110 if ((errStr = remap_validate_filter_args(rpp, (const char **)rp->argv, rp->argc, errStrBuf, errStrBufSize)) != NULL)
00111 break;
00112 }
00113 }
00114 if (!errStr && (bti->remap_optflg & REMAP_OPTFLG_ALL_FILTERS) != 0) {
00115 Debug("url_rewrite", "[process_filter_opt] Add per remap filter");
00116 for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next));
00117 errStr = remap_validate_filter_args(rpp, (const char **)bti->argv, bti->argc, errStrBuf, errStrBufSize);
00118 }
00119 return errStr;
00120 }
00121
00122 static bool
00123 is_inkeylist(const char * key, ...)
00124 {
00125 va_list ap;
00126
00127 if (unlikely(key == NULL || key[0] == '\0')) {
00128 return false;
00129 }
00130
00131 va_start(ap, key);
00132
00133 const char *str = va_arg(ap, const char *);
00134 for (unsigned idx = 1; str; idx++) {
00135 if (!strcasecmp(key, str)) {
00136 va_end(ap);
00137 return true;
00138 }
00139
00140 str = va_arg(ap, const char *);
00141 }
00142
00143 va_end(ap);
00144 return false;
00145 }
00146
00147 static const char *
00148 parse_define_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize)
00149 {
00150 bool flg;
00151 acl_filter_rule * rp;
00152 acl_filter_rule ** rpp;
00153 const char * cstr = NULL;
00154
00155 if (bti->paramc < 2) {
00156 snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive);
00157 Debug("url_rewrite", "[parse_directive] %s", errbuf);
00158 return (const char *) errbuf;
00159 }
00160 if (bti->argc < 1) {
00161 snprintf(errbuf, errbufsize, "Directive \"%s\" must have filter parameter(s)", directive);
00162 Debug("url_rewrite", "[parse_directive] %s", errbuf);
00163 return (const char *) errbuf;
00164 }
00165
00166 flg = ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) ? true : false;
00167
00168 if ((cstr = remap_validate_filter_args(&rp, (const char **)bti->argv, bti->argc, errbuf, errbufsize)) == NULL && rp) {
00169 if (flg) {
00170 Debug("url_rewrite", "[parse_directive] new rule \"%s\" was created", bti->paramv[1]);
00171 for (rpp = &bti->rules_list; *rpp; rpp = &((*rpp)->next));
00172 (*rpp = rp)->name(bti->paramv[1]);
00173 }
00174 Debug("url_rewrite", "[parse_directive] %d argument(s) were added to rule \"%s\"", bti->argc, bti->paramv[1]);
00175 rp->add_argv(bti->argc, bti->argv);
00176 }
00177
00178 return cstr;
00179 }
00180
00181 static const char *
00182 parse_delete_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize)
00183 {
00184 if (bti->paramc < 2) {
00185 snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive);
00186 Debug("url_rewrite", "[parse_directive] %s", errbuf);
00187 return (const char *) errbuf;
00188 }
00189
00190 acl_filter_rule::delete_byname(&bti->rules_list, (const char *) bti->paramv[1]);
00191 return NULL;
00192 }
00193
00194 static const char *
00195 parse_activate_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize)
00196 {
00197 acl_filter_rule * rp;
00198
00199 if (bti->paramc < 2) {
00200 snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive);
00201 Debug("url_rewrite", "[parse_directive] %s", errbuf);
00202 return (const char *) errbuf;
00203 }
00204
00205 if ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) {
00206 snprintf(errbuf, errbufsize, "Undefined filter \"%s\" in directive \"%s\"", bti->paramv[1], directive);
00207 Debug("url_rewrite", "[parse_directive] %s", errbuf);
00208 return (const char *) errbuf;
00209 }
00210
00211 acl_filter_rule::requeue_in_active_list(&bti->rules_list, rp);
00212 return NULL;
00213 }
00214
00215 static const char *
00216 parse_deactivate_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize)
00217 {
00218 acl_filter_rule * rp;
00219
00220 if (bti->paramc < 2) {
00221 snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive);
00222 Debug("url_rewrite", "[parse_directive] %s", errbuf);
00223 return (const char *) errbuf;
00224 }
00225
00226 if ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) {
00227 snprintf(errbuf, errbufsize, "Undefined filter \"%s\" in directive \"%s\"", bti->paramv[1], directive);
00228 Debug("url_rewrite", "[parse_directive] %s", errbuf);
00229 return (const char *) errbuf;
00230 }
00231
00232 acl_filter_rule::requeue_in_passive_list(&bti->rules_list, rp);
00233 return NULL;
00234 }
00235
00236 static const char *
00237 parse_include_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize)
00238 {
00239
00240 if (bti->paramc < 2) {
00241 snprintf(errbuf, errbufsize, "Directive \"%s\" must have a path argument", directive);
00242 Debug("url_rewrite", "[%s] %s", __func__, errbuf);
00243 return (const char *) errbuf;
00244 }
00245
00246 for (unsigned i = 1; i < (unsigned) bti->paramc; ++i) {
00247
00248
00249
00250 BUILD_TABLE_INFO nbti;
00251 ats_scoped_str path;
00252 bool success;
00253
00254
00255 path = Layout::relative_to(Layout::get()->sysconfdir, bti->paramv[i]);
00256
00257
00258 if (ink_file_is_directory(path)) {
00259 snprintf(errbuf, errbufsize, "included path %s is a directory", bti->paramv[i]);
00260 return (const char *)errbuf;
00261 }
00262
00263 nbti.rules_list = bti->rules_list;
00264 nbti.rewrite = bti->rewrite;
00265
00266
00267
00268
00269
00270 Debug("url_rewrite", "[%s] including remap configuration from %s", __func__, (const char *)path);
00271 success = remap_parse_config_bti(path, &nbti);
00272
00273
00274 bti->rules_list = nbti.rules_list;
00275
00276 if (!success) {
00277 snprintf(errbuf, errbufsize, "failed to parse included file %s", bti->paramv[i]);
00278 return (const char *)errbuf;
00279 }
00280 }
00281
00282 return NULL;
00283 }
00284
00285 struct remap_directive
00286 {
00287 const char * name;
00288 const char * (*parser)(const char *, BUILD_TABLE_INFO *, char *, size_t);
00289 };
00290
00291 static const remap_directive directives[] = {
00292
00293 { ".definefilter", parse_define_directive},
00294 { ".deffilter", parse_define_directive},
00295 { ".defflt", parse_define_directive},
00296
00297 { ".deletefilter", parse_delete_directive},
00298 { ".delfilter", parse_delete_directive},
00299 { ".delflt", parse_delete_directive},
00300
00301 { ".usefilter", parse_activate_directive},
00302 { ".activefilter", parse_activate_directive},
00303 { ".activatefilter", parse_activate_directive},
00304 { ".useflt", parse_activate_directive},
00305
00306 { ".unusefilter", parse_deactivate_directive},
00307 { ".deactivatefilter", parse_deactivate_directive},
00308 { ".unactivefilter", parse_deactivate_directive},
00309 { ".deuseflt", parse_deactivate_directive},
00310 { ".unuseflt", parse_deactivate_directive},
00311
00312 { ".include", parse_include_directive },
00313 };
00314
00315 const char *
00316 remap_parse_directive(BUILD_TABLE_INFO *bti, char * errbuf, size_t errbufsize)
00317 {
00318 const char * directive = NULL;
00319
00320
00321 if (unlikely(!bti || !errbuf || errbufsize <= 0 || !bti->paramc || (directive = bti->paramv[0]) == NULL)) {
00322 Debug("url_rewrite", "[parse_directive] Invalid argument(s)");
00323 return "Invalid argument(s)";
00324 }
00325
00326 for (unsigned i = 0; i < countof(directives); ++i) {
00327 if (strcmp(directive, directives[i].name) == 0) {
00328 return directives[i].parser(directive, bti, errbuf, errbufsize);
00329 }
00330 }
00331
00332 snprintf(errbuf, errbufsize, "Unknown directive \"%s\"", directive);
00333 Debug("url_rewrite", "[parse_directive] %s", errbuf);
00334 return (const char *) errbuf;
00335 }
00336
00337 const char *
00338 remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int argc, char * errStrBuf, size_t errStrBufSize)
00339 {
00340 acl_filter_rule *rule;
00341 unsigned long ul;
00342 const char *argptr;
00343 char tmpbuf[1024];
00344 src_ip_info_t *ipi;
00345 int i, j, m;
00346 bool new_rule_flg = false;
00347
00348 if (!rule_pp) {
00349 Debug("url_rewrite", "[validate_filter_args] Invalid argument(s)");
00350 return (const char *) "Invalid argument(s)";
00351 }
00352
00353 if (is_debug_tag_set("url_rewrite")) {
00354 printf("validate_filter_args: ");
00355 for (i = 0; i < argc; i++)
00356 printf("\"%s\" ", argv[i]);
00357 printf("\n");
00358 }
00359
00360 if ((rule = *rule_pp) == NULL) {
00361 rule = new acl_filter_rule();
00362 if (unlikely((*rule_pp = rule) == NULL)) {
00363 Debug("url_rewrite", "[validate_filter_args] Memory allocation error");
00364 return (const char *) "Memory allocation Error";
00365 }
00366 new_rule_flg = true;
00367 Debug("url_rewrite", "[validate_filter_args] new acl_filter_rule class was created during remap rule processing");
00368 }
00369
00370 for (i = 0; i < argc; i++) {
00371 if ((ul = remap_check_option((const char **)&argv[i], 1, 0, NULL, &argptr)) == 0) {
00372 Debug("url_rewrite", "[validate_filter_args] Unknow remap option - %s", argv[i]);
00373 snprintf(errStrBuf, errStrBufSize, "Unknown option - \"%s\"", argv[i]);
00374 errStrBuf[errStrBufSize - 1] = 0;
00375 if (new_rule_flg) {
00376 delete rule;
00377 *rule_pp = NULL;
00378 }
00379 return (const char *) errStrBuf;
00380 }
00381 if (!argptr || !argptr[0]) {
00382 Debug("url_rewrite", "[validate_filter_args] Empty argument in %s", argv[i]);
00383 snprintf(errStrBuf, errStrBufSize, "Empty argument in \"%s\"", argv[i]);
00384 errStrBuf[errStrBufSize - 1] = 0;
00385 if (new_rule_flg) {
00386 delete rule;
00387 *rule_pp = NULL;
00388 }
00389 return (const char *) errStrBuf;
00390 }
00391
00392 if (ul & REMAP_OPTFLG_METHOD) {
00393
00394
00395 m = -1;
00396 if (!strcasecmp(argptr, "CONNECT"))
00397 m = HTTP_WKSIDX_CONNECT;
00398 else if (!strcasecmp(argptr, "DELETE"))
00399 m = HTTP_WKSIDX_DELETE;
00400 else if (!strcasecmp(argptr, "GET"))
00401 m = HTTP_WKSIDX_GET;
00402 else if (!strcasecmp(argptr, "HEAD"))
00403 m = HTTP_WKSIDX_HEAD;
00404 else if (!strcasecmp(argptr, "ICP_QUERY"))
00405 m = HTTP_WKSIDX_ICP_QUERY;
00406 else if (!strcasecmp(argptr, "OPTIONS"))
00407 m = HTTP_WKSIDX_OPTIONS;
00408 else if (!strcasecmp(argptr, "POST"))
00409 m = HTTP_WKSIDX_POST;
00410 else if (!strcasecmp(argptr, "PURGE"))
00411 m = HTTP_WKSIDX_PURGE;
00412 else if (!strcasecmp(argptr, "PUT"))
00413 m = HTTP_WKSIDX_PUT;
00414 else if (!strcasecmp(argptr, "TRACE"))
00415 m = HTTP_WKSIDX_TRACE;
00416 else if (!strcasecmp(argptr, "PUSH"))
00417 m = HTTP_WKSIDX_PUSH;
00418 if (m != -1) {
00419 m = m - HTTP_WKSIDX_CONNECT;
00420 rule->standard_method_lookup[m] = true;
00421 } else {
00422 Debug("url_rewrite", "[validate_filter_args] Using nonstandard method [%s]", argptr);
00423 rule->nonstandard_methods.insert(argptr);
00424 }
00425 rule->method_restriction_enabled = true;
00426 } else if (ul & REMAP_OPTFLG_SRC_IP) {
00427 if (rule->src_ip_cnt >= ACL_FILTER_MAX_SRC_IP) {
00428 Debug("url_rewrite", "[validate_filter_args] Too many \"src_ip=\" filters");
00429 snprintf(errStrBuf, errStrBufSize, "Defined more than %d \"src_ip=\" filters!", ACL_FILTER_MAX_SRC_IP);
00430 errStrBuf[errStrBufSize - 1] = 0;
00431 if (new_rule_flg) {
00432 delete rule;
00433 *rule_pp = NULL;
00434 }
00435 return (const char *) errStrBuf;
00436 }
00437 ipi = &rule->src_ip_array[rule->src_ip_cnt];
00438 if (ul & REMAP_OPTFLG_INVERT)
00439 ipi->invert = true;
00440 ink_strlcpy(tmpbuf, argptr, sizeof(tmpbuf));
00441
00442 if (ExtractIpRange(tmpbuf, &ipi->start.sa, &ipi->end.sa) != NULL) {
00443 Debug("url_rewrite", "[validate_filter_args] Unable to parse IP value in %s", argv[i]);
00444 snprintf(errStrBuf, errStrBufSize, "Unable to parse IP value in %s", argv[i]);
00445 errStrBuf[errStrBufSize - 1] = 0;
00446 if (new_rule_flg) {
00447 delete rule;
00448 *rule_pp = NULL;
00449 }
00450 return (const char*) errStrBuf;
00451 }
00452 for (j = 0; j < rule->src_ip_cnt; j++) {
00453 if (rule->src_ip_array[j].start == ipi->start && rule->src_ip_array[j].end == ipi->end) {
00454 ipi->reset();
00455 ipi = NULL;
00456 break;
00457 }
00458 }
00459 if (ipi) {
00460 rule->src_ip_cnt++;
00461 rule->src_ip_valid = 1;
00462 }
00463 } else if (ul & REMAP_OPTFLG_ACTION) {
00464 if (is_inkeylist(argptr, "0", "off", "deny", "disable", NULL)) {
00465 rule->allow_flag = 0;
00466 } else if (is_inkeylist(argptr, "1", "on", "allow", "enable", NULL)) {
00467 rule->allow_flag = 1;
00468 } else {
00469 Debug("url_rewrite", "[validate_filter_args] Unknown argument \"%s\"", argv[i]);
00470 snprintf(errStrBuf, errStrBufSize, "Unknown argument \"%s\"", argv[i]);
00471 errStrBuf[errStrBufSize - 1] = 0;
00472 if (new_rule_flg) {
00473 delete rule;
00474 *rule_pp = NULL;
00475 }
00476 return (const char *) errStrBuf;
00477 }
00478 }
00479 }
00480
00481 if (is_debug_tag_set("url_rewrite"))
00482 rule->print();
00483
00484 return NULL;
00485 }
00486
00487 unsigned long
00488 remap_check_option(const char ** argv, int argc, unsigned long findmode, int *_ret_idx, const char **argptr)
00489 {
00490 unsigned long ret_flags = 0;
00491 int idx = 0;
00492
00493 if (argptr)
00494 *argptr = NULL;
00495 if (argv && argc > 0) {
00496 for (int i = 0; i < argc; i++) {
00497 if (!strcasecmp(argv[i], "map_with_referer")) {
00498 if ((findmode & REMAP_OPTFLG_MAP_WITH_REFERER) != 0)
00499 idx = i;
00500 ret_flags |= REMAP_OPTFLG_MAP_WITH_REFERER;
00501 } else if (!strncasecmp(argv[i], "plugin=", 7)) {
00502 if ((findmode & REMAP_OPTFLG_PLUGIN) != 0)
00503 idx = i;
00504 if (argptr)
00505 *argptr = &argv[i][7];
00506 ret_flags |= REMAP_OPTFLG_PLUGIN;
00507 } else if (!strncasecmp(argv[i], "pparam=", 7)) {
00508 if ((findmode & REMAP_OPTFLG_PPARAM) != 0)
00509 idx = i;
00510 if (argptr)
00511 *argptr = &argv[i][7];
00512 ret_flags |= REMAP_OPTFLG_PPARAM;
00513 } else if (!strncasecmp(argv[i], "method=", 7)) {
00514 if ((findmode & REMAP_OPTFLG_METHOD) != 0)
00515 idx = i;
00516 if (argptr)
00517 *argptr = &argv[i][7];
00518 ret_flags |= REMAP_OPTFLG_METHOD;
00519 } else if (!strncasecmp(argv[i], "src_ip=~", 8)) {
00520 if ((findmode & REMAP_OPTFLG_SRC_IP) != 0)
00521 idx = i;
00522 if (argptr)
00523 *argptr = &argv[i][8];
00524 ret_flags |= (REMAP_OPTFLG_SRC_IP | REMAP_OPTFLG_INVERT);
00525 } else if (!strncasecmp(argv[i], "src_ip=", 7)) {
00526 if ((findmode & REMAP_OPTFLG_SRC_IP) != 0)
00527 idx = i;
00528 if (argptr)
00529 *argptr = &argv[i][7];
00530 ret_flags |= REMAP_OPTFLG_SRC_IP;
00531 } else if (!strncasecmp(argv[i], "action=", 7)) {
00532 if ((findmode & REMAP_OPTFLG_ACTION) != 0)
00533 idx = i;
00534 if (argptr)
00535 *argptr = &argv[i][7];
00536 ret_flags |= REMAP_OPTFLG_ACTION;
00537 } else if (!strncasecmp(argv[i], "mapid=", 6)) {
00538 if ((findmode & REMAP_OPTFLG_MAP_ID) != 0)
00539 idx = i;
00540 if (argptr)
00541 *argptr = &argv[i][6];
00542 ret_flags |= REMAP_OPTFLG_MAP_ID;
00543 }
00544
00545 if ((findmode & ret_flags) && !argptr) {
00546 if (_ret_idx)
00547 *_ret_idx = idx;
00548 return ret_flags;
00549 }
00550
00551 }
00552 }
00553 if (_ret_idx)
00554 *_ret_idx = idx;
00555 return ret_flags;
00556 }
00557
00558 int
00559 remap_load_plugin(const char ** argv, int argc, url_mapping *mp, char *errbuf, int errbufsize,
00560 int jump_to_argc, int *plugin_found_at)
00561 {
00562 TSRemapInterface ri;
00563 struct stat stat_buf;
00564 remap_plugin_info *pi;
00565 char *c, *err, tmpbuf[2048], default_path[PATH_NAME_MAX];
00566 const char *new_argv[1024];
00567 char * parv[1024];
00568 int idx = 0, retcode = 0;
00569 int parc = 0;
00570
00571 *plugin_found_at = 0;
00572
00573 memset(parv, 0, sizeof(parv));
00574 memset(new_argv, 0, sizeof(new_argv));
00575 tmpbuf[0] = 0;
00576
00577 ink_assert((unsigned) argc < countof(new_argv));
00578
00579 if (jump_to_argc != 0) {
00580 argc -= jump_to_argc;
00581 int i = 0;
00582 while (argv[i + jump_to_argc]) {
00583 new_argv[i] = argv[i + jump_to_argc];
00584 i++;
00585 }
00586 argv = &new_argv[0];
00587 if (!remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx)) {
00588 return -1;
00589 }
00590 } else {
00591 if (unlikely(!mp || (remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx) & REMAP_OPTFLG_PLUGIN) == 0)) {
00592 snprintf(errbuf, errbufsize, "Can't find remap plugin keyword or \"url_mapping\" is NULL");
00593 return -1;
00594 }
00595 }
00596
00597 if (unlikely((c = (char *) strchr(argv[idx], (int) '=')) == NULL || !(*(++c)))) {
00598 snprintf(errbuf, errbufsize, "Can't find remap plugin file name in \"@%s\"", argv[idx]);
00599 return -2;
00600 }
00601
00602 if (stat(c, &stat_buf) != 0) {
00603 const char *plugin_default_path = TSPluginDirGet();
00604
00605
00606 if (strlen(c) + strlen(plugin_default_path) > (PATH_NAME_MAX - 1)) {
00607 Debug("remap_plugin", "way too large a path specified for remap plugin");
00608 return -3;
00609 }
00610
00611 snprintf(default_path, PATH_NAME_MAX, "%s/%s", plugin_default_path, c);
00612 Debug("remap_plugin", "attempting to stat default plugin path: %s", default_path);
00613
00614 if (stat(default_path, &stat_buf) == 0) {
00615 Debug("remap_plugin", "stat successful on %s using that", default_path);
00616 c = &default_path[0];
00617 } else {
00618 snprintf(errbuf, errbufsize, "Can't find remap plugin file \"%s\"", c);
00619 return -3;
00620 }
00621 }
00622
00623 Debug("remap_plugin", "using path %s for plugin", c);
00624
00625 if (!remap_pi_list || (pi = remap_pi_list->find_by_path(c)) == 0) {
00626 pi = new remap_plugin_info(c);
00627 if (!remap_pi_list) {
00628 remap_pi_list = pi;
00629 } else {
00630 remap_pi_list->add_to_list(pi);
00631 }
00632 Debug("remap_plugin", "New remap plugin info created for \"%s\"", c);
00633
00634
00635
00636 {
00637 uint32_t elevate_access = 0;
00638 REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
00639 ElevateAccess access(elevate_access != 0);
00640
00641 if ((pi->dlh = dlopen(c, RTLD_NOW)) == NULL) {
00642 #if defined(freebsd) || defined(openbsd)
00643 err = (char *)dlerror();
00644 #else
00645 err = dlerror();
00646 #endif
00647 snprintf(errbuf, errbufsize, "Can't load plugin \"%s\" - %s", c, err ? err : "Unknown dlopen() error");
00648 return -4;
00649 }
00650 pi->fp_tsremap_init = (remap_plugin_info::_tsremap_init *) dlsym(pi->dlh, TSREMAP_FUNCNAME_INIT);
00651 pi->fp_tsremap_done = (remap_plugin_info::_tsremap_done *) dlsym(pi->dlh, TSREMAP_FUNCNAME_DONE);
00652 pi->fp_tsremap_new_instance = (remap_plugin_info::_tsremap_new_instance *) dlsym(pi->dlh, TSREMAP_FUNCNAME_NEW_INSTANCE);
00653 pi->fp_tsremap_delete_instance = (remap_plugin_info::_tsremap_delete_instance *) dlsym(pi->dlh, TSREMAP_FUNCNAME_DELETE_INSTANCE);
00654 pi->fp_tsremap_do_remap = (remap_plugin_info::_tsremap_do_remap *) dlsym(pi->dlh, TSREMAP_FUNCNAME_DO_REMAP);
00655 pi->fp_tsremap_os_response = (remap_plugin_info::_tsremap_os_response *) dlsym(pi->dlh, TSREMAP_FUNCNAME_OS_RESPONSE);
00656
00657 if (!pi->fp_tsremap_init) {
00658 snprintf(errbuf, errbufsize, "Can't find \"%s\" function in remap plugin \"%s\"", TSREMAP_FUNCNAME_INIT, c);
00659 retcode = -10;
00660 } else if (!pi->fp_tsremap_new_instance) {
00661 snprintf(errbuf, errbufsize, "Can't find \"%s\" function in remap plugin \"%s\"",
00662 TSREMAP_FUNCNAME_NEW_INSTANCE, c);
00663 retcode = -11;
00664 } else if (!pi->fp_tsremap_do_remap) {
00665 snprintf(errbuf, errbufsize, "Can't find \"%s\" function in remap plugin \"%s\"", TSREMAP_FUNCNAME_DO_REMAP, c);
00666 retcode = -12;
00667 }
00668 if (retcode) {
00669 if (errbuf && errbufsize > 0)
00670 Debug("remap_plugin", "%s", errbuf);
00671 dlclose(pi->dlh);
00672 pi->dlh = NULL;
00673 return retcode;
00674 }
00675 memset(&ri, 0, sizeof(ri));
00676 ri.size = sizeof(ri);
00677 ri.tsremap_version = TSREMAP_VERSION;
00678
00679 if (pi->fp_tsremap_init(&ri, tmpbuf, sizeof(tmpbuf) - 1) != TS_SUCCESS) {
00680 Warning("Failed to initialize plugin %s (non-zero retval) ... bailing out", pi->path);
00681 return -5;
00682 }
00683 }
00684 Debug("remap_plugin", "Remap plugin \"%s\" - initialization completed", c);
00685 }
00686
00687 if (!pi->dlh) {
00688 snprintf(errbuf, errbufsize, "Can't load plugin \"%s\"", c);
00689 return -6;
00690 }
00691
00692 if ((err = mp->fromURL.string_get(NULL)) == NULL) {
00693 snprintf(errbuf, errbufsize, "Can't load fromURL from URL class");
00694 return -7;
00695 }
00696 parv[parc++] = ats_strdup(err);
00697 ats_free(err);
00698
00699 if ((err = mp->toUrl.string_get(NULL)) == NULL) {
00700 snprintf(errbuf, errbufsize, "Can't load toURL from URL class");
00701 return -7;
00702 }
00703 parv[parc++] = ats_strdup(err);
00704 ats_free(err);
00705
00706 bool plugin_encountered = false;
00707
00708 for (idx = 0; idx < argc && parc < (int) (countof(parv) - 1); idx++) {
00709
00710 if (plugin_encountered && !strncasecmp("plugin=", argv[idx], 7) && argv[idx][7]) {
00711 *plugin_found_at = idx;
00712 break;
00713 }
00714
00715 if (!strncasecmp("plugin=", argv[idx], 7)) {
00716 plugin_encountered = true;
00717 }
00718
00719 if (!strncasecmp("pparam=", argv[idx], 7) && argv[idx][7]) {
00720 parv[parc++] = const_cast<char *>(&(argv[idx][7]));
00721 }
00722 }
00723
00724 Debug("url_rewrite", "Viewing all parameters for config line");
00725 for (int k = 0; k < argc; k++) {
00726 Debug("url_rewrite", "Argument %d: %s", k, argv[k]);
00727 }
00728
00729 Debug("url_rewrite", "Viewing parsed plugin parameters for %s: [%d]", pi->path, *plugin_found_at);
00730 for (int k = 0; k < parc; k++) {
00731 Debug("url_rewrite", "Argument %d: %s", k, parv[k]);
00732 }
00733
00734 void* ih;
00735
00736 Debug("remap_plugin", "creating new plugin instance");
00737
00738 TSReturnCode res = TS_ERROR;
00739 res = pi->fp_tsremap_new_instance(parc, parv, &ih, tmpbuf, sizeof(tmpbuf) - 1);
00740
00741 Debug("remap_plugin", "done creating new plugin instance");
00742
00743 ats_free(parv[0]);
00744 ats_free(parv[1]);
00745
00746 if (res != TS_SUCCESS) {
00747 snprintf(errbuf, errbufsize, "Can't create new remap instance for plugin \"%s\" - %s", c,
00748 tmpbuf[0] ? tmpbuf : "Unknown plugin error");
00749 Warning("Failed to create new instance for plugin %s (not a TS_SUCCESS return)", pi->path);
00750 return -8;
00751 }
00752
00753 mp->add_plugin(pi, ih);
00754
00755 return 0;
00756 }
00757
00758
00759
00760
00761 static bool
00762 process_regex_mapping_config(const char *from_host_lower, url_mapping *new_mapping, UrlRewrite::RegexMapping *reg_map)
00763 {
00764 const char *str;
00765 int str_index;
00766 const char *to_host;
00767 int to_host_len;
00768 int substitution_id;
00769 int substitution_count = 0;
00770
00771 reg_map->re = NULL;
00772 reg_map->re_extra = NULL;
00773 reg_map->to_url_host_template = NULL;
00774 reg_map->to_url_host_template_len = 0;
00775 reg_map->n_substitutions = 0;
00776
00777 reg_map->url_map = new_mapping;
00778
00779
00780
00781 reg_map->re = pcre_compile(from_host_lower, 0, &str, &str_index, NULL);
00782 if (reg_map->re == NULL) {
00783 Warning("pcre_compile failed! Regex has error starting at %s", from_host_lower + str_index);
00784 goto lFail;
00785 }
00786
00787 reg_map->re_extra = pcre_study(reg_map->re, 0, &str);
00788 if ((reg_map->re_extra == NULL) && (str != NULL)) {
00789 Warning("pcre_study failed with message [%s]", str);
00790 goto lFail;
00791 }
00792
00793 int n_captures;
00794 if (pcre_fullinfo(reg_map->re, reg_map->re_extra, PCRE_INFO_CAPTURECOUNT, &n_captures) != 0) {
00795 Warning("pcre_fullinfo failed!");
00796 goto lFail;
00797 }
00798 if (n_captures >= UrlRewrite::MAX_REGEX_SUBS) {
00799 Warning("Regex has %d capturing subpatterns (including entire regex); Max allowed: %d",
00800 n_captures + 1, UrlRewrite::MAX_REGEX_SUBS);
00801 goto lFail;
00802 }
00803
00804 to_host = new_mapping->toUrl.host_get(&to_host_len);
00805 for (int i = 0; i < (to_host_len - 1); ++i) {
00806 if (to_host[i] == '$') {
00807 if (substitution_count > UrlRewrite::MAX_REGEX_SUBS) {
00808 Warning("Cannot have more than %d substitutions in mapping with host [%s]",
00809 UrlRewrite::MAX_REGEX_SUBS, from_host_lower);
00810 goto lFail;
00811 }
00812 substitution_id = to_host[i + 1] - '0';
00813 if ((substitution_id < 0) || (substitution_id > n_captures)) {
00814 Warning("Substitution id [%c] has no corresponding capture pattern in regex [%s]",
00815 to_host[i + 1], from_host_lower);
00816 goto lFail;
00817 }
00818 reg_map->substitution_markers[reg_map->n_substitutions] = i;
00819 reg_map->substitution_ids[reg_map->n_substitutions] = substitution_id;
00820 ++reg_map->n_substitutions;
00821 }
00822 }
00823
00824
00825
00826
00827 str = new_mapping->toUrl.host_get(&str_index);
00828 reg_map->to_url_host_template_len = str_index;
00829 reg_map->to_url_host_template = static_cast<char *>(ats_malloc(str_index));
00830 memcpy(reg_map->to_url_host_template, str, str_index);
00831
00832 return true;
00833
00834 lFail:
00835 if (reg_map->re) {
00836 pcre_free(reg_map->re);
00837 reg_map->re = NULL;
00838 }
00839 if (reg_map->re_extra) {
00840 pcre_free(reg_map->re_extra);
00841 reg_map->re_extra = NULL;
00842 }
00843 if (reg_map->to_url_host_template) {
00844 ats_free(reg_map->to_url_host_template);
00845 reg_map->to_url_host_template = NULL;
00846 reg_map->to_url_host_template_len = 0;
00847 }
00848 return false;
00849 }
00850
00851 static bool
00852 remap_parse_config_bti(const char * path, BUILD_TABLE_INFO * bti)
00853 {
00854
00855 char errBuf[1024], errStrBuf[1024];
00856 Tokenizer whiteTok(" \t");
00857 bool alarm_already = false;
00858 const char *errStr;
00859
00860
00861 char *tok_state, *cur_line, *cur_line_tmp;
00862 int rparse, cur_line_size, cln = 0;
00863
00864
00865 const char *fromScheme, *toScheme;
00866 int fromSchemeLen, toSchemeLen;
00867 const char *fromHost, *toHost;
00868 int fromHostLen, toHostLen;
00869 char *map_from, *map_from_start;
00870 char *map_to, *map_to_start;
00871 const char *tmp;
00872 char *fromHost_lower = NULL;
00873 char *fromHost_lower_ptr = NULL;
00874 char fromHost_lower_buf[1024];
00875 url_mapping *new_mapping = NULL;
00876 mapping_type maptype;
00877 referer_info *ri;
00878 int origLength;
00879 int length;
00880 int tok_count;
00881
00882 UrlRewrite::RegexMapping* reg_map;
00883 bool is_cur_mapping_regex;
00884 const char *type_id_str;
00885
00886 ats_scoped_str file_buf(readIntoBuffer(path, modulePrefix, NULL));
00887 if (!file_buf) {
00888 Warning("can't load remapping configuration file %s", path);
00889 return false;
00890 }
00891
00892 Debug("url_rewrite", "[BuildTable] UrlRewrite::BuildTable()");
00893
00894 for (cur_line = tokLine(file_buf, &tok_state, '\\'); cur_line != NULL;) {
00895 reg_map = NULL;
00896 new_mapping = NULL;
00897 errStrBuf[0] = 0;
00898 bti->reset();
00899
00900
00901 while (*cur_line && isascii(*cur_line) && isspace(*cur_line))
00902 ++cur_line;
00903
00904 if ((cur_line_size = strlen((char *) cur_line)) <= 0) {
00905 cur_line = tokLine(NULL, &tok_state, '\\');
00906 ++cln;
00907 continue;
00908 }
00909
00910
00911 cur_line_tmp = cur_line + cur_line_size - 1;
00912 while (cur_line_tmp != cur_line && isascii(*cur_line_tmp) && isspace(*cur_line_tmp)) {
00913 *cur_line_tmp = '\0';
00914 --cur_line_tmp;
00915 }
00916
00917 if ((cur_line_size = strlen((char *) cur_line)) <= 0 || *cur_line == '#' || *cur_line == '\0') {
00918 cur_line = tokLine(NULL, &tok_state, '\\');
00919 ++cln;
00920 continue;
00921 }
00922
00923 Debug("url_rewrite", "[BuildTable] Parsing: \"%s\"", cur_line);
00924
00925 tok_count = whiteTok.Initialize(cur_line, SHARE_TOKS);
00926
00927 for (int j = 0; j < tok_count; j++) {
00928 if (((char *) whiteTok[j])[0] == '@') {
00929 if (((char *) whiteTok[j])[1])
00930 bti->argv[bti->argc++] = ats_strdup(&(((char *) whiteTok[j])[1]));
00931 } else {
00932 bti->paramv[bti->paramc++] = ats_strdup((char *) whiteTok[j]);
00933 }
00934 }
00935
00936
00937 if (bti->paramc<1 || (bti->paramc < 3 && bti->paramv[0][0] != '.') || bti->paramc> BUILD_TABLE_MAX_ARGS) {
00938 snprintf(errBuf, sizeof(errBuf), "%s Malformed line %d in file %s", modulePrefix, cln + 1, path);
00939 errStr = errStrBuf;
00940 goto MAP_ERROR;
00941 }
00942
00943 bti->remap_optflg = remap_check_option((const char **)bti->argv, bti->argc);
00944
00945
00946 if (bti->paramv[0][0] == '.') {
00947 if ((errStr = remap_parse_directive(bti, errStrBuf, sizeof(errStrBuf))) != NULL) {
00948 snprintf(errBuf, sizeof(errBuf) - 1, "%s Error on line %d - %s", modulePrefix, cln + 1, errStr);
00949 errStr = errStrBuf;
00950 goto MAP_ERROR;
00951 }
00952
00953 cur_line = tokLine(NULL, &tok_state, '\\');
00954 ++cln;
00955 continue;
00956 }
00957
00958 is_cur_mapping_regex = (strncasecmp("regex_", bti->paramv[0], 6) == 0);
00959 type_id_str = is_cur_mapping_regex ? (bti->paramv[0] + 6) : bti->paramv[0];
00960
00961
00962 if (!strcasecmp("reverse_map", type_id_str)) {
00963 Debug("url_rewrite", "[BuildTable] - REVERSE_MAP");
00964 maptype = REVERSE_MAP;
00965 } else if (!strcasecmp("map", type_id_str)) {
00966 Debug("url_rewrite", "[BuildTable] - %s",
00967 ((bti->remap_optflg & REMAP_OPTFLG_MAP_WITH_REFERER) == 0) ? "FORWARD_MAP" : "FORWARD_MAP_REFERER");
00968 maptype = ((bti->remap_optflg & REMAP_OPTFLG_MAP_WITH_REFERER) == 0) ? FORWARD_MAP : FORWARD_MAP_REFERER;
00969 } else if (!strcasecmp("redirect", type_id_str)) {
00970 Debug("url_rewrite", "[BuildTable] - PERMANENT_REDIRECT");
00971 maptype = PERMANENT_REDIRECT;
00972 } else if (!strcasecmp("redirect_temporary", type_id_str)) {
00973 Debug("url_rewrite", "[BuildTable] - TEMPORARY_REDIRECT");
00974 maptype = TEMPORARY_REDIRECT;
00975 } else if (!strcasecmp("map_with_referer", type_id_str)) {
00976 Debug("url_rewrite", "[BuildTable] - FORWARD_MAP_REFERER");
00977 maptype = FORWARD_MAP_REFERER;
00978 } else if (!strcasecmp("map_with_recv_port", type_id_str)) {
00979 Debug("url_rewrite", "[BuildTable] - FORWARD_MAP_WITH_RECV_PORT");
00980 maptype = FORWARD_MAP_WITH_RECV_PORT;
00981 } else {
00982 snprintf(errBuf, sizeof(errBuf) - 1, "%s Unknown mapping type at line %d", modulePrefix, cln + 1);
00983 errStr = errStrBuf;
00984 goto MAP_ERROR;
00985 }
00986
00987 new_mapping = new url_mapping(cln);
00988
00989
00990 if ((errStr = process_filter_opt(new_mapping, bti, errStrBuf, sizeof(errStrBuf))) != NULL) {
00991 goto MAP_ERROR;
00992 }
00993
00994 new_mapping->map_id = 0;
00995 if ((bti->remap_optflg & REMAP_OPTFLG_MAP_ID) != 0) {
00996 int idx = 0;
00997 char *c;
00998 int ret = remap_check_option((const char **)bti->argv, bti->argc, REMAP_OPTFLG_MAP_ID, &idx);
00999 if (ret & REMAP_OPTFLG_MAP_ID) {
01000 c = strchr(bti->argv[idx], (int) '=');
01001 new_mapping->map_id = (unsigned int) atoi(++c);
01002 }
01003 }
01004
01005 map_from = bti->paramv[1];
01006 length = UrlWhack(map_from, &origLength);
01007
01008
01009
01010
01011
01012 if ((tmp = (map_from_start = map_from)) != NULL && length > 2 && tmp[length - 1] == '/' && tmp[length - 2] == '/') {
01013 new_mapping->unique = true;
01014 length -= 2;
01015 }
01016
01017 new_mapping->fromURL.create(NULL);
01018 rparse = new_mapping->fromURL.parse_no_path_component_breakdown(tmp, length);
01019
01020 map_from_start[origLength] = '\0';
01021
01022 if (rparse != PARSE_DONE) {
01023 errStr = "Malformed From URL";
01024 goto MAP_ERROR;
01025 }
01026
01027 map_to = bti->paramv[2];
01028 length = UrlWhack(map_to, &origLength);
01029 map_to_start = map_to;
01030 tmp = map_to;
01031
01032 new_mapping->toUrl.create(NULL);
01033 rparse = new_mapping->toUrl.parse_no_path_component_breakdown(tmp, length);
01034 map_to_start[origLength] = '\0';
01035
01036 if (rparse != PARSE_DONE) {
01037 errStr = "Malformed To URL";
01038 goto MAP_ERROR;
01039 }
01040
01041 fromScheme = new_mapping->fromURL.scheme_get(&fromSchemeLen);
01042
01043
01044 if (fromScheme == NULL || fromSchemeLen == 0) {
01045 new_mapping->fromURL.scheme_set(URL_SCHEME_HTTP, URL_LEN_HTTP);
01046 fromScheme = new_mapping->fromURL.scheme_get(&fromSchemeLen);
01047 new_mapping->wildcard_from_scheme = true;
01048 }
01049 toScheme = new_mapping->toUrl.scheme_get(&toSchemeLen);
01050
01051
01052
01053 if ((fromScheme != URL_SCHEME_HTTP && fromScheme != URL_SCHEME_HTTPS &&
01054 fromScheme != URL_SCHEME_FILE &&
01055 fromScheme != URL_SCHEME_TUNNEL &&
01056 fromScheme != URL_SCHEME_WS &&
01057 fromScheme != URL_SCHEME_WSS) ||
01058 (toScheme != URL_SCHEME_HTTP && toScheme != URL_SCHEME_HTTPS &&
01059 toScheme != URL_SCHEME_TUNNEL && toScheme != URL_SCHEME_WS &&
01060 toScheme != URL_SCHEME_WSS)) {
01061 errStr = "Only http, https, ws, wss, and tunnel remappings are supported";
01062 goto MAP_ERROR;
01063 }
01064
01065
01066 if ( (fromScheme == URL_SCHEME_WSS || fromScheme == URL_SCHEME_WS) &&
01067 (toScheme != URL_SCHEME_WSS && toScheme != URL_SCHEME_WS)) {
01068 errStr = "WS or WSS can only be mapped out to WS or WSS.";
01069 goto MAP_ERROR;
01070 }
01071
01072
01073 if (bti->paramv[3] != NULL) {
01074 if (maptype == FORWARD_MAP_REFERER) {
01075 new_mapping->filter_redirect_url = ats_strdup(bti->paramv[3]);
01076 if (!strcasecmp(bti->paramv[3], "<default>") || !strcasecmp(bti->paramv[3], "default") ||
01077 !strcasecmp(bti->paramv[3], "<default_redirect_url>") || !strcasecmp(bti->paramv[3], "default_redirect_url"))
01078 new_mapping->default_redirect_url = true;
01079 new_mapping->redir_chunk_list = redirect_tag_str::parse_format_redirect_url(bti->paramv[3]);
01080 for (int j = bti->paramc; j > 4; j--) {
01081 if (bti->paramv[j - 1] != NULL) {
01082 char refinfo_error_buf[1024];
01083 bool refinfo_error = false;
01084
01085 ri = new referer_info((char *)bti->paramv[j - 1], &refinfo_error, refinfo_error_buf,
01086 sizeof(refinfo_error_buf));
01087 if (refinfo_error) {
01088 snprintf(errBuf, sizeof(errBuf), "%s Incorrect Referer regular expression \"%s\" at line %d - %s",
01089 modulePrefix, bti->paramv[j - 1], cln + 1, refinfo_error_buf);
01090 SignalError(errBuf, alarm_already);
01091 delete ri;
01092 ri = 0;
01093 }
01094
01095 if (ri && ri->negative) {
01096 if (ri->any) {
01097 new_mapping->optional_referer = true;
01098 delete ri;
01099 ri = 0;
01100 } else {
01101 new_mapping->negative_referer = true;
01102 }
01103 }
01104 if (ri) {
01105 ri->next = new_mapping->referer_list;
01106 new_mapping->referer_list = ri;
01107 }
01108 }
01109 }
01110 } else {
01111 new_mapping->tag = ats_strdup(&(bti->paramv[3][0]));
01112 }
01113 }
01114
01115 fromHost = new_mapping->fromURL.host_get(&fromHostLen);
01116 if (fromHost == NULL || fromHostLen <= 0) {
01117 if (maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER || maptype == FORWARD_MAP_WITH_RECV_PORT) {
01118 if (*map_from_start != '/') {
01119 errStr = "Relative remappings must begin with a /";
01120 goto MAP_ERROR;
01121 } else {
01122 fromHost = "";
01123 fromHostLen = 0;
01124 }
01125 } else {
01126 errStr = "Remap source in reverse mappings requires a hostname";
01127 goto MAP_ERROR;
01128 }
01129 }
01130
01131 toHost = new_mapping->toUrl.host_get(&toHostLen);
01132 if (toHost == NULL || toHostLen <= 0) {
01133 errStr = "The remap destinations require a hostname";
01134 goto MAP_ERROR;
01135 }
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145 if (unlikely(fromHostLen >= (int) sizeof(fromHost_lower_buf))) {
01146 fromHost_lower = (fromHost_lower_ptr = (char *)ats_malloc(fromHostLen + 1));
01147 } else {
01148 fromHost_lower = &fromHost_lower_buf[0];
01149 }
01150
01151 memcpy(fromHost_lower, fromHost, fromHostLen);
01152 fromHost_lower[fromHostLen] = 0;
01153 LowerCaseStr(fromHost_lower);
01154
01155
01156 new_mapping->fromURL.host_set(fromHost_lower, fromHostLen);
01157
01158 reg_map = NULL;
01159 if (is_cur_mapping_regex) {
01160 reg_map = new UrlRewrite::RegexMapping();
01161 if (!process_regex_mapping_config(fromHost_lower, new_mapping, reg_map)) {
01162 errStr = "Could not process regex mapping config line";
01163 goto MAP_ERROR;
01164 }
01165 Debug("url_rewrite_regex", "Configured regex rule for host [%s]", fromHost_lower);
01166 }
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 if ((maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER || maptype == FORWARD_MAP_WITH_RECV_PORT) &&
01177 fromScheme == URL_SCHEME_TUNNEL && (fromHost_lower[0]<'0' || fromHost_lower[0]> '9')) {
01178 addrinfo* ai_records;
01179 ip_text_buffer ipb;
01180 if (0 == getaddrinfo(fromHost_lower, 0, 0, &ai_records)) {
01181 for ( addrinfo* ai_spot = ai_records ; ai_spot ; ai_spot = ai_spot->ai_next) {
01182 if (ats_is_ip(ai_spot->ai_addr) && !ats_is_ip_any(ai_spot->ai_addr)) {
01183 url_mapping *u_mapping;
01184
01185 ats_ip_ntop(ai_spot->ai_addr, ipb, sizeof ipb);
01186 u_mapping = new url_mapping;
01187 u_mapping->fromURL.create(NULL);
01188 u_mapping->fromURL.copy(&new_mapping->fromURL);
01189 u_mapping->fromURL.host_set(ipb, strlen(ipb));
01190 u_mapping->toUrl.create(NULL);
01191 u_mapping->toUrl.copy(&new_mapping->toUrl);
01192
01193 if (bti->paramv[3] != NULL) {
01194 u_mapping->tag = ats_strdup(&(bti->paramv[3][0]));
01195 }
01196
01197 if (!bti->rewrite->InsertForwardMapping(maptype, u_mapping, ipb)) {
01198 errStr = "Unable to add mapping rule to lookup table";
01199 freeaddrinfo(ai_records);
01200 goto MAP_ERROR;
01201 }
01202 }
01203 }
01204
01205 freeaddrinfo(ai_records);
01206 }
01207 }
01208
01209
01210 if ((bti->remap_optflg & REMAP_OPTFLG_PLUGIN) != 0 && (maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER ||
01211 maptype == FORWARD_MAP_WITH_RECV_PORT)) {
01212 if ((remap_check_option((const char **)bti->argv, bti->argc, REMAP_OPTFLG_PLUGIN, &tok_count) & REMAP_OPTFLG_PLUGIN) != 0) {
01213 int plugin_found_at = 0;
01214 int jump_to_argc = 0;
01215
01216
01217 if (remap_load_plugin((const char **)bti->argv, bti->argc, new_mapping, errStrBuf, sizeof(errStrBuf), 0, &plugin_found_at)) {
01218 Debug("remap_plugin", "Remap plugin load error - %s", errStrBuf[0] ? errStrBuf : "Unknown error");
01219 errStr = errStrBuf;
01220 goto MAP_ERROR;
01221 }
01222
01223 while (plugin_found_at) {
01224 jump_to_argc += plugin_found_at;
01225 if (remap_load_plugin((const char **)bti->argv, bti->argc, new_mapping, errStrBuf, sizeof(errStrBuf), jump_to_argc, &plugin_found_at)) {
01226 Debug("remap_plugin", "Remap plugin load error - %s", errStrBuf[0] ? errStrBuf : "Unknown error");
01227 errStr = errStrBuf;
01228 goto MAP_ERROR;
01229 }
01230 }
01231 }
01232 }
01233
01234
01235 if (!bti->rewrite->InsertMapping(maptype, new_mapping, reg_map, fromHost_lower, is_cur_mapping_regex)) {
01236 errStr = "Unable to add mapping rule to lookup table";
01237 goto MAP_ERROR;
01238 }
01239
01240 fromHost_lower_ptr = (char *)ats_free_null(fromHost_lower_ptr);
01241
01242 cur_line = tokLine(NULL, &tok_state, '\\');
01243 ++cln;
01244 continue;
01245
01246
01247 MAP_ERROR:
01248 Warning("Could not add rule at line #%d; Aborting!", cln + 1);
01249 snprintf(errBuf, sizeof(errBuf), "%s %s at line %d", modulePrefix, errStr, cln + 1);
01250 SignalError(errBuf, alarm_already);
01251 delete reg_map;
01252 delete new_mapping;
01253 return false;
01254 }
01255
01256 return true;
01257 }
01258
01259 bool
01260 remap_parse_config(const char * path, UrlRewrite * rewrite)
01261 {
01262 BUILD_TABLE_INFO bti;
01263
01264 bti.rewrite = rewrite;
01265 return remap_parse_config_bti(path, &bti);
01266 }