TS-2323: start separating remap config file parsing
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/4be46fb9 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/4be46fb9 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/4be46fb9 Branch: refs/heads/master Commit: 4be46fb9dbcfd743e08991f1920cd17a742f0db6 Parents: 2699900 Author: James Peach <[email protected]> Authored: Wed Oct 30 14:03:30 2013 -0700 Committer: James Peach <[email protected]> Committed: Tue Nov 5 16:46:15 2013 -0800 ---------------------------------------------------------------------- proxy/http/remap/Makefile.am | 8 +- proxy/http/remap/RemapConfig.cc | 456 +++++++++++++++++++++++++++++++ proxy/http/remap/RemapConfig.h | 61 +++++ proxy/http/remap/RemapPluginInfo.h | 11 - proxy/http/remap/UrlRewrite.cc | 458 +------------------------------- proxy/http/remap/UrlRewrite.h | 2 - 6 files changed, 531 insertions(+), 465 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4be46fb9/proxy/http/remap/Makefile.am ---------------------------------------------------------------------- diff --git a/proxy/http/remap/Makefile.am b/proxy/http/remap/Makefile.am index 73dfcac..0cab3d2 100644 --- a/proxy/http/remap/Makefile.am +++ b/proxy/http/remap/Makefile.am @@ -34,6 +34,8 @@ noinst_LIBRARIES = libhttp_remap.a libhttp_remap_a_SOURCES = \ AclFiltering.cc \ AclFiltering.h \ + RemapConfig.cc \ + RemapConfig.h \ RemapPluginInfo.cc \ RemapPluginInfo.h \ RemapPlugins.cc \ @@ -42,7 +44,7 @@ libhttp_remap_a_SOURCES = \ RemapProcessor.h \ UrlMapping.cc \ UrlMapping.h \ - UrlRewrite.cc \ - UrlRewrite.h \ + UrlMappingPathIndex.cc \ UrlMappingPathIndex.h \ - UrlMappingPathIndex.cc + UrlRewrite.cc \ + UrlRewrite.h http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4be46fb9/proxy/http/remap/RemapConfig.cc ---------------------------------------------------------------------- diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc new file mode 100644 index 0000000..bc5c86d --- /dev/null +++ b/proxy/http/remap/RemapConfig.cc @@ -0,0 +1,456 @@ +/** @file + * + * Remap configuration file parsing. + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "RemapConfig.h" +#include "libts.h" +#include "HTTP.h" + +static bool +is_inkeylist(const char * key, ...) +{ + unsigned i; + va_list ap; + + if (unlikely(key == NULL || key[0] == '\0')) { + return false; + } + + char tmpkey[512]; + va_start(ap, key); + + for (i = 0; i < (sizeof(tmpkey) - 2) && (tmpkey[i] = *key++) != 0;) { + if (tmpkey[i] != '_' && tmpkey[i] != '.') { + i++; + } + } + + tmpkey[i] = 0; + + if (tmpkey[0]) { + const char *str = va_arg(ap, const char *); + for (unsigned idx = 1; str; idx++) { + if (!strcasecmp(tmpkey, str)) { + va_end(ap); + return true; + } + + str = va_arg(ap, const char *); + } + } + + va_end(ap); + return false; +} + + +static const char * +parse_define_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize) +{ + bool flg; + acl_filter_rule * rp; + acl_filter_rule ** rpp; + const char * cstr = NULL; + + if (bti->paramc < 2) { + snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive); + Debug("url_rewrite", "[parse_directive] %s", errbuf); + return (const char *) errbuf; + } + if (bti->argc < 1) { + snprintf(errbuf, errbufsize, "Directive \"%s\" must have filter parameter(s)", directive); + Debug("url_rewrite", "[parse_directive] %s", errbuf); + return (const char *) errbuf; + } + + flg = ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) ? true : false; + // coverity[alloc_arg] + if ((cstr = remap_validate_filter_args(&rp, bti->argv, bti->argc, errbuf, errbufsize)) == NULL && rp) { + if (flg) { // new filter - add to list + Debug("url_rewrite", "[parse_directive] new rule \"%s\" was created", bti->paramv[1]); + for (rpp = &bti->rules_list; *rpp; rpp = &((*rpp)->next)); + (*rpp = rp)->name(bti->paramv[1]); + } + Debug("url_rewrite", "[parse_directive] %d argument(s) were added to rule \"%s\"", bti->argc, bti->paramv[1]); + rp->add_argv(bti->argc, bti->argv); // store string arguments for future processing + } + + return cstr; +} + +static const char * +parse_delete_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize) +{ + if (bti->paramc < 2) { + snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive); + Debug("url_rewrite", "[parse_directive] %s", errbuf); + return (const char *) errbuf; + } + + acl_filter_rule::delete_byname(&bti->rules_list, (const char *) bti->paramv[1]); + return NULL; +} + +static const char * +parse_activate_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize) +{ + acl_filter_rule * rp; + + if (bti->paramc < 2) { + snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive); + Debug("url_rewrite", "[parse_directive] %s", errbuf); + return (const char *) errbuf; + } + + if ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) { + snprintf(errbuf, errbufsize, "Undefined filter \"%s\" in directive \"%s\"", bti->paramv[1], directive); + Debug("url_rewrite", "[parse_directive] %s", errbuf); + return (const char *) errbuf; + } + + acl_filter_rule::requeue_in_active_list(&bti->rules_list, rp); + return NULL; +} + +static const char * +parse_deactivate_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize) +{ + acl_filter_rule * rp; + + if (bti->paramc < 2) { + snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive); + Debug("url_rewrite", "[parse_directive] %s", errbuf); + return (const char *) errbuf; + } + + if ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) { + snprintf(errbuf, errbufsize, "Undefined filter \"%s\" in directive \"%s\"", bti->paramv[1], directive); + Debug("url_rewrite", "[parse_directive] %s", errbuf); + return (const char *) errbuf; + } + + acl_filter_rule::requeue_in_passive_list(&bti->rules_list, rp); + return NULL; +} + +struct remap_directive +{ + const char * name; + const char * (*parser)(const char *, BUILD_TABLE_INFO *, char *, size_t); +}; + +static const remap_directive directives[] = { + + { ".definefilter", parse_define_directive}, + { ".deffilter", parse_define_directive}, + { ".defflt", parse_define_directive}, + + { ".deletefilter", parse_delete_directive}, + { ".delfilter", parse_delete_directive}, + { ".delflt", parse_delete_directive}, + + { ".usefilter", parse_activate_directive}, + { ".activefilter", parse_activate_directive}, + { ".activatefilter", parse_activate_directive}, + + { ".unusefilter", parse_deactivate_directive}, + { ".deactivatefilter", parse_deactivate_directive}, + { ".unactivefilter", parse_deactivate_directive}, + { ".deuseflt", parse_deactivate_directive}, + { ".unuseflt", parse_deactivate_directive}, + +}; + +const char * +remap_parse_directive(BUILD_TABLE_INFO *bti, char * errbuf, size_t errbufsize) +{ + const char * directive = NULL; + + // Check arguments + if (unlikely(!bti || !errbuf || errbufsize <= 0 || !bti->paramc || (directive = bti->paramv[0]) == NULL)) { + Debug("url_rewrite", "[parse_directive] Invalid argument(s)"); + return "Invalid argument(s)"; + } + + for (unsigned i = 0; i < countof(directives); ++i) { + if (strcmp(directive, directives[i].name) == 0) { + return directives[i].parser(directive, bti, errbuf, errbufsize); + } + } + + snprintf(errbuf, errbufsize, "Unknown directive \"%s\"", directive); + Debug("url_rewrite", "[parse_directive] %s", errbuf); + return (const char *) errbuf; +} + +const char * +remap_validate_filter_args(acl_filter_rule ** rule_pp, char ** argv, int argc, char * errStrBuf, size_t errStrBufSize) +{ + acl_filter_rule *rule; + unsigned long ul; + char *argptr, tmpbuf[1024]; + src_ip_info_t *ipi; + int i, j, m; + bool new_rule_flg = false; + + if (!rule_pp) { + Debug("url_rewrite", "[validate_filter_args] Invalid argument(s)"); + return (const char *) "Invalid argument(s)"; + } + + if (is_debug_tag_set("url_rewrite")) { + printf("validate_filter_args: "); + for (i = 0; i < argc; i++) + printf("\"%s\" ", argv[i]); + printf("\n"); + } + + if ((rule = *rule_pp) == NULL) { + rule = NEW(new acl_filter_rule()); + if (unlikely((*rule_pp = rule) == NULL)) { + Debug("url_rewrite", "[validate_filter_args] Memory allocation error"); + return (const char *) "Memory allocation Error"; + } + new_rule_flg = true; + Debug("url_rewrite", "[validate_filter_args] new acl_filter_rule class was created during remap rule processing"); + } + + for (i = 0; i < argc; i++) { + if ((ul = remap_check_option(&argv[i], 1, 0, NULL, &argptr)) == 0) { + Debug("url_rewrite", "[validate_filter_args] Unknow remap option - %s", argv[i]); + snprintf(errStrBuf, errStrBufSize, "Unknown option - \"%s\"", argv[i]); + errStrBuf[errStrBufSize - 1] = 0; + if (new_rule_flg) { + delete rule; + *rule_pp = NULL; + } + return (const char *) errStrBuf; + } + if (!argptr || !argptr[0]) { + Debug("url_rewrite", "[validate_filter_args] Empty argument in %s", argv[i]); + snprintf(errStrBuf, errStrBufSize, "Empty argument in \"%s\"", argv[i]); + errStrBuf[errStrBufSize - 1] = 0; + if (new_rule_flg) { + delete rule; + *rule_pp = NULL; + } + return (const char *) errStrBuf; + } + + if (ul & REMAP_OPTFLG_METHOD) { /* "method=" option */ + if (rule->method_cnt >= ACL_FILTER_MAX_METHODS) { + Debug("url_rewrite", "[validate_filter_args] Too many \"method=\" filters"); + snprintf(errStrBuf, errStrBufSize, "Defined more than %d \"method=\" filters!", ACL_FILTER_MAX_METHODS); + errStrBuf[errStrBufSize - 1] = 0; + if (new_rule_flg) { + delete rule; + *rule_pp = NULL; + } + return (const char *) errStrBuf; + } + // Please remember that the order of hash idx creation is very important and it is defined + // in HTTP.cc file + if (!strcasecmp(argptr, "CONNECT")) + m = HTTP_WKSIDX_CONNECT; + else if (!strcasecmp(argptr, "DELETE")) + m = HTTP_WKSIDX_DELETE; + else if (!strcasecmp(argptr, "GET")) + m = HTTP_WKSIDX_GET; + else if (!strcasecmp(argptr, "HEAD")) + m = HTTP_WKSIDX_HEAD; + else if (!strcasecmp(argptr, "ICP_QUERY")) + m = HTTP_WKSIDX_ICP_QUERY; + else if (!strcasecmp(argptr, "OPTIONS")) + m = HTTP_WKSIDX_OPTIONS; + else if (!strcasecmp(argptr, "POST")) + m = HTTP_WKSIDX_POST; + else if (!strcasecmp(argptr, "PURGE")) + m = HTTP_WKSIDX_PURGE; + else if (!strcasecmp(argptr, "PUT")) + m = HTTP_WKSIDX_PUT; + else if (!strcasecmp(argptr, "TRACE")) + m = HTTP_WKSIDX_TRACE; + else if (!strcasecmp(argptr, "PUSH")) + m = HTTP_WKSIDX_PUSH; + else { + Debug("url_rewrite", "[validate_filter_args] Unknown method value %s", argptr); + snprintf(errStrBuf, errStrBufSize, "Unknown method \"%s\"", argptr); + errStrBuf[errStrBufSize - 1] = 0; + if (new_rule_flg) { + delete rule; + *rule_pp = NULL; + } + return (const char *) errStrBuf; + } + for (j = 0; j < rule->method_cnt; j++) { + if (rule->method_array[j] == m) { + m = 0; + break; /* we already have it in the list */ + } + } + if ((j = m) != 0) { + j = j - HTTP_WKSIDX_CONNECT; // get method index + if (j<0 || j>= ACL_FILTER_MAX_METHODS) { + Debug("url_rewrite", "[validate_filter_args] Incorrect method index! Method sequence in HTTP.cc is broken"); + snprintf(errStrBuf, errStrBufSize, "Incorrect method index %d", j); + errStrBuf[errStrBufSize - 1] = 0; + if (new_rule_flg) { + delete rule; + *rule_pp = NULL; + } + return (const char *) errStrBuf; + } + rule->method_idx[j] = m; + rule->method_array[rule->method_cnt++] = m; + rule->method_valid = 1; + } + } else if (ul & REMAP_OPTFLG_SRC_IP) { /* "src_ip=" option */ + if (rule->src_ip_cnt >= ACL_FILTER_MAX_SRC_IP) { + Debug("url_rewrite", "[validate_filter_args] Too many \"src_ip=\" filters"); + snprintf(errStrBuf, errStrBufSize, "Defined more than %d \"src_ip=\" filters!", ACL_FILTER_MAX_SRC_IP); + errStrBuf[errStrBufSize - 1] = 0; + if (new_rule_flg) { + delete rule; + *rule_pp = NULL; + } + return (const char *) errStrBuf; + } + ipi = &rule->src_ip_array[rule->src_ip_cnt]; + if (ul & REMAP_OPTFLG_INVERT) + ipi->invert = true; + ink_strlcpy(tmpbuf, argptr, sizeof(tmpbuf)); + // important! use copy of argument + if (ExtractIpRange(tmpbuf, &ipi->start.sa, &ipi->end.sa) != NULL) { + Debug("url_rewrite", "[validate_filter_args] Unable to parse IP value in %s", argv[i]); + snprintf(errStrBuf, errStrBufSize, "Unable to parse IP value in %s", argv[i]); + errStrBuf[errStrBufSize - 1] = 0; + if (new_rule_flg) { + delete rule; + *rule_pp = NULL; + } + return (const char*) errStrBuf; + } + for (j = 0; j < rule->src_ip_cnt; j++) { + if (rule->src_ip_array[j].start == ipi->start && rule->src_ip_array[j].end == ipi->end) { + ipi->reset(); + ipi = NULL; + break; /* we have the same src_ip in the list */ + } + } + if (ipi) { + rule->src_ip_cnt++; + rule->src_ip_valid = 1; + } + } else if (ul & REMAP_OPTFLG_ACTION) { /* "action=" option */ + if (is_inkeylist(argptr, "0", "off", "deny", "disable", NULL)) { + rule->allow_flag = 0; + } else if (is_inkeylist(argptr, "1", "on", "allow", "enable", NULL)) { + rule->allow_flag = 1; + } else { + Debug("url_rewrite", "[validate_filter_args] Unknown argument \"%s\"", argv[i]); + snprintf(errStrBuf, errStrBufSize, "Unknown argument \"%s\"", argv[i]); + errStrBuf[errStrBufSize - 1] = 0; + if (new_rule_flg) { + delete rule; + *rule_pp = NULL; + } + return (const char *) errStrBuf; + } + } + } + + if (is_debug_tag_set("url_rewrite")) + rule->print(); + + return NULL; /* success */ +} + +unsigned long +remap_check_option(char *argv[], int argc, unsigned long findmode, int *_ret_idx, char **argptr) +{ + unsigned long ret_flags = 0; + int idx = 0; + + if (argptr) + *argptr = NULL; + if (argv && argc > 0) { + for (int i = 0; i < argc; i++) { + if (!strcasecmp(argv[i], "map_with_referer")) { + if ((findmode & REMAP_OPTFLG_MAP_WITH_REFERER) != 0) + idx = i; + ret_flags |= REMAP_OPTFLG_MAP_WITH_REFERER; + } else if (!strncasecmp(argv[i], "plugin=", 7)) { + if ((findmode & REMAP_OPTFLG_PLUGIN) != 0) + idx = i; + if (argptr) + *argptr = &argv[i][7]; + ret_flags |= REMAP_OPTFLG_PLUGIN; + } else if (!strncasecmp(argv[i], "pparam=", 7)) { + if ((findmode & REMAP_OPTFLG_PPARAM) != 0) + idx = i; + if (argptr) + *argptr = &argv[i][7]; + ret_flags |= REMAP_OPTFLG_PPARAM; + } else if (!strncasecmp(argv[i], "method=", 7)) { + if ((findmode & REMAP_OPTFLG_METHOD) != 0) + idx = i; + if (argptr) + *argptr = &argv[i][7]; + ret_flags |= REMAP_OPTFLG_METHOD; + } else if (!strncasecmp(argv[i], "src_ip=~", 8)) { + if ((findmode & REMAP_OPTFLG_SRC_IP) != 0) + idx = i; + if (argptr) + *argptr = &argv[i][8]; + ret_flags |= (REMAP_OPTFLG_SRC_IP | REMAP_OPTFLG_INVERT); + } else if (!strncasecmp(argv[i], "src_ip=", 7)) { + if ((findmode & REMAP_OPTFLG_SRC_IP) != 0) + idx = i; + if (argptr) + *argptr = &argv[i][7]; + ret_flags |= REMAP_OPTFLG_SRC_IP; + } else if (!strncasecmp(argv[i], "action=", 7)) { + if ((findmode & REMAP_OPTFLG_ACTION) != 0) + idx = i; + if (argptr) + *argptr = &argv[i][7]; + ret_flags |= REMAP_OPTFLG_ACTION; + } else if (!strncasecmp(argv[i], "mapid=", 6)) { + if ((findmode & REMAP_OPTFLG_MAP_ID) != 0) + idx = i; + if (argptr) + *argptr = &argv[i][6]; + ret_flags |= REMAP_OPTFLG_MAP_ID; + } + + if ((findmode & ret_flags) && !argptr) { + if (_ret_idx) + *_ret_idx = idx; + return ret_flags; + } + + } + } + if (_ret_idx) + *_ret_idx = idx; + return ret_flags; +} http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4be46fb9/proxy/http/remap/RemapConfig.h ---------------------------------------------------------------------- diff --git a/proxy/http/remap/RemapConfig.h b/proxy/http/remap/RemapConfig.h new file mode 100644 index 0000000..d0b9fe8 --- /dev/null +++ b/proxy/http/remap/RemapConfig.h @@ -0,0 +1,61 @@ +/** @file + * + * Remap configuration file parsing. + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef REMAPCONFIG_H_E862FB4C_EFFC_4F2A_8BF2_9AB6E1E5E9CF +#define REMAPCONFIG_H_E862FB4C_EFFC_4F2A_8BF2_9AB6E1E5E9CF + +#include "AclFiltering.h" + +#define BUILD_TABLE_MAX_ARGS 2048 + +// Remap inline options +#define REMAP_OPTFLG_MAP_WITH_REFERER 0x01 /* "map_with_referer" option */ +#define REMAP_OPTFLG_PLUGIN 0x02 /* "plugin=" option (per remap plugin) */ +#define REMAP_OPTFLG_PPARAM 0x04 /* "pparam=" option (per remap plugin option) */ +#define REMAP_OPTFLG_METHOD 0x08 /* "method=" option (used for ACL filtering) */ +#define REMAP_OPTFLG_SRC_IP 0x10 /* "src_ip=" option (used for ACL filtering) */ +#define REMAP_OPTFLG_ACTION 0x20 /* "action=" option (used for ACL filtering) */ +#define REMAP_OPTFLG_MAP_ID 0x800 /* associate a map ID with this rule */ +#define REMAP_OPTFLG_INVERT 0x80000000 /* "invert" the rule (for src_ip at least) */ +#define REMAP_OPTFLG_ALL_FILTERS (REMAP_OPTFLG_METHOD|REMAP_OPTFLG_SRC_IP|REMAP_OPTFLG_ACTION) + +struct BUILD_TABLE_INFO +{ + unsigned long remap_optflg; + int paramc; + int argc; + char *paramv[BUILD_TABLE_MAX_ARGS]; + char *argv[BUILD_TABLE_MAX_ARGS]; + acl_filter_rule *rules_list; // all rules defined in config files as .define_filter foobar @src_ip=..... +}; + +const char * +remap_parse_directive(BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize); +const char * + +remap_validate_filter_args(acl_filter_rule ** rule_pp, char ** argv, int argc, char * errStrBuf, size_t errStrBufSize); + +unsigned long +remap_check_option(char *argv[], int argc, unsigned long findmode = 0, int *_ret_idx = NULL, char **argptr = NULL); + +#endif /* REMAPCONFIG_H_E862FB4C_EFFC_4F2A_8BF2_9AB6E1E5E9CF */ http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4be46fb9/proxy/http/remap/RemapPluginInfo.h ---------------------------------------------------------------------- diff --git a/proxy/http/remap/RemapPluginInfo.h b/proxy/http/remap/RemapPluginInfo.h index 65ae63d..41caac8 100644 --- a/proxy/http/remap/RemapPluginInfo.h +++ b/proxy/http/remap/RemapPluginInfo.h @@ -27,17 +27,6 @@ #include "api/ts/ts.h" #include "api/ts/remap.h" -// Remap inline options -#define REMAP_OPTFLG_MAP_WITH_REFERER 0x01 /* "map_with_referer" option */ -#define REMAP_OPTFLG_PLUGIN 0x02 /* "plugin=" option (per remap plugin) */ -#define REMAP_OPTFLG_PPARAM 0x04 /* "pparam=" option (per remap plugin option) */ -#define REMAP_OPTFLG_METHOD 0x08 /* "method=" option (used for ACL filtering) */ -#define REMAP_OPTFLG_SRC_IP 0x10 /* "src_ip=" option (used for ACL filtering) */ -#define REMAP_OPTFLG_ACTION 0x20 /* "action=" option (used for ACL filtering) */ -#define REMAP_OPTFLG_MAP_ID 0x800 /* associate a map ID with this rule */ -#define REMAP_OPTFLG_INVERT 0x80000000 /* "invert" the rule (for src_ip at least) */ -#define REMAP_OPTFLG_ALL_FILTERS (REMAP_OPTFLG_METHOD|REMAP_OPTFLG_SRC_IP|REMAP_OPTFLG_ACTION) - #define TSREMAP_FUNCNAME_INIT "TSRemapInit" #define TSREMAP_FUNCNAME_DONE "TSRemapDone" #define TSREMAP_FUNCNAME_NEW_INSTANCE "TSRemapNewInstance" http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4be46fb9/proxy/http/remap/UrlRewrite.cc ---------------------------------------------------------------------- diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc index 4b7a1bf..f442ed5 100644 --- a/proxy/http/remap/UrlRewrite.cc +++ b/proxy/http/remap/UrlRewrite.cc @@ -32,22 +32,13 @@ #include "Tokenizer.h" #include "api/ts/remap.h" #include "UrlMappingPathIndex.h" +#include "RemapConfig.h" #include "ink_string.h" #include "ink_cap.h" #define modulePrefix "[ReverseProxy]" -struct BUILD_TABLE_INFO -{ - unsigned long remap_optflg; - int paramc; - int argc; - char *paramv[BUILD_TABLE_MAX_ARGS]; - char *argv[BUILD_TABLE_MAX_ARGS]; - acl_filter_rule *rules_list; // all rules defined in config files as .define_filter foobar @src_ip=..... -}; - /** Returns the length of the URL. @@ -74,77 +65,6 @@ UrlWhack(char *toWhack, int *origLength) return length; } -static unsigned long -check_remap_option(char *argv[], int argc, unsigned long findmode = 0, int *_ret_idx = NULL, char **argptr = NULL) -{ - unsigned long ret_flags = 0; - int idx = 0; - - if (argptr) - *argptr = NULL; - if (argv && argc > 0) { - for (int i = 0; i < argc; i++) { - if (!strcasecmp(argv[i], "map_with_referer")) { - if ((findmode & REMAP_OPTFLG_MAP_WITH_REFERER) != 0) - idx = i; - ret_flags |= REMAP_OPTFLG_MAP_WITH_REFERER; - } else if (!strncasecmp(argv[i], "plugin=", 7)) { - if ((findmode & REMAP_OPTFLG_PLUGIN) != 0) - idx = i; - if (argptr) - *argptr = &argv[i][7]; - ret_flags |= REMAP_OPTFLG_PLUGIN; - } else if (!strncasecmp(argv[i], "pparam=", 7)) { - if ((findmode & REMAP_OPTFLG_PPARAM) != 0) - idx = i; - if (argptr) - *argptr = &argv[i][7]; - ret_flags |= REMAP_OPTFLG_PPARAM; - } else if (!strncasecmp(argv[i], "method=", 7)) { - if ((findmode & REMAP_OPTFLG_METHOD) != 0) - idx = i; - if (argptr) - *argptr = &argv[i][7]; - ret_flags |= REMAP_OPTFLG_METHOD; - } else if (!strncasecmp(argv[i], "src_ip=~", 8)) { - if ((findmode & REMAP_OPTFLG_SRC_IP) != 0) - idx = i; - if (argptr) - *argptr = &argv[i][8]; - ret_flags |= (REMAP_OPTFLG_SRC_IP | REMAP_OPTFLG_INVERT); - } else if (!strncasecmp(argv[i], "src_ip=", 7)) { - if ((findmode & REMAP_OPTFLG_SRC_IP) != 0) - idx = i; - if (argptr) - *argptr = &argv[i][7]; - ret_flags |= REMAP_OPTFLG_SRC_IP; - } else if (!strncasecmp(argv[i], "action=", 7)) { - if ((findmode & REMAP_OPTFLG_ACTION) != 0) - idx = i; - if (argptr) - *argptr = &argv[i][7]; - ret_flags |= REMAP_OPTFLG_ACTION; - } else if (!strncasecmp(argv[i], "mapid=", 6)) { - if ((findmode & REMAP_OPTFLG_MAP_ID) != 0) - idx = i; - if (argptr) - *argptr = &argv[i][6]; - ret_flags |= REMAP_OPTFLG_MAP_ID; - } - - if ((findmode & ret_flags) && !argptr) { - if (_ret_idx) - *_ret_idx = idx; - return ret_flags; - } - - } - } - if (_ret_idx) - *_ret_idx = idx; - return ret_flags; -} - /** Determines where we are in a situation where a virtual path is being mapped to a server home page. If it is, we set a special flag @@ -163,45 +83,6 @@ SetHomePageRedirectFlag(url_mapping *new_mapping, URL &new_to_url) new_mapping->homePageRedirect = (from_path && !to_path) ? true : false; } - -// =============================================================================== -static bool -is_inkeylist(const char * key, ...) -{ - unsigned i; - va_list ap; - - if (unlikely(key == NULL || key[0] == '\0')) { - return false; - } - - char tmpkey[512]; - va_start(ap, key); - - for (i = 0; i < (sizeof(tmpkey) - 2) && (tmpkey[i] = *key++) != 0;) { - if (tmpkey[i] != '_' && tmpkey[i] != '.') { - i++; - } - } - - tmpkey[i] = 0; - - if (tmpkey[0]) { - const char *str = va_arg(ap, const char *); - for (unsigned idx = 1; str; idx++) { - if (!strcasecmp(tmpkey, str)) { - va_end(ap); - return true; - } - - str = va_arg(ap, const char *); - } - } - - va_end(ap); - return false; -} - /** Cleanup *char[] array - each item in array must be allocated via ats_malloc or similar "x..." function. @@ -217,327 +98,6 @@ clear_xstr_array(char *v[], int vsize) } static const char * -validate_filter_args(acl_filter_rule ** rule_pp, char **argv, int argc, char *errStrBuf, int errStrBufSize) -{ - acl_filter_rule *rule; - unsigned long ul; - char *argptr, tmpbuf[1024]; - src_ip_info_t *ipi; - int i, j, m; - bool new_rule_flg = false; - - if (!rule_pp) { - Debug("url_rewrite", "[validate_filter_args] Invalid argument(s)"); - return (const char *) "Invalid argument(s)"; - } - - if (is_debug_tag_set("url_rewrite")) { - printf("validate_filter_args: "); - for (i = 0; i < argc; i++) - printf("\"%s\" ", argv[i]); - printf("\n"); - } - - if ((rule = *rule_pp) == NULL) { - rule = NEW(new acl_filter_rule()); - if (unlikely((*rule_pp = rule) == NULL)) { - Debug("url_rewrite", "[validate_filter_args] Memory allocation error"); - return (const char *) "Memory allocation Error"; - } - new_rule_flg = true; - Debug("url_rewrite", "[validate_filter_args] new acl_filter_rule class was created during remap rule processing"); - } - - for (i = 0; i < argc; i++) { - if ((ul = check_remap_option(&argv[i], 1, 0, NULL, &argptr)) == 0) { - Debug("url_rewrite", "[validate_filter_args] Unknow remap option - %s", argv[i]); - snprintf(errStrBuf, errStrBufSize, "Unknown option - \"%s\"", argv[i]); - errStrBuf[errStrBufSize - 1] = 0; - if (new_rule_flg) { - delete rule; - *rule_pp = NULL; - } - return (const char *) errStrBuf; - } - if (!argptr || !argptr[0]) { - Debug("url_rewrite", "[validate_filter_args] Empty argument in %s", argv[i]); - snprintf(errStrBuf, errStrBufSize, "Empty argument in \"%s\"", argv[i]); - errStrBuf[errStrBufSize - 1] = 0; - if (new_rule_flg) { - delete rule; - *rule_pp = NULL; - } - return (const char *) errStrBuf; - } - - if (ul & REMAP_OPTFLG_METHOD) { /* "method=" option */ - if (rule->method_cnt >= ACL_FILTER_MAX_METHODS) { - Debug("url_rewrite", "[validate_filter_args] Too many \"method=\" filters"); - snprintf(errStrBuf, errStrBufSize, "Defined more than %d \"method=\" filters!", ACL_FILTER_MAX_METHODS); - errStrBuf[errStrBufSize - 1] = 0; - if (new_rule_flg) { - delete rule; - *rule_pp = NULL; - } - return (const char *) errStrBuf; - } - // Please remember that the order of hash idx creation is very important and it is defined - // in HTTP.cc file - if (!strcasecmp(argptr, "CONNECT")) - m = HTTP_WKSIDX_CONNECT; - else if (!strcasecmp(argptr, "DELETE")) - m = HTTP_WKSIDX_DELETE; - else if (!strcasecmp(argptr, "GET")) - m = HTTP_WKSIDX_GET; - else if (!strcasecmp(argptr, "HEAD")) - m = HTTP_WKSIDX_HEAD; - else if (!strcasecmp(argptr, "ICP_QUERY")) - m = HTTP_WKSIDX_ICP_QUERY; - else if (!strcasecmp(argptr, "OPTIONS")) - m = HTTP_WKSIDX_OPTIONS; - else if (!strcasecmp(argptr, "POST")) - m = HTTP_WKSIDX_POST; - else if (!strcasecmp(argptr, "PURGE")) - m = HTTP_WKSIDX_PURGE; - else if (!strcasecmp(argptr, "PUT")) - m = HTTP_WKSIDX_PUT; - else if (!strcasecmp(argptr, "TRACE")) - m = HTTP_WKSIDX_TRACE; - else if (!strcasecmp(argptr, "PUSH")) - m = HTTP_WKSIDX_PUSH; - else { - Debug("url_rewrite", "[validate_filter_args] Unknown method value %s", argptr); - snprintf(errStrBuf, errStrBufSize, "Unknown method \"%s\"", argptr); - errStrBuf[errStrBufSize - 1] = 0; - if (new_rule_flg) { - delete rule; - *rule_pp = NULL; - } - return (const char *) errStrBuf; - } - for (j = 0; j < rule->method_cnt; j++) { - if (rule->method_array[j] == m) { - m = 0; - break; /* we already have it in the list */ - } - } - if ((j = m) != 0) { - j = j - HTTP_WKSIDX_CONNECT; // get method index - if (j<0 || j>= ACL_FILTER_MAX_METHODS) { - Debug("url_rewrite", "[validate_filter_args] Incorrect method index! Method sequence in HTTP.cc is broken"); - snprintf(errStrBuf, errStrBufSize, "Incorrect method index %d", j); - errStrBuf[errStrBufSize - 1] = 0; - if (new_rule_flg) { - delete rule; - *rule_pp = NULL; - } - return (const char *) errStrBuf; - } - rule->method_idx[j] = m; - rule->method_array[rule->method_cnt++] = m; - rule->method_valid = 1; - } - } else if (ul & REMAP_OPTFLG_SRC_IP) { /* "src_ip=" option */ - if (rule->src_ip_cnt >= ACL_FILTER_MAX_SRC_IP) { - Debug("url_rewrite", "[validate_filter_args] Too many \"src_ip=\" filters"); - snprintf(errStrBuf, errStrBufSize, "Defined more than %d \"src_ip=\" filters!", ACL_FILTER_MAX_SRC_IP); - errStrBuf[errStrBufSize - 1] = 0; - if (new_rule_flg) { - delete rule; - *rule_pp = NULL; - } - return (const char *) errStrBuf; - } - ipi = &rule->src_ip_array[rule->src_ip_cnt]; - if (ul & REMAP_OPTFLG_INVERT) - ipi->invert = true; - ink_strlcpy(tmpbuf, argptr, sizeof(tmpbuf)); - // important! use copy of argument - if (ExtractIpRange(tmpbuf, &ipi->start.sa, &ipi->end.sa) != NULL) { - Debug("url_rewrite", "[validate_filter_args] Unable to parse IP value in %s", argv[i]); - snprintf(errStrBuf, errStrBufSize, "Unable to parse IP value in %s", argv[i]); - errStrBuf[errStrBufSize - 1] = 0; - if (new_rule_flg) { - delete rule; - *rule_pp = NULL; - } - return (const char*) errStrBuf; - } - for (j = 0; j < rule->src_ip_cnt; j++) { - if (rule->src_ip_array[j].start == ipi->start && rule->src_ip_array[j].end == ipi->end) { - ipi->reset(); - ipi = NULL; - break; /* we have the same src_ip in the list */ - } - } - if (ipi) { - rule->src_ip_cnt++; - rule->src_ip_valid = 1; - } - } else if (ul & REMAP_OPTFLG_ACTION) { /* "action=" option */ - if (is_inkeylist(argptr, "0", "off", "deny", "disable", NULL)) { - rule->allow_flag = 0; - } else if (is_inkeylist(argptr, "1", "on", "allow", "enable", NULL)) { - rule->allow_flag = 1; - } else { - Debug("url_rewrite", "[validate_filter_args] Unknown argument \"%s\"", argv[i]); - snprintf(errStrBuf, errStrBufSize, "Unknown argument \"%s\"", argv[i]); - errStrBuf[errStrBufSize - 1] = 0; - if (new_rule_flg) { - delete rule; - *rule_pp = NULL; - } - return (const char *) errStrBuf; - } - } - } - - if (is_debug_tag_set("url_rewrite")) - rule->print(); - - return NULL; /* success */ -} - -static const char * -parse_define_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize) -{ - bool flg; - acl_filter_rule * rp; - acl_filter_rule ** rpp; - const char * cstr = NULL; - - if (bti->paramc < 2) { - snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive); - Debug("url_rewrite", "[parse_directive] %s", errbuf); - return (const char *) errbuf; - } - if (bti->argc < 1) { - snprintf(errbuf, errbufsize, "Directive \"%s\" must have filter parameter(s)", directive); - Debug("url_rewrite", "[parse_directive] %s", errbuf); - return (const char *) errbuf; - } - - flg = ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) ? true : false; - // coverity[alloc_arg] - if ((cstr = validate_filter_args(&rp, bti->argv, bti->argc, errbuf, errbufsize)) == NULL && rp) { - if (flg) { // new filter - add to list - Debug("url_rewrite", "[parse_directive] new rule \"%s\" was created", bti->paramv[1]); - for (rpp = &bti->rules_list; *rpp; rpp = &((*rpp)->next)); - (*rpp = rp)->name(bti->paramv[1]); - } - Debug("url_rewrite", "[parse_directive] %d argument(s) were added to rule \"%s\"", bti->argc, bti->paramv[1]); - rp->add_argv(bti->argc, bti->argv); // store string arguments for future processing - } - - return cstr; -} - -static const char * -parse_delete_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize) -{ - if (bti->paramc < 2) { - snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive); - Debug("url_rewrite", "[parse_directive] %s", errbuf); - return (const char *) errbuf; - } - - acl_filter_rule::delete_byname(&bti->rules_list, (const char *) bti->paramv[1]); - return NULL; -} - -static const char * -parse_activate_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize) -{ - acl_filter_rule * rp; - - if (bti->paramc < 2) { - snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive); - Debug("url_rewrite", "[parse_directive] %s", errbuf); - return (const char *) errbuf; - } - - if ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) { - snprintf(errbuf, errbufsize, "Undefined filter \"%s\" in directive \"%s\"", bti->paramv[1], directive); - Debug("url_rewrite", "[parse_directive] %s", errbuf); - return (const char *) errbuf; - } - - acl_filter_rule::requeue_in_active_list(&bti->rules_list, rp); - return NULL; -} - -static const char * -parse_deactivate_directive(const char * directive, BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize) -{ - acl_filter_rule * rp; - - if (bti->paramc < 2) { - snprintf(errbuf, errbufsize, "Directive \"%s\" must have name argument", directive); - Debug("url_rewrite", "[parse_directive] %s", errbuf); - return (const char *) errbuf; - } - - if ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) { - snprintf(errbuf, errbufsize, "Undefined filter \"%s\" in directive \"%s\"", bti->paramv[1], directive); - Debug("url_rewrite", "[parse_directive] %s", errbuf); - return (const char *) errbuf; - } - - acl_filter_rule::requeue_in_passive_list(&bti->rules_list, rp); - return NULL; -} - -struct remap_directive -{ - const char * name; - const char * (*parser)(const char *, BUILD_TABLE_INFO *, char *, size_t); -}; - -static const remap_directive directives[] = { - - { ".definefilter", parse_define_directive}, - { ".deffilter", parse_define_directive}, - { ".defflt", parse_define_directive}, - - { ".deletefilter", parse_delete_directive}, - { ".delfilter", parse_delete_directive}, - { ".delflt", parse_delete_directive}, - - { ".usefilter", parse_activate_directive}, - { ".activefilter", parse_activate_directive}, - { ".activatefilter", parse_activate_directive}, - - { ".unusefilter", parse_deactivate_directive}, - { ".deactivatefilter", parse_deactivate_directive}, - { ".unactivefilter", parse_deactivate_directive}, - { ".deuseflt", parse_deactivate_directive}, - { ".unuseflt", parse_deactivate_directive}, - -}; - -static const char * -parse_directive(BUILD_TABLE_INFO *bti, char * errbuf, size_t errbufsize) -{ - const char * directive = NULL; - - // Check arguments - if (unlikely(!bti || !errbuf || errbufsize <= 0 || !bti->paramc || (directive = bti->paramv[0]) == NULL)) { - Debug("url_rewrite", "[parse_directive] Invalid argument(s)"); - return "Invalid argument(s)"; - } - - for (unsigned i = 0; i < countof(directives); ++i) { - if (strcmp(directive, directives[i].name) == 0) { - return directives[i].parser(directive, bti, errbuf, errbufsize); - } - } - - snprintf(errbuf, errbufsize, "Unknown directive \"%s\"", directive); - Debug("url_rewrite", "[parse_directive] %s", errbuf); - return (const char *) errbuf; -} - -static const char * process_filter_opt(url_mapping *mp, BUILD_TABLE_INFO *bti, char *errStrBuf, int errStrBufSize) { acl_filter_rule *rp, **rpp; @@ -552,14 +112,14 @@ process_filter_opt(url_mapping *mp, BUILD_TABLE_INFO *bti, char *errStrBuf, int Debug("url_rewrite", "[process_filter_opt] Add active main filter \"%s\" (argc=%d)", rp->filter_name ? rp->filter_name : "<NULL>", rp->argc); for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next)); - if ((errStr = validate_filter_args(rpp, rp->argv, rp->argc, errStrBuf, errStrBufSize)) != NULL) + if ((errStr = remap_validate_filter_args(rpp, rp->argv, rp->argc, errStrBuf, errStrBufSize)) != NULL) break; } } if (!errStr && (bti->remap_optflg & REMAP_OPTFLG_ALL_FILTERS) != 0) { Debug("url_rewrite", "[process_filter_opt] Add per remap filter"); for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next)); - errStr = validate_filter_args(rpp, bti->argv, bti->argc, errStrBuf, errStrBufSize); + errStr = remap_validate_filter_args(rpp, bti->argv, bti->argc, errStrBuf, errStrBufSize); } return errStr; } @@ -1293,11 +853,11 @@ UrlRewrite::_parseRemapConfigFile(const char * config_file_path, BUILD_TABLE_INF goto MAP_ERROR; } // just check all major flags/optional arguments - bti->remap_optflg = check_remap_option(bti->argv, bti->argc); + bti->remap_optflg = remap_check_option(bti->argv, bti->argc); // Check directive keywords (starting from '.') if (bti->paramv[0][0] == '.') { - if ((errStr = parse_directive(bti, errStrBuf, sizeof(errStrBuf))) != NULL) { + if ((errStr = remap_parse_directive(bti, errStrBuf, sizeof(errStrBuf))) != NULL) { snprintf(errBuf, sizeof(errBuf) - 1, "%s Error on line %d - %s", modulePrefix, cln + 1, errStr); errStr = errStrBuf; goto MAP_ERROR; @@ -1348,7 +908,7 @@ UrlRewrite::_parseRemapConfigFile(const char * config_file_path, BUILD_TABLE_INF if ((bti->remap_optflg & REMAP_OPTFLG_MAP_ID) != 0) { int idx = 0; char *c; - int ret = check_remap_option(bti->argv, bti->argc, REMAP_OPTFLG_MAP_ID, &idx); + int ret = remap_check_option(bti->argv, bti->argc, REMAP_OPTFLG_MAP_ID, &idx); if (ret & REMAP_OPTFLG_MAP_ID) { c = strchr(bti->argv[idx], (int) '='); new_mapping->map_id = (unsigned int) atoi(++c); @@ -1554,7 +1114,7 @@ UrlRewrite::_parseRemapConfigFile(const char * config_file_path, BUILD_TABLE_INF // Check "remap" plugin options and load .so object if ((bti->remap_optflg & REMAP_OPTFLG_PLUGIN) != 0 && (maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER || maptype == FORWARD_MAP_WITH_RECV_PORT)) { - if ((check_remap_option(bti->argv, bti->argc, REMAP_OPTFLG_PLUGIN, &tok_count) & REMAP_OPTFLG_PLUGIN) != 0) { + if ((remap_check_option(bti->argv, bti->argc, REMAP_OPTFLG_PLUGIN, &tok_count) & REMAP_OPTFLG_PLUGIN) != 0) { int plugin_found_at = 0; int jump_to_argc = 0; @@ -1691,11 +1251,11 @@ UrlRewrite::load_remap_plugin(char *argv[], int argc, url_mapping *mp, char *err i++; } argv = new_argv; - if (!check_remap_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx)) { + if (!remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx)) { return -1; } } else { - if (unlikely(!mp || (check_remap_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx) & REMAP_OPTFLG_PLUGIN) == 0)) { + if (unlikely(!mp || (remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx) & REMAP_OPTFLG_PLUGIN) == 0)) { snprintf(errbuf, errbufsize, "Can't find remap plugin keyword or \"url_mapping\" is NULL"); return -1; /* incorrect input data - almost impossible case */ } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4be46fb9/proxy/http/remap/UrlRewrite.h ---------------------------------------------------------------------- diff --git a/proxy/http/remap/UrlRewrite.h b/proxy/http/remap/UrlRewrite.h index f1810f4..66f0799 100644 --- a/proxy/http/remap/UrlRewrite.h +++ b/proxy/http/remap/UrlRewrite.h @@ -37,8 +37,6 @@ #define URL_REMAP_FILTER_REFERER 0x00000001 /* enable "referer" header validation */ #define URL_REMAP_FILTER_REDIRECT_FMT 0x00010000 /* enable redirect URL formatting */ -#define BUILD_TABLE_MAX_ARGS 2048 - struct BUILD_TABLE_INFO ; /**
