You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
3.8 KiB

  1. From e61737a721c3b91c79484e51fc1789293b269f9f Mon Sep 17 00:00:00 2001
  2. From: Willy Tarreau <w@1wt.eu>
  3. Date: Thu, 2 Oct 2014 14:30:14 +0200
  4. Subject: [PATCH 18/20] BUG/MEDIUM: check: rule-less tcp-check must detect
  5. connect failures
  6. When "option tcp-check" is specified without any tcp-check rules, the
  7. documentation says that it's the same as the default check method. But
  8. the code path is a bit different, and we used to consider that since
  9. the end of rules was reached, the check is always successful regardless
  10. of the connection status.
  11. This patch reorganizes the error detection, and considers the special
  12. case where there's no tcp-check rule as a real L4 check. It also avoids
  13. dereferencing the rule list head as a rule by itself.
  14. While fixing this bug, another one related to the output messages'
  15. accuracy was noticed, it will be fixed in a separate commit and is
  16. much less important.
  17. This bug is also present in 1.5, so this fix must be backported.
  18. (cherry picked from commit ef953953e7f33c6a72c432fce8d47c2d84c69512)
  19. ---
  20. src/checks.c | 40 +++++++++++++++++++++++++---------------
  21. 1 file changed, 25 insertions(+), 15 deletions(-)
  22. diff --git a/src/checks.c b/src/checks.c
  23. index f3b2b54..9c1a866 100644
  24. --- a/src/checks.c
  25. +++ b/src/checks.c
  26. @@ -1837,20 +1837,34 @@ static int tcpcheck_get_step_id(struct server *s)
  27. static void tcpcheck_main(struct connection *conn)
  28. {
  29. char *contentptr;
  30. - struct list *head = NULL;
  31. struct tcpcheck_rule *cur = NULL;
  32. int done = 0, ret = 0;
  33. -
  34. struct check *check = conn->owner;
  35. struct server *s = check->server;
  36. struct task *t = check->task;
  37. + struct list *head = &s->proxy->tcpcheck_rules;
  38. - /*
  39. - * don't do anything until the connection is established but if we're running
  40. - * first step which must be a connect
  41. + /* here, we know that the check is complete or that it failed */
  42. + if (check->result != CHK_RES_UNKNOWN)
  43. + goto out_end_tcpcheck;
  44. +
  45. + /* We have 4 possibilities here :
  46. + * 1. we've not yet attempted step 1, and step 1 is a connect, so no
  47. + * connection attempt was made yet ;
  48. + * 2. we've not yet attempted step 1, and step 1 is a not connect or
  49. + * does not exist (no rule), so a connection attempt was made
  50. + * before coming here.
  51. + * 3. we're coming back after having started with step 1, so we may
  52. + * be waiting for a connection attempt to complete.
  53. + * 4. the connection + handshake are complete
  54. + *
  55. + * #2 and #3 are quite similar, we want both the connection and the
  56. + * handshake to complete before going any further. Thus we must always
  57. + * wait for a connection to complete unless we're before and existing
  58. + * step 1.
  59. */
  60. - if (check->current_step && (!(conn->flags & CO_FL_CONNECTED))) {
  61. - /* update expire time, should be done by process_chk */
  62. + if ((!(conn->flags & CO_FL_CONNECTED) || (conn->flags & CO_FL_HANDSHAKE)) &&
  63. + (check->current_step || LIST_ISEMPTY(head))) {
  64. /* we allow up to min(inter, timeout.connect) for a connection
  65. * to establish but only when timeout.check is set
  66. * as it may be to short for a full check otherwise
  67. @@ -1867,12 +1881,11 @@ static void tcpcheck_main(struct connection *conn)
  68. return;
  69. }
  70. - /* here, we know that the connection is established */
  71. - if (check->result != CHK_RES_UNKNOWN)
  72. + /* special case: option tcp-check with no rule, a connect is enough */
  73. + if (LIST_ISEMPTY(head)) {
  74. + set_server_check_status(check, HCHK_STATUS_L4OK, NULL);
  75. goto out_end_tcpcheck;
  76. -
  77. - /* head is be the first element of the double chained list */
  78. - head = &s->proxy->tcpcheck_rules;
  79. + }
  80. /* no step means first step
  81. * initialisation */
  82. @@ -1891,9 +1904,6 @@ static void tcpcheck_main(struct connection *conn)
  83. cur = check->current_step;
  84. }
  85. - if (conn->flags & CO_FL_HANDSHAKE)
  86. - return;
  87. -
  88. /* It's only the rules which will enable send/recv */
  89. __conn_data_stop_both(conn);
  90. --
  91. 2.0.4