From 196729eff89e6627b784236f2496c4528da80c16 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 31 May 2012 19:30:26 +0200 Subject: [PATCH] BUG/MINOR: fix option httplog validation with TCP frontends Option httplog needs to be checked only once the proxy has been validated, so that its final mode (tcp/http) can be used. Also we need to check for httplog before checking the log format, so that we can report a warning about this specific option and not about the format it implies. --- include/types/proxy.h | 2 ++ src/cfgparse.c | 63 ++++++++++++++++++++++++++++--------------- src/haproxy.c | 6 +++++ src/proxy.c | 7 +++++ 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/include/types/proxy.h b/include/types/proxy.h index 622e1686c..15ed23af1 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -344,6 +344,8 @@ struct proxy { int no_options; /* PR_O_REDISP, PR_O_TRANSP, ... */ int no_options2; /* PR_O2_* */ + char *logformat_string; /* log format string */ + char *uniqueid_format_string; /* unique-id format string */ struct { const char *file; /* file where the section appears */ int line; /* line where the section appears */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 5bd2cfc37..a45acb15d 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1345,7 +1345,6 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) int err_code = 0; struct acl_cond *cond = NULL; struct logsrv *tmplogsrv; - struct logformat_node *tmplf; char *errmsg = NULL; if (!strcmp(args[0], "listen")) @@ -1564,21 +1563,17 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) LIST_ADDQ(&curproxy->logsrvs, &node->list); } - /* copy default log_format to curproxy */ - list_for_each_entry(tmplf, &defproxy.logformat, list) { - struct logformat_node *node = malloc(sizeof(struct logformat_node)); - memcpy(node, tmplf, sizeof(struct logformat_node)); - LIST_INIT(&node->list); - LIST_ADDQ(&curproxy->logformat, &node->list); - } + /* get either a pointer to the logformat string or a copy of it */ + curproxy->logformat_string = defproxy.logformat_string; + if (curproxy->logformat_string && + curproxy->logformat_string != default_http_log_format && + curproxy->logformat_string != default_tcp_log_format && + curproxy->logformat_string != clf_http_log_format) + curproxy->logformat_string = strdup(curproxy->logformat_string); - /* copy default unique_id to curproxy */ - list_for_each_entry(tmplf, &defproxy.format_unique_id, list) { - struct logformat_node *node = malloc(sizeof(struct logformat_node)); - memcpy(node, tmplf, sizeof(struct logformat_node)); - LIST_INIT(&node->list); - LIST_ADDQ(&curproxy->format_unique_id, &node->list); - } + curproxy->uniqueid_format_string = defproxy.uniqueid_format_string; + if (curproxy->uniqueid_format_string) + curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string); /* copy default header unique id */ if (defproxy.header_unique_id) @@ -1614,6 +1609,13 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) free(defproxy.expect_str); if (defproxy.expect_regex) regfree(defproxy.expect_regex); + if (defproxy.logformat_string == default_http_log_format || + defproxy.logformat_string == default_tcp_log_format || + defproxy.logformat_string == clf_http_log_format) + free(defproxy.logformat_string); + + free(defproxy.uniqueid_format_string); + for (rc = 0; rc < HTTP_ERR_SIZE; rc++) chunk_destroy(&defproxy.errmsg[rc]); @@ -3384,13 +3386,19 @@ stats_error_parsing: goto out; } } - parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode); + if (curproxy->logformat_string != default_http_log_format && + curproxy->logformat_string != default_tcp_log_format && + curproxy->logformat_string != clf_http_log_format) + free(curproxy->logformat_string); + curproxy->logformat_string = logformat; } else if (!strcmp(args[1], "tcplog")) { - char *logformat; /* generate a detailed TCP log */ - logformat = default_tcp_log_format; - parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode); + if (curproxy->logformat_string != default_http_log_format && + curproxy->logformat_string != default_tcp_log_format && + curproxy->logformat_string != clf_http_log_format) + free(curproxy->logformat_string); + curproxy->logformat_string = default_tcp_log_format; } else if (!strcmp(args[1], "tcpka")) { /* enable TCP keep-alives on client and server sessions */ @@ -4639,7 +4647,8 @@ stats_error_parsing: err_code |= ERR_ALERT | ERR_FATAL; goto out; } - parse_logformat_string(args[1], curproxy, &curproxy->format_unique_id, PR_MODE_HTTP); + free(curproxy->uniqueid_format_string); + curproxy->uniqueid_format_string = strdup(args[1]); } else if (strcmp(args[0], "unique-id-header") == 0) { @@ -4658,7 +4667,12 @@ stats_error_parsing: err_code |= ERR_ALERT | ERR_FATAL; goto out; } - parse_logformat_string(args[1], curproxy, &curproxy->logformat, curproxy->mode); + + if (curproxy->logformat_string != default_http_log_format && + curproxy->logformat_string != default_tcp_log_format && + curproxy->logformat_string != clf_http_log_format) + free(curproxy->logformat_string); + curproxy->logformat_string = strdup(args[1]); } else if (!strcmp(args[0], "log") && kwm == KWM_NO) { @@ -6208,6 +6222,13 @@ out_uri_auth_compat: } } + /* compile the log format */ + if (curproxy->logformat_string) + parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode); + + if (curproxy->uniqueid_format_string) + parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP); + /* first, we will invert the servers list order */ newsrv = NULL; while (curproxy->srv) { diff --git a/src/haproxy.c b/src/haproxy.c index 8d3e6e376..ff962c274 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -831,6 +831,12 @@ void deinit(void) free(p->capture_name); free(p->monitor_uri); free(p->rdp_cookie_name); + if (p->logformat_string == default_http_log_format || + p->logformat_string == default_tcp_log_format || + p->logformat_string == clf_http_log_format) + free(p->logformat_string); + + free(p->uniqueid_format_string); for (i = 0; i < HTTP_ERR_SIZE; i++) chunk_destroy(&p->errmsg[i]); diff --git a/src/proxy.c b/src/proxy.c index bc5779ff3..3568251df 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -406,6 +406,13 @@ int proxy_cfg_ensure_no_http(struct proxy *curproxy) Warning("config : 'option httplog' not usable with %s '%s' (needs 'mode http'). Falling back to 'option tcplog'.\n", proxy_type_str(curproxy), curproxy->id); } + if (curproxy->logformat_string == default_http_log_format || + curproxy->logformat_string == clf_http_log_format) { + curproxy->logformat_string = default_tcp_log_format; + Warning("config : 'option httplog' not usable with %s '%s' (needs 'mode http'). Falling back to 'option tcplog'.\n", + proxy_type_str(curproxy), curproxy->id); + } + return 0; }