[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()
This commit is contained in:
Krzysztof Piotr Oledzki 2007-11-03 23:41:58 +01:00 committed by Willy Tarreau
parent 2ee30416af
commit 6eb730ded9
3 changed files with 77 additions and 43 deletions

View File

@ -32,8 +32,10 @@ void soft_stop(void);
void pause_proxy(struct proxy *p); void pause_proxy(struct proxy *p);
void pause_proxies(void); void pause_proxies(void);
void listen_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 */ #endif /* _PROTO_PROXY_H */

View File

@ -539,9 +539,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
if (!strcmp(curproxy->id, args[1]) && if (!strcmp(curproxy->id, args[1]) &&
(rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) && (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))) { (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", Warning("Parsing [%s:%d]: duplicated proxy '%s' with conflicting capabilities: %s/%s!\n",
file, args[1], curproxy->cap, rc); file, linenum, args[1], proxy_type_str(curproxy), args[0]);
return -1;
} }
} }
@ -2529,21 +2528,14 @@ int readcfgfile(const char *file)
if (curproxy->defbe.name) { if (curproxy->defbe.name) {
struct proxy *target; struct proxy *target;
for (target = proxy; target != NULL; target = target->next) { target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
if ((target->cap & PR_CAP_BE) && !strcmp(target->id, curproxy->defbe.name)) if (!target) {
break; Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
} curproxy->id, curproxy->defbe.name);
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);
cfgerr++; cfgerr++;
} else if (target == curproxy) { } else if (target == curproxy) {
Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name); Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
cfgerr++; curproxy->id, curproxy->defbe.name);
} 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++;
} else { } else {
free(curproxy->defbe.name); free(curproxy->defbe.name);
curproxy->defbe.be = target; curproxy->defbe.be = target;
@ -2554,24 +2546,20 @@ int readcfgfile(const char *file)
if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) { if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
/* map jump target for ACT_SETBE in req_rep chain */ /* map jump target for ACT_SETBE in req_rep chain */
struct hdr_exp *exp; struct hdr_exp *exp;
struct proxy *target;
for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) { for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
struct proxy *target;
if (exp->action != ACT_SETBE) if (exp->action != ACT_SETBE)
continue; continue;
for (target = proxy; target != NULL; target = target->next) {
if ((target->cap & PR_CAP_BE) && !strcmp(target->id, exp->replace)) target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
break; if (!target) {
} Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
if (target == NULL) { curproxy->id, exp->replace);
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);
cfgerr++; cfgerr++;
} else if (target == curproxy) { } else if (target == curproxy) {
Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace); Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
cfgerr++; curproxy->id, exp->replace);
} 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);
cfgerr++; cfgerr++;
} else { } else {
free((void *)exp->replace); free((void *)exp->replace);
@ -2582,24 +2570,17 @@ int readcfgfile(const char *file)
/* find the target proxy for 'use_backend' rules */ /* find the target proxy for 'use_backend' rules */
list_for_each_entry(rule, &curproxy->switching_rules, list) { list_for_each_entry(rule, &curproxy->switching_rules, list) {
/* map jump target for ACT_SETBE in req_rep chain */
struct proxy *target; struct proxy *target;
for (target = proxy; target != NULL; target = target->next) { target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
if ((target->cap & PR_CAP_BE) && !strcmp(target->id, rule->be.name))
break;
}
if (target == NULL) { if (!target) {
Alert("parsing %s: proxy '%s' with backend capability in HTTP %s '%s' was not found!\n", Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
file, rule->be.name, proxy_type_str(curproxy), curproxy->id); curproxy->id, rule->be.name);
cfgerr++; cfgerr++;
} else if (target == curproxy) { } else if (target == curproxy) {
Alert("parsing %s : loop detected for backend %s !\n", file, rule->be.name); Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
cfgerr++; curproxy->id, rule->be.name);
} 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);
cfgerr++; cfgerr++;
} else { } else {
free((void *)rule->be.name); free((void *)rule->be.name);

View File

@ -55,6 +55,57 @@ const char *proxy_type_str(struct proxy *proxy)
return "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, * This function creates all proxy sockets. It should be done very early,