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);
|
int readcfgfile(const char *file);
|
||||||
void cfg_register_keywords(struct cfg_kw_list *kwl);
|
void cfg_register_keywords(struct cfg_kw_list *kwl);
|
||||||
void cfg_unregister_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 */
|
#endif /* _COMMON_CFGPARSE_H */
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ const char *proxy_cap_str(int cap);
|
|||||||
const char *proxy_mode_str(int mode);
|
const char *proxy_mode_str(int mode);
|
||||||
struct proxy *findproxy(const char *name, int mode, int cap);
|
struct proxy *findproxy(const char *name, int mode, int cap);
|
||||||
struct server *findserver(const struct proxy *px, const char *name);
|
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
|
* 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));
|
memset(&defproxy, 0, sizeof(defproxy));
|
||||||
defproxy.mode = PR_MODE_TCP;
|
defproxy.mode = PR_MODE_TCP;
|
||||||
@ -3163,17 +3163,11 @@ int readcfgfile(const char *file)
|
|||||||
char thisline[LINESIZE];
|
char thisline[LINESIZE];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int linenum = 0;
|
int linenum = 0;
|
||||||
int cfgerr = 0;
|
|
||||||
int confsect = CFG_NONE;
|
int confsect = CFG_NONE;
|
||||||
|
|
||||||
struct proxy *curproxy = NULL;
|
|
||||||
struct server *newsrv = NULL;
|
|
||||||
|
|
||||||
if ((f=fopen(file,"r")) == NULL)
|
if ((f=fopen(file,"r")) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
init_default_instance();
|
|
||||||
|
|
||||||
while (fgets(thisline, sizeof(thisline), f) != NULL) {
|
while (fgets(thisline, sizeof(thisline), f) != NULL) {
|
||||||
int arg, inv = 0 ;
|
int arg, inv = 0 ;
|
||||||
char *end;
|
char *end;
|
||||||
@ -3315,6 +3309,18 @@ int readcfgfile(const char *file)
|
|||||||
free(cursection);
|
free(cursection);
|
||||||
cursection = NULL;
|
cursection = NULL;
|
||||||
fclose(f);
|
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.
|
* Now, check for the integrity of all that we have collected.
|
||||||
@ -3337,8 +3343,7 @@ int readcfgfile(const char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((curproxy = proxy) == NULL) {
|
if ((curproxy = proxy) == NULL) {
|
||||||
Alert("parsing %s : no <listen> line. Nothing to do !\n",
|
Alert("config : no <listen> line. Nothing to do !\n");
|
||||||
file);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3355,54 +3360,54 @@ int readcfgfile(const char *file)
|
|||||||
|
|
||||||
switch (curproxy->mode) {
|
switch (curproxy->mode) {
|
||||||
case PR_MODE_HEALTH:
|
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)) {
|
if (!(curproxy->cap & PR_CAP_FE)) {
|
||||||
Alert("parsing %s : %s '%s' cannot be in health mode as it has no frontend capability.\n",
|
Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curproxy->srv != NULL)
|
if (curproxy->srv != NULL)
|
||||||
Warning("parsing %s : servers will be ignored for %s '%s'.\n",
|
Warning("config : servers will be ignored for %s '%s'.\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PR_MODE_TCP:
|
case PR_MODE_TCP:
|
||||||
cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
|
cfgerr += proxy_cfg_ensure_no_http(curproxy);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PR_MODE_HTTP:
|
case PR_MODE_HTTP:
|
||||||
if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
|
if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
|
||||||
Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
|
Alert("config : HTTP proxy %s has a cookie but no server list !\n",
|
||||||
file, curproxy->id);
|
curproxy->id);
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
|
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",
|
Alert("config : %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);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
|
if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
|
||||||
if (curproxy->lbprm.algo & BE_LB_ALGO) {
|
if (curproxy->lbprm.algo & BE_LB_ALGO) {
|
||||||
if (curproxy->options & PR_O_TRANSP) {
|
if (curproxy->options & PR_O_TRANSP) {
|
||||||
Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
|
Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
}
|
}
|
||||||
#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
|
#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
|
||||||
else if (curproxy->srv == NULL) {
|
else if (curproxy->srv == NULL) {
|
||||||
Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
|
Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
|
else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
|
||||||
Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
|
Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
|
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)) {
|
if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
|
||||||
curproxy->options &= ~PR_O_DISABLE404;
|
curproxy->options &= ~PR_O_DISABLE404;
|
||||||
Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
|
Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
|
||||||
file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
|
"disable-on-404", proxy_type_str(curproxy), curproxy->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if a default backend was specified, let's find it */
|
/* 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_FE) && !curproxy->timeout.client) ||
|
||||||
((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
|
((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
|
||||||
(!curproxy->timeout.connect || !curproxy->timeout.server)))) {
|
(!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"
|
" | While not properly invalid, you will certainly encounter various problems\n"
|
||||||
" | with such a configuration. To fix this, please ensure that all following\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",
|
" | 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.
|
/* Historically, the tarpit and queue timeouts were inherited from contimeout.
|
||||||
@ -3604,8 +3609,8 @@ int readcfgfile(const char *file)
|
|||||||
newsrv = curproxy->srv;
|
newsrv = curproxy->srv;
|
||||||
while (newsrv != NULL) {
|
while (newsrv != NULL) {
|
||||||
if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
|
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",
|
Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
|
||||||
file, linenum, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
newsrv = newsrv->next;
|
newsrv = newsrv->next;
|
||||||
@ -3628,8 +3633,8 @@ int readcfgfile(const char *file)
|
|||||||
/* minconn was not specified, so we set it to maxconn */
|
/* minconn was not specified, so we set it to maxconn */
|
||||||
newsrv->minconn = newsrv->maxconn;
|
newsrv->minconn = newsrv->maxconn;
|
||||||
} else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
|
} 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",
|
Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
|
||||||
file, linenum, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3651,8 +3656,8 @@ int readcfgfile(const char *file)
|
|||||||
if (pname) {
|
if (pname) {
|
||||||
px = findproxy(pname, curproxy->mode, PR_CAP_BE);
|
px = findproxy(pname, curproxy->mode, PR_CAP_BE);
|
||||||
if (!px) {
|
if (!px) {
|
||||||
Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
|
Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id,
|
proxy_type_str(curproxy), curproxy->id,
|
||||||
newsrv->id, pname);
|
newsrv->id, pname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -3661,25 +3666,25 @@ int readcfgfile(const char *file)
|
|||||||
|
|
||||||
srv = findserver(px, sname);
|
srv = findserver(px, sname);
|
||||||
if (!srv) {
|
if (!srv) {
|
||||||
Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
|
Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id,
|
proxy_type_str(curproxy), curproxy->id,
|
||||||
newsrv->id, sname);
|
newsrv->id, sname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(srv->state & SRV_CHECKED)) {
|
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",
|
"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);
|
newsrv->id, px->id, srv->id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curproxy != px &&
|
if (curproxy != px &&
|
||||||
(curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
|
(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",
|
"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);
|
newsrv->id, px->id, srv->id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -3720,7 +3725,7 @@ int readcfgfile(const char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cfgerr > 0) {
|
if (cfgerr > 0) {
|
||||||
Alert("Errors found in configuration file, aborting.\n");
|
Alert("Errors found in configuration, aborting.\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3740,13 +3745,8 @@ int readcfgfile(const char *file)
|
|||||||
global.last_checks |= cfg_opts2[optnum].checks;
|
global.last_checks |= cfg_opts2[optnum].checks;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(cursection);
|
|
||||||
cursection = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
free(cursection);
|
|
||||||
cursection = NULL;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,19 +529,27 @@ void init(int argc, char **argv)
|
|||||||
|
|
||||||
have_appsession = 0;
|
have_appsession = 0;
|
||||||
global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
|
global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
|
||||||
|
|
||||||
|
init_default_instance();
|
||||||
|
|
||||||
if (readcfgfile(cfg_cfgfile) < 0) {
|
if (readcfgfile(cfg_cfgfile) < 0) {
|
||||||
Alert("Error reading configuration file : %s\n", cfg_cfgfile);
|
Alert("Error reading configuration file : %s\n", cfg_cfgfile);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_appsession)
|
if (check_config_validity() < 0) {
|
||||||
appsession_init();
|
Alert("Errors found in configuration.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (global.mode & MODE_CHECK) {
|
if (global.mode & MODE_CHECK) {
|
||||||
qfprintf(stdout, "Configuration file is valid : %s\n", cfg_cfgfile);
|
qfprintf(stdout, "Configuration file is valid\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (have_appsession)
|
||||||
|
appsession_init();
|
||||||
|
|
||||||
if (start_checks() < 0)
|
if (start_checks() < 0)
|
||||||
exit(1);
|
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.
|
* 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.
|
* 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) {
|
if (curproxy->cookie_name != NULL) {
|
||||||
Warning("parsing %s : cookie will be ignored for %s '%s' (needs 'mode http').\n",
|
Warning("config : cookie will be ignored for %s '%s' (needs 'mode http').\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
}
|
}
|
||||||
if (curproxy->rsp_exp != NULL) {
|
if (curproxy->rsp_exp != NULL) {
|
||||||
Warning("parsing %s : server regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
|
Warning("config : server regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
}
|
}
|
||||||
if (curproxy->req_exp != NULL) {
|
if (curproxy->req_exp != NULL) {
|
||||||
Warning("parsing %s : client regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
|
Warning("config : client regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
}
|
}
|
||||||
if (curproxy->monitor_uri != NULL) {
|
if (curproxy->monitor_uri != NULL) {
|
||||||
Warning("parsing %s : monitor-uri will be ignored for %s '%s' (needs 'mode http').\n",
|
Warning("config : monitor-uri will be ignored for %s '%s' (needs 'mode http').\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
}
|
}
|
||||||
if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
|
if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
|
||||||
curproxy->lbprm.algo &= ~BE_LB_ALGO;
|
curproxy->lbprm.algo &= ~BE_LB_ALGO;
|
||||||
curproxy->lbprm.algo |= BE_LB_ALGO_RR;
|
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",
|
Warning("config : Layer 7 hash not possible for %s '%s' (needs 'mode http'). Falling back to round robin.\n",
|
||||||
file, proxy_type_str(curproxy), curproxy->id);
|
proxy_type_str(curproxy), curproxy->id);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user