MINOR: config: Support per-proxy and per-server post-check functions callbacks

Most of times, when a keyword is added in proxy section or on the server line,
we need to have a post-parser callback to check the config validity for the
proxy or the server which uses this keyword.

It is possible to register a global post-parser callback. But all these
callbacks need to loop on the proxies and servers to do their job. It is neither
handy nor efficient. Instead, it is now possible to register per-proxy and
per-server post-check callbacks.
diff --git a/include/types/global.h b/include/types/global.h
index 12f888c..bd08db1 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -288,6 +288,8 @@
 void deinit(void);
 void hap_register_build_opts(const char *str, int must_free);
 void hap_register_post_check(int (*fct)());
+void hap_register_post_proxy_check(int (*fct)(struct proxy *));
+void hap_register_post_server_check(int (*fct)(struct server *));
 void hap_register_post_deinit(void (*fct)());
 void hap_register_proxy_deinit(void (*fct)(struct proxy *));
 void hap_register_server_deinit(void (*fct)(struct server *));
@@ -308,6 +310,14 @@
 #define REGISTER_POST_CHECK(fct) \
 	INITCALL1(STG_REGISTER, hap_register_post_check, (fct))
 
+/* simplified way to declare a post-proxy-check callback in a file */
+#define REGISTER_POST_PROXY_CHECK(fct) \
+	INITCALL1(STG_REGISTER, hap_register_post_proxy_check, (fct))
+
+/* simplified way to declare a post-server-check callback in a file */
+#define REGISTER_POST_SERVER_CHECK(fct) \
+	INITCALL1(STG_REGISTER, hap_register_post_server_check, (fct))
+
 /* simplified way to declare a post-deinit callback in a file */
 #define REGISTER_POST_DEINIT(fct) \
 	INITCALL1(STG_REGISTER, hap_register_post_deinit, (fct))
diff --git a/src/haproxy.c b/src/haproxy.c
index 7b82139..cc3da92 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -268,6 +268,28 @@
 	int (*fct)();
 };
 
+/* These functions are called for each proxy just after the config validity
+ * check. The functions must return 0 on success, or a combination of ERR_*
+ * flags (ERR_WARN, ERR_ABORT, ERR_FATAL, ...). The 2 latter cause and immediate
+ * exit, so the function must have emitted any useful error.
+ */
+struct list post_proxy_check_list = LIST_HEAD_INIT(post_proxy_check_list);
+struct post_proxy_check_fct {
+	struct list list;
+	int (*fct)(struct proxy *);
+};
+
+/* These functions are called for each server just after the config validity
+ * check. The functions must return 0 on success, or a combination of ERR_*
+ * flags (ERR_WARN, ERR_ABORT, ERR_FATAL, ...). The 2 latter cause and immediate
+ * exit, so the function must have emitted any useful error.
+ */
+struct list post_server_check_list = LIST_HEAD_INIT(post_server_check_list);
+struct post_server_check_fct {
+	struct list list;
+	int (*fct)(struct server *);
+};
+
 /* These functions are called for each thread just after the thread creation
  * and before running the init functions. They should be used to do per-thread
  * (re-)allocations that are needed by subsequent functoins. They must return 0
@@ -377,6 +399,38 @@
 	LIST_ADDQ(&post_check_list, &b->list);
 }
 
+/* used to register some initialization functions to call for each proxy after
+ * the checks.
+ */
+void hap_register_post_proxy_check(int (*fct)(struct proxy *))
+{
+	struct post_proxy_check_fct *b;
+
+	b = calloc(1, sizeof(*b));
+	if (!b) {
+		fprintf(stderr, "out of memory\n");
+		exit(1);
+	}
+	b->fct = fct;
+	LIST_ADDQ(&post_proxy_check_list, &b->list);
+}
+
+/* used to register some initialization functions to call for each server after
+ * the checks.
+ */
+void hap_register_post_server_check(int (*fct)(struct server *))
+{
+	struct post_server_check_fct *b;
+
+	b = calloc(1, sizeof(*b));
+	if (!b) {
+		fprintf(stderr, "out of memory\n");
+		exit(1);
+	}
+	b->fct = fct;
+	LIST_ADDQ(&post_server_check_list, &b->list);
+}
+
 /* used to register some de-initialization functions to call after everything
  * has stopped.
  */
@@ -1799,6 +1853,18 @@
 	}
 
 	err_code |= check_config_validity();
+	for (px = proxies_list; px; px = px->next) {
+		struct server *srv;
+		struct post_proxy_check_fct *ppcf;
+		struct post_server_check_fct *pscf;
+
+		list_for_each_entry(pscf, &post_server_check_list, list) {
+			for (srv = px->srv; srv; srv = srv->next)
+				err_code |= pscf->fct(srv);
+		}
+		list_for_each_entry(ppcf, &post_proxy_check_list, list)
+			err_code |= ppcf->fct(px);
+	}
 	if (err_code & (ERR_ABORT|ERR_FATAL)) {
 		ha_alert("Fatal errors found in configuration.\n");
 		exit(1);