mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-28 22:31:06 +01:00
MEDIUM: checks: Support log-format strings for tcp-check send rules
An extra parameter for tcp-check send rules can be specified to handle the
string or the hexa string as a log-format one. Using "log-format" option,
instead of considering the data to send as raw data, it is parsed as a
log-format string. Thus it is possible to call sample fetches to customize data
sent to a server. Of course, because we have no stream attached to healthchecks,
not all sample fetches are available. So be careful.
tcp-check set-var(check.port) int(8000)
tcp-check set-var(check.uri) str(/status)
tcp-check connect port var(check.port)
tcp-check send "GET %[check.uri] HTTP/1.0\r\n" log-format
tcp-check send "Host: %[srv_name]\r\n" log-format
tcp-check send "\r\n"
This commit is contained in:
parent
b7d30098f3
commit
f50f4e956f
@ -230,15 +230,19 @@ struct tcpcheck_connect {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum tcpcheck_send_type {
|
enum tcpcheck_send_type {
|
||||||
TCPCHK_SEND_UNDEF = 0, /* Send is not parsed. */
|
TCPCHK_SEND_UNDEF = 0, /* Send is not parsed. */
|
||||||
TCPCHK_SEND_STRING, /* Send an ASCII string. */
|
TCPCHK_SEND_STRING, /* Send an ASCII string. */
|
||||||
TCPCHK_SEND_BINARY, /* Send a binary sequence. */
|
TCPCHK_SEND_BINARY, /* Send a binary sequence. */
|
||||||
|
TCPCHK_SEND_STRING_LF, /* Send an ASCII log-format string. */
|
||||||
|
TCPCHK_SEND_BINARY_LF, /* Send a binary log-format sequence. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tcpcheck_send {
|
struct tcpcheck_send {
|
||||||
enum tcpcheck_send_type type;
|
enum tcpcheck_send_type type;
|
||||||
char *string; /* Sending an ASCII string or a binary sequence. */
|
union {
|
||||||
int length; /* Size in bytes of the sequence referenced by string / binary. */
|
struct ist data; /* an ASCII string or a binary sequence */
|
||||||
|
struct list fmt; /* an ASCII or hexa log-format string */
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
enum tcpcheck_expect_type {
|
enum tcpcheck_expect_type {
|
||||||
|
|||||||
155
src/checks.c
155
src/checks.c
@ -3028,24 +3028,41 @@ static enum tcpcheck_eval_ret tcpcheck_eval_send(struct check *check, struct tcp
|
|||||||
struct tcpcheck_send *send = &rule->send;
|
struct tcpcheck_send *send = &rule->send;
|
||||||
struct conn_stream *cs = check->cs;
|
struct conn_stream *cs = check->cs;
|
||||||
struct connection *conn = cs_conn(cs);
|
struct connection *conn = cs_conn(cs);
|
||||||
|
struct buffer *tmp = NULL;
|
||||||
|
|
||||||
/* reset the read & write buffer */
|
/* reset the read & write buffer */
|
||||||
b_reset(&check->bi);
|
b_reset(&check->bi);
|
||||||
b_reset(&check->bo);
|
b_reset(&check->bo);
|
||||||
|
|
||||||
if (send->length >= b_size(&check->bo)) {
|
|
||||||
chunk_printf(&trash, "tcp-check send : string too large (%d) for buffer size (%u) at step %d",
|
|
||||||
send->length, (unsigned int)b_size(&check->bo),
|
|
||||||
tcpcheck_get_step_id(check, rule));
|
|
||||||
set_server_check_status(check, HCHK_STATUS_L7RSP, trash.area);
|
|
||||||
ret = TCPCHK_EVAL_STOP;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (send->type) {
|
switch (send->type) {
|
||||||
case TCPCHK_SEND_STRING:
|
case TCPCHK_SEND_STRING:
|
||||||
case TCPCHK_SEND_BINARY:
|
case TCPCHK_SEND_BINARY:
|
||||||
b_putblk(&check->bo, send->string, send->length);
|
if (istlen(send->data) >= b_size(&check->bo)) {
|
||||||
|
chunk_printf(&trash, "tcp-check send : string too large (%u) for buffer size (%u) at step %d",
|
||||||
|
(unsigned int)istlen(send->data), (unsigned int)b_size(&check->bo),
|
||||||
|
tcpcheck_get_step_id(check, rule));
|
||||||
|
set_server_check_status(check, HCHK_STATUS_L7RSP, trash.area);
|
||||||
|
ret = TCPCHK_EVAL_STOP;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
b_putist(&check->bo, send->data);
|
||||||
|
break;
|
||||||
|
case TCPCHK_SEND_STRING_LF:
|
||||||
|
check->bo.data = sess_build_logline(check->sess, NULL, b_orig(&check->bo), b_size(&check->bo), &rule->send.fmt);
|
||||||
|
if (!b_data(&check->bo))
|
||||||
|
goto out;
|
||||||
|
break;
|
||||||
|
case TCPCHK_SEND_BINARY_LF:
|
||||||
|
tmp = alloc_trash_chunk();
|
||||||
|
if (!tmp)
|
||||||
|
goto error_lf;
|
||||||
|
tmp->data = sess_build_logline(check->sess, NULL, b_orig(tmp), b_size(tmp), &rule->send.fmt);
|
||||||
|
if (!b_data(tmp))
|
||||||
|
goto out;
|
||||||
|
tmp->area[tmp->data] = '\0';
|
||||||
|
b_set_data(&check->bo, b_size(&check->bo));
|
||||||
|
if (parse_binary(b_orig(tmp), &check->bo.area, (int *)&check->bo.data, NULL) == 0)
|
||||||
|
goto error_lf;
|
||||||
break;
|
break;
|
||||||
case TCPCHK_SEND_UNDEF:
|
case TCPCHK_SEND_UNDEF:
|
||||||
/* Should never happen. */
|
/* Should never happen. */
|
||||||
@ -3066,7 +3083,16 @@ static enum tcpcheck_eval_ret tcpcheck_eval_send(struct check *check, struct tcp
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
free_trash_chunk(tmp);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
error_lf:
|
||||||
|
chunk_printf(&trash, "tcp-check send : failed to build log-format string at step %d",
|
||||||
|
tcpcheck_get_step_id(check, rule));
|
||||||
|
set_server_check_status(check, HCHK_STATUS_L7RSP, trash.area);
|
||||||
|
ret = TCPCHK_EVAL_STOP;
|
||||||
|
goto out;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate a TCPCHK_ACT_EXPECT rule. It returns 1 to evaluate the next rule, 0
|
/* Evaluate a TCPCHK_ACT_EXPECT rule. It returns 1 to evaluate the next rule, 0
|
||||||
@ -3443,6 +3469,8 @@ void free_check(struct check *check)
|
|||||||
|
|
||||||
static void free_tcpcheck(struct tcpcheck_rule *rule, int in_pool)
|
static void free_tcpcheck(struct tcpcheck_rule *rule, int in_pool)
|
||||||
{
|
{
|
||||||
|
struct logformat_node *lf, *lfb;
|
||||||
|
|
||||||
if (!rule)
|
if (!rule)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -3452,7 +3480,16 @@ static void free_tcpcheck(struct tcpcheck_rule *rule, int in_pool)
|
|||||||
switch (rule->send.type) {
|
switch (rule->send.type) {
|
||||||
case TCPCHK_SEND_STRING:
|
case TCPCHK_SEND_STRING:
|
||||||
case TCPCHK_SEND_BINARY:
|
case TCPCHK_SEND_BINARY:
|
||||||
free(rule->send.string);
|
free(rule->send.data.ptr);
|
||||||
|
break;
|
||||||
|
case TCPCHK_SEND_STRING_LF:
|
||||||
|
case TCPCHK_SEND_BINARY_LF:
|
||||||
|
list_for_each_entry_safe(lf, lfb, &rule->send.fmt, list) {
|
||||||
|
LIST_DEL(&lf->list);
|
||||||
|
release_sample_expr(lf->expr);
|
||||||
|
free(lf->arg);
|
||||||
|
free(lf);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TCPCHK_SEND_UNDEF:
|
case TCPCHK_SEND_UNDEF:
|
||||||
break;
|
break;
|
||||||
@ -3669,15 +3706,15 @@ static int add_tcpcheck_send_strs(struct list *list, const char * const *strs)
|
|||||||
send->type = TCPCHK_SEND_STRING;
|
send->type = TCPCHK_SEND_STRING;
|
||||||
|
|
||||||
for (i = 0; strs[i]; i++)
|
for (i = 0; strs[i]; i++)
|
||||||
send->length += strlen(strs[i]);
|
send->data.len += strlen(strs[i]);
|
||||||
|
|
||||||
send->string = malloc(send->length + 1);
|
send->data.ptr = malloc(send->data.len + 1);
|
||||||
if (!send->string) {
|
if (!isttest(send->data)) {
|
||||||
pool_free(pool_head_tcpcheck_rule, tcpcheck);
|
pool_free(pool_head_tcpcheck_rule, tcpcheck);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dst = send->string;
|
dst = send->data.ptr;
|
||||||
for (i = 0; strs[i]; i++)
|
for (i = 0; strs[i]; i++)
|
||||||
for (in = strs[i]; (*dst = *in++); dst++);
|
for (in = strs[i]; (*dst = *in++); dst++);
|
||||||
*dst = 0;
|
*dst = 0;
|
||||||
@ -4283,12 +4320,12 @@ static struct tcpcheck_rule *parse_tcpcheck_connect(char **args, int cur_arg, st
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tcpcheck_rule *parse_tcpcheck_send(char **args, int cur_arg, struct list *rules, char **errmsg)
|
static struct tcpcheck_rule *parse_tcpcheck_send(char **args, int cur_arg, struct proxy *px, struct list *rules,
|
||||||
|
char **errmsg)
|
||||||
{
|
{
|
||||||
struct tcpcheck_rule *chk = NULL;
|
struct tcpcheck_rule *chk = NULL;
|
||||||
char *str = NULL, *comment = NULL;
|
char *comment = NULL, *data = NULL;
|
||||||
enum tcpcheck_send_type type = TCPCHK_SEND_UNDEF;
|
enum tcpcheck_send_type type = TCPCHK_SEND_UNDEF;
|
||||||
int len;
|
|
||||||
|
|
||||||
type = ((strcmp(args[cur_arg], "send-binary") == 0) ? TCPCHK_SEND_BINARY : TCPCHK_SEND_STRING);
|
type = ((strcmp(args[cur_arg], "send-binary") == 0) ? TCPCHK_SEND_BINARY : TCPCHK_SEND_STRING);
|
||||||
if (!*(args[cur_arg+1])) {
|
if (!*(args[cur_arg+1])) {
|
||||||
@ -4297,33 +4334,35 @@ static struct tcpcheck_rule *parse_tcpcheck_send(char **args, int cur_arg, struc
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == TCPCHK_SEND_BINARY) {
|
data = args[cur_arg+1];
|
||||||
if (parse_binary(args[cur_arg+1], &str, &len, errmsg) == 0) {
|
|
||||||
memprintf(errmsg, "'%s' invalid binary string (%s).\n", args[cur_arg], *errmsg);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
str = strdup(args[cur_arg+1]);
|
|
||||||
len = strlen(args[cur_arg+1]);
|
|
||||||
if (!str) {
|
|
||||||
memprintf(errmsg, "out of memory");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cur_arg++;
|
|
||||||
|
|
||||||
if (strcmp(args[cur_arg], "comment") == 0) {
|
cur_arg += 2;
|
||||||
if (!*(args[cur_arg+1])) {
|
while (*(args[cur_arg])) {
|
||||||
memprintf(errmsg, "'%s' expects a string as argument.", args[cur_arg]);
|
if (strcmp(args[cur_arg], "comment") == 0) {
|
||||||
|
if (!*(args[cur_arg+1])) {
|
||||||
|
memprintf(errmsg, "'%s' expects a string as argument.", args[cur_arg]);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
cur_arg++;
|
||||||
|
free(comment);
|
||||||
|
comment = strdup(args[cur_arg]);
|
||||||
|
if (!comment) {
|
||||||
|
memprintf(errmsg, "out of memory");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(args[cur_arg], "log-format") == 0) {
|
||||||
|
if (type == TCPCHK_SEND_BINARY)
|
||||||
|
type = TCPCHK_SEND_BINARY_LF;
|
||||||
|
else if (type == TCPCHK_SEND_STRING)
|
||||||
|
type = TCPCHK_SEND_STRING_LF;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memprintf(errmsg, "expects 'comment', 'log-format' but got '%s' as argument.",
|
||||||
|
args[cur_arg]);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
cur_arg++;
|
cur_arg++;
|
||||||
comment = strdup(args[cur_arg]);
|
|
||||||
if (!comment) {
|
|
||||||
memprintf(errmsg, "out of memory");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chk = calloc(1, sizeof(*chk));
|
chk = calloc(1, sizeof(*chk));
|
||||||
@ -4334,12 +4373,38 @@ static struct tcpcheck_rule *parse_tcpcheck_send(char **args, int cur_arg, struc
|
|||||||
chk->action = TCPCHK_ACT_SEND;
|
chk->action = TCPCHK_ACT_SEND;
|
||||||
chk->comment = comment;
|
chk->comment = comment;
|
||||||
chk->send.type = type;
|
chk->send.type = type;
|
||||||
chk->send.string = str;
|
|
||||||
chk->send.length = len;
|
switch (chk->send.type) {
|
||||||
|
case TCPCHK_SEND_STRING:
|
||||||
|
chk->send.data = ist2(strdup(data), strlen(data));
|
||||||
|
if (!isttest(chk->send.data)) {
|
||||||
|
memprintf(errmsg, "out of memory");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TCPCHK_SEND_BINARY:
|
||||||
|
if (parse_binary(data, &chk->send.data.ptr, (int *)&chk->send.data.len, errmsg) == 0) {
|
||||||
|
memprintf(errmsg, "'%s' invalid binary string (%s).\n", data, *errmsg);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TCPCHK_SEND_STRING_LF:
|
||||||
|
case TCPCHK_SEND_BINARY_LF:
|
||||||
|
LIST_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);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TCPCHK_SEND_UNDEF:
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
return chk;
|
return chk;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
free(str);
|
free(chk);
|
||||||
free(comment);
|
free(comment);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -4578,7 +4643,7 @@ static int proxy_parse_tcpcheck(char **args, int section, struct proxy *curpx,
|
|||||||
if (strcmp(args[cur_arg], "connect") == 0)
|
if (strcmp(args[cur_arg], "connect") == 0)
|
||||||
chk = parse_tcpcheck_connect(args, cur_arg, curpx, rules, file, line, errmsg);
|
chk = parse_tcpcheck_connect(args, cur_arg, curpx, rules, file, line, errmsg);
|
||||||
else if (strcmp(args[cur_arg], "send") == 0 || strcmp(args[cur_arg], "send-binary") == 0)
|
else if (strcmp(args[cur_arg], "send") == 0 || strcmp(args[cur_arg], "send-binary") == 0)
|
||||||
chk = parse_tcpcheck_send(args, cur_arg, rules, errmsg);
|
chk = parse_tcpcheck_send(args, cur_arg, curpx, rules, errmsg);
|
||||||
else if (strcmp(args[cur_arg], "expect") == 0)
|
else if (strcmp(args[cur_arg], "expect") == 0)
|
||||||
chk = parse_tcpcheck_expect(args, cur_arg, rules, errmsg);
|
chk = parse_tcpcheck_expect(args, cur_arg, rules, errmsg);
|
||||||
else if (strcmp(args[cur_arg], "comment") == 0)
|
else if (strcmp(args[cur_arg], "comment") == 0)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user