From: Krzysztof Piotr Oledzki Date: Sat, 3 Nov 2007 22:41:58 +0000 (+0100) Subject: [MEDIUM] Implement and use generic findproxy and relax duplicated proxy check X-Git-Tag: v1.3.14~60 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6eb730ded961e264328bece700df0ebaa1aa2190;p=thirdparty%2Fhaproxy.git [MEDIUM] Implement and use generic findproxy and relax duplicated proxy check This patch: - adds proxy_mode_str() similar to proxy_type_str() - adds a generic findproxy function used with default_backend/setbe/use_backed - rewrite default_backend/senbe/use_backed to use introduced findproxy() - relaxes duplicated proxy check - changes capabilities displaying from "%X" to "%s" with a call to proxy_type_str() --- diff --git a/include/proto/proxy.h b/include/proto/proxy.h index 38d7325cc3..839cce5812 100644 --- a/include/proto/proxy.h +++ b/include/proto/proxy.h @@ -32,8 +32,10 @@ void soft_stop(void); void pause_proxy(struct proxy *p); void pause_proxies(void); void listen_proxies(void); -const char *proxy_type_str(struct proxy *proxy); +const char *proxy_type_str(struct proxy *proxy); +const char *proxy_mode_str(int mode); +struct proxy *findproxy(const char *name, int mode, int cap); #endif /* _PROTO_PROXY_H */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 5e6ce4ecd5..fc333bfbbf 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -539,9 +539,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args) if (!strcmp(curproxy->id, args[1]) && (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) && (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) { - Alert("parsing %s: duplicated proxy %s with conflicting capabilities: %X/%X!\n", - file, args[1], curproxy->cap, rc); - return -1; + Warning("Parsing [%s:%d]: duplicated proxy '%s' with conflicting capabilities: %s/%s!\n", + file, linenum, args[1], proxy_type_str(curproxy), args[0]); } } @@ -2529,21 +2528,14 @@ int readcfgfile(const char *file) if (curproxy->defbe.name) { struct proxy *target; - for (target = proxy; target != NULL; target = target->next) { - if ((target->cap & PR_CAP_BE) && !strcmp(target->id, curproxy->defbe.name)) - break; - } - if (target == NULL) { - Alert("parsing %s: default proxy '%s' with backend capability in HTTP %s '%s' was not found!\n", - file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id); + target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE); + if (!target) { + Alert("Proxy '%s': unable to find required default_backend: '%s'.\n", + curproxy->id, curproxy->defbe.name); cfgerr++; } else if (target == curproxy) { - Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name); - cfgerr++; - } else if (target->mode != curproxy->mode) { - Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n", - file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id); - cfgerr++; + Alert("Proxy '%s': loop detected for default_backend: '%s'.\n", + curproxy->id, curproxy->defbe.name); } else { free(curproxy->defbe.name); curproxy->defbe.be = target; @@ -2554,24 +2546,20 @@ int readcfgfile(const char *file) if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) { /* map jump target for ACT_SETBE in req_rep chain */ struct hdr_exp *exp; - struct proxy *target; for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) { + struct proxy *target; + if (exp->action != ACT_SETBE) continue; - for (target = proxy; target != NULL; target = target->next) { - if ((target->cap & PR_CAP_BE) && !strcmp(target->id, exp->replace)) - break; - } - if (target == NULL) { - Alert("parsing %s: proxy '%s' with backend capability in HTTP %s '%s' was not found!\n", - file, exp->replace, proxy_type_str(curproxy), curproxy->id); + + target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE); + if (!target) { + Alert("Proxy '%s': unable to find required setbe: '%s'.\n", + curproxy->id, exp->replace); cfgerr++; } else if (target == curproxy) { - Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace); - cfgerr++; - } else if (target->mode != PR_MODE_HTTP) { - Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n", - file, exp->replace, proxy_type_str(curproxy), curproxy->id); + Alert("Proxy '%s': loop detected for setbe: '%s'.\n", + curproxy->id, exp->replace); cfgerr++; } else { free((void *)exp->replace); @@ -2582,24 +2570,17 @@ int readcfgfile(const char *file) /* find the target proxy for 'use_backend' rules */ list_for_each_entry(rule, &curproxy->switching_rules, list) { - /* map jump target for ACT_SETBE in req_rep chain */ struct proxy *target; - for (target = proxy; target != NULL; target = target->next) { - if ((target->cap & PR_CAP_BE) && !strcmp(target->id, rule->be.name)) - break; - } + target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE); - if (target == NULL) { - Alert("parsing %s: proxy '%s' with backend capability in HTTP %s '%s' was not found!\n", - file, rule->be.name, proxy_type_str(curproxy), curproxy->id); + if (!target) { + Alert("Proxy '%s': unable to find required use_backend: '%s'.\n", + curproxy->id, rule->be.name); cfgerr++; } else if (target == curproxy) { - Alert("parsing %s : loop detected for backend %s !\n", file, rule->be.name); - cfgerr++; - } else if (target->mode != curproxy->mode) { - Alert("parsing %s : backend '%s' referenced in %s '%s' is of different mode !\n", - file, rule->be.name, proxy_type_str(curproxy), curproxy->id); + Alert("Proxy '%s': loop detected for use_backend: '%s'.\n", + curproxy->id, rule->be.name); cfgerr++; } else { free((void *)rule->be.name); diff --git a/src/proxy.c b/src/proxy.c index 435a1e206b..1f5481868f 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -55,6 +55,57 @@ const char *proxy_type_str(struct proxy *proxy) return "proxy"; } +/* + * This function returns a string containing the mode of the proxy in a format + * suitable for error messages. + */ + +const char *proxy_mode_str(int mode) { + + if (mode == PR_MODE_TCP) + return "tcp"; + else if (mode == PR_MODE_HTTP) + return "http"; + else if (mode == PR_MODE_HEALTH) + return "health"; + else + return "unknown"; +} + +/* + * This function finds a proxy with matching name, mode and with satisfying + * capabilities. It also checks if there are more matching proxies with + * requested name as this often leads into unexpected situations. + */ + +struct proxy *findproxy(const char *name, int mode, int cap) { + + struct proxy *curproxy, *target=NULL; + + for (curproxy = proxy; curproxy; curproxy = curproxy->next) { + if ((curproxy->cap & cap)!=cap || strcmp(curproxy->id, name)) + continue; + + if (curproxy->mode != mode) { + Alert("Unable to use proxy '%s' with wrong mode, required: %s, has: %s.\n", + name, proxy_mode_str(mode), proxy_mode_str(curproxy->mode)); + Alert("You may want to use 'mode %s'.\n", proxy_mode_str(mode)); + return NULL; + } + + if (!target) { + target = curproxy; + continue; + } + + Alert("Refusing to use duplicated proxy '%s' with conflicting capabilities: %s/%s!\n", + name, proxy_type_str(curproxy), proxy_type_str(target)); + + return NULL; + } + + return target; +} /* * This function creates all proxy sockets. It should be done very early,