]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] Implement and use generic findproxy and relax duplicated proxy check
authorKrzysztof Piotr Oledzki <ole@ans.pl>
Sat, 3 Nov 2007 22:41:58 +0000 (23:41 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 4 Nov 2007 07:14:20 +0000 (08:14 +0100)
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()

include/proto/proxy.h
src/cfgparse.c
src/proxy.c

index 38d7325cc36db602ed9cc824812da1ec5e686b6d..839cce5812bbef63494f888c072a10b11e833f28 100644 (file)
@@ -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 */
 
index 5e6ce4ecd53bed52f8035e0ba0233e0297b03053..fc333bfbbfd8a1cf2408212538652cbea7c0c749 100644 (file)
@@ -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);
index 435a1e206b036d90dbd8ef384795258ec109b550..1f5481868f156f76c6006174ee67fb0d392608d4 100644 (file)
@@ -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,