MEDIUM: tree-wide: add logformat expressions wrapper

log format expressions are broadly used within the code: once they are
parsed from input string, they are converted to a linked list of
logformat nodes.

We're starting to face some limitations because we're simply storing the
converted expression as a generic logformat_node list.

The first issue we're facing is that storing logformat expressions that
way doesn't allow us to add metadata alongside the list, which is part
of the prerequites for implementing log-profiles.

Another issue with storing logformat expressions as generic lists of
logformat_node elements is that it's starting to become really hard to
tell when we rely on logformat expressions or not in the code given that
there isn't always a comment near the list declaration or manipulation
to indicate that it's relying on logformat expressions under the hood,
so this adds some complexity for code maintenance.

This patch looks quite impressive due to changes in a lot of header and
source files (since logformat expressions are broadly used), but it does
a simple thing: it defines the lf_expr structure which itself holds a
generic list of logformat nodes, and then declares some helpers to
manipulate lf_expr elements and fixes the code so that we now exclusively
manipulate logformat_node lists as lf_expr elements outside of log.c.

For now, lf_expr struct only contains the list of logformat nodes (no
additional metadata), but now that we have dedicated type and helpers,
doing so in the future won't be problematic at all and won't require
extensive code changes.
This commit is contained in:
Aurelien DARRAGON 2024-02-23 15:57:21 +01:00
parent 7d8f45b647
commit 6810c41f8e
26 changed files with 206 additions and 160 deletions

View File

@ -25,6 +25,7 @@
#include <haproxy/applet-t.h>
#include <haproxy/stick_table-t.h>
#include <haproxy/vars-t.h>
#include <haproxy/log-t.h>
struct session;
struct stream;
@ -141,15 +142,15 @@ struct act_rule {
struct {
int i; /* integer param (status, nice, loglevel, ..) */
struct ist str; /* string param (reason, header name, ...) */
struct list fmt; /* log-format compatible expression */
struct lf_expr fmt; /* log-format compatible expression */
struct my_regex *re; /* used by replace-header/value/uri/path */
} http; /* args used by some HTTP rules */
struct http_reply *http_reply; /* HTTP response to be used by return/deny/tarpit rules */
struct redirect_rule *redir; /* redirect rule or "http-request redirect" */
struct {
char *ref; /* MAP or ACL file name to update */
struct list key; /* pattern to retrieve MAP or ACL key */
struct list value; /* pattern to retrieve MAP value */
struct lf_expr key; /* pattern to retrieve MAP or ACL key */
struct lf_expr value; /* pattern to retrieve MAP value */
} map;
struct sample_expr *expr;
struct {
@ -167,7 +168,7 @@ struct act_rule {
} timeout;
struct hlua_rule *hlua_rule;
struct {
struct list fmt; /* log-format compatible expression */
struct lf_expr fmt; /* log-format compatible expression */
struct sample_expr *expr;
uint64_t name_hash;
enum vars_scope scope;

View File

@ -28,6 +28,7 @@
#include <haproxy/acl-t.h>
#include <haproxy/api-t.h>
#include <haproxy/arg-t.h>
#include <haproxy/log-t.h>
#include <haproxy/fcgi.h>
#include <haproxy/filters-t.h>
#include <haproxy/regex-t.h>
@ -59,7 +60,7 @@ struct fcgi_rule_conf {
struct fcgi_rule {
enum fcgi_rule_type type;
struct ist name; /* name of the parameter/header */
struct list value; /* log-format compatible expression, may be empty */
struct lf_expr value; /* log-format compatible expression, may be empty */
struct acl_cond *cond; /* acl condition to set the param */
struct list list;
};
@ -67,7 +68,7 @@ struct fcgi_rule {
/* parameter rule to set/unset a param at the end of the analyzis */
struct fcgi_param_rule {
struct ist name;
struct list *value; /* if empty , unset the parameter */
struct lf_expr *value; /* if empty , unset the parameter */
struct ebpt_node node;
};

View File

@ -28,6 +28,7 @@
#include <haproxy/buf-t.h>
#include <haproxy/http-t.h>
#include <haproxy/log-t.h>
#include <haproxy/htx-t.h>
/* Context used to find/remove an HTTP header. */
@ -41,9 +42,9 @@ struct http_hdr_ctx {
/* Structure used to build the header list of an HTTP reply */
struct http_reply_hdr {
struct ist name; /* the header name */
struct list value; /* the log-format string value */
struct list list; /* header chained list */
struct ist name; /* the header name */
struct lf_expr value; /* the log-format string value */
struct list list; /* header linked list */
};
#define HTTP_REPLY_EMPTY 0x00 /* the reply has no payload */
@ -60,7 +61,7 @@ struct http_reply {
char *ctype; /* The response content-type, may be NULL */
struct list hdrs; /* A list of http_reply_hdr */
union {
struct list fmt; /* A log-format string (type = HTTP_REPLY_LOGFMT) */
struct lf_expr fmt; /* A log-format string (type = HTTP_REPLY_LOGFMT) */
struct buffer obj; /* A raw string (type = HTTP_REPLY_RAW) */
struct buffer *errmsg; /* The error message to use as response (type = HTTP_REPLY_ERRMSG).
* may be NULL, if so rely on the proxy error messages */

View File

@ -168,6 +168,11 @@ struct logformat_node {
const struct logformat_tag *tag; // set if ->type == LOG_FMT_TAG
};
/* a full logformat expr made of one or multiple logformat nodes */
struct lf_expr {
struct list nodes; /* logformat_node list */
};
/* Range of indexes for log sampling. */
struct smp_log_range {
unsigned int low; /* Low limit of the indexes of this range. */

View File

@ -64,12 +64,20 @@ void syslog_fd_handler(int fd);
int init_log_buffers(void);
void deinit_log_buffers(void);
void lf_expr_init(struct lf_expr *expr);
void lf_expr_xfer(struct lf_expr *src, struct lf_expr *dst);
void lf_expr_deinit(struct lf_expr *expr);
static inline int lf_expr_isempty(const struct lf_expr *expr)
{
return LIST_ISEMPTY(&expr->nodes);
}
/* Deinitialize log buffers used for syslog messages */
void free_logformat_list(struct list *fmt);
void free_logformat_node(struct logformat_node *node);
/* build a log line for the session and an optional stream */
int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct list *list_format);
int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct lf_expr *lf_expr);
/*
* send a log for the stream when we have enough info about it.
@ -85,7 +93,7 @@ void app_log(struct list *loggers, struct buffer *tag, int level, const char *fo
/*
* add to the logformat linked list
*/
int add_to_logformat_list(char *start, char *end, int type, struct list *list_format, char **err);
int add_to_logformat_list(char *start, char *end, int type, struct lf_expr *lf_expr, char **err);
ssize_t syslog_applet_append_event(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len);
@ -94,7 +102,7 @@ ssize_t syslog_applet_append_event(void *ctx, struct ist v1, struct ist v2, size
* Tag name are preceded by % and composed by characters [a-zA-Z0-9]* : %tagname
* You can set arguments using { } : %{many arguments}tagname
*/
int parse_logformat_string(const char *str, struct proxy *curproxy, struct list *list_format, int options, int cap, char **err);
int parse_logformat_string(const char *str, struct proxy *curproxy, struct lf_expr *lf_expr, int options, int cap, char **err);
int postresolve_logger_list(struct list *loggers, const char *section, const char *section_name);
@ -168,9 +176,9 @@ char * get_format_pid_sep2(int format, size_t *len);
/*
* Builds a log line for the stream (must be valid).
*/
static inline int build_logline(struct stream *s, char *dst, size_t maxsize, struct list *list_format)
static inline int build_logline(struct stream *s, char *dst, size_t maxsize, struct lf_expr *lf_expr)
{
return sess_build_logline(strm_sess(s), s, dst, maxsize, list_format);
return sess_build_logline(strm_sess(s), s, dst, maxsize, lf_expr);
}
struct ist *build_log_header(struct log_header hdr, size_t *nbelem);

View File

@ -373,12 +373,12 @@ struct proxy {
struct proxy *next_stkt_ref; /* Link to the list of proxies which refer to the same stick-table. */
struct list loggers; /* one per 'log' directive */
struct list logformat; /* log_format linked list */
struct list logformat_sd; /* log_format linked list for the RFC5424 structured-data part */
struct list logformat_error; /* log_format linked list used in case of connection error on the frontend */
struct lf_expr logformat; /* log_format linked list */
struct lf_expr logformat_sd; /* log_format linked list for the RFC5424 structured-data part */
struct lf_expr logformat_error; /* log_format linked list used in case of connection error on the frontend */
struct buffer log_tag; /* override default syslog tag */
struct ist header_unique_id; /* unique-id header */
struct list format_unique_id; /* unique-id format */
struct lf_expr format_unique_id; /* unique-id format */
int to_log; /* things to be logged (LW_*) */
int nb_req_cap, nb_rsp_cap; /* # of headers to be captured */
struct cap_hdr *req_cap; /* chained list of request headers to be captured */
@ -478,7 +478,7 @@ struct switching_rule {
union {
struct proxy *backend; /* target backend */
char *name; /* target backend name during config parsing */
struct list expr; /* logformat expression to use for dynamic rules */
struct lf_expr expr; /* logformat expression to use for dynamic rules */
} be;
char *file;
int line;
@ -492,7 +492,7 @@ struct server_rule {
struct server *ptr; /* target server */
char *name; /* target server name during config parsing */
} srv;
struct list expr; /* logformat expression to use for dynamic rules */
struct lf_expr expr; /* logformat expression to use for dynamic rules */
char *file;
int line;
};
@ -521,7 +521,7 @@ struct redirect_rule {
int type;
int rdr_len;
char *rdr_str;
struct list rdr_fmt;
struct lf_expr rdr_fmt;
int code;
unsigned int flags;
int cookie_len;

View File

@ -41,6 +41,7 @@
#include <haproxy/task-t.h>
#include <haproxy/thread-t.h>
#include <haproxy/event_hdl-t.h>
#include <haproxy/log-t.h>
#include <haproxy/tools-t.h>
@ -269,7 +270,7 @@ enum __attribute__((__packed__)) srv_ws_mode {
*/
struct srv_pp_tlv_list {
struct list list;
struct list fmt;
struct lf_expr fmt;
char *fmt_string;
unsigned char type;
};

View File

@ -69,7 +69,7 @@ void stream_shutdown(struct stream *stream, int why);
void stream_dump_and_crash(enum obj_type *obj, int rate);
void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const char *pfx, uint32_t anon_key);
struct ist stream_generate_unique_id(struct stream *strm, struct list *format);
struct ist stream_generate_unique_id(struct stream *strm, struct lf_expr *format);
void stream_process_counters(struct stream *s);
void sess_change_server(struct stream *strm, struct server *newsrv);

View File

@ -134,9 +134,9 @@ struct tcpcheck_connect {
};
struct tcpcheck_http_hdr {
struct ist name; /* the header name */
struct list value; /* the log-format string value */
struct list list; /* header chained list */
struct ist name; /* the header name */
struct lf_expr value; /* the log-format string value */
struct list list; /* header linked list */
};
struct tcpcheck_codes {
@ -147,20 +147,20 @@ struct tcpcheck_codes {
struct tcpcheck_send {
enum tcpcheck_send_type type;
union {
struct ist data; /* an ASCII string or a binary sequence */
struct list fmt; /* an ASCII or hexa log-format string */
struct ist data; /* an ASCII string or a binary sequence */
struct lf_expr fmt; /* an ASCII or hexa log-format string */
struct {
unsigned int flags; /* TCPCHK_SND_HTTP_FL_* */
struct http_meth meth; /* the HTTP request method */
union {
struct ist uri; /* the HTTP request uri is a string */
struct list uri_fmt; /* or a log-format string */
struct lf_expr uri_fmt; /* or a log-format string */
};
struct ist vsn; /* the HTTP request version string */
struct list hdrs; /* the HTTP request header list */
union {
struct ist body; /* the HTTP request payload is a string */
struct list body_fmt; /* or a log-format string */
struct lf_expr body_fmt;/* or a log-format string */
};
} http; /* Info about the HTTP request to send */
};
@ -173,16 +173,16 @@ struct tcpcheck_expect {
struct ist data; /* Matching a literal string / binary anywhere in the response. */
struct my_regex *regex; /* Matching a regex pattern. */
struct tcpcheck_codes codes; /* Matching a list of codes */
struct list fmt; /* Matching a log-format string / binary */
struct lf_expr fmt; /* Matching a log-format string / binary */
struct {
union {
struct ist name;
struct list name_fmt;
struct lf_expr name_fmt;
struct my_regex *name_re;
};
union {
struct ist value;
struct list value_fmt;
struct lf_expr value_fmt;
struct my_regex *value_re;
};
} hdr; /* Matching a header pattern */
@ -196,9 +196,9 @@ struct tcpcheck_expect {
enum healthcheck_status ok_status; /* The healthcheck status to use on success (default: L7OKD) */
enum healthcheck_status err_status; /* The healthcheck status to use on error (default: L7RSP) */
enum healthcheck_status tout_status; /* The healthcheck status to use on timeout (default: L7TOUT) */
struct list onerror_fmt; /* log-format string to use as comment on error */
struct list onsuccess_fmt; /* log-format string to use as comment on success (if last rule) */
struct sample_expr *status_expr; /* sample expr to determine the check status code */
struct lf_expr onerror_fmt; /* log-format string to use as comment on error */
struct lf_expr onsuccess_fmt; /* log-format string to use as comment on success (if last rule) */
struct sample_expr *status_expr; /* sample expr to determine the check status code */
};
struct tcpcheck_action_kw {

View File

@ -3127,7 +3127,7 @@ init_proxies_list_stage1:
* parsing is cancelled and be.name is restored to be resolved.
*/
pxname = rule->be.name;
LIST_INIT(&rule->be.expr);
lf_expr_init(&rule->be.expr);
curproxy->conf.args.ctx = ARGC_UBK;
curproxy->conf.args.file = rule->file;
curproxy->conf.args.line = rule->line;
@ -3139,10 +3139,10 @@ init_proxies_list_stage1:
cfgerr++;
continue;
}
node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
node = LIST_NEXT(&rule->be.expr.nodes, struct logformat_node *, list);
if (!LIST_ISEMPTY(&rule->be.expr)) {
if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
if (!lf_expr_isempty(&rule->be.expr)) {
if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr.nodes) {
rule->dynamic = 1;
free(pxname);
/* backend is not yet known so we cannot assume its type,
@ -3155,8 +3155,7 @@ init_proxies_list_stage1:
/* Only one element in the list, a simple string: free the expression and
* fall back to static rule
*/
LIST_DELETE(&node->list);
free_logformat_node(node);
lf_expr_deinit(&rule->be.expr);
}
rule->dynamic = 0;
@ -3204,7 +3203,7 @@ init_proxies_list_stage1:
* to a static rule, thus the parsing is cancelled and we fall back to setting srv.ptr.
*/
server_name = srule->srv.name;
LIST_INIT(&srule->expr);
lf_expr_init(&srule->expr);
curproxy->conf.args.ctx = ARGC_USRV;
err = NULL;
if (!parse_logformat_string(server_name, curproxy, &srule->expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
@ -3214,10 +3213,10 @@ init_proxies_list_stage1:
cfgerr++;
continue;
}
node = LIST_NEXT(&srule->expr, struct logformat_node *, list);
node = LIST_NEXT(&srule->expr.nodes, struct logformat_node *, list);
if (!LIST_ISEMPTY(&srule->expr)) {
if (node->type != LOG_FMT_TEXT || node->list.n != &srule->expr) {
if (!lf_expr_isempty(&srule->expr)) {
if (node->type != LOG_FMT_TEXT || node->list.n != &srule->expr.nodes) {
srule->dynamic = 1;
free(server_name);
continue;
@ -3225,8 +3224,7 @@ init_proxies_list_stage1:
/* Only one element in the list, a simple string: free the expression and
* fall back to static rule
*/
LIST_DELETE(&node->list);
free_logformat_node(node);
lf_expr_deinit(&srule->expr);
}
srule->dynamic = 0;
@ -3774,7 +3772,7 @@ out_uri_auth_compat:
if (!(curproxy->cap & PR_CAP_INT) && (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
(curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->loggers) &&
(!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
(!lf_expr_isempty(&curproxy->logformat) || !lf_expr_isempty(&curproxy->logformat_sd))) {
ha_warning("log format ignored for %s '%s' since it has no log address.\n",
proxy_type_str(curproxy), curproxy->id);
err_code |= ERR_WARN;

View File

@ -3137,7 +3137,7 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
pendconn_free(s);
/* let's do a final log if we need it */
if (!LIST_ISEMPTY(&fe->logformat) && s->logs.logwait &&
if (!lf_expr_isempty(&fe->logformat) && s->logs.logwait &&
!(s->flags & SF_MONITOR) &&
(!(fe->options & PR_O_NULLNOLOG) || s->req.total)) {
s->do_log(s);

View File

@ -2030,7 +2030,7 @@ static int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct
/* Users will always need to provide a value, in case of forwarding, they should use fc_pp_tlv.
* for generic types. Otherwise, we will send an empty TLV.
*/
if (!LIST_ISEMPTY(&srv_tlv->fmt)) {
if (!lf_expr_isempty(&srv_tlv->fmt)) {
replace = alloc_trash_chunk();
if (unlikely(!replace))
return 0;

View File

@ -134,7 +134,7 @@ static void fcgi_release_rule(struct fcgi_rule *rule)
if (!rule)
return;
free_logformat_list(&rule->value);
lf_expr_deinit(&rule->value);
/* ->cond and ->name are not owned by the rule */
free(rule);
}
@ -247,7 +247,7 @@ static int fcgi_flt_check(struct proxy *px, struct flt_conf *fconf)
rule->type = crule->type;
rule->name = ist(crule->name);
rule->cond = crule->cond;
LIST_INIT(&rule->value);
lf_expr_init(&rule->value);
if (crule->value) {
if (!parse_logformat_string(crule->value, px, &rule->value, LOG_OPT_HTTP,

View File

@ -55,7 +55,7 @@ int frontend_accept(struct stream *s)
if ((fe->mode == PR_MODE_TCP || fe->mode == PR_MODE_HTTP)
&& (!LIST_ISEMPTY(&fe->loggers))) {
if (likely(!LIST_ISEMPTY(&fe->logformat))) {
if (likely(!lf_expr_isempty(&fe->logformat))) {
/* we have the client ip */
if (s->logs.logwait & LW_CLIP)
if (!(s->logs.logwait &= ~(LW_CLIP|LW_INIT)))

View File

@ -49,7 +49,7 @@ static void release_http_action(struct act_rule *rule)
istfree(&rule->arg.http.str);
if (rule->arg.http.re)
regex_free(rule->arg.http.re);
free_logformat_list(&rule->arg.http.fmt);
lf_expr_deinit(&rule->arg.http.fmt);
}
/* Release memory allocated by HTTP actions relying on an http reply. Concretly,
@ -172,7 +172,7 @@ static enum act_parse_ret parse_set_req_line(const char **args, int *orig_arg, s
}
rule->action_ptr = http_action_set_req_line;
rule->release_ptr = release_http_action;
LIST_INIT(&rule->arg.http.fmt);
lf_expr_init(&rule->arg.http.fmt);
if (!*args[cur_arg] ||
(*args[cur_arg + 1] && strcmp(args[cur_arg + 1], "if") != 0 && strcmp(args[cur_arg + 1], "unless") != 0)) {
@ -609,7 +609,7 @@ static enum act_parse_ret parse_replace_uri(const char **args, int *orig_arg, st
rule->action_ptr = http_action_replace_uri;
rule->release_ptr = release_http_action;
LIST_INIT(&rule->arg.http.fmt);
lf_expr_init(&rule->arg.http.fmt);
if (!*args[cur_arg] || !*args[cur_arg+1] ||
(*args[cur_arg+2] && strcmp(args[cur_arg+2], "if") != 0 && strcmp(args[cur_arg+2], "unless") != 0)) {
@ -673,7 +673,7 @@ static enum act_parse_ret parse_http_set_status(const char **args, int *orig_arg
rule->action = ACT_CUSTOM;
rule->action_ptr = action_http_set_status;
rule->release_ptr = release_http_action;
LIST_INIT(&rule->arg.http.fmt);
lf_expr_init(&rule->arg.http.fmt);
/* Check if an argument is available */
if (!*args[*orig_arg]) {
@ -1310,7 +1310,7 @@ static enum act_parse_ret parse_http_auth(const char **args, int *orig_arg, stru
rule->flags |= ACT_FLAG_FINAL;
rule->action_ptr = http_action_auth;
rule->release_ptr = release_http_action;
LIST_INIT(&rule->arg.http.fmt);
lf_expr_init(&rule->arg.http.fmt);
cur_arg = *orig_arg;
if (strcmp(args[cur_arg], "realm") == 0) {
@ -1490,7 +1490,7 @@ static enum act_parse_ret parse_http_set_header(const char **args, int *orig_arg
rule->action_ptr = http_action_set_header;
}
rule->release_ptr = release_http_action;
LIST_INIT(&rule->arg.http.fmt);
lf_expr_init(&rule->arg.http.fmt);
cur_arg = *orig_arg;
if (!*args[cur_arg] || !*args[cur_arg+1]) {
@ -1616,7 +1616,7 @@ static enum act_parse_ret parse_http_replace_header(const char **args, int *orig
rule->action = 1; // replace-value
rule->action_ptr = http_action_replace_header;
rule->release_ptr = release_http_action;
LIST_INIT(&rule->arg.http.fmt);
lf_expr_init(&rule->arg.http.fmt);
cur_arg = *orig_arg;
if (!*args[cur_arg] || !*args[cur_arg+1] || !*args[cur_arg+2]) {
@ -1719,7 +1719,7 @@ static enum act_parse_ret parse_http_del_header(const char **args, int *orig_arg
rule->action = PAT_MATCH_STR;
rule->action_ptr = http_action_del_header;
rule->release_ptr = release_http_action;
LIST_INIT(&rule->arg.http.fmt);
lf_expr_init(&rule->arg.http.fmt);
cur_arg = *orig_arg;
if (!*args[cur_arg]) {
@ -1895,9 +1895,9 @@ static enum act_return http_action_set_map(struct act_rule *rule, struct proxy *
static void release_http_map(struct act_rule *rule)
{
free(rule->arg.map.ref);
free_logformat_list(&rule->arg.map.key);
lf_expr_deinit(&rule->arg.map.key);
if (rule->action == 1)
free_logformat_list(&rule->arg.map.value);
lf_expr_deinit(&rule->arg.map.value);
}
/* Parse a "add-acl", "del-acl", "set-map" or "del-map" actions. It takes one or
@ -1959,7 +1959,7 @@ static enum act_parse_ret parse_http_set_map(const char **args, int *orig_arg, s
}
/* key pattern */
LIST_INIT(&rule->arg.map.key);
lf_expr_init(&rule->arg.map.key);
if (!parse_logformat_string(args[cur_arg], px, &rule->arg.map.key, LOG_OPT_HTTP, cap, err)) {
free(rule->arg.map.ref);
return ACT_RET_PRS_ERR;
@ -1968,7 +1968,7 @@ static enum act_parse_ret parse_http_set_map(const char **args, int *orig_arg, s
if (rule->action == 1) {
/* value pattern for set-map only */
cur_arg++;
LIST_INIT(&rule->arg.map.value);
lf_expr_init(&rule->arg.map.value);
if (!parse_logformat_string(args[cur_arg], px, &rule->arg.map.value, LOG_OPT_HTTP, cap, err)) {
free(rule->arg.map.ref);
return ACT_RET_PRS_ERR;

View File

@ -657,7 +657,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
* A unique ID is generated even when it is not sent to ensure that the ID can make use of
* fetches only available in the HTTP request processing stage.
*/
if (!LIST_ISEMPTY(&sess->fe->format_unique_id)) {
if (!lf_expr_isempty(&sess->fe->format_unique_id)) {
struct ist unique_id = stream_generate_unique_id(s, &sess->fe->format_unique_id);
if (!isttest(unique_id)) {
@ -1900,7 +1900,7 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
* bytes from the server, then this is the right moment. We have
* to temporarily assign bytes_out to log what we currently have.
*/
if (!LIST_ISEMPTY(&sess->fe->logformat) && !(s->logs.logwait & LW_BYTES)) {
if (!lf_expr_isempty(&sess->fe->logformat) && !(s->logs.logwait & LW_BYTES)) {
s->logs.t_close = s->logs.t_data; /* to get a valid end date */
s->logs.bytes_out = htx->data;
s->do_log(s);

View File

@ -36,6 +36,7 @@
#include <haproxy/sample.h>
#include <haproxy/sc_strm.h>
#include <haproxy/stream.h>
#include <haproxy/log.h>
#include <haproxy/tools.h>
#include <haproxy/version.h>
@ -477,7 +478,7 @@ static int smp_fetch_uniqueid(const struct arg *args, struct sample *smp, const
{
struct ist unique_id;
if (LIST_ISEMPTY(&smp->sess->fe->format_unique_id))
if (lf_expr_isempty(&smp->sess->fe->format_unique_id))
return 0;
if (!smp->strm)

View File

@ -1125,7 +1125,7 @@ void release_http_reply(struct http_reply *http_reply)
ha_free(&http_reply->ctype);
list_for_each_entry_safe(hdr, hdrb, &http_reply->hdrs, list) {
LIST_DELETE(&hdr->list);
free_logformat_list(&hdr->value);
lf_expr_deinit(&hdr->value);
istfree(&hdr->name);
free(hdr);
}
@ -1136,7 +1136,7 @@ void release_http_reply(struct http_reply *http_reply)
else if (http_reply->type == HTTP_REPLY_RAW)
chunk_destroy(&http_reply->body.obj);
else if (http_reply->type == HTTP_REPLY_LOGFMT)
free_logformat_list(&http_reply->body.fmt);
lf_expr_deinit(&http_reply->body.fmt);
free(http_reply);
}
@ -1669,7 +1669,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
fd = -1;
obj[objlen] = '\0';
reply->type = HTTP_REPLY_LOGFMT;
LIST_INIT(&reply->body.fmt);
lf_expr_init(&reply->body.fmt);
cur_arg++;
}
else if (strcmp(args[cur_arg], "lf-string") == 0) {
@ -1686,7 +1686,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
obj = strdup(args[cur_arg]);
objlen = strlen(args[cur_arg]);
reply->type = HTTP_REPLY_LOGFMT;
LIST_INIT(&reply->body.fmt);
lf_expr_init(&reply->body.fmt);
cur_arg++;
}
else if (strcmp(args[cur_arg], "hdr") == 0) {
@ -1709,7 +1709,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
goto error;
}
LIST_APPEND(&reply->hdrs, &hdr->list);
LIST_INIT(&hdr->value);
lf_expr_init(&hdr->value);
hdr->name = ist(strdup(args[cur_arg]));
if (!isttest(hdr->name)) {
memprintf(errmsg, "out of memory");
@ -1765,7 +1765,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
px->conf.args.file, px->conf.args.line);
list_for_each_entry_safe(hdr, hdrb, &reply->hdrs, list) {
LIST_DELETE(&hdr->list);
free_logformat_list(&hdr->value);
lf_expr_deinit(&hdr->value);
istfree(&hdr->name);
free(hdr);
}
@ -1793,7 +1793,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
}
}
else if (reply->type == HTTP_REPLY_LOGFMT) { /* log-format payload using 'lf-file' of 'lf-string' parameter */
LIST_INIT(&reply->body.fmt);
lf_expr_init(&reply->body.fmt);
if ((reply->status == 204 || reply->status == 304)) {
memprintf(errmsg, "No body expected for %d responses", reply->status);
goto error;

View File

@ -323,7 +323,7 @@ void http_free_redirect_rule(struct redirect_rule *rdr)
free_acl_cond(rdr->cond);
free(rdr->rdr_str);
free(rdr->cookie_str);
free_logformat_list(&rdr->rdr_fmt);
lf_expr_deinit(&rdr->rdr_fmt);
free(rdr);
}
@ -440,7 +440,7 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
if (!rule)
goto out_of_memory;
rule->cond = cond;
LIST_INIT(&rule->rdr_fmt);
lf_expr_init(&rule->rdr_fmt);
if (!use_fmt) {
/* old-style static redirect rule */

View File

@ -370,9 +370,10 @@ int parse_logformat_tag_args(char *args, struct logformat_node *node, char **err
* ignored when arg_len is 0. Neither <tag> nor <tag_len> may be null.
* Returns false in error case and err is filled, otherwise returns true.
*/
int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len, int typecast, char *tag, int tag_len, struct proxy *curproxy, struct list *list_format, int *defoptions, char **err)
int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len, int typecast, char *tag, int tag_len, struct proxy *curproxy, struct lf_expr *lf_expr, int *defoptions, char **err)
{
int j;
struct list *list_format= &lf_expr->nodes;
struct logformat_node *node = NULL;
for (j = 0; logformat_tags[j].name; j++) { // search a log type
@ -431,13 +432,14 @@ int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len, int ty
* start: start pointer
* end: end text pointer
* type: string type
* list_format: destination list
* lf_expr: destination logformat expr (list of fmt nodes)
*
* LOG_TEXT: copy chars from start to end excluding end.
*
*/
int add_to_logformat_list(char *start, char *end, int type, struct list *list_format, char **err)
int add_to_logformat_list(char *start, char *end, int type, struct lf_expr *lf_expr, char **err)
{
struct list *list_format = &lf_expr->nodes;
char *str;
if (type == LF_TEXT) { /* type text */
@ -465,16 +467,17 @@ int add_to_logformat_list(char *start, char *end, int type, struct list *list_fo
}
/*
* Parse the sample fetch expression <text> and add a node to <list_format> upon
* Parse the sample fetch expression <text> and add a node to <lf_expr> upon
* success. The curpx->conf.args.ctx must be set by the caller. If an end pointer
* is passed in <endptr>, it will be updated with the pointer to the first character
* not part of the sample expression.
*
* In error case, the function returns 0, otherwise it returns 1.
*/
int add_sample_to_logformat_list(char *text, char *name, int name_len, int typecast, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options, int cap, char **err, char **endptr)
int add_sample_to_logformat_list(char *text, char *name, int name_len, int typecast, char *arg, int arg_len, struct proxy *curpx, struct lf_expr *lf_expr, int options, int cap, char **err, char **endptr)
{
char *cmd[2];
struct list *list_format = &lf_expr->nodes;
struct sample_expr *expr = NULL;
struct logformat_node *node = NULL;
int cmd_arg;
@ -551,13 +554,13 @@ int add_sample_to_logformat_list(char *text, char *name, int name_len, int typec
*
* fmt: the string to parse
* curproxy: the proxy affected
* list_format: the destination list
* lf_expr: the destination logformat expression (logformat_node list)
* options: LOG_OPT_* to force on every node
* cap: all SMP_VAL_* flags supported by the consumer
*
* The function returns 1 in success case, otherwise, it returns 0 and err is filled.
*/
int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list *list_format, int options, int cap, char **err)
int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct lf_expr *lf_expr, int options, int cap, char **err)
{
char *sp, *str, *backfmt; /* start pointer for text parts */
char *arg = NULL; /* start pointer for args */
@ -578,8 +581,8 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
}
curproxy->to_log |= LW_INIT;
/* flush the list first. */
free_logformat_list(list_format);
/* reset the old expr first (if previously defined) */
lf_expr_deinit(lf_expr);
for (cformat = LF_INIT; cformat != LF_END; str++) {
pformat = cformat;
@ -694,7 +697,7 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
* part of the expression, which MUST be the trailing
* angle bracket.
*/
if (!add_sample_to_logformat_list(tag, name, name_len, typecast, arg, arg_len, curproxy, list_format, options, cap, err, &str))
if (!add_sample_to_logformat_list(tag, name, name_len, typecast, arg, arg_len, curproxy, lf_expr, options, cap, err, &str))
goto fail;
if (*str == ']') {
@ -740,12 +743,12 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
if (cformat != pformat || pformat == LF_SEPARATOR) {
switch (pformat) {
case LF_TAG:
if (!parse_logformat_tag(arg, arg_len, name, name_len, typecast, tag, tag_len, curproxy, list_format, &options, err))
if (!parse_logformat_tag(arg, arg_len, name, name_len, typecast, tag, tag_len, curproxy, lf_expr, &options, err))
goto fail;
break;
case LF_TEXT:
case LF_SEPARATOR:
if (!add_to_logformat_list(sp, str, pformat, list_format, err))
if (!add_to_logformat_list(sp, str, pformat, lf_expr, err))
goto fail;
break;
}
@ -2592,19 +2595,53 @@ void free_logformat_list(struct list *fmt)
}
}
/* Builds a log line in <dst> based on <list_format>, and stops before reaching
/* Prepares log-format expression struct */
void lf_expr_init(struct lf_expr *expr)
{
LIST_INIT(&expr->nodes);
}
/* Releases and resets a log-format expression */
void lf_expr_deinit(struct lf_expr *expr)
{
free_logformat_list(&expr->nodes);
lf_expr_init(expr);
}
/* Transfer log-format expression from <src> to <dst>
* at the end of the operation, <src> is reset
*/
void lf_expr_xfer(struct lf_expr *src, struct lf_expr *dst)
{
struct logformat_node *lf, *lfb;
/* first, reset any existing expr */
lf_expr_deinit(dst);
/* then proceed with transfer between <src> and <dst> */
list_for_each_entry_safe(lf, lfb, &src->nodes, list) {
LIST_DELETE(&lf->list);
LIST_APPEND(&dst->nodes, &lf->list);
}
/* src is now empty, perform an explicit reset */
lf_expr_init(src);
}
/* Builds a log line in <dst> based on <lf_expr>, and stops before reaching
* <maxsize> characters. Returns the size of the output string in characters,
* not counting the trailing zero which is always added if the resulting size
* is not zero. It requires a valid session and optionally a stream. If the
* stream is NULL, default values will be assumed for the stream part.
*/
int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct list *list_format)
int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct lf_expr *lf_expr)
{
struct proxy *fe = sess->fe;
struct proxy *be;
struct http_txn *txn;
const struct strm_logs *logs;
struct connection *fe_conn, *be_conn;
struct list *list_format = &lf_expr->nodes;
unsigned int s_flags;
unsigned int uniq_id;
struct buffer chunk;
@ -2708,7 +2745,7 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t
tmplog = dst;
/* fill logbuffer */
if (LIST_ISEMPTY(list_format))
if (lf_expr_isempty(lf_expr))
return 0;
list_for_each_entry(tmp, list_format, list) {
@ -3668,11 +3705,11 @@ void strm_log(struct stream *s)
}
/* if unique-id was not generated */
if (!isttest(s->unique_id) && !LIST_ISEMPTY(&sess->fe->format_unique_id)) {
if (!isttest(s->unique_id) && !lf_expr_isempty(&sess->fe->format_unique_id)) {
stream_generate_unique_id(s, &sess->fe->format_unique_id);
}
if (!LIST_ISEMPTY(&sess->fe->logformat_sd)) {
if (!lf_expr_isempty(&sess->fe->logformat_sd)) {
sd_size = build_logline(s, logline_rfc5424, global.max_syslog_len,
&sess->fe->logformat_sd);
}
@ -3710,13 +3747,13 @@ void sess_log(struct session *sess)
if (sess->fe->options2 & PR_O2_LOGERRORS)
level = LOG_ERR;
if (!LIST_ISEMPTY(&sess->fe->logformat_sd)) {
if (!lf_expr_isempty(&sess->fe->logformat_sd)) {
sd_size = sess_build_logline(sess, NULL,
logline_rfc5424, global.max_syslog_len,
&sess->fe->logformat_sd);
}
if (!LIST_ISEMPTY(&sess->fe->logformat_error))
if (!lf_expr_isempty(&sess->fe->logformat_error))
size = sess_build_logline(sess, NULL, logline, global.max_syslog_len, &sess->fe->logformat_error);
else
size = sess_build_logline(sess, NULL, logline, global.max_syslog_len, &sess->fe->logformat);

View File

@ -184,7 +184,7 @@ void free_server_rules(struct list *srules)
list_for_each_entry_safe(srule, sruleb, srules, list) {
LIST_DELETE(&srule->list);
free_acl_cond(srule->cond);
free_logformat_list(&srule->expr);
lf_expr_deinit(&srule->expr);
free(srule->file);
free(srule);
}
@ -264,7 +264,7 @@ void free_proxy(struct proxy *p)
LIST_DELETE(&rule->list);
free_acl_cond(rule->cond);
if (rule->dynamic)
free_logformat_list(&rule->be.expr);
lf_expr_deinit(&rule->be.expr);
free(rule->file);
free(rule);
}
@ -279,10 +279,10 @@ void free_proxy(struct proxy *p)
free_logger(log);
}
free_logformat_list(&p->logformat);
free_logformat_list(&p->logformat_sd);
free_logformat_list(&p->format_unique_id);
free_logformat_list(&p->logformat_error);
lf_expr_deinit(&p->logformat);
lf_expr_deinit(&p->logformat_sd);
lf_expr_deinit(&p->format_unique_id);
lf_expr_deinit(&p->logformat_error);
free_act_rules(&p->tcp_req.inspect_rules);
free_act_rules(&p->tcp_rep.inspect_rules);
@ -1348,10 +1348,10 @@ void init_new_proxy(struct proxy *p)
LIST_INIT(&p->tcp_req.l5_rules);
MT_LIST_INIT(&p->listener_queue);
LIST_INIT(&p->loggers);
LIST_INIT(&p->logformat);
LIST_INIT(&p->logformat_sd);
LIST_INIT(&p->format_unique_id);
LIST_INIT(&p->logformat_error);
lf_expr_init(&p->logformat);
lf_expr_init(&p->logformat_sd);
lf_expr_init(&p->format_unique_id);
lf_expr_init(&p->logformat_error);
LIST_INIT(&p->conf.bind);
LIST_INIT(&p->conf.listeners);
LIST_INIT(&p->conf.errors);

View File

@ -3525,7 +3525,7 @@ static int _srv_parse_finalize(char **args, int cur_arg,
}
list_for_each_entry(srv_tlv, &srv->pp_tlvs, list) {
LIST_INIT(&srv_tlv->fmt);
lf_expr_init(&srv_tlv->fmt);
if (srv_tlv->fmt_string && unlikely(!parse_logformat_string(srv_tlv->fmt_string,
srv->proxy, &srv_tlv->fmt, 0, SMP_VAL_BE_SRV_CON, &errmsg))) {
if (errmsg) {

View File

@ -428,7 +428,7 @@ static void session_kill_embryonic(struct session *sess, unsigned int state)
conn->err_code = CO_ER_SSL_TIMEOUT;
}
if(!LIST_ISEMPTY(&sess->fe->logformat_error)) {
if(!lf_expr_isempty(&sess->fe->logformat_error)) {
/* Display a log line following the configured error-log-format. */
sess_log(sess);
}

View File

@ -920,7 +920,7 @@ void back_establish(struct stream *s)
if (!IS_HTX_STRM(s)) { /* let's allow immediate data connection in this case */
/* if the user wants to log as soon as possible, without counting
* bytes from the server, then this is the right moment. */
if (!LIST_ISEMPTY(&strm_fe(s)->logformat) && !(s->logs.logwait & LW_BYTES)) {
if (!lf_expr_isempty(&strm_fe(s)->logformat) && !(s->logs.logwait & LW_BYTES)) {
/* note: no pend_pos here, session is established */
s->logs.t_close = s->logs.t_connect; /* to get a valid end date */
s->do_log(s);
@ -2597,7 +2597,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
}
/* let's do a final log if we need it */
if (!LIST_ISEMPTY(&sess->fe->logformat) && s->logs.logwait &&
if (!lf_expr_isempty(&sess->fe->logformat) && s->logs.logwait &&
!(s->flags & SF_MONITOR) &&
(!(sess->fe->options & PR_O_NULLNOLOG) || req->total)) {
/* we may need to know the position in the queue */
@ -2847,7 +2847,7 @@ INITCALL0(STG_INIT, init_stream);
* If an ID is already stored within the stream nothing happens existing unique ID is
* returned.
*/
struct ist stream_generate_unique_id(struct stream *strm, struct list *format)
struct ist stream_generate_unique_id(struct stream *strm, struct lf_expr *format)
{
if (isttest(strm->unique_id)) {
return strm->unique_id;

View File

@ -81,7 +81,7 @@ void free_tcpcheck_http_hdr(struct tcpcheck_http_hdr *hdr)
if (!hdr)
return;
free_logformat_list(&hdr->value);
lf_expr_deinit(&hdr->value);
istfree(&hdr->name);
free(hdr);
}
@ -118,28 +118,28 @@ void free_tcpcheck(struct tcpcheck_rule *rule, int in_pool)
break;
case TCPCHK_SEND_STRING_LF:
case TCPCHK_SEND_BINARY_LF:
free_logformat_list(&rule->send.fmt);
lf_expr_deinit(&rule->send.fmt);
break;
case TCPCHK_SEND_HTTP:
free(rule->send.http.meth.str.area);
if (!(rule->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT))
istfree(&rule->send.http.uri);
else
free_logformat_list(&rule->send.http.uri_fmt);
lf_expr_deinit(&rule->send.http.uri_fmt);
istfree(&rule->send.http.vsn);
free_tcpcheck_http_hdrs(&rule->send.http.hdrs);
if (!(rule->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT))
istfree(&rule->send.http.body);
else
free_logformat_list(&rule->send.http.body_fmt);
lf_expr_deinit(&rule->send.http.body_fmt);
break;
case TCPCHK_SEND_UNDEF:
break;
}
break;
case TCPCHK_ACT_EXPECT:
free_logformat_list(&rule->expect.onerror_fmt);
free_logformat_list(&rule->expect.onsuccess_fmt);
lf_expr_deinit(&rule->expect.onerror_fmt);
lf_expr_deinit(&rule->expect.onsuccess_fmt);
release_sample_expr(rule->expect.status_expr);
switch (rule->expect.type) {
case TCPCHK_EXPECT_HTTP_STATUS:
@ -159,20 +159,20 @@ void free_tcpcheck(struct tcpcheck_rule *rule, int in_pool)
case TCPCHK_EXPECT_STRING_LF:
case TCPCHK_EXPECT_BINARY_LF:
case TCPCHK_EXPECT_HTTP_BODY_LF:
free_logformat_list(&rule->expect.fmt);
lf_expr_deinit(&rule->expect.fmt);
break;
case TCPCHK_EXPECT_HTTP_HEADER:
if (rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HNAME_REG)
regex_free(rule->expect.hdr.name_re);
else if (rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HNAME_FMT)
free_logformat_list(&rule->expect.hdr.name_fmt);
lf_expr_deinit(&rule->expect.hdr.name_fmt);
else
istfree(&rule->expect.hdr.name);
if (rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HVAL_REG)
regex_free(rule->expect.hdr.value_re);
else if (rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HVAL_FMT)
free_logformat_list(&rule->expect.hdr.value_fmt);
lf_expr_deinit(&rule->expect.hdr.value_fmt);
else if (!(rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HVAL_NONE))
istfree(&rule->expect.hdr.value);
break;
@ -421,7 +421,7 @@ static void tcpcheck_expect_onerror_message(struct buffer *msg, struct check *ch
chunk_istcat(msg, info);
goto comment;
}
else if (!LIST_ISEMPTY(&rule->expect.onerror_fmt)) {
else if (!lf_expr_isempty(&rule->expect.onerror_fmt)) {
msg->data += sess_build_logline(check->sess, NULL, b_tail(msg), b_room(msg), &rule->expect.onerror_fmt);
goto comment;
}
@ -516,7 +516,7 @@ static void tcpcheck_expect_onsuccess_message(struct buffer *msg, struct check *
*/
if (istlen(info))
chunk_istcat(msg, info);
if (!LIST_ISEMPTY(&rule->expect.onsuccess_fmt))
if (!lf_expr_isempty(&rule->expect.onsuccess_fmt))
msg->data += sess_build_logline(check->sess, NULL, b_tail(msg), b_room(msg),
&rule->expect.onsuccess_fmt);
else if (check->type == PR_O2_TCPCHK_CHK &&
@ -1684,7 +1684,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
/* Set status and description in case of error */
status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7STS);
if (LIST_ISEMPTY(&expect->onerror_fmt))
if (lf_expr_isempty(&expect->onerror_fmt))
desc = htx_sl_res_reason(sl);
break;
case TCPCHK_EXPECT_HTTP_STATUS_REGEX:
@ -1692,7 +1692,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
/* Set status and description in case of error */
status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7STS);
if (LIST_ISEMPTY(&expect->onerror_fmt))
if (lf_expr_isempty(&expect->onerror_fmt))
desc = htx_sl_res_reason(sl);
break;
@ -1823,7 +1823,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
end_of_match:
status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7STS);
if (LIST_ISEMPTY(&expect->onerror_fmt))
if (lf_expr_isempty(&expect->onerror_fmt))
desc = htx_sl_res_reason(sl);
break;
}
@ -1850,7 +1850,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
goto wait_more_data;
}
status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7RSP);
if (LIST_ISEMPTY(&expect->onerror_fmt))
if (lf_expr_isempty(&expect->onerror_fmt))
desc = ist("HTTP content check could not find a response body");
TRACE_ERROR("no response boduy found while expected", CHK_EV_TCPCHK_EXP|CHK_EV_TCPCHK_ERR, check);
goto error;
@ -1899,7 +1899,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
/* Set status and description in case of error */
status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7RSP);
if (LIST_ISEMPTY(&expect->onerror_fmt))
if (lf_expr_isempty(&expect->onerror_fmt))
desc = (inverse
? ist("HTTP check matched unwanted content")
: ist("HTTP content check did not match"));
@ -2636,7 +2636,7 @@ struct tcpcheck_rule *parse_tcpcheck_send(char **args, int cur_arg, struct proxy
}
case TCPCHK_SEND_STRING_LF:
case TCPCHK_SEND_BINARY_LF:
LIST_INIT(&chk->send.fmt);
lf_expr_init(&chk->send.fmt);
px->conf.args.ctx = ARGC_SRV;
if (!parse_logformat_string(data, px, &chk->send.fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
memprintf(errmsg, "'%s' invalid log-format string (%s).\n", data, *errmsg);
@ -2777,7 +2777,7 @@ struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, struct
}
if (uri) {
if (chk->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT) {
LIST_INIT(&chk->send.http.uri_fmt);
lf_expr_init(&chk->send.http.uri_fmt);
px->conf.args.ctx = ARGC_SRV;
if (!parse_logformat_string(uri, px, &chk->send.http.uri_fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
memprintf(errmsg, "'%s' invalid log-format string (%s).\n", uri, *errmsg);
@ -2805,7 +2805,7 @@ struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, struct
memprintf(errmsg, "out of memory");
goto error;
}
LIST_INIT(&hdr->value);
lf_expr_init(&hdr->value);
hdr->name = istdup(hdrs[i].n);
if (!isttest(hdr->name)) {
memprintf(errmsg, "out of memory");
@ -2821,7 +2821,7 @@ struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, struct
if (body) {
if (chk->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT) {
LIST_INIT(&chk->send.http.body_fmt);
lf_expr_init(&chk->send.http.body_fmt);
px->conf.args.ctx = ARGC_SRV;
if (!parse_logformat_string(body, px, &chk->send.http.body_fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
memprintf(errmsg, "'%s' invalid log-format string (%s).\n", body, *errmsg);
@ -3288,8 +3288,8 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
goto error;
}
chk->action = TCPCHK_ACT_EXPECT;
LIST_INIT(&chk->expect.onerror_fmt);
LIST_INIT(&chk->expect.onsuccess_fmt);
lf_expr_init(&chk->expect.onerror_fmt);
lf_expr_init(&chk->expect.onsuccess_fmt);
chk->comment = comment; comment = NULL;
chk->expect.type = type;
chk->expect.min_recv = min_recv;
@ -3382,7 +3382,7 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
case TCPCHK_EXPECT_STRING_LF:
case TCPCHK_EXPECT_BINARY_LF:
case TCPCHK_EXPECT_HTTP_BODY_LF:
LIST_INIT(&chk->expect.fmt);
lf_expr_init(&chk->expect.fmt);
px->conf.args.ctx = ARGC_SRV;
if (!parse_logformat_string(pattern, px, &chk->expect.fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
memprintf(errmsg, "'%s' invalid log-format string (%s).\n", pattern, *errmsg);
@ -3402,7 +3402,7 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
}
else if (chk->expect.flags & TCPCHK_EXPT_FL_HTTP_HNAME_FMT) {
px->conf.args.ctx = ARGC_SRV;
LIST_INIT(&chk->expect.hdr.name_fmt);
lf_expr_init(&chk->expect.hdr.name_fmt);
if (!parse_logformat_string(npat, px, &chk->expect.hdr.name_fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
memprintf(errmsg, "'%s' invalid log-format string (%s).\n", npat, *errmsg);
goto error;
@ -3432,7 +3432,7 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
}
else if (chk->expect.flags & TCPCHK_EXPT_FL_HTTP_HVAL_FMT) {
px->conf.args.ctx = ARGC_SRV;
LIST_INIT(&chk->expect.hdr.value_fmt);
lf_expr_init(&chk->expect.hdr.value_fmt);
if (!parse_logformat_string(vpat, px, &chk->expect.hdr.value_fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
memprintf(errmsg, "'%s' invalid log-format string (%s).\n", npat, *errmsg);
goto error;
@ -3484,7 +3484,6 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
*/
void tcpcheck_overwrite_send_http_rule(struct tcpcheck_rule *old, struct tcpcheck_rule *new)
{
struct logformat_node *lf, *lfb;
struct tcpcheck_http_hdr *hdr, *bhdr;
@ -3500,22 +3499,19 @@ void tcpcheck_overwrite_send_http_rule(struct tcpcheck_rule *old, struct tcpchec
if (!(old->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT))
istfree(&old->send.http.uri);
else
free_logformat_list(&old->send.http.uri_fmt);
lf_expr_deinit(&old->send.http.uri_fmt);
old->send.http.flags &= ~TCPCHK_SND_HTTP_FL_URI_FMT;
old->send.http.uri = new->send.http.uri;
new->send.http.uri = IST_NULL;
}
else if ((new->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT) && !LIST_ISEMPTY(&new->send.http.uri_fmt)) {
else if ((new->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT) && !lf_expr_isempty(&new->send.http.uri_fmt)) {
if (!(old->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT))
istfree(&old->send.http.uri);
else
free_logformat_list(&old->send.http.uri_fmt);
lf_expr_deinit(&old->send.http.uri_fmt);
old->send.http.flags |= TCPCHK_SND_HTTP_FL_URI_FMT;
LIST_INIT(&old->send.http.uri_fmt);
list_for_each_entry_safe(lf, lfb, &new->send.http.uri_fmt, list) {
LIST_DELETE(&lf->list);
LIST_APPEND(&old->send.http.uri_fmt, &lf->list);
}
lf_expr_init(&old->send.http.uri_fmt);
lf_expr_xfer(&new->send.http.uri_fmt, &old->send.http.uri_fmt);
}
if (isttest(new->send.http.vsn)) {
@ -3536,22 +3532,19 @@ void tcpcheck_overwrite_send_http_rule(struct tcpcheck_rule *old, struct tcpchec
if (!(old->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT))
istfree(&old->send.http.body);
else
free_logformat_list(&old->send.http.body_fmt);
lf_expr_deinit(&old->send.http.body_fmt);
old->send.http.flags &= ~TCPCHK_SND_HTTP_FL_BODY_FMT;
old->send.http.body = new->send.http.body;
new->send.http.body = IST_NULL;
}
else if ((new->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT) && !LIST_ISEMPTY(&new->send.http.body_fmt)) {
else if ((new->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT) && !lf_expr_isempty(&new->send.http.body_fmt)) {
if (!(old->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT))
istfree(&old->send.http.body);
else
free_logformat_list(&old->send.http.body_fmt);
lf_expr_deinit(&old->send.http.body_fmt);
old->send.http.flags |= TCPCHK_SND_HTTP_FL_BODY_FMT;
LIST_INIT(&old->send.http.body_fmt);
list_for_each_entry_safe(lf, lfb, &new->send.http.body_fmt, list) {
LIST_DELETE(&lf->list);
LIST_APPEND(&old->send.http.body_fmt, &lf->list);
}
lf_expr_init(&old->send.http.body_fmt);
lf_expr_xfer(&new->send.http.body_fmt, &old->send.http.body_fmt);
}
}
@ -3802,8 +3795,8 @@ int add_tcpcheck_expect_str(struct tcpcheck_rules *rules, const char *str)
expect = &tcpcheck->expect;
expect->type = TCPCHK_EXPECT_STRING;
LIST_INIT(&expect->onerror_fmt);
LIST_INIT(&expect->onsuccess_fmt);
lf_expr_init(&expect->onerror_fmt);
lf_expr_init(&expect->onsuccess_fmt);
expect->ok_status = HCHK_STATUS_L7OKD;
expect->err_status = HCHK_STATUS_L7RSP;
expect->tout_status = HCHK_STATUS_L7TOUT;

View File

@ -787,7 +787,7 @@ static enum act_return action_store(struct act_rule *rule, struct proxy *px,
/* Process the expression. */
memset(&smp, 0, sizeof(smp));
if (!LIST_ISEMPTY(&rule->arg.vars.fmt)) {
if (!lf_expr_isempty(&rule->arg.vars.fmt)) {
/* a format-string is used */
fmtstr = alloc_trash_chunk();
@ -838,7 +838,7 @@ static enum act_return action_clear(struct act_rule *rule, struct proxy *px,
static void release_store_rule(struct act_rule *rule)
{
free_logformat_list(&rule->arg.vars.fmt);
lf_expr_deinit(&rule->arg.vars.fmt);
release_sample_expr(rule->arg.vars.expr);
}
@ -942,7 +942,7 @@ static enum act_parse_ret parse_store(const char **args, int *arg, struct proxy
condition = istsplit(&var, ',');
}
LIST_INIT(&rule->arg.vars.fmt);
lf_expr_init(&rule->arg.vars.fmt);
if (!vars_hash_name(var_name, var_len, &rule->arg.vars.scope, &rule->arg.vars.name_hash, err))
return ACT_RET_PRS_ERR;