MINOR: checks: define a tcp expect type
Extract the expect definition from its tcpcheck ; create a standalone type.
diff --git a/include/types/checks.h b/include/types/checks.h
index d284d3f..36b22fe 100644
--- a/include/types/checks.h
+++ b/include/types/checks.h
@@ -211,6 +211,25 @@
unsigned char lr[HANA_OBS_SIZE]; /* result for l4/l7: 0 = ignore, 1 - error, 2 - OK */
};
+enum tcpcheck_expect_type {
+ TCPCHK_EXPECT_UNDEF = 0, /* Match is not used. */
+ TCPCHK_EXPECT_STRING, /* Matches a string. */
+ TCPCHK_EXPECT_REGEX, /* Matches a regular pattern. */
+ TCPCHK_EXPECT_BINARY, /* Matches a binary sequence. */
+};
+
+struct tcpcheck_expect {
+ enum tcpcheck_expect_type type; /* Type of pattern used for matching. */
+ union {
+ char *string; /* Matching a literal string / binary anywhere in the response. */
+ struct my_regex *regex; /* Matching a regex pattern. */
+ };
+ struct tcpcheck_rule *head; /* first expect of a chain. */
+ int length; /* Size in bytes of the pattern referenced by string / binary. */
+ int inverse; /* Match is inversed. */
+ int min_recv; /* Minimum amount of data before an expect can be applied. (default: -1, ignored) */
+};
+
/* possible actions for tcpcheck_rule->action */
enum tcpcheck_rule_type {
TCPCHK_ACT_SEND = 0, /* send action, regular string format */
@@ -229,16 +248,11 @@
struct list list; /* list linked to from the proxy */
enum tcpcheck_rule_type action; /* type of the rule. */
char *comment; /* comment to be used in the logs and on the stats socket */
- /* match type uses NON-NULL pointer from either string or expect_regex below */
- /* sent string is string */
- char *string; /* sent or expected string */
- int string_len; /* string length */
- int min_recv; /* Minimum amount of data before an expect can be applied. (default: -1, ignored) */
- struct my_regex *expect_regex; /* expected */
- int inverse; /* 0 = regular match, 1 = inverse match */
+ char *string; /* sent string */
+ int string_len; /* sent string length */
+ struct tcpcheck_expect expect; /* Expected pattern. */
unsigned short port; /* port to connect to */
unsigned short conn_opts; /* options when setting up a new connection */
- struct tcpcheck_rule *expect_head; /* first expect of a chain. */
};
#endif /* _TYPES_CHECKS_H */
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index 1f74ddb..6c1d986 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -3142,7 +3142,6 @@
tcpcheck->action = TCPCHK_ACT_SEND;
tcpcheck->string_len = strlen(args[2]);
tcpcheck->string = strdup(args[2]);
- tcpcheck->expect_regex = NULL;
/* comment for this tcpcheck line */
if (strcmp(args[3], "comment") == 0) {
@@ -3178,7 +3177,6 @@
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- tcpcheck->expect_regex = NULL;
/* comment for this tcpcheck line */
if (strcmp(args[3], "comment") == 0) {
@@ -3196,6 +3194,7 @@
}
else if (strcmp(args[1], "expect") == 0) {
struct tcpcheck_rule *tcpcheck, *prev_check;
+ struct tcpcheck_expect *expect;
long min_recv = -1;
const char *ptr_arg;
int cur_arg;
@@ -3249,8 +3248,9 @@
tcpcheck = calloc(1, sizeof(*tcpcheck));
tcpcheck->action = TCPCHK_ACT_EXPECT;
- tcpcheck->inverse = inverse;
- tcpcheck->min_recv = min_recv;
+ expect = &tcpcheck->expect;
+ expect->inverse = inverse;
+ expect->min_recv = min_recv;
if (strcmp(ptr_arg, "binary") == 0) {
char *err = NULL;
@@ -3262,7 +3262,8 @@
goto out;
}
- if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
+ expect->type = TCPCHK_EXPECT_BINARY;
+ if (parse_binary(args[cur_arg + 1], &expect->string, &expect->length, &err) == 0) {
ha_alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
file, linenum, args[0], args[1], args[2], err);
err_code |= ERR_ALERT | ERR_FATAL;
@@ -3277,8 +3278,9 @@
goto out;
}
- tcpcheck->string_len = strlen(args[cur_arg + 1]);
- tcpcheck->string = strdup(args[cur_arg + 1]);
+ expect->type = TCPCHK_EXPECT_STRING;
+ expect->string = strdup(args[cur_arg + 1]);
+ expect->length = strlen(expect->string);
}
else if (strcmp(ptr_arg, "rstring") == 0) {
if (!*(args[cur_arg + 1])) {
@@ -3288,8 +3290,10 @@
goto out;
}
+ expect->type = TCPCHK_EXPECT_REGEX;
+
error = NULL;
- if (!(tcpcheck->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
+ if (!(expect->regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n",
file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
free(error);
@@ -3319,11 +3323,11 @@
/* All tcp-check expect points back to the first inverse expect rule
* in a chain of one or more expect rule, potentially itself.
*/
- tcpcheck->expect_head = tcpcheck;
+ tcpcheck->expect.head = tcpcheck;
list_for_each_entry_rev(prev_check, &curproxy->tcpcheck_rules, list) {
if (prev_check->action == TCPCHK_ACT_EXPECT) {
- if (prev_check->inverse)
- tcpcheck->expect_head = prev_check;
+ if (prev_check->expect.inverse)
+ tcpcheck->expect.head = prev_check;
continue;
}
if (prev_check->action != TCPCHK_ACT_COMMENT)
diff --git a/src/checks.c b/src/checks.c
index 65030af..ef82c41 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -640,10 +640,22 @@
chunk_appendf(chk, " (connect)");
}
else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_EXPECT) {
- if (check->last_started_step->string)
- chunk_appendf(chk, " (expect string '%s')", check->last_started_step->string);
- else if (check->last_started_step->expect_regex)
+ struct tcpcheck_expect *expect = &check->last_started_step->expect;
+
+ switch (expect->type) {
+ case TCPCHK_EXPECT_STRING:
+ chunk_appendf(chk, " (expect string '%s')", expect->string);
+ break;
+ case TCPCHK_EXPECT_BINARY:
+ chunk_appendf(chk, " (expect binary '%s')", expect->string);
+ break;
+ case TCPCHK_EXPECT_REGEX:
chunk_appendf(chk, " (expect regex)");
+ break;
+ case TCPCHK_EXPECT_UNDEF:
+ chunk_appendf(chk, " (undefined expect!)");
+ break;
+ }
}
else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_SEND) {
chunk_appendf(chk, " (send)");
@@ -3100,6 +3112,8 @@
} /* end 'send' */
else if (check->current_step->action == TCPCHK_ACT_EXPECT) {
+ struct tcpcheck_expect *expect = &check->current_step->expect;
+
if (unlikely(check->result == CHK_RES_FAILED))
goto out_end_tcpcheck;
@@ -3128,7 +3142,7 @@
}
/* Having received new data, reset the expect chain to its head. */
- check->current_step = check->current_step->expect_head;
+ check->current_step = expect->head;
/* mark the step as started */
check->last_started_step = check->current_step;
@@ -3165,39 +3179,61 @@
}
tcpcheck_expect:
-
/* The current expect might need more data than the previous one, check again
* that the minimum amount data required to match is respected.
*/
- if (!done &&
- (((check->current_step->string != NULL) && (b_data(&check->bi) < check->current_step->string_len)) ||
- ((check->current_step->min_recv > 0 && (b_data(&check->bi) < check->current_step->min_recv)))))
- continue; /* try to read more */
- if (check->current_step->string != NULL)
- ret = my_memmem(contentptr, b_data(&check->bi), check->current_step->string, check->current_step->string_len) != NULL;
- else if (check->current_step->expect_regex != NULL)
- ret = regex_exec(check->current_step->expect_regex, contentptr);
+ if (!done) {
+ if ((expect->type == TCPCHK_EXPECT_STRING || expect->type == TCPCHK_EXPECT_BINARY) &&
+ (b_data(&check->bi) < expect->length))
+ continue; /* try to read more */
+ if (expect->min_recv > 0 && (b_data(&check->bi) < expect->min_recv))
+ continue; /* try to read more */
+ }
+
+ switch (expect->type) {
+ case TCPCHK_EXPECT_STRING:
+ case TCPCHK_EXPECT_BINARY:
+ ret = my_memmem(contentptr, b_data(&check->bi), expect->string, expect->length) != NULL;
+ break;
+ case TCPCHK_EXPECT_REGEX:
+ ret = regex_exec(expect->regex, contentptr);
+ break;
+ case TCPCHK_EXPECT_UNDEF:
+ /* Should never happen. */
+ retcode = -1;
+ goto out;
+ }
/* Wait for more data on mismatch only if no minimum is defined (-1),
* otherwise the absence of match is already conclusive.
*/
- if (!ret && !done && (check->current_step->min_recv == -1))
+ if (!ret && !done && (expect->min_recv == -1))
continue; /* try to read more */
/* matched */
step = tcpcheck_get_step_id(check);
if (ret) {
/* matched but we did not want to => ERROR */
- if (check->current_step->inverse) {
- /* we were looking for a string */
- if (check->current_step->string != NULL) {
+ if (expect->inverse) {
+ switch (expect->type) {
+ case TCPCHK_EXPECT_STRING:
chunk_printf(&trash, "TCPCHK matched unwanted content '%s' at step %d",
- check->current_step->string, step);
- }
- else {
- /* we were looking for a regex */
- chunk_printf(&trash, "TCPCHK matched unwanted content (regex) at step %d", step);
+ expect->string, step);
+ break;
+ case TCPCHK_EXPECT_BINARY:
+ chunk_printf(&trash, "TCPCHK matched unwanted content (binary) at step %d",
+ step);
+ break;
+ case TCPCHK_EXPECT_REGEX:
+ chunk_printf(&trash, "TCPCHK matched unwanted content (regex) at step %d",
+ step);
+ break;
+ case TCPCHK_EXPECT_UNDEF:
+ /* Should never happen. */
+ retcode = -1;
+ goto out;
}
+
comment = tcpcheck_get_step_comment(check, step);
if (comment)
chunk_appendf(&trash, " comment: '%s'", comment);
@@ -3218,14 +3254,16 @@
if (&check->current_step->list == head)
break;
- if (check->current_step->action == TCPCHK_ACT_EXPECT)
+ if (check->current_step->action == TCPCHK_ACT_EXPECT) {
+ expect = &check->current_step->expect;
goto tcpcheck_expect;
+ }
}
}
else {
/* not matched */
/* not matched and was not supposed to => OK, next step */
- if (check->current_step->inverse) {
+ if (expect->inverse) {
/* allow next rule */
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
@@ -3237,21 +3275,32 @@
if (&check->current_step->list == head)
break;
- if (check->current_step->action == TCPCHK_ACT_EXPECT)
+ if (check->current_step->action == TCPCHK_ACT_EXPECT) {
+ expect = &check->current_step->expect;
goto tcpcheck_expect;
+ }
}
/* not matched but was supposed to => ERROR */
else {
- /* we were looking for a string */
- if (check->current_step->string != NULL) {
+ switch (expect->type) {
+ case TCPCHK_EXPECT_STRING:
chunk_printf(&trash, "TCPCHK did not match content '%s' at step %d",
check->current_step->string, step);
- }
- else {
- /* we were looking for a regex */
+ break;
+ case TCPCHK_EXPECT_BINARY:
+ chunk_printf(&trash, "TCPCHK did not match content (binary) at step %d",
+ step);
+ break;
+ case TCPCHK_EXPECT_REGEX:
chunk_printf(&trash, "TCPCHK did not match content (regex) at step %d",
- step);
+ step);
+ break;
+ case TCPCHK_EXPECT_UNDEF:
+ /* Should never happen. */
+ retcode = -1;
+ goto out;
}
+
comment = tcpcheck_get_step_comment(check, step);
if (comment)
chunk_appendf(&trash, " comment: '%s'", comment);
@@ -3358,8 +3407,17 @@
list_for_each_entry_safe(rule, back, &alert->tcpcheck_rules, list) {
LIST_DEL(&rule->list);
free(rule->comment);
- free(rule->string);
- regex_free(rule->expect_regex);
+ switch (rule->expect.type) {
+ case TCPCHK_EXPECT_STRING:
+ case TCPCHK_EXPECT_BINARY:
+ free(rule->expect.string);
+ break;
+ case TCPCHK_EXPECT_REGEX:
+ regex_free(rule->expect.regex);
+ break;
+ case TCPCHK_EXPECT_UNDEF:
+ break;
+ }
pool_free(pool_head_tcpcheck_rule, rule);
}
pool_free(pool_head_email_alert, alert);
@@ -3480,27 +3538,30 @@
static int add_tcpcheck_expect_str(struct list *list, const char *str)
{
struct tcpcheck_rule *tcpcheck, *prev_check;
+ struct tcpcheck_expect *expect;
if ((tcpcheck = pool_alloc(pool_head_tcpcheck_rule)) == NULL)
return 0;
memset(tcpcheck, 0, sizeof(*tcpcheck));
- tcpcheck->action = TCPCHK_ACT_EXPECT;
- tcpcheck->string = strdup(str);
- tcpcheck->expect_regex = NULL;
- tcpcheck->comment = NULL;
- if (!tcpcheck->string) {
+ tcpcheck->action = TCPCHK_ACT_EXPECT;
+
+ expect = &tcpcheck->expect;
+ expect->type = TCPCHK_EXPECT_STRING;
+ expect->string = strdup(str);
+ if (!expect->string) {
pool_free(pool_head_tcpcheck_rule, tcpcheck);
return 0;
}
+ expect->length = strlen(expect->string);
/* All tcp-check expect points back to the first inverse expect rule
* in a chain of one or more expect rule, potentially itself.
*/
- tcpcheck->expect_head = tcpcheck;
+ tcpcheck->expect.head = tcpcheck;
list_for_each_entry_rev(prev_check, list, list) {
if (prev_check->action == TCPCHK_ACT_EXPECT) {
- if (prev_check->inverse)
- tcpcheck->expect_head = prev_check;
+ if (prev_check->expect.inverse)
+ tcpcheck->expect.head = prev_check;
continue;
}
if (prev_check->action != TCPCHK_ACT_COMMENT)
@@ -3521,7 +3582,6 @@
return 0;
memset(tcpcheck, 0, sizeof(*tcpcheck));
tcpcheck->action = TCPCHK_ACT_SEND;
- tcpcheck->expect_regex = NULL;
tcpcheck->comment = NULL;
tcpcheck->string_len = 0;
for (i = 0; strs[i]; i++)
@@ -3561,7 +3621,6 @@
tcpcheck->action = TCPCHK_ACT_CONNECT;
tcpcheck->comment = NULL;
tcpcheck->string = NULL;
- tcpcheck->expect_regex = NULL;
LIST_ADDQ(&alert->tcpcheck_rules, &tcpcheck->list);
if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "220 "))