mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-14 11:06:56 +02:00
[MEDIUM] config: split parser and checker in two functions
This is a first step towards support of multiple configuration files.
Now readcfgfile() only reads a file in memory and performs very minimal
parsing. The checks are performed afterwards.
(cherry picked from commit 915e1ebe63
)
This commit is contained in:
parent
e7345f355d
commit
b2bec3ad3d
@ -64,6 +64,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv);
|
||||
int readcfgfile(const char *file);
|
||||
void cfg_register_keywords(struct cfg_kw_list *kwl);
|
||||
void cfg_unregister_keywords(struct cfg_kw_list *kwl);
|
||||
void init_default_instance();
|
||||
int check_config_validity();
|
||||
|
||||
#endif /* _COMMON_CFGPARSE_H */
|
||||
|
||||
|
@ -40,7 +40,7 @@ const char *proxy_cap_str(int cap);
|
||||
const char *proxy_mode_str(int mode);
|
||||
struct proxy *findproxy(const char *name, int mode, int cap);
|
||||
struct server *findserver(const struct proxy *px, const char *name);
|
||||
int proxy_cfg_ensure_no_http(struct proxy *curproxy, const char *file);
|
||||
int proxy_cfg_ensure_no_http(struct proxy *curproxy);
|
||||
|
||||
/*
|
||||
* This function returns a string containing the type of the proxy in a format
|
||||
|
@ -661,7 +661,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int inv)
|
||||
}
|
||||
|
||||
|
||||
static void init_default_instance()
|
||||
void init_default_instance()
|
||||
{
|
||||
memset(&defproxy, 0, sizeof(defproxy));
|
||||
defproxy.mode = PR_MODE_TCP;
|
||||
@ -3163,17 +3163,11 @@ int readcfgfile(const char *file)
|
||||
char thisline[LINESIZE];
|
||||
FILE *f;
|
||||
int linenum = 0;
|
||||
int cfgerr = 0;
|
||||
int confsect = CFG_NONE;
|
||||
|
||||
struct proxy *curproxy = NULL;
|
||||
struct server *newsrv = NULL;
|
||||
|
||||
if ((f=fopen(file,"r")) == NULL)
|
||||
return -1;
|
||||
|
||||
init_default_instance();
|
||||
|
||||
while (fgets(thisline, sizeof(thisline), f) != NULL) {
|
||||
int arg, inv = 0 ;
|
||||
char *end;
|
||||
@ -3315,6 +3309,18 @@ int readcfgfile(const char *file)
|
||||
free(cursection);
|
||||
cursection = NULL;
|
||||
fclose(f);
|
||||
return 0;
|
||||
err:
|
||||
free(cursection);
|
||||
cursection = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int check_config_validity()
|
||||
{
|
||||
int cfgerr = 0;
|
||||
struct proxy *curproxy = NULL;
|
||||
struct server *newsrv = NULL;
|
||||
|
||||
/*
|
||||
* Now, check for the integrity of all that we have collected.
|
||||
@ -3337,8 +3343,7 @@ int readcfgfile(const char *file)
|
||||
}
|
||||
|
||||
if ((curproxy = proxy) == NULL) {
|
||||
Alert("parsing %s : no <listen> line. Nothing to do !\n",
|
||||
file);
|
||||
Alert("config : no <listen> line. Nothing to do !\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -3355,54 +3360,54 @@ int readcfgfile(const char *file)
|
||||
|
||||
switch (curproxy->mode) {
|
||||
case PR_MODE_HEALTH:
|
||||
cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
|
||||
cfgerr += proxy_cfg_ensure_no_http(curproxy);
|
||||
if (!(curproxy->cap & PR_CAP_FE)) {
|
||||
Alert("parsing %s : %s '%s' cannot be in health mode as it has no frontend capability.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
|
||||
if (curproxy->srv != NULL)
|
||||
Warning("parsing %s : servers will be ignored for %s '%s'.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Warning("config : servers will be ignored for %s '%s'.\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
break;
|
||||
|
||||
case PR_MODE_TCP:
|
||||
cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
|
||||
cfgerr += proxy_cfg_ensure_no_http(curproxy);
|
||||
break;
|
||||
|
||||
case PR_MODE_HTTP:
|
||||
if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
|
||||
Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
|
||||
file, curproxy->id);
|
||||
Alert("config : HTTP proxy %s has a cookie but no server list !\n",
|
||||
curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
|
||||
Alert("parsing %s : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
|
||||
if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
|
||||
if (curproxy->lbprm.algo & BE_LB_ALGO) {
|
||||
if (curproxy->options & PR_O_TRANSP) {
|
||||
Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
|
||||
else if (curproxy->srv == NULL) {
|
||||
Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
#endif
|
||||
else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
|
||||
Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
}
|
||||
}
|
||||
else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
|
||||
@ -3418,8 +3423,8 @@ int readcfgfile(const char *file)
|
||||
|
||||
if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
|
||||
curproxy->options &= ~PR_O_DISABLE404;
|
||||
Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
|
||||
file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
|
||||
Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
|
||||
"disable-on-404", proxy_type_str(curproxy), curproxy->id);
|
||||
}
|
||||
|
||||
/* if a default backend was specified, let's find it */
|
||||
@ -3505,11 +3510,11 @@ int readcfgfile(const char *file)
|
||||
(((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
|
||||
((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
|
||||
(!curproxy->timeout.connect || !curproxy->timeout.server)))) {
|
||||
Warning("parsing %s : missing timeouts for %s '%s'.\n"
|
||||
Warning("config : missing timeouts for %s '%s'.\n"
|
||||
" | While not properly invalid, you will certainly encounter various problems\n"
|
||||
" | with such a configuration. To fix this, please ensure that all following\n"
|
||||
" | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
}
|
||||
|
||||
/* Historically, the tarpit and queue timeouts were inherited from contimeout.
|
||||
@ -3604,8 +3609,8 @@ int readcfgfile(const char *file)
|
||||
newsrv = curproxy->srv;
|
||||
while (newsrv != NULL) {
|
||||
if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
|
||||
Alert("parsing [%s:%d] : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
|
||||
file, linenum, proxy_type_str(curproxy), curproxy->id);
|
||||
Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
goto err;
|
||||
}
|
||||
newsrv = newsrv->next;
|
||||
@ -3628,8 +3633,8 @@ int readcfgfile(const char *file)
|
||||
/* minconn was not specified, so we set it to maxconn */
|
||||
newsrv->minconn = newsrv->maxconn;
|
||||
} else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
|
||||
Alert("parsing [%s:%d] : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
|
||||
file, linenum, proxy_type_str(curproxy), curproxy->id);
|
||||
Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -3651,8 +3656,8 @@ int readcfgfile(const char *file)
|
||||
if (pname) {
|
||||
px = findproxy(pname, curproxy->mode, PR_CAP_BE);
|
||||
if (!px) {
|
||||
Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id,
|
||||
Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
|
||||
proxy_type_str(curproxy), curproxy->id,
|
||||
newsrv->id, pname);
|
||||
return -1;
|
||||
}
|
||||
@ -3661,25 +3666,25 @@ int readcfgfile(const char *file)
|
||||
|
||||
srv = findserver(px, sname);
|
||||
if (!srv) {
|
||||
Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id,
|
||||
Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
|
||||
proxy_type_str(curproxy), curproxy->id,
|
||||
newsrv->id, sname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(srv->state & SRV_CHECKED)) {
|
||||
Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
|
||||
Alert("config : %s '%s', server '%s': unable to use %s/%s for "
|
||||
"tracing as it does not have checks enabled.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id,
|
||||
proxy_type_str(curproxy), curproxy->id,
|
||||
newsrv->id, px->id, srv->id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (curproxy != px &&
|
||||
(curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
|
||||
Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
|
||||
Alert("config : %s '%s', server '%s': unable to use %s/%s for"
|
||||
"tracing: disable-on-404 option inconsistency.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id,
|
||||
proxy_type_str(curproxy), curproxy->id,
|
||||
newsrv->id, px->id, srv->id);
|
||||
return -1;
|
||||
}
|
||||
@ -3720,7 +3725,7 @@ int readcfgfile(const char *file)
|
||||
}
|
||||
|
||||
if (cfgerr > 0) {
|
||||
Alert("Errors found in configuration file, aborting.\n");
|
||||
Alert("Errors found in configuration, aborting.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -3740,13 +3745,8 @@ int readcfgfile(const char *file)
|
||||
global.last_checks |= cfg_opts2[optnum].checks;
|
||||
}
|
||||
|
||||
free(cursection);
|
||||
cursection = NULL;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free(cursection);
|
||||
cursection = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -529,19 +529,27 @@ void init(int argc, char **argv)
|
||||
|
||||
have_appsession = 0;
|
||||
global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
|
||||
|
||||
init_default_instance();
|
||||
|
||||
if (readcfgfile(cfg_cfgfile) < 0) {
|
||||
Alert("Error reading configuration file : %s\n", cfg_cfgfile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (have_appsession)
|
||||
appsession_init();
|
||||
if (check_config_validity() < 0) {
|
||||
Alert("Errors found in configuration.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (global.mode & MODE_CHECK) {
|
||||
qfprintf(stdout, "Configuration file is valid : %s\n", cfg_cfgfile);
|
||||
qfprintf(stdout, "Configuration file is valid\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (have_appsession)
|
||||
appsession_init();
|
||||
|
||||
if (start_checks() < 0)
|
||||
exit(1);
|
||||
|
||||
|
22
src/proxy.c
22
src/proxy.c
@ -303,29 +303,29 @@ struct server *findserver(const struct proxy *px, const char *name) {
|
||||
* at the end of the configuration parsing if the proxy is not in http mode.
|
||||
* The <file> argument is used to construct the error message.
|
||||
*/
|
||||
int proxy_cfg_ensure_no_http(struct proxy *curproxy, const char *file)
|
||||
int proxy_cfg_ensure_no_http(struct proxy *curproxy)
|
||||
{
|
||||
if (curproxy->cookie_name != NULL) {
|
||||
Warning("parsing %s : cookie will be ignored for %s '%s' (needs 'mode http').\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Warning("config : cookie will be ignored for %s '%s' (needs 'mode http').\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
}
|
||||
if (curproxy->rsp_exp != NULL) {
|
||||
Warning("parsing %s : server regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Warning("config : server regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
}
|
||||
if (curproxy->req_exp != NULL) {
|
||||
Warning("parsing %s : client regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Warning("config : client regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
}
|
||||
if (curproxy->monitor_uri != NULL) {
|
||||
Warning("parsing %s : monitor-uri will be ignored for %s '%s' (needs 'mode http').\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Warning("config : monitor-uri will be ignored for %s '%s' (needs 'mode http').\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
}
|
||||
if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
|
||||
curproxy->lbprm.algo &= ~BE_LB_ALGO;
|
||||
curproxy->lbprm.algo |= BE_LB_ALGO_RR;
|
||||
Warning("parsing %s : Layer 7 hash not possible for %s '%s' (needs 'mode http'). Falling back to round robin.\n",
|
||||
file, proxy_type_str(curproxy), curproxy->id);
|
||||
Warning("config : Layer 7 hash not possible for %s '%s' (needs 'mode http'). Falling back to round robin.\n",
|
||||
proxy_type_str(curproxy), curproxy->id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user