SHA256
1
0
forked from pool/haproxy

Accepting request 314323 from network:ha-clustering:Factory

1

OBS-URL: https://build.opensuse.org/request/show/314323
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/haproxy?expand=0&rev=30
This commit is contained in:
Dominique Leuenberger 2015-06-30 08:19:18 +00:00 committed by Git OBS Bridge
parent bc564798e8
commit 6ef3b657c7
13 changed files with 90 additions and 767 deletions

View File

@ -1,32 +0,0 @@
From 0aa5899911bbc765ba16ce52a80fa76230781779 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Mon, 4 May 2015 18:07:56 +0200
Subject: [PATCH 1/2] BUG/MEDIUM: stats: properly initialize the scope before
dumping stats
Issuing a "show sess all" prior to a "show stat" on the CLI results in no
proxy being dumped because the scope_len union member was not properly
reinitialized.
This fix must be backported into 1.5.
(cherry picked from commit 6bcb95da5b9cb143088102b460c7bcb37c1b3d81)
---
src/dumpstats.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/dumpstats.c b/src/dumpstats.c
index b616478..ca084ac 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -1109,6 +1109,8 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
arg++;
}
+ appctx->ctx.stats.scope_str = 0;
+ appctx->ctx.stats.scope_len = 0;
appctx->ctx.stats.flags = 0;
if (strcmp(args[0], "show") == 0) {
if (strcmp(args[1], "stat") == 0) {
--
2.1.4

View File

@ -1,82 +0,0 @@
From 294e4676a3b775a7accb50eb8428f293c218b5e2 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Mon, 11 May 2015 18:30:33 +0200
Subject: [PATCH 2/2] BUG/MEDIUM: http: don't forward client shutdown without
NOLINGER except for tunnels
There's an issue related with shutting down POST transfers or closing the
connection after the end of the upload : the shutdown is forwarded to the
server regardless of the abortonclose option. The problem it causes is that
during a scan, brute force or whatever, it becomes possible that all source
ports are exhausted with all sockets in TIME_WAIT state.
There are multiple issues at once in fact :
- no action is done for the close, it automatically happens at the lower
layers thanks for channel_auto_close(), so we cannot act on NOLINGER ;
- we *do* want to continue to send a clean shutdown in tunnel mode because
some protocols transported over HTTP may need this, regardless of option
abortonclose, thus we can't set the option inconditionally
- for all other modes, we do want to close the dirty way because we're
certain whether we've sent everything or not, and we don't want to eat
all source ports.
The solution is a bit complex and applies to DONE/TUNNEL states :
1) disable automatic close for everything not a tunnel and not just
keep-alive / server-close. Force-close is now covered, as is HTTP/1.0
which implicitly works in force-close mode ;
2) when processing option abortonclose, we know we can disable lingering
if the client has closed and the connection is not in tunnel mode.
Since the last case above leads to a situation where the client side reports
an error, we know the connection will not be reused, so leaving the flag on
the stream-interface is safe. A client closing in the middle of the data
transmission already aborts the transaction so this case is not a problem.
This fix must be backported to 1.5 where the problem was detected.
(cherry picked from commit bbfb6c40854925367ae5f9e8b22c5c9a18dc69d5)
---
src/proto_http.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/src/proto_http.c b/src/proto_http.c
index 0ac3a47..5db64b5 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -5452,9 +5452,10 @@ int http_request_forward_body(struct session *s, struct channel *req, int an_bit
msg->sov -= msg->next;
msg->next = 0;
- /* for keep-alive we don't want to forward closes on DONE */
- if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
- (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL)
+ /* we don't want to forward closes on DONE except in
+ * tunnel mode.
+ */
+ if ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN)
channel_dont_close(req);
if (http_resync_states(s)) {
/* some state changes occurred, maybe the analyser
@@ -5478,10 +5479,15 @@ int http_request_forward_body(struct session *s, struct channel *req, int an_bit
* want to monitor the client's connection and forward
* any shutdown notification to the server, which will
* decide whether to close or to go on processing the
- * request.
+ * request. We only do that in tunnel mode, and not in
+ * other modes since it can be abused to exhaust source
+ * ports.
*/
if (s->be->options & PR_O_ABRT_CLOSE) {
channel_auto_read(req);
+ if ((req->flags & (CF_SHUTR|CF_READ_NULL)) &&
+ ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN))
+ s->si[1].flags |= SI_FL_NOLINGER;
channel_auto_close(req);
}
else if (s->txn.meth == HTTP_METH_POST) {
--
2.1.4

View File

@ -1,28 +0,0 @@
From 68e4fc2b9910dd090c5e729203b72444f75aaa75 Mon Sep 17 00:00:00 2001
From: Baptiste Assmann <bedis9@gmail.com>
Date: Fri, 1 May 2015 08:09:29 +0200
Subject: [PATCH 3/9] BUG/MINOR: check: fix tcpcheck error message
add the keyword 'string' when required (error in a tcpcheck expect
string)
(cherry picked from commit 96a5c9b57738c05ecce7822093b9c4118123dc1e)
---
src/checks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/checks.c b/src/checks.c
index 71debb6..8b53f97 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -614,7 +614,7 @@ static void chk_report_conn_err(struct connection *conn, int errno_bck, int expi
}
else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_EXPECT) {
if (check->last_started_step->string)
- chunk_appendf(chk, " (string '%s')", check->last_started_step->string);
+ chunk_appendf(chk, " (expect string '%s')", check->last_started_step->string);
else if (check->last_started_step->expect_regex)
chunk_appendf(chk, " (expect regex)");
}
--
2.3.7

View File

@ -1,178 +0,0 @@
From 4f889006269e4d3f802de46f280ed198a15e3a69 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Wed, 13 May 2015 11:23:01 +0200
Subject: [PATCH 4/9] CLEANUP: checks: fix double usage of cur / current_step
in tcp-checks
This cleanup is a preliminary requirement to the upcoming fixes for
the bug that affect tcp-check's improper use of lists. It will have
to be backported to 1.5 though it will not easily apply.
There are two variables pointing to the current rule within the loop,
and either one or the other is used depending on the code blocks,
making it much harder to apply checks to fix the list walking bug.
So first get rid of "cur" and only focus on current_step.
(cherry picked from commit ce8c42a37a44a1e0cb94e81abb7cc2baf3d0ef80)
[wt: 1.5 doesn't have comments so this patch differs significantly
from 1.6, but it's needed for the next batch of fixes]
---
src/checks.c | 57 ++++++++++++++++++++++++++++-----------------------------
1 file changed, 28 insertions(+), 29 deletions(-)
diff --git a/src/checks.c b/src/checks.c
index 8b53f97..cfdfe8c 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -1859,7 +1859,7 @@ static int tcpcheck_get_step_id(struct server *s)
static void tcpcheck_main(struct connection *conn)
{
char *contentptr;
- struct tcpcheck_rule *cur, *next;
+ struct tcpcheck_rule *next;
int done = 0, ret = 0;
struct check *check = conn->owner;
struct server *s = check->server;
@@ -1916,15 +1916,11 @@ static void tcpcheck_main(struct connection *conn)
check->bo->o = 0;
check->bi->p = check->bi->data;
check->bi->i = 0;
- cur = check->current_step = LIST_ELEM(head->n, struct tcpcheck_rule *, list);
+ check->current_step = LIST_ELEM(head->n, struct tcpcheck_rule *, list);
t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
if (s->proxy->timeout.check)
t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);
}
- /* keep on processing step */
- else {
- cur = check->current_step;
- }
/* It's only the rules which will enable send/recv */
__conn_data_stop_both(conn);
@@ -1934,7 +1930,7 @@ static void tcpcheck_main(struct connection *conn)
* or if we're about to send a string that does not fit in the remaining space.
*/
if (check->bo->o &&
- (&cur->list == head ||
+ (&check->current_step->list == head ||
check->current_step->action != TCPCHK_ACT_SEND ||
check->current_step->string_len >= buffer_total_space(check->bo))) {
@@ -1949,14 +1945,17 @@ static void tcpcheck_main(struct connection *conn)
}
/* did we reach the end ? If so, let's check that everything was sent */
- if (&cur->list == head) {
+ if (&check->current_step->list == head) {
if (check->bo->o)
goto out_need_io;
break;
}
- /* have 'next' point to the next rule or NULL if we're on the last one */
- next = (struct tcpcheck_rule *)cur->list.n;
+ /* have 'next' point to the next rule or NULL if we're on the
+ * last one, connect() needs this.
+ */
+ next = (struct tcpcheck_rule *)check->current_step->list.n;
+
if (&next->list == head)
next = NULL;
@@ -2058,8 +2057,7 @@ static void tcpcheck_main(struct connection *conn)
}
/* allow next rule */
- cur = (struct tcpcheck_rule *)cur->list.n;
- check->current_step = cur;
+ check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
/* don't do anything until the connection is established */
if (!(conn->flags & CO_FL_CONNECTED)) {
@@ -2113,8 +2111,7 @@ static void tcpcheck_main(struct connection *conn)
*check->bo->p = '\0'; /* to make gdb output easier to read */
/* go to next rule and try to send */
- cur = (struct tcpcheck_rule *)cur->list.n;
- check->current_step = cur;
+ check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
} /* end 'send' */
else if (check->current_step->action == TCPCHK_ACT_EXPECT) {
if (unlikely(check->result == CHK_RES_FAILED))
@@ -2167,14 +2164,14 @@ static void tcpcheck_main(struct connection *conn)
goto out_end_tcpcheck;
}
- if (!done && (cur->string != NULL) && (check->bi->i < cur->string_len) )
+ if (!done && (check->current_step->string != NULL) && (check->bi->i < check->current_step->string_len) )
continue; /* try to read more */
tcpcheck_expect:
- if (cur->string != NULL)
- ret = my_memmem(contentptr, check->bi->i, cur->string, cur->string_len) != NULL;
- else if (cur->expect_regex != NULL)
- ret = regex_exec(cur->expect_regex, contentptr);
+ if (check->current_step->string != NULL)
+ ret = my_memmem(contentptr, check->bi->i, 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 (!ret && !done)
continue; /* try to read more */
@@ -2182,11 +2179,11 @@ static void tcpcheck_main(struct connection *conn)
/* matched */
if (ret) {
/* matched but we did not want to => ERROR */
- if (cur->inverse) {
+ if (check->current_step->inverse) {
/* we were looking for a string */
- if (cur->string != NULL) {
+ if (check->current_step->string != NULL) {
chunk_printf(&trash, "TCPCHK matched unwanted content '%s' at step %d",
- cur->string, tcpcheck_get_step_id(s));
+ check->current_step->string, tcpcheck_get_step_id(s));
}
else {
/* we were looking for a regex */
@@ -2198,8 +2195,9 @@ static void tcpcheck_main(struct connection *conn)
}
/* matched and was supposed to => OK, next step */
else {
- cur = (struct tcpcheck_rule*)cur->list.n;
- check->current_step = cur;
+ /* allow next rule */
+ check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+
if (check->current_step->action == TCPCHK_ACT_EXPECT)
goto tcpcheck_expect;
__conn_data_stop_recv(conn);
@@ -2208,9 +2206,10 @@ static void tcpcheck_main(struct connection *conn)
else {
/* not matched */
/* not matched and was not supposed to => OK, next step */
- if (cur->inverse) {
- cur = (struct tcpcheck_rule*)cur->list.n;
- check->current_step = cur;
+ if (check->current_step->inverse) {
+ /* allow next rule */
+ check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+
if (check->current_step->action == TCPCHK_ACT_EXPECT)
goto tcpcheck_expect;
__conn_data_stop_recv(conn);
@@ -2218,9 +2217,9 @@ static void tcpcheck_main(struct connection *conn)
/* not matched but was supposed to => ERROR */
else {
/* we were looking for a string */
- if (cur->string != NULL) {
+ if (check->current_step->string != NULL) {
chunk_printf(&trash, "TCPCHK did not match content '%s' at step %d",
- cur->string, tcpcheck_get_step_id(s));
+ check->current_step->string, tcpcheck_get_step_id(s));
}
else {
/* we were looking for a regex */
--
2.3.7

View File

@ -1,53 +0,0 @@
From b94a6d5a37499ce6649ad58f4a8c4664779abd8b Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Wed, 13 May 2015 11:38:17 +0200
Subject: [PATCH 5/9] BUG/MEDIUM: checks: do not dereference head of a
tcp-check at the end
When the end of the list is reached, the current step's action is checked
to know if we must poll or not. Unfortunately, the main reason for going
there is that we walked past the end of list and current_step points to
the head. We cannot dereference ->action since it does not belong to this
structure and can definitely crash if the address is not mapped.
This bug is unlikely to cause a crash since the action appears just after
the list, and corresponds to the "char *check_req" pointer in the proxy
struct, and it seems that we can't go there with current_step being null.
At worst it can cause the check to register for recv events.
This fix needs to be backported to 1.5 since the code is incorrect there
as well.
(cherry picked from commit 53c5a049e1f4dbf67412472e23690dc6b3c8d0f8)
---
src/checks.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/checks.c b/src/checks.c
index cfdfe8c..a887be1 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -2237,10 +2237,12 @@ static void tcpcheck_main(struct connection *conn)
goto out_end_tcpcheck;
out_need_io:
+ /* warning, current_step may now point to the head */
if (check->bo->o)
__conn_data_want_send(conn);
- if (check->current_step->action == TCPCHK_ACT_EXPECT)
+ if (&check->current_step->list != head &&
+ check->current_step->action == TCPCHK_ACT_EXPECT)
__conn_data_want_recv(conn);
return;
@@ -2256,7 +2258,6 @@ static void tcpcheck_main(struct connection *conn)
conn->flags |= CO_FL_ERROR;
__conn_data_stop_both(conn);
-
return;
}
--
2.3.7

View File

@ -1,82 +0,0 @@
From ebb2bceb34d7787453548627ed0e99c60354672b Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Wed, 13 May 2015 11:59:14 +0200
Subject: [PATCH 6/9] CLEANUP: checks: simplify the loop processing of
tcp-checks
There is some unobvious redundancy between the various ways we can leave
the loop. Some of them can be factored out. So now we leave the loop when
we can't go further, whether it's caused by reaching the end of the rules
or by a blocking I/O.
(cherry picked from commit 263013d031d754c9f96de0d0cb5afcc011af6441)
[wt: this patch is required for the next fix]
---
src/checks.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/checks.c b/src/checks.c
index a887be1..a0c42f2 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -1926,8 +1926,10 @@ static void tcpcheck_main(struct connection *conn)
__conn_data_stop_both(conn);
while (1) {
- /* we have to try to flush the output buffer before reading, at the end,
- * or if we're about to send a string that does not fit in the remaining space.
+ /* We have to try to flush the output buffer before reading, at
+ * the end, or if we're about to send a string that does not fit
+ * in the remaining space. That explains why we break out of the
+ * loop after this control.
*/
if (check->bo->o &&
(&check->current_step->list == head ||
@@ -1940,16 +1942,12 @@ static void tcpcheck_main(struct connection *conn)
__conn_data_stop_both(conn);
goto out_end_tcpcheck;
}
- goto out_need_io;
+ break;
}
}
- /* did we reach the end ? If so, let's check that everything was sent */
- if (&check->current_step->list == head) {
- if (check->bo->o)
- goto out_need_io;
+ if (&check->current_step->list == head)
break;
- }
/* have 'next' point to the next rule or NULL if we're on the
* last one, connect() needs this.
@@ -2131,7 +2129,7 @@ static void tcpcheck_main(struct connection *conn)
}
}
else
- goto out_need_io;
+ break;
}
/* mark the step as started */
@@ -2233,10 +2231,14 @@ static void tcpcheck_main(struct connection *conn)
} /* end expect */
} /* end loop over double chained step list */
- set_server_check_status(check, HCHK_STATUS_L7OKD, "(tcp-check)");
- goto out_end_tcpcheck;
+ /* We're waiting for some I/O to complete, we've reached the end of the
+ * rules, or both. Do what we have to do, otherwise we're done.
+ */
+ if (&check->current_step->list == head && !check->bo->o) {
+ set_server_check_status(check, HCHK_STATUS_L7OKD, "(tcp-check)");
+ goto out_end_tcpcheck;
+ }
- out_need_io:
/* warning, current_step may now point to the head */
if (check->bo->o)
__conn_data_want_send(conn);
--
2.3.7

View File

@ -1,90 +0,0 @@
From 97fccc87f1297d189ee80735e5b8746c34956eda Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Wed, 13 May 2015 12:08:21 +0200
Subject: [PATCH 7/9] BUG/MAJOR: checks: always check for end of list before
proceeding
This is the most important fix of this series. There's a risk of endless
loop and crashes caused by the fact that we go past the head of the list
when skipping to next rule, without checking if it's still a valid element.
Most of the time, the ->action field is checked, which points to the proxy's
check_req pointer (generally NULL), meaning the element is confused with a
TCPCHK_ACT_SEND action.
The situation was accidently made worse with the addition of tcp-check
comment since it also skips list elements. However, since the action that
makes it go forward is TCPCHK_ACT_COMMENT (3), there's little chance to
see this as a valid pointer, except on 64-bit machines where it can match
the end of a check_req string pointer.
This fix heavily depends on previous cleanup and both must be backported
to 1.5 where the bug is present.
(cherry picked from commit f2c87353a7f8160930b5f342bb6d6ad0991ee3d1)
[wt: this patch differs significantly from 1.6 since we don't have comments]
---
src/cfgparse.c | 4 +++-
src/checks.c | 12 ++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 746c7eb..dba59d1 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -4368,7 +4368,9 @@ stats_error_parsing:
l = (struct list *)&curproxy->tcpcheck_rules;
if (l->p != l->n) {
tcpcheck = (struct tcpcheck_rule *)l->n;
- if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
+
+ if (&tcpcheck->list != &curproxy->tcpcheck_rules
+ && tcpcheck->action != TCPCHK_ACT_CONNECT) {
Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
file, linenum);
err_code |= ERR_ALERT | ERR_FATAL;
diff --git a/src/checks.c b/src/checks.c
index a0c42f2..e13d561 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -2057,6 +2057,9 @@ static void tcpcheck_main(struct connection *conn)
/* allow next rule */
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+ if (&check->current_step->list == head)
+ break;
+
/* don't do anything until the connection is established */
if (!(conn->flags & CO_FL_CONNECTED)) {
/* update expire time, should be done by process_chk */
@@ -2110,6 +2113,9 @@ static void tcpcheck_main(struct connection *conn)
/* go to next rule and try to send */
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+
+ if (&check->current_step->list == head)
+ break;
} /* end 'send' */
else if (check->current_step->action == TCPCHK_ACT_EXPECT) {
if (unlikely(check->result == CHK_RES_FAILED))
@@ -2196,6 +2202,9 @@ static void tcpcheck_main(struct connection *conn)
/* allow next rule */
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+ if (&check->current_step->list == head)
+ break;
+
if (check->current_step->action == TCPCHK_ACT_EXPECT)
goto tcpcheck_expect;
__conn_data_stop_recv(conn);
@@ -2208,6 +2217,9 @@ static void tcpcheck_main(struct connection *conn)
/* allow next rule */
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+ if (&check->current_step->list == head)
+ break;
+
if (check->current_step->action == TCPCHK_ACT_EXPECT)
goto tcpcheck_expect;
__conn_data_stop_recv(conn);
--
2.3.7

View File

@ -1,116 +0,0 @@
From 5bff05986c501d9ffb67873b60472f9c2a2e41be Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Wed, 13 May 2015 12:24:53 +0200
Subject: [PATCH 8/9] BUG/MEDIUM: checks: do not dereference a list as a
tcpcheck struct
The method used to skip to next rule in the list is wrong, it assumes
that the list element starts at the same offset as the rule. It happens
to be true on most architectures since the list is the first element for
now but it's definitely wrong. Now the code doesn't crash anymore when
the struct list is moved anywhere else in the struct tcpcheck_rule.
This fix must be backported to 1.5.
(cherry picked from commit 5581c27b579cbfc53afb0ca04cdeebe7e2200131)
[wt: changes from 1.6 : no tcp-check comments, check becomes s->proxy]
---
src/cfgparse.c | 18 +++++++-----------
src/checks.c | 15 +++++++++------
2 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/src/cfgparse.c b/src/cfgparse.c
index dba59d1..e04eff8 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -4362,20 +4362,16 @@ stats_error_parsing:
const char *ptr_arg;
int cur_arg;
struct tcpcheck_rule *tcpcheck;
- struct list *l;
/* check if first rule is also a 'connect' action */
- l = (struct list *)&curproxy->tcpcheck_rules;
- if (l->p != l->n) {
- tcpcheck = (struct tcpcheck_rule *)l->n;
+ tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
- if (&tcpcheck->list != &curproxy->tcpcheck_rules
- && tcpcheck->action != TCPCHK_ACT_CONNECT) {
- Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
- file, linenum);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
+ if (&tcpcheck->list != &curproxy->tcpcheck_rules
+ && tcpcheck->action != TCPCHK_ACT_CONNECT) {
+ Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
+ file, linenum);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
}
cur_arg = 2;
diff --git a/src/checks.c b/src/checks.c
index e13d561..27a23b2 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -1444,7 +1444,10 @@ static int connect_chk(struct task *t)
quickack = check->type == 0 || check->type == PR_O2_TCPCHK_CHK;
if (check->type == PR_O2_TCPCHK_CHK && !LIST_ISEMPTY(&s->proxy->tcpcheck_rules)) {
- struct tcpcheck_rule *r = (struct tcpcheck_rule *) s->proxy->tcpcheck_rules.n;
+ struct tcpcheck_rule *r;
+
+ r = LIST_NEXT(&s->proxy->tcpcheck_rules, struct tcpcheck_rule *, list);
+
/* if first step is a 'connect', then tcpcheck_main must run it */
if (r->action == TCPCHK_ACT_CONNECT) {
tcpcheck_main(conn);
@@ -1952,7 +1955,7 @@ static void tcpcheck_main(struct connection *conn)
/* have 'next' point to the next rule or NULL if we're on the
* last one, connect() needs this.
*/
- next = (struct tcpcheck_rule *)check->current_step->list.n;
+ next = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
if (&next->list == head)
next = NULL;
@@ -2055,7 +2058,7 @@ static void tcpcheck_main(struct connection *conn)
}
/* allow next rule */
- check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+ check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
if (&check->current_step->list == head)
break;
@@ -2112,7 +2115,7 @@ static void tcpcheck_main(struct connection *conn)
*check->bo->p = '\0'; /* to make gdb output easier to read */
/* go to next rule and try to send */
- check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+ check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
if (&check->current_step->list == head)
break;
@@ -2200,7 +2203,7 @@ static void tcpcheck_main(struct connection *conn)
/* matched and was supposed to => OK, next step */
else {
/* allow next rule */
- check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+ check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
if (&check->current_step->list == head)
break;
@@ -2215,7 +2218,7 @@ static void tcpcheck_main(struct connection *conn)
/* not matched and was not supposed to => OK, next step */
if (check->current_step->inverse) {
/* allow next rule */
- check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
+ check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
if (&check->current_step->list == head)
break;
--
2.3.7

View File

@ -1,77 +0,0 @@
From 76a06b2804bcdba0fb2c19f834bdb511ce3cf344 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Wed, 20 May 2015 10:39:04 +0200
Subject: [PATCH 9/9] BUG/MEDIUM: peers: apply a random reconnection timeout
Commit 9ff95bb ("BUG/MEDIUM: peers: correctly configure the client timeout")
uncovered an old bug in the peers : upon disconnect, we reconnect immediately.
This sometimes results in both ends to do the same thing in parallel causing
a loop of connect/accept/close/close that can last several seconds. The risk
of occurrence of the trouble increases with latency, and is emphasized by the
fact that idle connections are now frequently recycled (after 5s of idle).
In order to avoid this we must apply a random delay before reconnecting.
Fortunately the mechanism already supports a reconnect delay, so here we
compute the random timeout when killing a session. The delay is 50ms plus
a random between 0 and 2 seconds. Ideally an exponential back-off would
be preferred but it's preferable to keep the fix simple.
This bug was reported by Marco Corte.
This fix must be backported to 1.5 since the fix above was backported into
1.5.12.
(cherry picked from commit b4e34da692d8a7f6837ad16b3389f5830dbc11d2)
---
src/peers.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/peers.c b/src/peers.c
index b196d88..159f0a4 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -1063,6 +1063,7 @@ static void peer_session_forceshutdown(struct session * session)
{
struct stream_interface *oldsi = NULL;
struct appctx *appctx = NULL;
+ struct peer_session *ps;
int i;
for (i = 0; i <= 1; i++) {
@@ -1079,6 +1080,14 @@ static void peer_session_forceshutdown(struct session * session)
if (!appctx)
return;
+ ps = (struct peer_session *)appctx->ctx.peers.ptr;
+ /* we're killing a connection, we must apply a random delay before
+ * retrying otherwise the other end will do the same and we can loop
+ * for a while.
+ */
+ if (ps)
+ ps->reconnect = tick_add(now_ms, MS_TO_TICKS(50 + random() % 2000));
+
/* call release to reinit resync states if needed */
peer_session_release(oldsi);
appctx->st0 = PEER_SESS_ST_END;
@@ -1352,8 +1361,8 @@ static struct task *process_peer_sync(struct task * task)
if (!ps->session) {
/* no active session */
if (ps->statuscode == 0 ||
- ps->statuscode == PEER_SESS_SC_SUCCESSCODE ||
((ps->statuscode == PEER_SESS_SC_CONNECTCODE ||
+ ps->statuscode == PEER_SESS_SC_SUCCESSCODE ||
ps->statuscode == PEER_SESS_SC_CONNECTEDCODE) &&
tick_is_expired(ps->reconnect, now_ms))) {
/* connection never tried
@@ -1364,8 +1373,7 @@ static struct task *process_peer_sync(struct task * task)
/* retry a connect */
ps->session = peer_session_create(ps->peer, ps);
}
- else if (ps->statuscode == PEER_SESS_SC_CONNECTCODE ||
- ps->statuscode == PEER_SESS_SC_CONNECTEDCODE) {
+ else if (!tick_is_expired(ps->reconnect, now_ms)) {
/* If previous session failed during connection
* but reconnection timer is not expired */
--
2.3.7

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6648dd7d6b958d83dd7101eab5792178212a66c884bec0ebcd8abc39df83bb78
size 1344813

3
haproxy-1.5.13.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:de901c23d976cb21b816dc671924176918b691a430fb5a52e0f1afbc6faeb5f9
size 1345323

View File

@ -1,3 +1,88 @@
-------------------------------------------------------------------
Fri Jun 26 11:45:33 UTC 2015 - kgronlund@suse.com
- Update to 1.5.13
- Dropped all patches backported from git, no further changes
than those patches provided.
- Removed patches:
+ Remove 0001-BUG-MEDIUM-stats-properly-initialize-the-scope-befor.patch
+ Remove 0002-BUG-MEDIUM-http-don-t-forward-client-shutdown-withou.patch
+ Remove 0003-BUG-MINOR-check-fix-tcpcheck-error-message.patch
+ Remove 0004-CLEANUP-checks-fix-double-usage-of-cur-current_step-.patch
+ Remove 0005-BUG-MEDIUM-checks-do-not-dereference-head-of-a-tcp-c.patch
+ Remove 0006-CLEANUP-checks-simplify-the-loop-processing-of-tcp-c.patch
+ Remove 0007-BUG-MAJOR-checks-always-check-for-end-of-list-before.patch
+ Remove 0008-BUG-MEDIUM-checks-do-not-dereference-a-list-as-a-tcp.patch
+ Remove 0009-BUG-MEDIUM-peers-apply-a-random-reconnection-timeout.patch
+ Remove 0010-DOC-Update-doc-about-weight-act-and-bck-fields-in-th.patch
+ Remove 0011-MINOR-ssl-add-a-destructor-to-free-allocated-SSL-res.patch
+ Remove 0012-BUG-MEDIUM-ssl-fix-tune.ssl.default-dh-param-value-b.patch
+ Remove 0013-BUG-MINOR-cfgparse-fix-typo-in-option-httplog-error-.patch
+ Remove 0014-BUG-MEDIUM-cfgparse-segfault-when-userlist-is-misuse.patch
+ Remove 0015-MEDIUM-ssl-replace-standards-DH-groups-with-custom-o.patch
+ Remove 0016-BUG-MINOR-debug-display-null-in-place-of-meth.patch
+ Remove 0017-CLEANUP-deinit-remove-codes-for-cleaning-p-block_rul.patch
+ Remove 0018-BUG-MINOR-ssl-fix-smp_fetch_ssl_fc_session_id.patch
+ Remove 0019-MEDIUM-init-don-t-stop-proxies-in-parent-process-whe.patch
+ Remove 0020-MINOR-peers-store-the-pointer-to-the-signal-handler.patch
+ Remove 0021-MEDIUM-peers-unregister-peers-that-were-never-starte.patch
+ Remove 0022-MEDIUM-config-propagate-the-table-s-process-list-to-.patch
+ Remove 0023-MEDIUM-init-stop-any-peers-section-not-bound-to-the-.patch
+ Remove 0024-MEDIUM-config-validate-that-peers-sections-are-bound.patch
+ Remove 0025-MAJOR-peers-allow-peers-section-to-be-used-with-nbpr.patch
+ Remove 0026-DOC-relax-the-peers-restriction-to-single-process.patch
+ Remove 0027-CLEANUP-config-fix-misleading-information-in-error-m.patch
+ Remove 0028-MINOR-config-report-the-number-of-processes-using-a-.patch
+ Remove 0029-BUG-MEDIUM-config-properly-compute-the-default-numbe.patch
-------------------------------------------------------------------
Thu Jun 25 15:01:34 UTC 2015 - kgronlund@suse.com
- Backport upstream patches:
+ DOC: Update doc about weight, act and bck fields in the statistics
+ MINOR: ssl: add a destructor to free allocated SSL ressources
+ BUG/MEDIUM: ssl: fix tune.ssl.default-dh-param value being overwritten
+ BUG/MINOR: cfgparse: fix typo in 'option httplog' error message
+ BUG/MEDIUM: cfgparse: segfault when userlist is misused
+ MEDIUM: ssl: replace standards DH groups with custom ones
+ BUG/MINOR: debug: display (null) in place of "meth"
+ CLEANUP: deinit: remove codes for cleaning p->block_rules
+ BUG/MINOR: ssl: fix smp_fetch_ssl_fc_session_id
+ MEDIUM: init: don't stop proxies in parent process when exiting
+ MINOR: peers: store the pointer to the signal handler
+ MEDIUM: peers: unregister peers that were never started
+ MEDIUM: config: propagate the table's process list to the peers sections
+ MEDIUM: init: stop any peers section not bound to the correct process
+ MEDIUM: config: validate that peers sections are bound to exactly one process
+ MAJOR: peers: allow peers section to be used with nbproc > 1
+ DOC: relax the peers restriction to single-process
+ CLEANUP: config: fix misleading information in error message.
+ MINOR: config: report the number of processes using a peers section in the error case
+ BUG/MEDIUM: config: properly compute the default number of processes for a proxy
- Added patches:
+ Add 0010-DOC-Update-doc-about-weight-act-and-bck-fields-in-th.patch
+ Add 0011-MINOR-ssl-add-a-destructor-to-free-allocated-SSL-res.patch
+ Add 0012-BUG-MEDIUM-ssl-fix-tune.ssl.default-dh-param-value-b.patch
+ Add 0013-BUG-MINOR-cfgparse-fix-typo-in-option-httplog-error-.patch
+ Add 0014-BUG-MEDIUM-cfgparse-segfault-when-userlist-is-misuse.patch
+ Add 0015-MEDIUM-ssl-replace-standards-DH-groups-with-custom-o.patch
+ Add 0016-BUG-MINOR-debug-display-null-in-place-of-meth.patch
+ Add 0017-CLEANUP-deinit-remove-codes-for-cleaning-p-block_rul.patch
+ Add 0018-BUG-MINOR-ssl-fix-smp_fetch_ssl_fc_session_id.patch
+ Add 0019-MEDIUM-init-don-t-stop-proxies-in-parent-process-whe.patch
+ Add 0020-MINOR-peers-store-the-pointer-to-the-signal-handler.patch
+ Add 0021-MEDIUM-peers-unregister-peers-that-were-never-starte.patch
+ Add 0022-MEDIUM-config-propagate-the-table-s-process-list-to-.patch
+ Add 0023-MEDIUM-init-stop-any-peers-section-not-bound-to-the-.patch
+ Add 0024-MEDIUM-config-validate-that-peers-sections-are-bound.patch
+ Add 0025-MAJOR-peers-allow-peers-section-to-be-used-with-nbpr.patch
+ Add 0026-DOC-relax-the-peers-restriction-to-single-process.patch
+ Add 0027-CLEANUP-config-fix-misleading-information-in-error-m.patch
+ Add 0028-MINOR-config-report-the-number-of-processes-using-a-.patch
+ Add 0029-BUG-MEDIUM-config-properly-compute-the-default-numbe.patch
------------------------------------------------------------------- -------------------------------------------------------------------
Mon May 25 09:34:58 UTC 2015 - kgronlund@suse.com Mon May 25 09:34:58 UTC 2015 - kgronlund@suse.com

View File

@ -33,7 +33,7 @@
%bcond_without apparmor %bcond_without apparmor
Name: haproxy Name: haproxy
Version: 1.5.12 Version: 1.5.13
Release: 0 Release: 0
# #
# #
@ -61,22 +61,6 @@ Patch1: haproxy-1.2.16_config_haproxy_user.patch
Patch2: haproxy-makefile_lib.patch Patch2: haproxy-makefile_lib.patch
Patch3: sec-options.patch Patch3: sec-options.patch
Patch4: haproxy-1.5.8-fix-bashisms.patch Patch4: haproxy-1.5.8-fix-bashisms.patch
Patch5: 0001-BUG-MEDIUM-stats-properly-initialize-the-scope-befor.patch
Patch6: 0002-BUG-MEDIUM-http-don-t-forward-client-shutdown-withou.patch
# PATCH-FIX-UPSTREAM: BUG/MINOR: check: fix tcpcheck error message
Patch7: 0003-BUG-MINOR-check-fix-tcpcheck-error-message.patch
# PATCH-FIX-UPSTREAM: CLEANUP: checks: fix double usage of cur / current_step in tcp-checks
Patch8: 0004-CLEANUP-checks-fix-double-usage-of-cur-current_step-.patch
# PATCH-FIX-UPSTREAM: BUG/MEDIUM: checks: do not dereference head of a tcp-check at the end
Patch9: 0005-BUG-MEDIUM-checks-do-not-dereference-head-of-a-tcp-c.patch
# PATCH-FIX-UPSTREAM: CLEANUP: checks: simplify the loop processing of tcp-checks
Patch10: 0006-CLEANUP-checks-simplify-the-loop-processing-of-tcp-c.patch
# PATCH-FIX-UPSTREAM: BUG/MAJOR: checks: always check for end of list before proceeding
Patch11: 0007-BUG-MAJOR-checks-always-check-for-end-of-list-before.patch
# PATCH-FIX-UPSTREAM: BUG/MEDIUM: checks: do not dereference a list as a tcpcheck struct
Patch12: 0008-BUG-MEDIUM-checks-do-not-dereference-a-list-as-a-tcp.patch
# PATCH-FIX-UPSTREAM: BUG/MEDIUM: peers: apply a random reconnection timeout
Patch13: 0009-BUG-MEDIUM-peers-apply-a-random-reconnection-timeout.patch
# #
Source99: haproxy-rpmlintrc Source99: haproxy-rpmlintrc
@ -112,15 +96,7 @@ the most work done from every CPU cycle.
%patch2 %patch2
%patch3 %patch3
%patch4 -p1 %patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%build %build
%{__make} \ %{__make} \