~ubuntu-branches/debian/stretch/haproxy/stretch

« back to all changes in this revision

Viewing changes to src/checks.c

  • Committer: Package Import Robot
  • Author(s): Apollon Oikonomopoulos
  • Date: 2014-06-20 11:05:17 UTC
  • mfrom: (1.1.15) (15.1.12 experimental)
  • Revision ID: package-import@ubuntu.com-20140620110517-u6q5p9kyy2f3ozw9
Tags: 1.5.0-1
* New upstream stable series. Notable changes since the 1.4 series:
  + Native SSL support on both sides with SNI/NPN/ALPN and OCSP stapling.
  + IPv6 and UNIX sockets are supported everywhere
  + End-to-end HTTP keep-alive for better support of NTLM and improved
    efficiency in static farms
  + HTTP/1.1 response compression (deflate, gzip) to save bandwidth
  + PROXY protocol versions 1 and 2 on both sides
  + Data sampling on everything in request or response, including payload
  + ACLs can use any matching method with any input sample
  + Maps and dynamic ACLs updatable from the CLI
  + Stick-tables support counters to track activity on any input sample
  + Custom format for logs, unique-id, header rewriting, and redirects
  + Improved health checks (SSL, scripted TCP, check agent, ...)
  + Much more scalable configuration supports hundreds of thousands of
    backends and certificates without sweating

* Upload to unstable, merge all 1.5 work from experimental. Most important
  packaging changes since 1.4.25-1 include:
  + systemd support.
  + A more sane default config file.
  + Zero-downtime upgrades between 1.5 releases by gracefully reloading
    HAProxy during upgrades.
  + HTML documentation shipped in the haproxy-doc package.
  + kqueue support for kfreebsd.

* Packaging changes since 1.5~dev26-2:
  + Drop patches merged upstream:
    o Fix-reference-location-in-manpage.patch
    o 0001-BUILD-stats-workaround-stupid-and-bogus-Werror-forma.patch
  + d/watch: look for stable 1.5 releases
  + systemd: respect CONFIG and EXTRAOPTS when specified in
    /etc/default/haproxy.
  + initscript: test the configuration before start or reload.
  + initscript: remove the ENABLED flag and logic.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <netinet/tcp.h>
27
27
#include <arpa/inet.h>
28
28
 
 
29
#include <common/chunk.h>
29
30
#include <common/compat.h>
30
31
#include <common/config.h>
31
32
#include <common/mini-clist.h>
34
35
 
35
36
#include <types/global.h>
36
37
 
 
38
#ifdef USE_OPENSSL
 
39
#include <types/ssl_sock.h>
 
40
#include <proto/ssl_sock.h>
 
41
#endif /* USE_OPENSSL */
 
42
 
37
43
#include <proto/backend.h>
38
44
#include <proto/checks.h>
39
 
#include <proto/buffers.h>
 
45
#include <proto/dumpstats.h>
40
46
#include <proto/fd.h>
41
47
#include <proto/log.h>
42
48
#include <proto/queue.h>
43
49
#include <proto/port_range.h>
44
50
#include <proto/proto_http.h>
45
51
#include <proto/proto_tcp.h>
 
52
#include <proto/protocol.h>
46
53
#include <proto/proxy.h>
 
54
#include <proto/raw_sock.h>
47
55
#include <proto/server.h>
 
56
#include <proto/session.h>
 
57
#include <proto/stream_interface.h>
48
58
#include <proto/task.h>
49
59
 
50
60
static int httpchk_expect(struct server *s, int done);
 
61
static int tcpcheck_get_step_id(struct server *);
 
62
static void tcpcheck_main(struct connection *);
51
63
 
52
 
const struct check_status check_statuses[HCHK_STATUS_SIZE] = {
53
 
        [HCHK_STATUS_UNKNOWN]   = { SRV_CHK_UNKNOWN,                   "UNK",     "Unknown" },
54
 
        [HCHK_STATUS_INI]       = { SRV_CHK_UNKNOWN,                   "INI",     "Initializing" },
 
64
static const struct check_status check_statuses[HCHK_STATUS_SIZE] = {
 
65
        [HCHK_STATUS_UNKNOWN]   = { CHK_RES_UNKNOWN,  "UNK",     "Unknown" },
 
66
        [HCHK_STATUS_INI]       = { CHK_RES_UNKNOWN,  "INI",     "Initializing" },
55
67
        [HCHK_STATUS_START]     = { /* SPECIAL STATUS*/ },
56
68
 
57
 
        [HCHK_STATUS_HANA]      = { SRV_CHK_ERROR,                     "HANA",    "Health analyze" },
58
 
 
59
 
        [HCHK_STATUS_SOCKERR]   = { SRV_CHK_ERROR,                     "SOCKERR", "Socket error" },
60
 
 
61
 
        [HCHK_STATUS_L4OK]      = { SRV_CHK_RUNNING,                   "L4OK",    "Layer4 check passed" },
62
 
        [HCHK_STATUS_L4TOUT]    = { SRV_CHK_ERROR,                     "L4TOUT",  "Layer4 timeout" },
63
 
        [HCHK_STATUS_L4CON]     = { SRV_CHK_ERROR,                     "L4CON",   "Layer4 connection problem" },
64
 
 
65
 
        [HCHK_STATUS_L6OK]      = { SRV_CHK_RUNNING,                   "L6OK",    "Layer6 check passed" },
66
 
        [HCHK_STATUS_L6TOUT]    = { SRV_CHK_ERROR,                     "L6TOUT",  "Layer6 timeout" },
67
 
        [HCHK_STATUS_L6RSP]     = { SRV_CHK_ERROR,                     "L6RSP",   "Layer6 invalid response" },
68
 
 
69
 
        [HCHK_STATUS_L7TOUT]    = { SRV_CHK_ERROR,                     "L7TOUT",  "Layer7 timeout" },
70
 
        [HCHK_STATUS_L7RSP]     = { SRV_CHK_ERROR,                     "L7RSP",   "Layer7 invalid response" },
 
69
        /* Below we have finished checks */
 
70
        [HCHK_STATUS_CHECKED]   = { CHK_RES_NEUTRAL,  "CHECKED", "No status change" },
 
71
        [HCHK_STATUS_HANA]      = { CHK_RES_FAILED,   "HANA",    "Health analyze" },
 
72
 
 
73
        [HCHK_STATUS_SOCKERR]   = { CHK_RES_FAILED,   "SOCKERR", "Socket error" },
 
74
 
 
75
        [HCHK_STATUS_L4OK]      = { CHK_RES_PASSED,   "L4OK",    "Layer4 check passed" },
 
76
        [HCHK_STATUS_L4TOUT]    = { CHK_RES_FAILED,   "L4TOUT",  "Layer4 timeout" },
 
77
        [HCHK_STATUS_L4CON]     = { CHK_RES_FAILED,   "L4CON",   "Layer4 connection problem" },
 
78
 
 
79
        [HCHK_STATUS_L6OK]      = { CHK_RES_PASSED,   "L6OK",    "Layer6 check passed" },
 
80
        [HCHK_STATUS_L6TOUT]    = { CHK_RES_FAILED,   "L6TOUT",  "Layer6 timeout" },
 
81
        [HCHK_STATUS_L6RSP]     = { CHK_RES_FAILED,   "L6RSP",   "Layer6 invalid response" },
 
82
 
 
83
        [HCHK_STATUS_L7TOUT]    = { CHK_RES_FAILED,   "L7TOUT",  "Layer7 timeout" },
 
84
        [HCHK_STATUS_L7RSP]     = { CHK_RES_FAILED,   "L7RSP",   "Layer7 invalid response" },
71
85
 
72
86
        [HCHK_STATUS_L57DATA]   = { /* DUMMY STATUS */ },
73
87
 
74
 
        [HCHK_STATUS_L7OKD]     = { SRV_CHK_RUNNING,                   "L7OK",    "Layer7 check passed" },
75
 
        [HCHK_STATUS_L7OKCD]    = { SRV_CHK_RUNNING | SRV_CHK_DISABLE, "L7OKC",   "Layer7 check conditionally passed" },
76
 
        [HCHK_STATUS_L7STS]     = { SRV_CHK_ERROR,                     "L7STS",   "Layer7 wrong status" },
 
88
        [HCHK_STATUS_L7OKD]     = { CHK_RES_PASSED,   "L7OK",    "Layer7 check passed" },
 
89
        [HCHK_STATUS_L7OKCD]    = { CHK_RES_CONDPASS, "L7OKC",   "Layer7 check conditionally passed" },
 
90
        [HCHK_STATUS_L7STS]     = { CHK_RES_FAILED,   "L7STS",   "Layer7 wrong status" },
77
91
};
78
92
 
79
 
const struct analyze_status analyze_statuses[HANA_STATUS_SIZE] = {              /* 0: ignore, 1: error, 2: OK */
 
93
static const struct analyze_status analyze_statuses[HANA_STATUS_SIZE] = {               /* 0: ignore, 1: error, 2: OK */
80
94
        [HANA_STATUS_UNKNOWN]           = { "Unknown",                         { 0, 0 }},
81
95
 
82
96
        [HANA_STATUS_L4_OK]             = { "L4 successful connection",        { 2, 0 }},
143
157
                return analyze_statuses[HANA_STATUS_UNKNOWN].desc;
144
158
}
145
159
 
146
 
#define SSP_O_HCHK      0x0002
147
 
 
148
 
static void server_status_printf(struct chunk *msg, struct server *s, unsigned options, int xferred) {
149
 
 
150
 
        if (s->tracked)
151
 
                chunk_printf(msg, " via %s/%s",
152
 
                        s->tracked->proxy->id, s->tracked->id);
153
 
 
154
 
        if (options & SSP_O_HCHK) {
155
 
                chunk_printf(msg, ", reason: %s", get_check_status_description(s->check_status));
156
 
 
157
 
                if (s->check_status >= HCHK_STATUS_L57DATA)
158
 
                        chunk_printf(msg, ", code: %d", s->check_code);
159
 
 
160
 
                if (*s->check_desc) {
161
 
                        struct chunk src;
162
 
 
163
 
                        chunk_printf(msg, ", info: \"");
164
 
 
165
 
                        chunk_initlen(&src, s->check_desc, 0, strlen(s->check_desc));
166
 
                        chunk_asciiencode(msg, &src, '"');
167
 
 
168
 
                        chunk_printf(msg, "\"");
169
 
                }
170
 
 
171
 
                if (s->check_duration >= 0)
172
 
                        chunk_printf(msg, ", check duration: %ldms", s->check_duration);
173
 
        }
174
 
 
175
 
        if (xferred >= 0) {
176
 
                if (!(s->state & SRV_RUNNING))
177
 
                        chunk_printf(msg, ". %d active and %d backup servers left.%s"
178
 
                                " %d sessions active, %d requeued, %d remaining in queue",
179
 
                                s->proxy->srv_act, s->proxy->srv_bck,
180
 
                                (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
181
 
                                s->cur_sess, xferred, s->nbpend);
182
 
                else 
183
 
                        chunk_printf(msg, ". %d active and %d backup servers online.%s"
184
 
                                " %d sessions requeued, %d total in queue",
185
 
                                s->proxy->srv_act, s->proxy->srv_bck,
186
 
                                (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
187
 
                                xferred, s->nbpend);
188
 
        }
 
160
/* Builds a string containing some information about the health check's result.
 
161
 * The output string is allocated from the trash chunks. If the check is NULL,
 
162
 * NULL is returned. This is designed to be used when emitting logs about health
 
163
 * checks.
 
164
 */
 
165
static const char *check_reason_string(struct check *check)
 
166
{
 
167
        struct chunk *msg;
 
168
 
 
169
        if (!check)
 
170
                return NULL;
 
171
 
 
172
        msg = get_trash_chunk();
 
173
        chunk_printf(msg, "reason: %s", get_check_status_description(check->status));
 
174
 
 
175
        if (check->status >= HCHK_STATUS_L57DATA)
 
176
                chunk_appendf(msg, ", code: %d", check->code);
 
177
 
 
178
        if (*check->desc) {
 
179
                struct chunk src;
 
180
 
 
181
                chunk_appendf(msg, ", info: \"");
 
182
 
 
183
                chunk_initlen(&src, check->desc, 0, strlen(check->desc));
 
184
                chunk_asciiencode(msg, &src, '"');
 
185
 
 
186
                chunk_appendf(msg, "\"");
 
187
        }
 
188
 
 
189
        if (check->duration >= 0)
 
190
                chunk_appendf(msg, ", check duration: %ldms", check->duration);
 
191
 
 
192
        return msg->str;
189
193
}
190
194
 
191
195
/*
192
 
 * Set s->check_status, update s->check_duration and fill s->result with
193
 
 * an adequate SRV_CHK_* value.
 
196
 * Set check->status, update check->duration and fill check->result with
 
197
 * an adequate CHK_RES_* value. The new check->health is computed based
 
198
 * on the result.
194
199
 *
195
200
 * Show information in logs about failed health check if server is UP
196
201
 * or succeeded health checks if server is DOWN.
197
202
 */
198
 
static void set_server_check_status(struct server *s, short status, char *desc) {
199
 
 
200
 
        struct chunk msg;
 
203
static void set_server_check_status(struct check *check, short status, const char *desc)
 
204
{
 
205
        struct server *s = check->server;
 
206
        short prev_status = check->status;
 
207
        int report = 0;
201
208
 
202
209
        if (status == HCHK_STATUS_START) {
203
 
                s->result = SRV_CHK_UNKNOWN;    /* no result yet */
204
 
                s->check_desc[0] = '\0';
205
 
                s->check_start = now;
 
210
                check->result = CHK_RES_UNKNOWN;        /* no result yet */
 
211
                check->desc[0] = '\0';
 
212
                check->start = now;
206
213
                return;
207
214
        }
208
215
 
209
 
        if (!s->check_status)
 
216
        if (!check->status)
210
217
                return;
211
218
 
212
219
        if (desc && *desc) {
213
 
                strncpy(s->check_desc, desc, HCHK_DESC_LEN-1);
214
 
                s->check_desc[HCHK_DESC_LEN-1] = '\0';
 
220
                strncpy(check->desc, desc, HCHK_DESC_LEN-1);
 
221
                check->desc[HCHK_DESC_LEN-1] = '\0';
215
222
        } else
216
 
                s->check_desc[0] = '\0';
 
223
                check->desc[0] = '\0';
217
224
 
218
 
        s->check_status = status;
 
225
        check->status = status;
219
226
        if (check_statuses[status].result)
220
 
                s->result = check_statuses[status].result;
 
227
                check->result = check_statuses[status].result;
221
228
 
222
229
        if (status == HCHK_STATUS_HANA)
223
 
                s->check_duration = -1;
224
 
        else if (!tv_iszero(&s->check_start)) {
 
230
                check->duration = -1;
 
231
        else if (!tv_iszero(&check->start)) {
225
232
                /* set_server_check_status() may be called more than once */
226
 
                s->check_duration = tv_ms_elapsed(&s->check_start, &now);
227
 
                tv_zero(&s->check_start);
 
233
                check->duration = tv_ms_elapsed(&check->start, &now);
 
234
                tv_zero(&check->start);
 
235
        }
 
236
 
 
237
        /* no change is expected if no state change occurred */
 
238
        if (check->result == CHK_RES_NEUTRAL)
 
239
                return;
 
240
 
 
241
        report = 0;
 
242
 
 
243
        switch (check->result) {
 
244
        case CHK_RES_FAILED:
 
245
                /* Failure to connect to the agent as a secondary check should not
 
246
                 * cause the server to be marked down.
 
247
                 */
 
248
                if ((!(check->state & CHK_ST_AGENT) ||
 
249
                    (check->status >= HCHK_STATUS_L7TOUT)) &&
 
250
                    (check->health >= check->rise)) {
 
251
                        s->counters.failed_checks++;
 
252
                        report = 1;
 
253
                        check->health--;
 
254
                        if (check->health < check->rise)
 
255
                                check->health = 0;
 
256
                }
 
257
                break;
 
258
 
 
259
        case CHK_RES_PASSED:
 
260
        case CHK_RES_CONDPASS:  /* "condpass" cannot make the first step but it OK after a "passed" */
 
261
                if ((check->health < check->rise + check->fall - 1) &&
 
262
                    (check->result == CHK_RES_PASSED || check->health > 0)) {
 
263
                        report = 1;
 
264
                        check->health++;
 
265
 
 
266
                        if (check->health >= check->rise)
 
267
                                check->health = check->rise + check->fall - 1; /* OK now */
 
268
                }
 
269
 
 
270
                /* clear consecutive_errors if observing is enabled */
 
271
                if (s->onerror)
 
272
                        s->consecutive_errors = 0;
 
273
                break;
 
274
 
 
275
        default:
 
276
                break;
228
277
        }
229
278
 
230
279
        if (s->proxy->options2 & PR_O2_LOGHCHKS &&
231
 
        (((s->health != 0) && (s->result & SRV_CHK_ERROR)) ||
232
 
            ((s->health != s->rise + s->fall - 1) && (s->result & SRV_CHK_RUNNING)) ||
233
 
            ((s->state & SRV_GOINGDOWN) && !(s->result & SRV_CHK_DISABLE)) ||
234
 
            (!(s->state & SRV_GOINGDOWN) && (s->result & SRV_CHK_DISABLE)))) {
235
 
 
236
 
                int health, rise, fall, state;
237
 
 
238
 
                chunk_init(&msg, trash, trashlen);
239
 
 
240
 
                /* FIXME begin: calculate local version of the health/rise/fall/state */
241
 
                health = s->health;
242
 
                rise   = s->rise;
243
 
                fall   = s->fall;
244
 
                state  = s->state;
245
 
 
246
 
                if (s->result & SRV_CHK_ERROR) {
247
 
                        if (health > rise) {
248
 
                                health--; /* still good */
249
 
                        } else {
250
 
                                if (health == rise)
251
 
                                        state &= ~(SRV_RUNNING | SRV_GOINGDOWN);
252
 
 
253
 
                                health = 0;
254
 
                        }
255
 
                }
256
 
 
257
 
                if (s->result & SRV_CHK_RUNNING) {
258
 
                        if (health < rise + fall - 1) {
259
 
                                health++; /* was bad, stays for a while */
260
 
 
261
 
                                if (health == rise)
262
 
                                        state |= SRV_RUNNING;
263
 
 
264
 
                                if (health >= rise)
265
 
                                        health = rise + fall - 1; /* OK now */
266
 
                        }
267
 
 
268
 
                        /* clear consecutive_errors if observing is enabled */
269
 
                        if (s->onerror)
270
 
                                s->consecutive_errors = 0;
271
 
                }
272
 
                /* FIXME end: calculate local version of the health/rise/fall/state */
273
 
 
274
 
                chunk_printf(&msg,
275
 
                        "Health check for %sserver %s/%s %s%s",
276
 
                        s->state & SRV_BACKUP ? "backup " : "",
277
 
                        s->proxy->id, s->id,
278
 
                        (s->result & SRV_CHK_DISABLE)?"conditionally ":"",
279
 
                        (s->result & SRV_CHK_RUNNING)?"succeeded":"failed");
280
 
 
281
 
                server_status_printf(&msg, s, SSP_O_HCHK, -1);
282
 
 
283
 
                chunk_printf(&msg, ", status: %d/%d %s",
284
 
                        (state & SRV_RUNNING) ? (health - rise + 1) : (health),
285
 
                        (state & SRV_RUNNING) ? (fall) : (rise),
286
 
                        (state & SRV_RUNNING)?"UP":"DOWN");
287
 
 
288
 
                Warning("%s.\n", trash);
289
 
                send_log(s->proxy, LOG_NOTICE, "%s.\n", trash);
290
 
        }
291
 
}
292
 
 
293
 
/* sends a log message when a backend goes down, and also sets last
294
 
 * change date.
295
 
 */
296
 
static void set_backend_down(struct proxy *be)
297
 
{
298
 
        be->last_change = now.tv_sec;
299
 
        be->down_trans++;
300
 
 
301
 
        Alert("%s '%s' has no server available!\n", proxy_type_str(be), be->id);
302
 
        send_log(be, LOG_EMERG, "%s %s has no server available!\n", proxy_type_str(be), be->id);
303
 
}
304
 
 
305
 
/* Redistribute pending connections when a server goes down. The number of
306
 
 * connections redistributed is returned.
307
 
 */
308
 
static int redistribute_pending(struct server *s)
309
 
{
310
 
        struct pendconn *pc, *pc_bck, *pc_end;
311
 
        int xferred = 0;
312
 
 
313
 
        FOREACH_ITEM_SAFE(pc, pc_bck, &s->pendconns, pc_end, struct pendconn *, list) {
314
 
                struct session *sess = pc->sess;
315
 
                if ((sess->be->options & (PR_O_REDISP|PR_O_PERSIST)) == PR_O_REDISP &&
316
 
                    !(sess->flags & SN_FORCE_PRST)) {
317
 
                        /* The REDISP option was specified. We will ignore
318
 
                         * cookie and force to balance or use the dispatcher.
319
 
                         */
320
 
 
321
 
                        /* it's left to the dispatcher to choose a server */
322
 
                        sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
323
 
 
324
 
                        pendconn_free(pc);
325
 
                        task_wakeup(sess->task, TASK_WOKEN_RES);
326
 
                        xferred++;
327
 
                }
328
 
        }
329
 
        return xferred;
330
 
}
331
 
 
332
 
/* Check for pending connections at the backend, and assign some of them to
333
 
 * the server coming up. The server's weight is checked before being assigned
334
 
 * connections it may not be able to handle. The total number of transferred
335
 
 * connections is returned.
336
 
 */
337
 
static int check_for_pending(struct server *s)
338
 
{
339
 
        int xferred;
340
 
 
341
 
        if (!s->eweight)
342
 
                return 0;
343
 
 
344
 
        for (xferred = 0; !s->maxconn || xferred < srv_dynamic_maxconn(s); xferred++) {
345
 
                struct session *sess;
346
 
                struct pendconn *p;
347
 
 
348
 
                p = pendconn_from_px(s->proxy);
349
 
                if (!p)
350
 
                        break;
351
 
                p->sess->srv = s;
352
 
                sess = p->sess;
353
 
                pendconn_free(p);
354
 
                task_wakeup(sess->task, TASK_WOKEN_RES);
355
 
        }
356
 
        return xferred;
357
 
}
358
 
 
359
 
/* Sets server <s> down, notifies by all available means, recounts the
360
 
 * remaining servers on the proxy and transfers queued sessions whenever
361
 
 * possible to other servers. It automatically recomputes the number of
362
 
 * servers, but not the map.
363
 
 */
364
 
void set_server_down(struct server *s)
365
 
{
366
 
        struct server *srv;
367
 
        struct chunk msg;
368
 
        int xferred;
369
 
 
370
 
        if (s->state & SRV_MAINTAIN) {
371
 
                s->health = s->rise;
372
 
        }
373
 
 
374
 
        if (s->health == s->rise || s->tracked) {
375
 
                int srv_was_paused = s->state & SRV_GOINGDOWN;
376
 
                int prev_srv_count = s->proxy->srv_bck + s->proxy->srv_act;
377
 
 
378
 
                s->last_change = now.tv_sec;
379
 
                s->state &= ~(SRV_RUNNING | SRV_GOINGDOWN);
380
 
                if (s->proxy->lbprm.set_server_status_down)
381
 
                        s->proxy->lbprm.set_server_status_down(s);
382
 
 
383
 
                /* we might have sessions queued on this server and waiting for
384
 
                 * a connection. Those which are redispatchable will be queued
385
 
                 * to another server or to the proxy itself.
386
 
                 */
387
 
                xferred = redistribute_pending(s);
388
 
 
389
 
                chunk_init(&msg, trash, trashlen);
390
 
 
391
 
                if (s->state & SRV_MAINTAIN) {
392
 
                        chunk_printf(&msg,
393
 
                                "%sServer %s/%s is DOWN for maintenance", s->state & SRV_BACKUP ? "Backup " : "",
394
 
                                s->proxy->id, s->id);
395
 
                } else {
396
 
                        chunk_printf(&msg,
397
 
                                "%sServer %s/%s is DOWN", s->state & SRV_BACKUP ? "Backup " : "",
398
 
                                s->proxy->id, s->id);
399
 
 
400
 
                        server_status_printf(&msg, s,
401
 
                                                ((!s->tracked && !(s->proxy->options2 & PR_O2_LOGHCHKS))?SSP_O_HCHK:0),
402
 
                                                xferred);
403
 
                }
404
 
                Warning("%s.\n", trash);
405
 
 
406
 
                /* we don't send an alert if the server was previously paused */
407
 
                if (srv_was_paused)
408
 
                        send_log(s->proxy, LOG_NOTICE, "%s.\n", trash);
409
 
                else
410
 
                        send_log(s->proxy, LOG_ALERT, "%s.\n", trash);
411
 
 
412
 
                if (prev_srv_count && s->proxy->srv_bck == 0 && s->proxy->srv_act == 0)
413
 
                        set_backend_down(s->proxy);
414
 
 
415
 
                s->counters.down_trans++;
416
 
 
417
 
                if (s->state & SRV_CHECKED)
418
 
                        for(srv = s->tracknext; srv; srv = srv->tracknext)
419
 
                                if (! (srv->state & SRV_MAINTAIN))
420
 
                                        /* Only notify tracking servers that are not already in maintenance. */
421
 
                                        set_server_down(srv);
422
 
        }
423
 
 
424
 
        s->health = 0; /* failure */
425
 
}
426
 
 
427
 
void set_server_up(struct server *s) {
428
 
 
429
 
        struct server *srv;
430
 
        struct chunk msg;
431
 
        int xferred;
432
 
        unsigned int old_state = s->state;
433
 
 
434
 
        if (s->state & SRV_MAINTAIN) {
435
 
                s->health = s->rise;
436
 
        }
437
 
 
438
 
        if (s->health == s->rise || s->tracked) {
439
 
                if (s->proxy->srv_bck == 0 && s->proxy->srv_act == 0) {
440
 
                        if (s->proxy->last_change < now.tv_sec)         // ignore negative times
441
 
                                s->proxy->down_time += now.tv_sec - s->proxy->last_change;
442
 
                        s->proxy->last_change = now.tv_sec;
443
 
                }
444
 
 
445
 
                if (s->last_change < now.tv_sec)                        // ignore negative times
446
 
                        s->down_time += now.tv_sec - s->last_change;
447
 
 
448
 
                s->last_change = now.tv_sec;
449
 
                s->state |= SRV_RUNNING;
450
 
                s->state &= ~SRV_MAINTAIN;
451
 
 
452
 
                if (s->slowstart > 0) {
453
 
                        s->state |= SRV_WARMINGUP;
454
 
                        task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20))));
455
 
                }
456
 
 
457
 
                server_recalc_eweight(s);
458
 
 
459
 
                /* check if we can handle some connections queued at the proxy. We
460
 
                 * will take as many as we can handle.
461
 
                 */
462
 
                xferred = check_for_pending(s);
463
 
 
464
 
                chunk_init(&msg, trash, trashlen);
465
 
 
466
 
                if (old_state & SRV_MAINTAIN) {
467
 
                        chunk_printf(&msg,
468
 
                                "%sServer %s/%s is UP (leaving maintenance)", s->state & SRV_BACKUP ? "Backup " : "",
469
 
                                s->proxy->id, s->id);
470
 
                } else {
471
 
                        chunk_printf(&msg,
472
 
                                "%sServer %s/%s is UP", s->state & SRV_BACKUP ? "Backup " : "",
473
 
                                s->proxy->id, s->id);
474
 
 
475
 
                        server_status_printf(&msg, s,
476
 
                                                ((!s->tracked && !(s->proxy->options2 & PR_O2_LOGHCHKS))?SSP_O_HCHK:0),
477
 
                                                xferred);
478
 
                }
479
 
 
480
 
                Warning("%s.\n", trash);
481
 
                send_log(s->proxy, LOG_NOTICE, "%s.\n", trash);
482
 
 
483
 
                if (s->state & SRV_CHECKED)
484
 
                        for(srv = s->tracknext; srv; srv = srv->tracknext)
485
 
                                if (! (srv->state & SRV_MAINTAIN))
486
 
                                        /* Only notify tracking servers if they're not in maintenance. */
487
 
                                        set_server_up(srv);
488
 
        }
489
 
 
490
 
        if (s->health >= s->rise)
491
 
                s->health = s->rise + s->fall - 1; /* OK now */
492
 
 
493
 
}
494
 
 
495
 
static void set_server_disabled(struct server *s) {
496
 
 
497
 
        struct server *srv;
498
 
        struct chunk msg;
499
 
        int xferred;
500
 
 
501
 
        s->state |= SRV_GOINGDOWN;
502
 
        if (s->proxy->lbprm.set_server_status_down)
503
 
                s->proxy->lbprm.set_server_status_down(s);
504
 
 
505
 
        /* we might have sessions queued on this server and waiting for
506
 
         * a connection. Those which are redispatchable will be queued
507
 
         * to another server or to the proxy itself.
508
 
         */
509
 
        xferred = redistribute_pending(s);
510
 
 
511
 
        chunk_init(&msg, trash, trashlen);
512
 
 
513
 
        chunk_printf(&msg,
514
 
                "Load-balancing on %sServer %s/%s is disabled",
515
 
                s->state & SRV_BACKUP ? "Backup " : "",
516
 
                s->proxy->id, s->id);
517
 
 
518
 
        server_status_printf(&msg, s,
519
 
                                ((!s->tracked && !(s->proxy->options2 & PR_O2_LOGHCHKS))?SSP_O_HCHK:0),
520
 
                                xferred);
521
 
 
522
 
        Warning("%s.\n", trash);
523
 
        send_log(s->proxy, LOG_NOTICE, "%s.\n", trash);
524
 
 
525
 
        if (!s->proxy->srv_bck && !s->proxy->srv_act)
526
 
                set_backend_down(s->proxy);
527
 
 
528
 
        if (s->state & SRV_CHECKED)
529
 
                for(srv = s->tracknext; srv; srv = srv->tracknext)
530
 
                        set_server_disabled(srv);
531
 
}
532
 
 
533
 
static void set_server_enabled(struct server *s) {
534
 
 
535
 
        struct server *srv;
536
 
        struct chunk msg;
537
 
        int xferred;
538
 
 
539
 
        s->state &= ~SRV_GOINGDOWN;
540
 
        if (s->proxy->lbprm.set_server_status_up)
541
 
                s->proxy->lbprm.set_server_status_up(s);
542
 
 
543
 
        /* check if we can handle some connections queued at the proxy. We
544
 
         * will take as many as we can handle.
545
 
         */
546
 
        xferred = check_for_pending(s);
547
 
 
548
 
        chunk_init(&msg, trash, trashlen);
549
 
 
550
 
        chunk_printf(&msg,
551
 
                "Load-balancing on %sServer %s/%s is enabled again",
552
 
                s->state & SRV_BACKUP ? "Backup " : "",
553
 
                s->proxy->id, s->id);
554
 
 
555
 
        server_status_printf(&msg, s,
556
 
                                ((!s->tracked && !(s->proxy->options2 & PR_O2_LOGHCHKS))?SSP_O_HCHK:0),
557
 
                                xferred);
558
 
 
559
 
        Warning("%s.\n", trash);
560
 
        send_log(s->proxy, LOG_NOTICE, "%s.\n", trash);
561
 
 
562
 
        if (s->state & SRV_CHECKED)
563
 
                for(srv = s->tracknext; srv; srv = srv->tracknext)
564
 
                        set_server_enabled(srv);
565
 
}
566
 
 
567
 
void health_adjust(struct server *s, short status) {
568
 
 
 
280
            (status != prev_status || report)) {
 
281
                chunk_printf(&trash,
 
282
                             "%s check for %sserver %s/%s %s%s",
 
283
                             (check->state & CHK_ST_AGENT) ? "Agent" : "Health",
 
284
                             s->flags & SRV_F_BACKUP ? "backup " : "",
 
285
                             s->proxy->id, s->id,
 
286
                             (check->result == CHK_RES_CONDPASS) ? "conditionally ":"",
 
287
                             (check->result >= CHK_RES_PASSED)   ? "succeeded" : "failed");
 
288
 
 
289
                srv_append_status(&trash, s, check_reason_string(check), -1, 0);
 
290
 
 
291
                chunk_appendf(&trash, ", status: %d/%d %s",
 
292
                             (check->health >= check->rise) ? check->health - check->rise + 1 : check->health,
 
293
                             (check->health >= check->rise) ? check->fall : check->rise,
 
294
                             (check->health >= check->rise) ? (s->uweight ? "UP" : "DRAIN") : "DOWN");
 
295
 
 
296
                Warning("%s.\n", trash.str);
 
297
                send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
 
298
        }
 
299
}
 
300
 
 
301
/* Marks the check <check>'s server down if the current check is already failed
 
302
 * and the server is not down yet nor in maintenance.
 
303
 */
 
304
static void check_notify_failure(struct check *check)
 
305
{
 
306
        struct server *s = check->server;
 
307
 
 
308
        /* The agent secondary check should only cause a server to be marked
 
309
         * as down if check->status is HCHK_STATUS_L7STS, which indicates
 
310
         * that the agent returned "fail", "stopped" or "down".
 
311
         * The implication here is that failure to connect to the agent
 
312
         * as a secondary check should not cause the server to be marked
 
313
         * down. */
 
314
        if ((check->state & CHK_ST_AGENT) && check->status != HCHK_STATUS_L7STS)
 
315
                return;
 
316
 
 
317
        if (check->health > 0)
 
318
                return;
 
319
 
 
320
        /* We only report a reason for the check if we did not do so previously */
 
321
        srv_set_stopped(s, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check_reason_string(check) : NULL);
 
322
}
 
323
 
 
324
/* Marks the check <check> as valid and tries to set its server up, provided
 
325
 * it isn't in maintenance, it is not tracking a down server and other checks
 
326
 * comply. The rule is simple : by default, a server is up, unless any of the
 
327
 * following conditions is true :
 
328
 *   - health check failed (check->health < rise)
 
329
 *   - agent check failed (agent->health < rise)
 
330
 *   - the server tracks a down server (track && track->state == STOPPED)
 
331
 * Note that if the server has a slowstart, it will switch to STARTING instead
 
332
 * of RUNNING. Also, only the health checks support the nolb mode, so the
 
333
 * agent's success may not take the server out of this mode.
 
334
 */
 
335
static void check_notify_success(struct check *check)
 
336
{
 
337
        struct server *s = check->server;
 
338
 
 
339
        if (s->admin & SRV_ADMF_MAINT)
 
340
                return;
 
341
 
 
342
        if (s->track && s->track->state == SRV_ST_STOPPED)
 
343
                return;
 
344
 
 
345
        if ((s->check.state & CHK_ST_ENABLED) && (s->check.health < s->check.rise))
 
346
                return;
 
347
 
 
348
        if ((s->agent.state & CHK_ST_ENABLED) && (s->agent.health < s->agent.rise))
 
349
                return;
 
350
 
 
351
        if ((check->state & CHK_ST_AGENT) && s->state == SRV_ST_STOPPING)
 
352
                return;
 
353
 
 
354
        srv_set_running(s, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check_reason_string(check) : NULL);
 
355
}
 
356
 
 
357
/* Marks the check <check> as valid and tries to set its server into stopping mode
 
358
 * if it was running or starting, and provided it isn't in maintenance and other
 
359
 * checks comply. The conditions for the server to be marked in stopping mode are
 
360
 * the same as for it to be turned up. Also, only the health checks support the
 
361
 * nolb mode.
 
362
 */
 
363
static void check_notify_stopping(struct check *check)
 
364
{
 
365
        struct server *s = check->server;
 
366
 
 
367
        if (s->admin & SRV_ADMF_MAINT)
 
368
                return;
 
369
 
 
370
        if (check->state & CHK_ST_AGENT)
 
371
                return;
 
372
 
 
373
        if (s->track && s->track->state == SRV_ST_STOPPED)
 
374
                return;
 
375
 
 
376
        if ((s->check.state & CHK_ST_ENABLED) && (s->check.health < s->check.rise))
 
377
                return;
 
378
 
 
379
        if ((s->agent.state & CHK_ST_ENABLED) && (s->agent.health < s->agent.rise))
 
380
                return;
 
381
 
 
382
        srv_set_stopping(s, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check_reason_string(check) : NULL);
 
383
}
 
384
 
 
385
/* note: use health_adjust() only, which first checks that the observe mode is
 
386
 * enabled.
 
387
 */
 
388
void __health_adjust(struct server *s, short status)
 
389
{
569
390
        int failed;
570
391
        int expire;
571
392
 
572
 
        /* return now if observing nor health check is not enabled */
573
 
        if (!s->observe || !s->check)
574
 
                return;
575
 
 
576
393
        if (s->observe >= HANA_OBS_SIZE)
577
394
                return;
578
395
 
603
420
        if (s->consecutive_errors < s->consecutive_errors_limit)
604
421
                return;
605
422
 
606
 
        sprintf(trash, "Detected %d consecutive errors, last one was: %s",
607
 
                s->consecutive_errors, get_analyze_status(status));
 
423
        chunk_printf(&trash, "Detected %d consecutive errors, last one was: %s",
 
424
                     s->consecutive_errors, get_analyze_status(status));
608
425
 
609
426
        switch (s->onerror) {
610
427
                case HANA_ONERR_FASTINTER:
613
430
 
614
431
                case HANA_ONERR_SUDDTH:
615
432
                /* simulate a pre-fatal failed health check */
616
 
                        if (s->health > s->rise)
617
 
                                s->health = s->rise + 1;
 
433
                        if (s->check.health > s->check.rise)
 
434
                                s->check.health = s->check.rise + 1;
618
435
 
619
436
                        /* no break - fall through */
620
437
 
621
438
                case HANA_ONERR_FAILCHK:
622
439
                /* simulate a failed health check */
623
 
                        set_server_check_status(s, HCHK_STATUS_HANA, trash);
624
 
 
625
 
                        if (s->health > s->rise) {
626
 
                                s->health--; /* still good */
627
 
                                s->counters.failed_checks++;
628
 
                        }
629
 
                        else
630
 
                                set_server_down(s);
631
 
 
 
440
                        set_server_check_status(&s->check, HCHK_STATUS_HANA, trash.str);
 
441
                        check_notify_failure(&s->check);
632
442
                        break;
633
443
 
634
444
                case HANA_ONERR_MARKDWN:
635
445
                /* mark server down */
636
 
                        s->health = s->rise;
637
 
                        set_server_check_status(s, HCHK_STATUS_HANA, trash);
638
 
                        set_server_down(s);
639
 
 
 
446
                        s->check.health = s->check.rise;
 
447
                        set_server_check_status(&s->check, HCHK_STATUS_HANA, trash.str);
 
448
                        check_notify_failure(&s->check);
640
449
                        break;
641
450
 
642
451
                default:
647
456
        s->consecutive_errors = 0;
648
457
        s->counters.failed_hana++;
649
458
 
650
 
        if (s->fastinter) {
651
 
                expire = tick_add(now_ms, MS_TO_TICKS(s->fastinter));
652
 
                if (s->check->expire > expire) {
653
 
                        s->check->expire = expire;
 
459
        if (s->check.fastinter) {
 
460
                expire = tick_add(now_ms, MS_TO_TICKS(s->check.fastinter));
 
461
                if (s->check.task->expire > expire) {
 
462
                        s->check.task->expire = expire;
654
463
                        /* requeue check task with new expire */
655
 
                        task_queue(s->check);
 
464
                        task_queue(s->check.task);
656
465
                }
657
466
        }
658
467
}
659
468
 
660
 
static int httpchk_build_status_header(struct server *s, char *buffer)
 
469
static int httpchk_build_status_header(struct server *s, char *buffer, int size)
661
470
{
662
471
        int sv_state;
663
472
        int ratio;
670
479
        memcpy(buffer + hlen, "X-Haproxy-Server-State: ", 24);
671
480
        hlen += 24;
672
481
 
673
 
        if (!(s->state & SRV_CHECKED))
674
 
                sv_state = 6; /* should obviously never happen */
675
 
        else if (s->state & SRV_RUNNING) {
676
 
                if (s->health == s->rise + s->fall - 1)
 
482
        if (!(s->check.state & CHK_ST_ENABLED))
 
483
                sv_state = 6;
 
484
        else if (s->state != SRV_ST_STOPPED) {
 
485
                if (s->check.health == s->check.rise + s->check.fall - 1)
677
486
                        sv_state = 3; /* UP */
678
487
                else
679
488
                        sv_state = 2; /* going down */
680
489
 
681
 
                if (s->state & SRV_GOINGDOWN)
 
490
                if (s->state == SRV_ST_STOPPING)
682
491
                        sv_state += 2;
683
492
        } else {
684
 
                if (s->health)
 
493
                if (s->check.health)
685
494
                        sv_state = 1; /* going up */
686
495
                else
687
496
                        sv_state = 0; /* DOWN */
688
497
        }
689
498
 
690
 
        hlen += sprintf(buffer + hlen,
 
499
        hlen += snprintf(buffer + hlen, size - hlen,
691
500
                             srv_hlt_st[sv_state],
692
 
                             (s->state & SRV_RUNNING) ? (s->health - s->rise + 1) : (s->health),
693
 
                             (s->state & SRV_RUNNING) ? (s->fall) : (s->rise));
 
501
                             (s->state != SRV_ST_STOPPED) ? (s->check.health - s->check.rise + 1) : (s->check.health),
 
502
                             (s->state != SRV_ST_STOPPED) ? (s->check.fall) : (s->check.rise));
694
503
 
695
 
        hlen += sprintf(buffer + hlen, "; name=%s/%s; node=%s; weight=%d/%d; scur=%d/%d; qcur=%d",
 
504
        hlen += snprintf(buffer + hlen,  size - hlen, "; name=%s/%s; node=%s; weight=%d/%d; scur=%d/%d; qcur=%d",
696
505
                             s->proxy->id, s->id,
697
506
                             global.node,
698
507
                             (s->eweight * s->proxy->lbprm.wmult + s->proxy->lbprm.wdiv - 1) / s->proxy->lbprm.wdiv,
700
509
                             s->cur_sess, s->proxy->beconn - s->proxy->nbpend,
701
510
                             s->nbpend);
702
511
 
703
 
        if ((s->state & SRV_WARMINGUP) &&
 
512
        if ((s->state == SRV_ST_STARTING) &&
704
513
            now.tv_sec < s->last_change + s->slowstart &&
705
514
            now.tv_sec >= s->last_change) {
706
515
                ratio = MAX(1, 100 * (now.tv_sec - s->last_change) / s->slowstart);
707
 
                hlen += sprintf(buffer + hlen, "; throttle=%d%%", ratio);
 
516
                hlen += snprintf(buffer + hlen, size - hlen, "; throttle=%d%%", ratio);
708
517
        }
709
518
 
710
519
        buffer[hlen++] = '\r';
713
522
        return hlen;
714
523
}
715
524
 
 
525
/* Check the connection. If an error has already been reported or the socket is
 
526
 * closed, keep errno intact as it is supposed to contain the valid error code.
 
527
 * If no error is reported, check the socket's error queue using getsockopt().
 
528
 * Warning, this must be done only once when returning from poll, and never
 
529
 * after an I/O error was attempted, otherwise the error queue might contain
 
530
 * inconsistent errors. If an error is detected, the CO_FL_ERROR is set on the
 
531
 * socket. Returns non-zero if an error was reported, zero if everything is
 
532
 * clean (including a properly closed socket).
 
533
 */
 
534
static int retrieve_errno_from_socket(struct connection *conn)
 
535
{
 
536
        int skerr;
 
537
        socklen_t lskerr = sizeof(skerr);
 
538
 
 
539
        if (conn->flags & CO_FL_ERROR && ((errno && errno != EAGAIN) || !conn->ctrl))
 
540
                return 1;
 
541
 
 
542
        if (!conn_ctrl_ready(conn))
 
543
                return 0;
 
544
 
 
545
        if (getsockopt(conn->t.sock.fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr) == 0)
 
546
                errno = skerr;
 
547
 
 
548
        if (errno == EAGAIN)
 
549
                errno = 0;
 
550
 
 
551
        if (!errno) {
 
552
                /* we could not retrieve an error, that does not mean there is
 
553
                 * none. Just don't change anything and only report the prior
 
554
                 * error if any.
 
555
                 */
 
556
                if (conn->flags & CO_FL_ERROR)
 
557
                        return 1;
 
558
                else
 
559
                        return 0;
 
560
        }
 
561
 
 
562
        conn->flags |= CO_FL_ERROR | CO_FL_SOCK_WR_SH | CO_FL_SOCK_RD_SH;
 
563
        return 1;
 
564
}
 
565
 
 
566
/* Try to collect as much information as possible on the connection status,
 
567
 * and adjust the server status accordingly. It may make use of <errno_bck>
 
568
 * if non-null when the caller is absolutely certain of its validity (eg:
 
569
 * checked just after a syscall). If the caller doesn't have a valid errno,
 
570
 * it can pass zero, and retrieve_errno_from_socket() will be called to try
 
571
 * to extract errno from the socket. If no error is reported, it will consider
 
572
 * the <expired> flag. This is intended to be used when a connection error was
 
573
 * reported in conn->flags or when a timeout was reported in <expired>. The
 
574
 * function takes care of not updating a server status which was already set.
 
575
 * All situations where at least one of <expired> or CO_FL_ERROR are set
 
576
 * produce a status.
 
577
 */
 
578
static void chk_report_conn_err(struct connection *conn, int errno_bck, int expired)
 
579
{
 
580
        struct check *check = conn->owner;
 
581
        const char *err_msg;
 
582
        struct chunk *chk;
 
583
 
 
584
        if (check->result != CHK_RES_UNKNOWN)
 
585
                return;
 
586
 
 
587
        errno = errno_bck;
 
588
        if (!errno || errno == EAGAIN)
 
589
                retrieve_errno_from_socket(conn);
 
590
 
 
591
        if (!(conn->flags & CO_FL_ERROR) && !expired)
 
592
                return;
 
593
 
 
594
        /* we'll try to build a meaningful error message depending on the
 
595
         * context of the error possibly present in conn->err_code, and the
 
596
         * socket error possibly collected above. This is useful to know the
 
597
         * exact step of the L6 layer (eg: SSL handshake).
 
598
         */
 
599
        chk = get_trash_chunk();
 
600
 
 
601
        if (check->type == PR_O2_TCPCHK_CHK) {
 
602
                chunk_printf(chk, " at step %d of tcp-check", tcpcheck_get_step_id(check->server));
 
603
                /* we were looking for a string */
 
604
                if (check->current_step && check->current_step->action == TCPCHK_ACT_CONNECT) {
 
605
                        chunk_appendf(chk, " (connect)");
 
606
                }
 
607
                else if (check->current_step && check->current_step->action == TCPCHK_ACT_EXPECT) {
 
608
                        if (check->current_step->string)
 
609
                                chunk_appendf(chk, " (string '%s')", check->current_step->string);
 
610
                        else if (check->current_step->expect_regex)
 
611
                                chunk_appendf(chk, " (expect regex)");
 
612
                }
 
613
                else if (check->current_step && check->current_step->action == TCPCHK_ACT_SEND) {
 
614
                        chunk_appendf(chk, " (send)");
 
615
                }
 
616
        }
 
617
 
 
618
        if (conn->err_code) {
 
619
                if (errno && errno != EAGAIN)
 
620
                        chunk_printf(&trash, "%s (%s)%s", conn_err_code_str(conn), strerror(errno), chk->str);
 
621
                else
 
622
                        chunk_printf(&trash, "%s%s", conn_err_code_str(conn), chk->str);
 
623
                err_msg = trash.str;
 
624
        }
 
625
        else {
 
626
                if (errno && errno != EAGAIN) {
 
627
                        chunk_printf(&trash, "%s%s", strerror(errno), chk->str);
 
628
                        err_msg = trash.str;
 
629
                }
 
630
                else {
 
631
                        err_msg = chk->str;
 
632
                }
 
633
        }
 
634
 
 
635
        if ((conn->flags & (CO_FL_CONNECTED|CO_FL_WAIT_L4_CONN)) == CO_FL_WAIT_L4_CONN) {
 
636
                /* L4 not established (yet) */
 
637
                if (conn->flags & CO_FL_ERROR)
 
638
                        set_server_check_status(check, HCHK_STATUS_L4CON, err_msg);
 
639
                else if (expired)
 
640
                        set_server_check_status(check, HCHK_STATUS_L4TOUT, err_msg);
 
641
        }
 
642
        else if ((conn->flags & (CO_FL_CONNECTED|CO_FL_WAIT_L6_CONN)) == CO_FL_WAIT_L6_CONN) {
 
643
                /* L6 not established (yet) */
 
644
                if (conn->flags & CO_FL_ERROR)
 
645
                        set_server_check_status(check, HCHK_STATUS_L6RSP, err_msg);
 
646
                else if (expired)
 
647
                        set_server_check_status(check, HCHK_STATUS_L6TOUT, err_msg);
 
648
        }
 
649
        else if (conn->flags & CO_FL_ERROR) {
 
650
                /* I/O error after connection was established and before we could diagnose */
 
651
                set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
 
652
        }
 
653
        else if (expired) {
 
654
                /* connection established but expired check */
 
655
                if (check->type == PR_O2_SSL3_CHK)
 
656
                        set_server_check_status(check, HCHK_STATUS_L6TOUT, err_msg);
 
657
                else    /* HTTP, SMTP, ... */
 
658
                        set_server_check_status(check, HCHK_STATUS_L7TOUT, err_msg);
 
659
        }
 
660
 
 
661
        return;
 
662
}
 
663
 
716
664
/*
717
665
 * This function is used only for server health-checks. It handles
718
666
 * the connection acknowledgement. If the proxy requires L7 health-checks,
719
667
 * it sends the request. In other cases, it calls set_server_check_status()
720
 
 * to set s->check_status, s->check_duration and s->result.
721
 
 * The function itself returns 0 if it needs some polling before being called
722
 
 * again, otherwise 1.
 
668
 * to set check->status, check->duration and check->result.
723
669
 */
724
 
static int event_srv_chk_w(int fd)
 
670
static void event_srv_chk_w(struct connection *conn)
725
671
{
726
 
        __label__ out_wakeup, out_nowake, out_poll, out_error;
727
 
        struct task *t = fdtab[fd].owner;
728
 
        struct server *s = t->context;
729
 
 
730
 
        //fprintf(stderr, "event_srv_chk_w, state=%ld\n", unlikely(fdtab[fd].state));
731
 
        if (unlikely(fdtab[fd].state == FD_STERROR || (fdtab[fd].ev & FD_POLL_ERR))) {
732
 
                int skerr, err = errno;
733
 
                socklen_t lskerr = sizeof(skerr);
734
 
 
735
 
                if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr) && skerr)
736
 
                        err = skerr;
737
 
 
738
 
                set_server_check_status(s, HCHK_STATUS_L4CON, strerror(err));
739
 
                goto out_error;
740
 
        }
741
 
 
742
 
        /* here, we know that the connection is established */
743
 
 
744
 
        if (!(s->result & SRV_CHK_ERROR)) {
745
 
                /* we don't want to mark 'UP' a server on which we detected an error earlier */
746
 
                if ((s->proxy->options & PR_O_HTTP_CHK) ||
747
 
                    (s->proxy->options & PR_O_SMTP_CHK) ||
748
 
                    (s->proxy->options2 & PR_O2_SSL3_CHK) ||
749
 
                    (s->proxy->options2 & PR_O2_MYSQL_CHK) ||
750
 
                    (s->proxy->options2 & PR_O2_LDAP_CHK)) {
751
 
                        int ret;
752
 
                        const char *check_req = s->proxy->check_req;
753
 
                        int check_len = s->proxy->check_len;
754
 
 
755
 
                        /* we want to check if this host replies to HTTP or SSLv3 requests
756
 
                         * so we'll send the request, and won't wake the checker up now.
757
 
                         */
758
 
 
759
 
                        if (s->proxy->options2 & PR_O2_SSL3_CHK) {
760
 
                                /* SSL requires that we put Unix time in the request */
761
 
                                int gmt_time = htonl(date.tv_sec);
762
 
                                memcpy(s->proxy->check_req + 11, &gmt_time, 4);
763
 
                        }
764
 
                        else if (s->proxy->options & PR_O_HTTP_CHK) {
765
 
                                memcpy(trash, check_req, check_len);
766
 
 
767
 
                                if (s->proxy->options2 & PR_O2_CHK_SNDST)
768
 
                                        check_len += httpchk_build_status_header(s, trash + check_len);
769
 
 
770
 
                                trash[check_len++] = '\r';
771
 
                                trash[check_len++] = '\n';
772
 
                                trash[check_len] = '\0';
773
 
                                check_req = trash;
774
 
                        }
775
 
 
776
 
                        ret = send(fd, check_req, check_len, MSG_DONTWAIT | MSG_NOSIGNAL);
777
 
                        if (ret == check_len) {
778
 
                                /* we allow up to <timeout.check> if nonzero for a responce */
779
 
                                if (s->proxy->timeout.check) {
780
 
                                        t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);
781
 
                                        task_queue(t);
782
 
                                }
783
 
                                EV_FD_SET(fd, DIR_RD);   /* prepare for reading reply */
784
 
                                goto out_nowake;
785
 
                        }
786
 
                        else if (ret == 0 || errno == EAGAIN)
787
 
                                goto out_poll;
788
 
                        else {
789
 
                                switch (errno) {
790
 
                                        case ECONNREFUSED:
791
 
                                        case ENETUNREACH:
792
 
                                                set_server_check_status(s, HCHK_STATUS_L4CON, strerror(errno));
793
 
                                                break;
794
 
 
795
 
                                        default:
796
 
                                                set_server_check_status(s, HCHK_STATUS_SOCKERR, strerror(errno));
797
 
                                }
798
 
 
799
 
                                goto out_error;
800
 
                        }
801
 
                }
802
 
                else {
803
 
                        /* We have no data to send to check the connection, and
804
 
                         * getsockopt() will not inform us whether the connection
805
 
                         * is still pending. So we'll reuse connect() to check the
806
 
                         * state of the socket. This has the advantage of givig us
807
 
                         * the following info :
808
 
                         *  - error
809
 
                         *  - connecting (EALREADY, EINPROGRESS)
810
 
                         *  - connected (EISCONN, 0)
811
 
                         */
812
 
 
813
 
                        struct sockaddr_in sa;
814
 
 
815
 
                        sa = (s->check_addr.sin_addr.s_addr) ? s->check_addr : s->addr;
816
 
                        sa.sin_port = htons(s->check_port);
817
 
 
818
 
                        if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == 0)
819
 
                                errno = 0;
820
 
 
821
 
                        if (errno == EALREADY || errno == EINPROGRESS)
822
 
                                goto out_poll;
823
 
 
824
 
                        if (errno && errno != EISCONN) {
825
 
                                set_server_check_status(s, HCHK_STATUS_L4CON, strerror(errno));
826
 
                                goto out_error;
827
 
                        }
828
 
 
829
 
                        /* good TCP connection is enough */
830
 
                        set_server_check_status(s, HCHK_STATUS_L4OK, NULL);
831
 
 
832
 
                        /* avoid accumulating TIME_WAIT on connect-only checks */
833
 
                        if (!tcp_drain(fd))
834
 
                                setsockopt(fd, SOL_SOCKET, SO_LINGER,
835
 
                                           (struct linger *) &nolinger, sizeof(struct linger));
 
672
        struct check *check = conn->owner;
 
673
        struct server *s = check->server;
 
674
        struct task *t = check->task;
 
675
 
 
676
        if (unlikely(check->result == CHK_RES_FAILED))
 
677
                goto out_wakeup;
 
678
 
 
679
        if (conn->flags & CO_FL_HANDSHAKE)
 
680
                return;
 
681
 
 
682
        if (retrieve_errno_from_socket(conn)) {
 
683
                chk_report_conn_err(conn, errno, 0);
 
684
                __conn_data_stop_both(conn);
 
685
                goto out_wakeup;
 
686
        }
 
687
 
 
688
        if (conn->flags & (CO_FL_SOCK_WR_SH | CO_FL_DATA_WR_SH)) {
 
689
                /* if the output is closed, we can't do anything */
 
690
                conn->flags |= CO_FL_ERROR;
 
691
                chk_report_conn_err(conn, 0, 0);
 
692
                goto out_wakeup;
 
693
        }
 
694
 
 
695
        /* here, we know that the connection is established. That's enough for
 
696
         * a pure TCP check.
 
697
         */
 
698
        if (!check->type)
 
699
                goto out_wakeup;
 
700
 
 
701
        if (check->type == PR_O2_TCPCHK_CHK) {
 
702
                tcpcheck_main(conn);
 
703
                return;
 
704
        }
 
705
 
 
706
        if (check->bo->o) {
 
707
                conn->xprt->snd_buf(conn, check->bo, 0);
 
708
                if (conn->flags & CO_FL_ERROR) {
 
709
                        chk_report_conn_err(conn, errno, 0);
 
710
                        __conn_data_stop_both(conn);
836
711
                        goto out_wakeup;
837
712
                }
838
 
        }
 
713
                if (check->bo->o)
 
714
                        return;
 
715
        }
 
716
 
 
717
        /* full request sent, we allow up to <timeout.check> if nonzero for a response */
 
718
        if (s->proxy->timeout.check) {
 
719
                t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);
 
720
                task_queue(t);
 
721
        }
 
722
        goto out_nowake;
 
723
 
839
724
 out_wakeup:
840
725
        task_wakeup(t, TASK_WOKEN_IO);
841
726
 out_nowake:
842
 
        EV_FD_CLR(fd, DIR_WR);   /* nothing more to write */
843
 
        fdtab[fd].ev &= ~FD_POLL_OUT;
844
 
        return 1;
845
 
 out_poll:
846
 
        /* The connection is still pending. We'll have to poll it
847
 
         * before attempting to go further. */
848
 
        fdtab[fd].ev &= ~FD_POLL_OUT;
849
 
        return 0;
850
 
 out_error:
851
 
        fdtab[fd].state = FD_STERROR;
852
 
        goto out_wakeup;
 
727
        __conn_data_stop_send(conn);   /* nothing more to write */
853
728
}
854
729
 
855
 
 
856
730
/*
857
731
 * This function is used only for server health-checks. It handles the server's
858
732
 * reply to an HTTP request, SSL HELLO or MySQL client Auth. It calls
859
 
 * set_server_check_status() to update s->check_status, s->check_duration
860
 
 * and s->result.
 
733
 * set_server_check_status() to update check->status, check->duration
 
734
 * and check->result.
861
735
 
862
736
 * The set_server_check_status function is called with HCHK_STATUS_L7OKD if
863
737
 * an HTTP server replies HTTP 2xx or 3xx (valid responses), if an SMTP server
866
740
 * distinguish between an SSL server and a pure TCP relay). All other cases will
867
741
 * call it with a proper error status like HCHK_STATUS_L7STS, HCHK_STATUS_L6RSP,
868
742
 * etc.
869
 
 *
870
 
 * The function returns 0 if it needs to be called again after some polling,
871
 
 * otherwise non-zero..
872
743
 */
873
 
static int event_srv_chk_r(int fd)
 
744
static void event_srv_chk_r(struct connection *conn)
874
745
{
875
 
        __label__ out_wakeup;
876
 
        int len = 0;
877
 
        struct task *t = fdtab[fd].owner;
878
 
        struct server *s = t->context;
 
746
        struct check *check = conn->owner;
 
747
        struct server *s = check->server;
 
748
        struct task *t = check->task;
879
749
        char *desc;
880
 
        int done, shutr;
 
750
        int done;
881
751
        unsigned short msglen;
882
752
 
883
 
        if (unlikely((s->result & SRV_CHK_ERROR) || (fdtab[fd].state == FD_STERROR))) {
884
 
                /* in case of TCP only, this tells us if the connection failed */
885
 
                if (!(s->result & SRV_CHK_ERROR))
886
 
                        set_server_check_status(s, HCHK_STATUS_SOCKERR, NULL);
887
 
                shutr = 1;
 
753
        if (unlikely(check->result == CHK_RES_FAILED))
888
754
                goto out_wakeup;
 
755
 
 
756
        if (conn->flags & CO_FL_HANDSHAKE)
 
757
                return;
 
758
 
 
759
        if (check->type == PR_O2_TCPCHK_CHK) {
 
760
                tcpcheck_main(conn);
 
761
                return;
889
762
        }
890
763
 
891
764
        /* Warning! Linux returns EAGAIN on SO_ERROR if data are still available
898
771
         * with running the checks without attempting another socket read.
899
772
         */
900
773
 
901
 
        done = shutr = 0;
902
 
        for (len = 0; s->check_data_len < global.tune.chksize; s->check_data_len += len) {
903
 
                len = recv(fd, s->check_data + s->check_data_len, global.tune.chksize - s->check_data_len, 0);
904
 
                if (len <= 0)
905
 
                        break;
906
 
        }
 
774
        done = 0;
907
775
 
908
 
        if (len == 0)
909
 
                done = shutr = 1; /* connection hangup received */
910
 
        else if (len < 0 && errno != EAGAIN) {
911
 
                /* Report network errors only if we got no other data. Otherwise
912
 
                 * we'll let the upper layers decide whether the response is OK
913
 
                 * or not. It is very common that an RST sent by the server is
914
 
                 * reported as an error just after the last data chunk.
915
 
                 */
916
 
                done = shutr = 1;
917
 
                if (!s->check_data_len) {
918
 
                        if (!(s->result & SRV_CHK_ERROR))
919
 
                                set_server_check_status(s, HCHK_STATUS_SOCKERR, NULL);
 
776
        conn->xprt->rcv_buf(conn, check->bi, check->bi->size);
 
777
        if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH)) {
 
778
                done = 1;
 
779
                if ((conn->flags & CO_FL_ERROR) && !check->bi->i) {
 
780
                        /* Report network errors only if we got no other data. Otherwise
 
781
                         * we'll let the upper layers decide whether the response is OK
 
782
                         * or not. It is very common that an RST sent by the server is
 
783
                         * reported as an error just after the last data chunk.
 
784
                         */
 
785
                        chk_report_conn_err(conn, errno, 0);
920
786
                        goto out_wakeup;
921
787
                }
922
788
        }
923
 
        /* Note: we keep len = -1 if EAGAIN was detected */
 
789
 
924
790
 
925
791
        /* Intermediate or complete response received.
926
 
         * Terminate string in check_data buffer.
 
792
         * Terminate string in check->bi->data buffer.
927
793
         */
928
 
        if (s->check_data_len < global.tune.chksize)
929
 
                s->check_data[s->check_data_len] = '\0';
 
794
        if (check->bi->i < check->bi->size)
 
795
                check->bi->data[check->bi->i] = '\0';
930
796
        else {
931
 
                s->check_data[s->check_data_len - 1] = '\0';
 
797
                check->bi->data[check->bi->i - 1] = '\0';
932
798
                done = 1; /* buffer full, don't wait for more data */
933
799
        }
934
800
 
935
801
        /* Run the checks... */
936
 
        if (s->proxy->options & PR_O_HTTP_CHK) {
937
 
                if (!done && s->check_data_len < strlen("HTTP/1.0 000\r"))
 
802
        switch (check->type) {
 
803
        case PR_O2_HTTP_CHK:
 
804
                if (!done && check->bi->i < strlen("HTTP/1.0 000\r"))
938
805
                        goto wait_more_data;
939
806
 
940
807
                /* Check if the server speaks HTTP 1.X */
941
 
                if ((s->check_data_len < strlen("HTTP/1.0 000\r")) ||
942
 
                    (memcmp(s->check_data, "HTTP/1.", 7) != 0 ||
943
 
                    (*(s->check_data + 12) != ' ' && *(s->check_data + 12) != '\r')) ||
944
 
                    !isdigit((unsigned char) *(s->check_data + 9)) || !isdigit((unsigned char) *(s->check_data + 10)) ||
945
 
                    !isdigit((unsigned char) *(s->check_data + 11))) {
946
 
                        cut_crlf(s->check_data);
947
 
                        set_server_check_status(s, HCHK_STATUS_L7RSP, s->check_data);
 
808
                if ((check->bi->i < strlen("HTTP/1.0 000\r")) ||
 
809
                    (memcmp(check->bi->data, "HTTP/1.", 7) != 0 ||
 
810
                    (*(check->bi->data + 12) != ' ' && *(check->bi->data + 12) != '\r')) ||
 
811
                    !isdigit((unsigned char) *(check->bi->data + 9)) || !isdigit((unsigned char) *(check->bi->data + 10)) ||
 
812
                    !isdigit((unsigned char) *(check->bi->data + 11))) {
 
813
                        cut_crlf(check->bi->data);
 
814
                        set_server_check_status(check, HCHK_STATUS_L7RSP, check->bi->data);
948
815
 
949
816
                        goto out_wakeup;
950
817
                }
951
818
 
952
 
                s->check_code = str2uic(s->check_data + 9);
953
 
                desc = ltrim(s->check_data + 12, ' ');
 
819
                check->code = str2uic(check->bi->data + 9);
 
820
                desc = ltrim(check->bi->data + 12, ' ');
954
821
                
955
822
                if ((s->proxy->options & PR_O_DISABLE404) &&
956
 
                         (s->state & SRV_RUNNING) && (s->check_code == 404)) {
 
823
                         (s->state != SRV_ST_STOPPED) && (check->code == 404)) {
957
824
                        /* 404 may be accepted as "stopping" only if the server was up */
958
825
                        cut_crlf(desc);
959
 
                        set_server_check_status(s, HCHK_STATUS_L7OKCD, desc);
 
826
                        set_server_check_status(check, HCHK_STATUS_L7OKCD, desc);
960
827
                }
961
828
                else if (s->proxy->options2 & PR_O2_EXP_TYPE) {
962
829
                        /* Run content verification check... We know we have at least 13 chars */
964
831
                                goto wait_more_data;
965
832
                }
966
833
                /* check the reply : HTTP/1.X 2xx and 3xx are OK */
967
 
                else if (*(s->check_data + 9) == '2' || *(s->check_data + 9) == '3') {
 
834
                else if (*(check->bi->data + 9) == '2' || *(check->bi->data + 9) == '3') {
968
835
                        cut_crlf(desc);
969
 
                        set_server_check_status(s, HCHK_STATUS_L7OKD, desc);
 
836
                        set_server_check_status(check,  HCHK_STATUS_L7OKD, desc);
970
837
                }
971
838
                else {
972
839
                        cut_crlf(desc);
973
 
                        set_server_check_status(s, HCHK_STATUS_L7STS, desc);
 
840
                        set_server_check_status(check, HCHK_STATUS_L7STS, desc);
974
841
                }
975
 
        }
976
 
        else if (s->proxy->options2 & PR_O2_SSL3_CHK) {
977
 
                if (!done && s->check_data_len < 5)
 
842
                break;
 
843
 
 
844
        case PR_O2_SSL3_CHK:
 
845
                if (!done && check->bi->i < 5)
978
846
                        goto wait_more_data;
979
847
 
980
848
                /* Check for SSLv3 alert or handshake */
981
 
                if ((s->check_data_len >= 5) && (*s->check_data == 0x15 || *s->check_data == 0x16))
982
 
                        set_server_check_status(s, HCHK_STATUS_L6OK, NULL);
 
849
                if ((check->bi->i >= 5) && (*check->bi->data == 0x15 || *check->bi->data == 0x16))
 
850
                        set_server_check_status(check, HCHK_STATUS_L6OK, NULL);
983
851
                else
984
 
                        set_server_check_status(s, HCHK_STATUS_L6RSP, NULL);
985
 
        }
986
 
        else if (s->proxy->options & PR_O_SMTP_CHK) {
987
 
                if (!done && s->check_data_len < strlen("000\r"))
 
852
                        set_server_check_status(check, HCHK_STATUS_L6RSP, NULL);
 
853
                break;
 
854
 
 
855
        case PR_O2_SMTP_CHK:
 
856
                if (!done && check->bi->i < strlen("000\r"))
988
857
                        goto wait_more_data;
989
858
 
990
859
                /* Check if the server speaks SMTP */
991
 
                if ((s->check_data_len < strlen("000\r")) ||
992
 
                    (*(s->check_data + 3) != ' ' && *(s->check_data + 3) != '\r') ||
993
 
                    !isdigit((unsigned char) *s->check_data) || !isdigit((unsigned char) *(s->check_data + 1)) ||
994
 
                    !isdigit((unsigned char) *(s->check_data + 2))) {
995
 
                        cut_crlf(s->check_data);
996
 
                        set_server_check_status(s, HCHK_STATUS_L7RSP, s->check_data);
 
860
                if ((check->bi->i < strlen("000\r")) ||
 
861
                    (*(check->bi->data + 3) != ' ' && *(check->bi->data + 3) != '\r') ||
 
862
                    !isdigit((unsigned char) *check->bi->data) || !isdigit((unsigned char) *(check->bi->data + 1)) ||
 
863
                    !isdigit((unsigned char) *(check->bi->data + 2))) {
 
864
                        cut_crlf(check->bi->data);
 
865
                        set_server_check_status(check, HCHK_STATUS_L7RSP, check->bi->data);
997
866
 
998
867
                        goto out_wakeup;
999
868
                }
1000
869
 
1001
 
                s->check_code = str2uic(s->check_data);
 
870
                check->code = str2uic(check->bi->data);
1002
871
 
1003
 
                desc = ltrim(s->check_data + 3, ' ');
 
872
                desc = ltrim(check->bi->data + 3, ' ');
1004
873
                cut_crlf(desc);
1005
874
 
1006
875
                /* Check for SMTP code 2xx (should be 250) */
1007
 
                if (*s->check_data == '2')
1008
 
                        set_server_check_status(s, HCHK_STATUS_L7OKD, desc);
1009
 
                else
1010
 
                        set_server_check_status(s, HCHK_STATUS_L7STS, desc);
 
876
                if (*check->bi->data == '2')
 
877
                        set_server_check_status(check, HCHK_STATUS_L7OKD, desc);
 
878
                else
 
879
                        set_server_check_status(check, HCHK_STATUS_L7STS, desc);
 
880
                break;
 
881
 
 
882
        case PR_O2_LB_AGENT_CHK: {
 
883
                int status = HCHK_STATUS_CHECKED;
 
884
                const char *hs = NULL; /* health status      */
 
885
                const char *as = NULL; /* admin status */
 
886
                const char *ps = NULL; /* performance status */
 
887
                const char *err = NULL; /* first error to report */
 
888
                const char *wrn = NULL; /* first warning to report */
 
889
                char *cmd, *p;
 
890
 
 
891
                /* We're getting an agent check response. The agent could
 
892
                 * have been disabled in the mean time with a long check
 
893
                 * still pending. It is important that we ignore the whole
 
894
                 * response.
 
895
                 */
 
896
                if (!(check->server->agent.state & CHK_ST_ENABLED))
 
897
                        break;
 
898
 
 
899
                /* The agent supports strings made of a single line ended by the
 
900
                 * first CR ('\r') or LF ('\n'). This line is composed of words
 
901
                 * delimited by spaces (' '), tabs ('\t'), or commas (','). The
 
902
                 * line may optionally contained a description of a state change
 
903
                 * after a sharp ('#'), which is only considered if a health state
 
904
                 * is announced.
 
905
                 *
 
906
                 * Words may be composed of :
 
907
                 *   - a numeric weight suffixed by the percent character ('%').
 
908
                 *   - a health status among "up", "down", "stopped", and "fail".
 
909
                 *   - an admin status among "ready", "drain", "maint".
 
910
                 *
 
911
                 * These words may appear in any order. If multiple words of the
 
912
                 * same category appear, the last one wins.
 
913
                 */
 
914
 
 
915
                p = check->bi->data;
 
916
                while (*p && *p != '\n' && *p != '\r')
 
917
                        p++;
 
918
 
 
919
                if (!*p) {
 
920
                        if (!done)
 
921
                                goto wait_more_data;
 
922
 
 
923
                        /* at least inform the admin that the agent is mis-behaving */
 
924
                        set_server_check_status(check, check->status, "Ignoring incomplete line from agent");
 
925
                        break;
 
926
                }
 
927
 
 
928
                *p = 0;
 
929
                cmd = check->bi->data;
 
930
 
 
931
                while (*cmd) {
 
932
                        /* look for next word */
 
933
                        if (*cmd == ' ' || *cmd == '\t' || *cmd == ',') {
 
934
                                cmd++;
 
935
                                continue;
 
936
                        }
 
937
 
 
938
                        if (*cmd == '#') {
 
939
                                /* this is the beginning of a health status description,
 
940
                                 * skip the sharp and blanks.
 
941
                                 */
 
942
                                cmd++;
 
943
                                while (*cmd == '\t' || *cmd == ' ')
 
944
                                        cmd++;
 
945
                                break;
 
946
                        }
 
947
 
 
948
                        /* find the end of the word so that we have a null-terminated
 
949
                         * word between <cmd> and <p>.
 
950
                         */
 
951
                        p = cmd + 1;
 
952
                        while (*p && *p != '\t' && *p != ' ' && *p != '\n' && *p != ',')
 
953
                                p++;
 
954
                        if (*p)
 
955
                                *p++ = 0;
 
956
 
 
957
                        /* first, health statuses */
 
958
                        if (strcasecmp(cmd, "up") == 0) {
 
959
                                check->health = check->rise + check->fall - 1;
 
960
                                status = HCHK_STATUS_L7OKD;
 
961
                                hs = cmd;
 
962
                        }
 
963
                        else if (strcasecmp(cmd, "down") == 0) {
 
964
                                check->health = 0;
 
965
                                status = HCHK_STATUS_L7STS;
 
966
                                hs = cmd;
 
967
                        }
 
968
                        else if (strcasecmp(cmd, "stopped") == 0) {
 
969
                                check->health = 0;
 
970
                                status = HCHK_STATUS_L7STS;
 
971
                                hs = cmd;
 
972
                        }
 
973
                        else if (strcasecmp(cmd, "fail") == 0) {
 
974
                                check->health = 0;
 
975
                                status = HCHK_STATUS_L7STS;
 
976
                                hs = cmd;
 
977
                        }
 
978
                        /* admin statuses */
 
979
                        else if (strcasecmp(cmd, "ready") == 0) {
 
980
                                as = cmd;
 
981
                        }
 
982
                        else if (strcasecmp(cmd, "drain") == 0) {
 
983
                                as = cmd;
 
984
                        }
 
985
                        else if (strcasecmp(cmd, "maint") == 0) {
 
986
                                as = cmd;
 
987
                        }
 
988
                        /* else try to parse a weight here and keep the last one */
 
989
                        else if (isdigit((unsigned char)*cmd) && strchr(cmd, '%') != NULL) {
 
990
                                ps = cmd;
 
991
                        }
 
992
                        else {
 
993
                                /* keep a copy of the first error */
 
994
                                if (!err)
 
995
                                        err = cmd;
 
996
                        }
 
997
                        /* skip to next word */
 
998
                        cmd = p;
 
999
                }
 
1000
                /* here, cmd points either to \0 or to the beginning of a
 
1001
                 * description. Skip possible leading spaces.
 
1002
                 */
 
1003
                while (*cmd == ' ' || *cmd == '\n')
 
1004
                        cmd++;
 
1005
 
 
1006
                /* First, update the admin status so that we avoid sending other
 
1007
                 * possibly useless warnings and can also update the health if
 
1008
                 * present after going back up.
 
1009
                 */
 
1010
                if (as) {
 
1011
                        if (strcasecmp(as, "drain") == 0)
 
1012
                                srv_adm_set_drain(check->server);
 
1013
                        else if (strcasecmp(as, "maint") == 0)
 
1014
                                srv_adm_set_maint(check->server);
 
1015
                        else
 
1016
                                srv_adm_set_ready(check->server);
 
1017
                }
 
1018
 
 
1019
                /* now change weights */
 
1020
                if (ps) {
 
1021
                        const char *msg;
 
1022
 
 
1023
                        msg = server_parse_weight_change_request(s, ps);
 
1024
                        if (!wrn || !*wrn)
 
1025
                                wrn = msg;
 
1026
                }
 
1027
 
 
1028
                /* and finally health status */
 
1029
                if (hs) {
 
1030
                        /* We'll report some of the warnings and errors we have
 
1031
                         * here. Down reports are critical, we leave them untouched.
 
1032
                         * Lack of report, or report of 'UP' leaves the room for
 
1033
                         * ERR first, then WARN.
 
1034
                         */
 
1035
                        const char *msg = cmd;
 
1036
                        struct chunk *t;
 
1037
 
 
1038
                        if (!*msg || status == HCHK_STATUS_L7OKD) {
 
1039
                                if (err && *err)
 
1040
                                        msg = err;
 
1041
                                else if (wrn && *wrn)
 
1042
                                        msg = wrn;
 
1043
                        }
 
1044
 
 
1045
                        t = get_trash_chunk();
 
1046
                        chunk_printf(t, "via agent : %s%s%s%s",
 
1047
                                     hs, *msg ? " (" : "",
 
1048
                                     msg, *msg ? ")" : "");
 
1049
 
 
1050
                        set_server_check_status(check, status, t->str);
 
1051
                }
 
1052
                else if (err && *err) {
 
1053
                        /* No status change but we'd like to report something odd.
 
1054
                         * Just report the current state and copy the message.
 
1055
                         */
 
1056
                        chunk_printf(&trash, "agent reports an error : %s", err);
 
1057
                        set_server_check_status(check, status/*check->status*/, trash.str);
 
1058
 
 
1059
                }
 
1060
                else if (wrn && *wrn) {
 
1061
                        /* No status change but we'd like to report something odd.
 
1062
                         * Just report the current state and copy the message.
 
1063
                         */
 
1064
                        chunk_printf(&trash, "agent warns : %s", wrn);
 
1065
                        set_server_check_status(check, status/*check->status*/, trash.str);
 
1066
                }
 
1067
                else
 
1068
                        set_server_check_status(check, status, NULL);
 
1069
                break;
1011
1070
        }
1012
 
        else if (s->proxy->options2 & PR_O2_MYSQL_CHK) {
1013
 
                if (!done && s->check_data_len < 5)
 
1071
 
 
1072
        case PR_O2_PGSQL_CHK:
 
1073
                if (!done && check->bi->i < 9)
 
1074
                        goto wait_more_data;
 
1075
 
 
1076
                if (check->bi->data[0] == 'R') {
 
1077
                        set_server_check_status(check, HCHK_STATUS_L7OKD, "PostgreSQL server is ok");
 
1078
                }
 
1079
                else {
 
1080
                        if ((check->bi->data[0] == 'E') && (check->bi->data[5]!=0) && (check->bi->data[6]!=0))
 
1081
                                desc = &check->bi->data[6];
 
1082
                        else
 
1083
                                desc = "PostgreSQL unknown error";
 
1084
 
 
1085
                        set_server_check_status(check, HCHK_STATUS_L7STS, desc);
 
1086
                }
 
1087
                break;
 
1088
 
 
1089
        case PR_O2_REDIS_CHK:
 
1090
                if (!done && check->bi->i < 7)
 
1091
                        goto wait_more_data;
 
1092
 
 
1093
                if (strcmp(check->bi->data, "+PONG\r\n") == 0) {
 
1094
                        set_server_check_status(check, HCHK_STATUS_L7OKD, "Redis server is ok");
 
1095
                }
 
1096
                else {
 
1097
                        set_server_check_status(check, HCHK_STATUS_L7STS, check->bi->data);
 
1098
                }
 
1099
                break;
 
1100
 
 
1101
        case PR_O2_MYSQL_CHK:
 
1102
                if (!done && check->bi->i < 5)
1014
1103
                        goto wait_more_data;
1015
1104
 
1016
1105
                if (s->proxy->check_len == 0) { // old mode
1017
 
                        if (*(s->check_data + 4) != '\xff') {
 
1106
                        if (*(check->bi->data + 4) != '\xff') {
1018
1107
                                /* We set the MySQL Version in description for information purpose
1019
1108
                                 * FIXME : it can be cool to use MySQL Version for other purpose,
1020
1109
                                 * like mark as down old MySQL server.
1021
1110
                                 */
1022
 
                                if (s->check_data_len > 51) {
1023
 
                                        desc = ltrim(s->check_data + 5, ' ');
1024
 
                                        set_server_check_status(s, HCHK_STATUS_L7OKD, desc);
 
1111
                                if (check->bi->i > 51) {
 
1112
                                        desc = ltrim(check->bi->data + 5, ' ');
 
1113
                                        set_server_check_status(check, HCHK_STATUS_L7OKD, desc);
1025
1114
                                }
1026
1115
                                else {
1027
1116
                                        if (!done)
1029
1118
                                        /* it seems we have a OK packet but without a valid length,
1030
1119
                                         * it must be a protocol error
1031
1120
                                         */
1032
 
                                        set_server_check_status(s, HCHK_STATUS_L7RSP, s->check_data);
 
1121
                                        set_server_check_status(check, HCHK_STATUS_L7RSP, check->bi->data);
1033
1122
                                }
1034
1123
                        }
1035
1124
                        else {
1036
1125
                                /* An error message is attached in the Error packet */
1037
 
                                desc = ltrim(s->check_data + 7, ' ');
1038
 
                                set_server_check_status(s, HCHK_STATUS_L7STS, desc);
 
1126
                                desc = ltrim(check->bi->data + 7, ' ');
 
1127
                                set_server_check_status(check, HCHK_STATUS_L7STS, desc);
1039
1128
                        }
1040
1129
                } else {
1041
 
                        unsigned int first_packet_len = ((unsigned int) *s->check_data) +
1042
 
                                                        (((unsigned int) *(s->check_data + 1)) << 8) +
1043
 
                                                        (((unsigned int) *(s->check_data + 2)) << 16);
 
1130
                        unsigned int first_packet_len = ((unsigned int) *check->bi->data) +
 
1131
                                                        (((unsigned int) *(check->bi->data + 1)) << 8) +
 
1132
                                                        (((unsigned int) *(check->bi->data + 2)) << 16);
1044
1133
 
1045
 
                        if (s->check_data_len == first_packet_len + 4) {
 
1134
                        if (check->bi->i == first_packet_len + 4) {
1046
1135
                                /* MySQL Error packet always begin with field_count = 0xff */
1047
 
                                if (*(s->check_data + 4) != '\xff') {
 
1136
                                if (*(check->bi->data + 4) != '\xff') {
1048
1137
                                        /* We have only one MySQL packet and it is a Handshake Initialization packet
1049
1138
                                        * but we need to have a second packet to know if it is alright
1050
1139
                                        */
1051
 
                                        if (!done && s->check_data_len < first_packet_len + 5)
 
1140
                                        if (!done && check->bi->i < first_packet_len + 5)
1052
1141
                                                goto wait_more_data;
1053
1142
                                }
1054
1143
                                else {
1055
1144
                                        /* We have only one packet and it is an Error packet,
1056
1145
                                        * an error message is attached, so we can display it
1057
1146
                                        */
1058
 
                                        desc = &s->check_data[7];
 
1147
                                        desc = &check->bi->data[7];
1059
1148
                                        //Warning("onlyoneERR: %s\n", desc);
1060
 
                                        set_server_check_status(s, HCHK_STATUS_L7STS, desc);
 
1149
                                        set_server_check_status(check, HCHK_STATUS_L7STS, desc);
1061
1150
                                }
1062
 
                        } else if (s->check_data_len > first_packet_len + 4) {
1063
 
                                unsigned int second_packet_len = ((unsigned int) *(s->check_data + first_packet_len + 4)) +
1064
 
                                                                 (((unsigned int) *(s->check_data + first_packet_len + 5)) << 8) +
1065
 
                                                                 (((unsigned int) *(s->check_data + first_packet_len + 6)) << 16);
 
1151
                        } else if (check->bi->i > first_packet_len + 4) {
 
1152
                                unsigned int second_packet_len = ((unsigned int) *(check->bi->data + first_packet_len + 4)) +
 
1153
                                                                 (((unsigned int) *(check->bi->data + first_packet_len + 5)) << 8) +
 
1154
                                                                 (((unsigned int) *(check->bi->data + first_packet_len + 6)) << 16);
1066
1155
 
1067
 
                                if (s->check_data_len == first_packet_len + 4 + second_packet_len + 4 ) {
 
1156
                                if (check->bi->i == first_packet_len + 4 + second_packet_len + 4 ) {
1068
1157
                                        /* We have 2 packets and that's good */
1069
1158
                                        /* Check if the second packet is a MySQL Error packet or not */
1070
 
                                        if (*(s->check_data + first_packet_len + 8) != '\xff') {
 
1159
                                        if (*(check->bi->data + first_packet_len + 8) != '\xff') {
1071
1160
                                                /* No error packet */
1072
1161
                                                /* We set the MySQL Version in description for information purpose */
1073
 
                                                desc = &s->check_data[5];
 
1162
                                                desc = &check->bi->data[5];
1074
1163
                                                //Warning("2packetOK: %s\n", desc);
1075
 
                                                set_server_check_status(s, HCHK_STATUS_L7OKD, desc);
 
1164
                                                set_server_check_status(check, HCHK_STATUS_L7OKD, desc);
1076
1165
                                        }
1077
1166
                                        else {
1078
1167
                                                /* An error message is attached in the Error packet
1079
1168
                                                * so we can display it ! :)
1080
1169
                                                */
1081
 
                                                desc = &s->check_data[first_packet_len+11];
 
1170
                                                desc = &check->bi->data[first_packet_len+11];
1082
1171
                                                //Warning("2packetERR: %s\n", desc);
1083
 
                                                set_server_check_status(s, HCHK_STATUS_L7STS, desc);
 
1172
                                                set_server_check_status(check, HCHK_STATUS_L7STS, desc);
1084
1173
                                        }
1085
1174
                                }
1086
1175
                        }
1090
1179
                                /* it seems we have a Handshake Initialization packet but without a valid length,
1091
1180
                                 * it must be a protocol error
1092
1181
                                 */
1093
 
                                desc = &s->check_data[5];
 
1182
                                desc = &check->bi->data[5];
1094
1183
                                //Warning("protoerr: %s\n", desc);
1095
 
                                set_server_check_status(s, HCHK_STATUS_L7RSP, desc);
 
1184
                                set_server_check_status(check, HCHK_STATUS_L7RSP, desc);
1096
1185
                        }
1097
1186
                }
1098
 
        }
1099
 
        else if (s->proxy->options2 & PR_O2_LDAP_CHK) {
1100
 
                if (!done && s->check_data_len < 14)
 
1187
                break;
 
1188
 
 
1189
        case PR_O2_LDAP_CHK:
 
1190
                if (!done && check->bi->i < 14)
1101
1191
                        goto wait_more_data;
1102
1192
 
1103
1193
                /* Check if the server speaks LDAP (ASN.1/BER)
1108
1198
                /* http://tools.ietf.org/html/rfc4511#section-4.1.1
1109
1199
                 *   LDAPMessage: 0x30: SEQUENCE
1110
1200
                 */
1111
 
                if ((s->check_data_len < 14) || (*(s->check_data) != '\x30')) {
1112
 
                        set_server_check_status(s, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
 
1201
                if ((check->bi->i < 14) || (*(check->bi->data) != '\x30')) {
 
1202
                        set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
1113
1203
                }
1114
1204
                else {
1115
1205
                         /* size of LDAPMessage */
1116
 
                        msglen = (*(s->check_data + 1) & 0x80) ? (*(s->check_data + 1) & 0x7f) : 0;
 
1206
                        msglen = (*(check->bi->data + 1) & 0x80) ? (*(check->bi->data + 1) & 0x7f) : 0;
1117
1207
 
1118
1208
                        /* http://tools.ietf.org/html/rfc4511#section-4.2.2
1119
1209
                         *   messageID: 0x02 0x01 0x01: INTEGER 1
1120
1210
                         *   protocolOp: 0x61: bindResponse
1121
1211
                         */
1122
1212
                        if ((msglen > 2) ||
1123
 
                            (memcmp(s->check_data + 2 + msglen, "\x02\x01\x01\x61", 4) != 0)) {
1124
 
                                set_server_check_status(s, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
 
1213
                            (memcmp(check->bi->data + 2 + msglen, "\x02\x01\x01\x61", 4) != 0)) {
 
1214
                                set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
1125
1215
 
1126
1216
                                goto out_wakeup;
1127
1217
                        }
1128
1218
 
1129
1219
                        /* size of bindResponse */
1130
 
                        msglen += (*(s->check_data + msglen + 6) & 0x80) ? (*(s->check_data + msglen + 6) & 0x7f) : 0;
 
1220
                        msglen += (*(check->bi->data + msglen + 6) & 0x80) ? (*(check->bi->data + msglen + 6) & 0x7f) : 0;
1131
1221
 
1132
1222
                        /* http://tools.ietf.org/html/rfc4511#section-4.1.9
1133
1223
                         *   ldapResult: 0x0a 0x01: ENUMERATION
1134
1224
                         */
1135
1225
                        if ((msglen > 4) ||
1136
 
                            (memcmp(s->check_data + 7 + msglen, "\x0a\x01", 2) != 0)) {
1137
 
                                set_server_check_status(s, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
 
1226
                            (memcmp(check->bi->data + 7 + msglen, "\x0a\x01", 2) != 0)) {
 
1227
                                set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
1138
1228
 
1139
1229
                                goto out_wakeup;
1140
1230
                        }
1142
1232
                        /* http://tools.ietf.org/html/rfc4511#section-4.1.9
1143
1233
                         *   resultCode
1144
1234
                         */
1145
 
                        s->check_code = *(s->check_data + msglen + 9);
1146
 
                        if (s->check_code) {
1147
 
                                set_server_check_status(s, HCHK_STATUS_L7STS, "See RFC: http://tools.ietf.org/html/rfc4511#section-4.1.9");
 
1235
                        check->code = *(check->bi->data + msglen + 9);
 
1236
                        if (check->code) {
 
1237
                                set_server_check_status(check, HCHK_STATUS_L7STS, "See RFC: http://tools.ietf.org/html/rfc4511#section-4.1.9");
1148
1238
                        } else {
1149
 
                                set_server_check_status(s, HCHK_STATUS_L7OKD, "Success");
 
1239
                                set_server_check_status(check, HCHK_STATUS_L7OKD, "Success");
1150
1240
                        }
1151
1241
                }
1152
 
        }
1153
 
        else {
1154
 
                /* other checks are valid if the connection succeeded anyway */
1155
 
                set_server_check_status(s, HCHK_STATUS_L4OK, NULL);
1156
 
        }
 
1242
                break;
 
1243
 
 
1244
        default:
 
1245
                /* for other checks (eg: pure TCP), delegate to the main task */
 
1246
                break;
 
1247
        } /* switch */
1157
1248
 
1158
1249
 out_wakeup:
1159
 
        if (s->result & SRV_CHK_ERROR)
1160
 
                fdtab[fd].state = FD_STERROR;
 
1250
        /* collect possible new errors */
 
1251
        if (conn->flags & CO_FL_ERROR)
 
1252
                chk_report_conn_err(conn, 0, 0);
1161
1253
 
1162
1254
        /* Reset the check buffer... */
1163
 
        *s->check_data = '\0';
1164
 
        s->check_data_len = 0;
 
1255
        *check->bi->data = '\0';
 
1256
        check->bi->i = 0;
1165
1257
 
1166
1258
        /* Close the connection... We absolutely want to perform a hard close
1167
1259
         * and reset the connection if some data are pending, otherwise we end
1169
1261
         * To avoid sending RSTs all the time, we first try to drain pending
1170
1262
         * data.
1171
1263
         */
1172
 
        if (!shutr && (len == -1 || !tcp_drain(fd)))
1173
 
                setsockopt(fd, SOL_SOCKET, SO_LINGER,
1174
 
                           (struct linger *) &nolinger, sizeof(struct linger));
1175
 
        shutdown(fd, SHUT_RDWR);
1176
 
        EV_FD_CLR(fd, DIR_RD);
 
1264
        if (conn->xprt && conn->xprt->shutw)
 
1265
                conn->xprt->shutw(conn, 0);
 
1266
 
 
1267
        /* OK, let's not stay here forever */
 
1268
        if (check->result == CHK_RES_FAILED)
 
1269
                conn->flags |= CO_FL_ERROR;
 
1270
 
 
1271
        __conn_data_stop_both(conn);
1177
1272
        task_wakeup(t, TASK_WOKEN_IO);
1178
 
        fdtab[fd].ev &= ~FD_POLL_IN;
1179
 
        return 1;
 
1273
        return;
1180
1274
 
1181
1275
 wait_more_data:
1182
 
        fdtab[fd].ev &= ~FD_POLL_IN;
 
1276
        __conn_data_want_recv(conn);
 
1277
}
 
1278
 
 
1279
/*
 
1280
 * This function is used only for server health-checks. It handles connection
 
1281
 * status updates including errors. If necessary, it wakes the check task up.
 
1282
 * It always returns 0.
 
1283
 */
 
1284
static int wake_srv_chk(struct connection *conn)
 
1285
{
 
1286
        struct check *check = conn->owner;
 
1287
 
 
1288
        if (unlikely(conn->flags & CO_FL_ERROR)) {
 
1289
                /* We may get error reports bypassing the I/O handlers, typically
 
1290
                 * the case when sending a pure TCP check which fails, then the I/O
 
1291
                 * handlers above are not called. This is completely handled by the
 
1292
                 * main processing task so let's simply wake it up. If we get here,
 
1293
                 * we expect errno to still be valid.
 
1294
                 */
 
1295
                chk_report_conn_err(conn, errno, 0);
 
1296
 
 
1297
                __conn_data_stop_both(conn);
 
1298
                task_wakeup(check->task, TASK_WOKEN_IO);
 
1299
        }
 
1300
        else if (!(conn->flags & (CO_FL_DATA_RD_ENA|CO_FL_DATA_WR_ENA|CO_FL_HANDSHAKE))) {
 
1301
                /* we may get here if only a connection probe was required : we
 
1302
                 * don't have any data to send nor anything expected in response,
 
1303
                 * so the completion of the connection establishment is enough.
 
1304
                 */
 
1305
                task_wakeup(check->task, TASK_WOKEN_IO);
 
1306
        }
 
1307
 
 
1308
        if (check->result != CHK_RES_UNKNOWN) {
 
1309
                /* We're here because nobody wants to handle the error, so we
 
1310
                 * sure want to abort the hard way.
 
1311
                 */
 
1312
                conn_drain(conn);
 
1313
                conn_force_close(conn);
 
1314
        }
1183
1315
        return 0;
1184
1316
}
1185
1317
 
 
1318
struct data_cb check_conn_cb = {
 
1319
        .recv = event_srv_chk_r,
 
1320
        .send = event_srv_chk_w,
 
1321
        .wake = wake_srv_chk,
 
1322
};
 
1323
 
1186
1324
/*
1187
1325
 * updates the server's weight during a warmup stage. Once the final weight is
1188
1326
 * reached, the task automatically stops. Note that any server status change
1194
1332
 
1195
1333
        /* by default, plan on stopping the task */
1196
1334
        t->expire = TICK_ETERNITY;
1197
 
        if ((s->state & (SRV_RUNNING|SRV_WARMINGUP|SRV_MAINTAIN)) != (SRV_RUNNING|SRV_WARMINGUP))
 
1335
        if ((s->admin & SRV_ADMF_MAINT) ||
 
1336
            (s->state != SRV_ST_STARTING))
1198
1337
                return t;
1199
1338
 
 
1339
        /* recalculate the weights and update the state */
1200
1340
        server_recalc_eweight(s);
1201
1341
 
1202
1342
        /* probably that we can refill this server with a bit more connections */
1203
 
        check_for_pending(s);
 
1343
        pendconn_grab_from_px(s);
1204
1344
 
1205
1345
        /* get back there in 1 second or 1/20th of the slowstart interval,
1206
1346
         * whichever is greater, resulting in small 5% steps.
1207
1347
         */
1208
 
        if (s->state & SRV_WARMINGUP)
 
1348
        if (s->state == SRV_ST_STARTING)
1209
1349
                t->expire = tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20)));
1210
1350
        return t;
1211
1351
}
1212
1352
 
1213
1353
/*
 
1354
 * establish a server health-check.
 
1355
 *
 
1356
 * It can return one of :
 
1357
 *  - SN_ERR_NONE if everything's OK and tcpcheck_main() was not called
 
1358
 *  - SN_ERR_UP if if everything's OK and tcpcheck_main() was called
 
1359
 *  - SN_ERR_SRVTO if there are no more servers
 
1360
 *  - SN_ERR_SRVCL if the connection was refused by the server
 
1361
 *  - SN_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
 
1362
 *  - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
 
1363
 *  - SN_ERR_INTERNAL for any other purely internal errors
 
1364
 * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
 
1365
 * Note that we try to prevent the network stack from sending the ACK during the
 
1366
 * connect() when a pure TCP check is used (without PROXY protocol).
 
1367
 */
 
1368
static int connect_chk(struct task *t)
 
1369
{
 
1370
        struct check *check = t->context;
 
1371
        struct server *s = check->server;
 
1372
        struct connection *conn = check->conn;
 
1373
        struct protocol *proto;
 
1374
        int ret;
 
1375
 
 
1376
        /* tcpcheck send/expect initialisation */
 
1377
        if (check->type == PR_O2_TCPCHK_CHK)
 
1378
                check->current_step = NULL;
 
1379
 
 
1380
        /* prepare the check buffer.
 
1381
         * This should not be used if check is the secondary agent check
 
1382
         * of a server as s->proxy->check_req will relate to the
 
1383
         * configuration of the primary check. Similarly, tcp-check uses
 
1384
         * its own strings.
 
1385
         */
 
1386
        if (check->type && check->type != PR_O2_TCPCHK_CHK && !(check->state & CHK_ST_AGENT)) {
 
1387
                bo_putblk(check->bo, s->proxy->check_req, s->proxy->check_len);
 
1388
 
 
1389
                /* we want to check if this host replies to HTTP or SSLv3 requests
 
1390
                 * so we'll send the request, and won't wake the checker up now.
 
1391
                 */
 
1392
                if ((check->type) == PR_O2_SSL3_CHK) {
 
1393
                        /* SSL requires that we put Unix time in the request */
 
1394
                        int gmt_time = htonl(date.tv_sec);
 
1395
                        memcpy(check->bo->data + 11, &gmt_time, 4);
 
1396
                }
 
1397
                else if ((check->type) == PR_O2_HTTP_CHK) {
 
1398
                        if (s->proxy->options2 & PR_O2_CHK_SNDST)
 
1399
                                bo_putblk(check->bo, trash.str, httpchk_build_status_header(s, trash.str, trash.size));
 
1400
                        bo_putstr(check->bo, "\r\n");
 
1401
                        *check->bo->p = '\0'; /* to make gdb output easier to read */
 
1402
                }
 
1403
        }
 
1404
 
 
1405
        /* prepare a new connection */
 
1406
        conn_init(conn);
 
1407
        conn_prepare(conn, s->check_common.proto, s->check_common.xprt);
 
1408
        conn_attach(conn, check, &check_conn_cb);
 
1409
        conn->target = &s->obj_type;
 
1410
 
 
1411
        /* no client address */
 
1412
        clear_addr(&conn->addr.from);
 
1413
 
 
1414
        if (is_addr(&s->check_common.addr)) {
 
1415
 
 
1416
                /* we'll connect to the check addr specified on the server */
 
1417
                conn->addr.to = s->check_common.addr;
 
1418
                proto = s->check_common.proto;
 
1419
        }
 
1420
        else {
 
1421
                /* we'll connect to the addr on the server */
 
1422
                conn->addr.to = s->addr;
 
1423
                proto = s->proto;
 
1424
        }
 
1425
 
 
1426
        if (check->port) {
 
1427
                set_host_port(&conn->addr.to, check->port);
 
1428
        }
 
1429
 
 
1430
        if (check->type == PR_O2_TCPCHK_CHK) {
 
1431
                struct tcpcheck_rule *r = (struct tcpcheck_rule *) s->proxy->tcpcheck_rules.n;
 
1432
                /* if first step is a 'connect', then tcpcheck_main must run it */
 
1433
                if (r->action == TCPCHK_ACT_CONNECT) {
 
1434
                        tcpcheck_main(conn);
 
1435
                        return SN_ERR_UP;
 
1436
                }
 
1437
        }
 
1438
 
 
1439
        ret = SN_ERR_INTERNAL;
 
1440
        if (proto->connect)
 
1441
                ret = proto->connect(conn, check->type, (check->type) ? 0 : 2);
 
1442
        conn->flags |= CO_FL_WAKE_DATA;
 
1443
        if (s->check.send_proxy) {
 
1444
                conn->send_proxy_ofs = 1;
 
1445
                conn->flags |= CO_FL_SEND_PROXY;
 
1446
        }
 
1447
 
 
1448
        return ret;
 
1449
}
 
1450
 
 
1451
/*
1214
1452
 * manages a server health-check. Returns
1215
1453
 * the time the task accepts to wait, or TIME_ETERNITY for infinity.
1216
1454
 */
1217
 
struct task *process_chk(struct task *t)
 
1455
static struct task *process_chk(struct task *t)
1218
1456
{
1219
 
        int attempts = 0;
1220
 
        struct server *s = t->context;
1221
 
        struct sockaddr_in sa;
1222
 
        int fd;
 
1457
        struct check *check = t->context;
 
1458
        struct server *s = check->server;
 
1459
        struct connection *conn = check->conn;
1223
1460
        int rv;
 
1461
        int ret;
 
1462
        int expired = tick_is_expired(t->expire, now_ms);
1224
1463
 
1225
 
 new_chk:
1226
 
        if (attempts++ > 0) {
1227
 
                /* we always fail to create a server, let's stop insisting... */
1228
 
                while (tick_is_expired(t->expire, now_ms))
1229
 
                        t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
1230
 
                return t;
1231
 
        }
1232
 
        fd = s->curfd;
1233
 
        if (fd < 0) {   /* no check currently running */
1234
 
                if (!tick_is_expired(t->expire, now_ms)) /* woke up too early */
 
1464
        if (!(check->state & CHK_ST_INPROGRESS)) {
 
1465
                /* no check currently running */
 
1466
                if (!expired) /* woke up too early */
1235
1467
                        return t;
1236
1468
 
1237
 
                /* we don't send any health-checks when the proxy is stopped or when
1238
 
                 * the server should not be checked.
 
1469
                /* we don't send any health-checks when the proxy is
 
1470
                 * stopped, the server should not be checked or the check
 
1471
                 * is disabled.
1239
1472
                 */
1240
 
                if (!(s->state & SRV_CHECKED) || s->proxy->state == PR_STSTOPPED || (s->state & SRV_MAINTAIN)) {
1241
 
                        while (tick_is_expired(t->expire, now_ms))
1242
 
                                t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
1243
 
                        return t;
1244
 
                }
 
1473
                if (((check->state & (CHK_ST_ENABLED | CHK_ST_PAUSED)) != CHK_ST_ENABLED) ||
 
1474
                    s->proxy->state == PR_STSTOPPED)
 
1475
                        goto reschedule;
1245
1476
 
1246
1477
                /* we'll initiate a new check */
1247
 
                set_server_check_status(s, HCHK_STATUS_START, NULL);
1248
 
                if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1) {
1249
 
                        if ((fd < global.maxsock) &&
1250
 
                            (fcntl(fd, F_SETFL, O_NONBLOCK) != -1) &&
1251
 
                            (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) != -1)) {
1252
 
                                //fprintf(stderr, "process_chk: 3\n");
1253
 
 
1254
 
                                if (s->proxy->options & PR_O_TCP_NOLING) {
1255
 
                                        /* We don't want to useless data */
1256
 
                                        setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
1257
 
                                }
1258
 
                                
1259
 
                                if (s->check_addr.sin_addr.s_addr)
1260
 
                                        /* we'll connect to the check addr specified on the server */
1261
 
                                        sa = s->check_addr;
1262
 
                                else
1263
 
                                        /* we'll connect to the addr on the server */
1264
 
                                        sa = s->addr;
1265
 
 
1266
 
                                /* we'll connect to the check port on the server */
1267
 
                                sa.sin_port = htons(s->check_port);
1268
 
 
1269
 
                                /* allow specific binding :
1270
 
                                 * - server-specific at first
1271
 
                                 * - proxy-specific next
1272
 
                                 */
1273
 
                                if (s->state & SRV_BIND_SRC) {
1274
 
                                        struct sockaddr_in *remote = NULL;
1275
 
                                        int ret, flags = 0;
1276
 
 
1277
 
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1278
 
                                        if ((s->state & SRV_TPROXY_MASK) == SRV_TPROXY_ADDR) {
1279
 
                                                remote = (struct sockaddr_in *)&s->tproxy_addr;
1280
 
                                                flags  = 3;
1281
 
                                        }
1282
 
#endif
1283
 
#ifdef SO_BINDTODEVICE
1284
 
                                        /* Note: this might fail if not CAP_NET_RAW */
1285
 
                                        if (s->iface_name)
1286
 
                                                setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
1287
 
                                                           s->iface_name, s->iface_len + 1);
1288
 
#endif
1289
 
                                        if (s->sport_range) {
1290
 
                                                int bind_attempts = 10; /* should be more than enough to find a spare port */
1291
 
                                                struct sockaddr_in src;
1292
 
 
1293
 
                                                ret = 1;
1294
 
                                                src = s->source_addr;
1295
 
 
1296
 
                                                do {
1297
 
                                                        /* note: in case of retry, we may have to release a previously
1298
 
                                                         * allocated port, hence this loop's construct.
1299
 
                                                         */
1300
 
                                                        port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
1301
 
                                                        fdinfo[fd].port_range = NULL;
1302
 
 
1303
 
                                                        if (!bind_attempts)
1304
 
                                                                break;
1305
 
                                                        bind_attempts--;
1306
 
 
1307
 
                                                        fdinfo[fd].local_port = port_range_alloc_port(s->sport_range);
1308
 
                                                        if (!fdinfo[fd].local_port)
1309
 
                                                                break;
1310
 
 
1311
 
                                                        fdinfo[fd].port_range = s->sport_range;
1312
 
                                                        src.sin_port = htons(fdinfo[fd].local_port);
1313
 
 
1314
 
                                                        ret = tcpv4_bind_socket(fd, flags, &src, remote);
1315
 
                                                } while (ret != 0); /* binding NOK */
1316
 
                                        }
1317
 
                                        else {
1318
 
                                                ret = tcpv4_bind_socket(fd, flags, &s->source_addr, remote);
1319
 
                                        }
1320
 
 
1321
 
                                        if (ret) {
1322
 
                                                set_server_check_status(s, HCHK_STATUS_SOCKERR, NULL);
1323
 
                                                switch (ret) {
1324
 
                                                case 1:
1325
 
                                                        Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
1326
 
                                                              s->proxy->id, s->id);
1327
 
                                                        break;
1328
 
                                                case 2:
1329
 
                                                        Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
1330
 
                                                              s->proxy->id, s->id);
1331
 
                                                        break;
1332
 
                                                }
1333
 
                                        }
1334
 
                                }
1335
 
                                else if (s->proxy->options & PR_O_BIND_SRC) {
1336
 
                                        struct sockaddr_in *remote = NULL;
1337
 
                                        int ret, flags = 0;
1338
 
 
1339
 
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1340
 
                                        if ((s->proxy->options & PR_O_TPXY_MASK) == PR_O_TPXY_ADDR) {
1341
 
                                                remote = (struct sockaddr_in *)&s->proxy->tproxy_addr;
1342
 
                                                flags  = 3;
1343
 
                                        }
1344
 
#endif
1345
 
#ifdef SO_BINDTODEVICE
1346
 
                                        /* Note: this might fail if not CAP_NET_RAW */
1347
 
                                        if (s->proxy->iface_name)
1348
 
                                                setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
1349
 
                                                           s->proxy->iface_name, s->proxy->iface_len + 1);
1350
 
#endif
1351
 
                                        ret = tcpv4_bind_socket(fd, flags, &s->proxy->source_addr, remote);
1352
 
                                        if (ret) {
1353
 
                                                set_server_check_status(s, HCHK_STATUS_SOCKERR, NULL);
1354
 
                                                switch (ret) {
1355
 
                                                case 1:
1356
 
                                                        Alert("Cannot bind to source address before connect() for %s '%s'. Aborting.\n",
1357
 
                                                              proxy_type_str(s->proxy), s->proxy->id);
1358
 
                                                        break;
1359
 
                                                case 2:
1360
 
                                                        Alert("Cannot bind to tproxy source address before connect() for %s '%s'. Aborting.\n",
1361
 
                                                              proxy_type_str(s->proxy), s->proxy->id);
1362
 
                                                        break;
1363
 
                                                }
1364
 
                                        }
1365
 
                                }
1366
 
 
1367
 
                                if (s->result == SRV_CHK_UNKNOWN) {
1368
 
#if defined(TCP_QUICKACK)
1369
 
                                        /* disabling tcp quick ack now allows
1370
 
                                         * the request to leave the machine with
1371
 
                                         * the first ACK.
1372
 
                                         * We also want to do this to perform a
1373
 
                                         * SYN-SYN/ACK-RST sequence when raw TCP
1374
 
                                         * checks are configured.
1375
 
                                         */
1376
 
                                        if ((s->proxy->options2 & PR_O2_SMARTCON) ||
1377
 
                                            (!(s->proxy->options & (PR_O_HTTP_CHK|PR_O_SMTP_CHK)) &&
1378
 
                                             !(s->proxy->options2 & (PR_O2_SSL3_CHK|PR_O2_MYSQL_CHK|PR_O2_LDAP_CHK))))
1379
 
                                                setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, (char *) &zero, sizeof(zero));
1380
 
#endif
1381
 
                                        if ((connect(fd, (struct sockaddr *)&sa, sizeof(sa)) != -1) || (errno == EINPROGRESS)) {
1382
 
                                                /* OK, connection in progress or established */
1383
 
                        
1384
 
                                                //fprintf(stderr, "process_chk: 4\n");
1385
 
                        
1386
 
                                                s->curfd = fd; /* that's how we know a test is in progress ;-) */
1387
 
                                                fd_insert(fd);
1388
 
                                                fdtab[fd].owner = t;
1389
 
                                                fdtab[fd].cb[DIR_RD].f = &event_srv_chk_r;
1390
 
                                                fdtab[fd].cb[DIR_RD].b = NULL;
1391
 
                                                fdtab[fd].cb[DIR_WR].f = &event_srv_chk_w;
1392
 
                                                fdtab[fd].cb[DIR_WR].b = NULL;
1393
 
                                                fdinfo[fd].peeraddr = (struct sockaddr *)&sa;
1394
 
                                                fdinfo[fd].peerlen = sizeof(sa);
1395
 
                                                fdtab[fd].state = FD_STCONN; /* connection in progress */
1396
 
                                                fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
1397
 
                                                EV_FD_SET(fd, DIR_WR);  /* for connect status */
1398
 
#ifdef DEBUG_FULL
1399
 
                                                assert (!EV_FD_ISSET(fd, DIR_RD));
1400
 
#endif
1401
 
                                                //fprintf(stderr, "process_chk: 4+, %lu\n", __tv_to_ms(&s->proxy->timeout.connect));
1402
 
                                                /* we allow up to min(inter, timeout.connect) for a connection
1403
 
                                                 * to establish but only when timeout.check is set
1404
 
                                                 * as it may be to short for a full check otherwise
1405
 
                                                 */
1406
 
                                                t->expire = tick_add(now_ms, MS_TO_TICKS(s->inter));
1407
 
 
1408
 
                                                if (s->proxy->timeout.check && s->proxy->timeout.connect) {
1409
 
                                                        int t_con = tick_add(now_ms, s->proxy->timeout.connect);
1410
 
                                                        t->expire = tick_first(t->expire, t_con);
1411
 
                                                }
1412
 
                                                return t;
1413
 
                                        }
1414
 
                                        else if (errno != EALREADY && errno != EISCONN && errno != EAGAIN) {
1415
 
                                                /* a real error */
1416
 
 
1417
 
                                                switch (errno) {
1418
 
                                                        /* FIXME: is it possible to get ECONNREFUSED/ENETUNREACH with O_NONBLOCK? */
1419
 
                                                        case ECONNREFUSED:
1420
 
                                                        case ENETUNREACH:
1421
 
                                                                set_server_check_status(s, HCHK_STATUS_L4CON, strerror(errno));
1422
 
                                                                break;
1423
 
 
1424
 
                                                        default:
1425
 
                                                                set_server_check_status(s, HCHK_STATUS_SOCKERR, strerror(errno));
1426
 
                                                }
1427
 
                                        }
1428
 
                                }
 
1478
                set_server_check_status(check, HCHK_STATUS_START, NULL);
 
1479
 
 
1480
                check->state |= CHK_ST_INPROGRESS;
 
1481
                check->bi->p = check->bi->data;
 
1482
                check->bi->i = 0;
 
1483
                check->bo->p = check->bo->data;
 
1484
                check->bo->o = 0;
 
1485
 
 
1486
                ret = connect_chk(t);
 
1487
                switch (ret) {
 
1488
                case SN_ERR_UP:
 
1489
                        return t;
 
1490
                case SN_ERR_NONE:
 
1491
                        /* we allow up to min(inter, timeout.connect) for a connection
 
1492
                         * to establish but only when timeout.check is set
 
1493
                         * as it may be to short for a full check otherwise
 
1494
                         */
 
1495
                        t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
 
1496
 
 
1497
                        if (s->proxy->timeout.check && s->proxy->timeout.connect) {
 
1498
                                int t_con = tick_add(now_ms, s->proxy->timeout.connect);
 
1499
                                t->expire = tick_first(t->expire, t_con);
1429
1500
                        }
1430
 
                        port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
1431
 
                        fdinfo[fd].port_range = NULL;
1432
 
                        close(fd); /* socket creation error */
1433
 
                }
1434
 
 
1435
 
                if (s->result == SRV_CHK_UNKNOWN) { /* nothing done */
1436
 
                        //fprintf(stderr, "process_chk: 6\n");
1437
 
                        while (tick_is_expired(t->expire, now_ms))
1438
 
                                t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
1439
 
                        goto new_chk; /* may be we should initialize a new check */
1440
 
                }
1441
 
 
1442
 
                /* here, we have seen a failure */
1443
 
                if (s->health > s->rise) {
1444
 
                        s->health--; /* still good */
1445
 
                        s->counters.failed_checks++;
1446
 
                }
1447
 
                else
1448
 
                        set_server_down(s);
1449
 
 
1450
 
                //fprintf(stderr, "process_chk: 7, %lu\n", __tv_to_ms(&s->proxy->timeout.connect));
 
1501
 
 
1502
                        if (check->type)
 
1503
                                conn_data_want_recv(conn);   /* prepare for reading a possible reply */
 
1504
 
 
1505
                        goto reschedule;
 
1506
 
 
1507
                case SN_ERR_SRVTO: /* ETIMEDOUT */
 
1508
                case SN_ERR_SRVCL: /* ECONNREFUSED, ENETUNREACH, ... */
 
1509
                        conn->flags |= CO_FL_ERROR;
 
1510
                        chk_report_conn_err(conn, errno, 0);
 
1511
                        break;
 
1512
                case SN_ERR_PRXCOND:
 
1513
                case SN_ERR_RESOURCE:
 
1514
                case SN_ERR_INTERNAL:
 
1515
                        conn->flags |= CO_FL_ERROR;
 
1516
                        chk_report_conn_err(conn, 0, 0);
 
1517
                        break;
 
1518
                }
 
1519
 
 
1520
                /* here, we have seen a synchronous error, no fd was allocated */
 
1521
 
 
1522
                check->state &= ~CHK_ST_INPROGRESS;
 
1523
                check_notify_failure(check);
 
1524
 
1451
1525
                /* we allow up to min(inter, timeout.connect) for a connection
1452
1526
                 * to establish but only when timeout.check is set
1453
1527
                 * as it may be to short for a full check otherwise
1456
1530
                        int t_con;
1457
1531
 
1458
1532
                        t_con = tick_add(t->expire, s->proxy->timeout.connect);
1459
 
                        t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
 
1533
                        t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
1460
1534
 
1461
1535
                        if (s->proxy->timeout.check)
1462
1536
                                t->expire = tick_first(t->expire, t_con);
1463
1537
                }
1464
 
                goto new_chk;
1465
1538
        }
1466
1539
        else {
1467
 
                /* there was a test running */
1468
 
                if ((s->result & (SRV_CHK_ERROR|SRV_CHK_RUNNING)) == SRV_CHK_RUNNING) { /* good server detected */
1469
 
                        /* we may have to add/remove this server from the LB group */
1470
 
                        if ((s->state & SRV_RUNNING) && (s->proxy->options & PR_O_DISABLE404)) {
1471
 
                                if ((s->state & SRV_GOINGDOWN) &&
1472
 
                                    ((s->result & (SRV_CHK_RUNNING|SRV_CHK_DISABLE)) == SRV_CHK_RUNNING))
1473
 
                                        set_server_enabled(s);
1474
 
                                else if (!(s->state & SRV_GOINGDOWN) &&
1475
 
                                         ((s->result & (SRV_CHK_RUNNING | SRV_CHK_DISABLE)) ==
1476
 
                                          (SRV_CHK_RUNNING | SRV_CHK_DISABLE)))
1477
 
                                        set_server_disabled(s);
1478
 
                        }
1479
 
 
1480
 
                        if (!(s->state & SRV_MAINTAIN) && s->health < s->rise + s->fall - 1) {
1481
 
                                s->health++; /* was bad, stays for a while */
1482
 
                                set_server_up(s);
1483
 
                        }
1484
 
                        s->curfd = -1; /* no check running anymore */
1485
 
                        fd_delete(fd);
1486
 
 
1487
 
                        rv = 0;
1488
 
                        if (global.spread_checks > 0) {
1489
 
                                rv = srv_getinter(s) * global.spread_checks / 100;
1490
 
                                rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
1491
 
                        }
1492
 
                        t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(s) + rv));
1493
 
                        goto new_chk;
1494
 
                }
1495
 
                else if ((s->result & SRV_CHK_ERROR) || tick_is_expired(t->expire, now_ms)) {
1496
 
                        if (!(s->result & SRV_CHK_ERROR)) {
1497
 
                                if (!EV_FD_ISSET(fd, DIR_RD)) {
1498
 
                                        set_server_check_status(s, HCHK_STATUS_L4TOUT, NULL);
1499
 
                                } else {
1500
 
                                        if (s->proxy->options2 & PR_O2_SSL3_CHK)
1501
 
                                                set_server_check_status(s, HCHK_STATUS_L6TOUT, NULL);
1502
 
                                        else    /* HTTP, SMTP */
1503
 
                                                set_server_check_status(s, HCHK_STATUS_L7TOUT, NULL);
1504
 
                                }
1505
 
                        }
1506
 
 
1507
 
                        /* failure or timeout detected */
1508
 
                        if (s->health > s->rise) {
1509
 
                                s->health--; /* still good */
1510
 
                                s->counters.failed_checks++;
 
1540
                /* there was a test running.
 
1541
                 * First, let's check whether there was an uncaught error,
 
1542
                 * which can happen on connect timeout or error.
 
1543
                 */
 
1544
                if (s->check.result == CHK_RES_UNKNOWN) {
 
1545
                        /* good connection is enough for pure TCP check */
 
1546
                        if ((conn->flags & CO_FL_CONNECTED) && !check->type) {
 
1547
                                if (check->use_ssl)
 
1548
                                        set_server_check_status(check, HCHK_STATUS_L6OK, NULL);
 
1549
                                else
 
1550
                                        set_server_check_status(check, HCHK_STATUS_L4OK, NULL);
 
1551
                        }
 
1552
                        else if ((conn->flags & CO_FL_ERROR) || expired) {
 
1553
                                chk_report_conn_err(conn, 0, expired);
1511
1554
                        }
1512
1555
                        else
1513
 
                                set_server_down(s);
1514
 
                        s->curfd = -1;
1515
 
                        /* avoid accumulating TIME_WAIT on timeouts */
1516
 
                        setsockopt(fd, SOL_SOCKET, SO_LINGER,
1517
 
                                   (struct linger *) &nolinger, sizeof(struct linger));
1518
 
                        fd_delete(fd);
1519
 
 
1520
 
                        rv = 0;
1521
 
                        if (global.spread_checks > 0) {
1522
 
                                rv = srv_getinter(s) * global.spread_checks / 100;
1523
 
                                rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
1524
 
                        }
1525
 
                        t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(s) + rv));
1526
 
                        goto new_chk;
1527
 
                }
1528
 
                /* if result is unknown and there's no timeout, we have to wait again */
 
1556
                                goto out_wait; /* timeout not reached, wait again */
 
1557
                }
 
1558
 
 
1559
                /* check complete or aborted */
 
1560
                if (conn->xprt) {
 
1561
                        /* The check was aborted and the connection was not yet closed.
 
1562
                         * This can happen upon timeout, or when an external event such
 
1563
                         * as a failed response coupled with "observe layer7" caused the
 
1564
                         * server state to be suddenly changed.
 
1565
                         */
 
1566
                        conn_drain(conn);
 
1567
                        conn_force_close(conn);
 
1568
                }
 
1569
 
 
1570
                if (check->result == CHK_RES_FAILED) {
 
1571
                        /* a failure or timeout detected */
 
1572
                        check_notify_failure(check);
 
1573
                }
 
1574
                else if (check->result == CHK_RES_CONDPASS) {
 
1575
                        /* check is OK but asks for stopping mode */
 
1576
                        check_notify_stopping(check);
 
1577
                }
 
1578
                else if (check->result == CHK_RES_PASSED) {
 
1579
                        /* a success was detected */
 
1580
                        check_notify_success(check);
 
1581
                }
 
1582
                check->state &= ~CHK_ST_INPROGRESS;
 
1583
 
 
1584
                rv = 0;
 
1585
                if (global.spread_checks > 0) {
 
1586
                        rv = srv_getinter(check) * global.spread_checks / 100;
 
1587
                        rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
 
1588
                }
 
1589
                t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(check) + rv));
1529
1590
        }
1530
 
        s->result = SRV_CHK_UNKNOWN;
 
1591
 
 
1592
 reschedule:
 
1593
        while (tick_is_expired(t->expire, now_ms))
 
1594
                t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
 
1595
 out_wait:
1531
1596
        return t;
1532
1597
}
1533
1598
 
 
1599
static int start_check_task(struct check *check, int mininter,
 
1600
                            int nbcheck, int srvpos)
 
1601
{
 
1602
        struct task *t;
 
1603
        /* task for the check */
 
1604
        if ((t = task_new()) == NULL) {
 
1605
                Alert("Starting [%s:%s] check: out of memory.\n",
 
1606
                      check->server->proxy->id, check->server->id);
 
1607
                return 0;
 
1608
        }
 
1609
 
 
1610
        check->task = t;
 
1611
        t->process = process_chk;
 
1612
        t->context = check;
 
1613
 
 
1614
        if (mininter < srv_getinter(check))
 
1615
                mininter = srv_getinter(check);
 
1616
 
 
1617
        if (global.max_spread_checks && mininter > global.max_spread_checks)
 
1618
                mininter = global.max_spread_checks;
 
1619
 
 
1620
        /* check this every ms */
 
1621
        t->expire = tick_add(now_ms, MS_TO_TICKS(mininter * srvpos / nbcheck));
 
1622
        check->start = now;
 
1623
        task_queue(t);
 
1624
 
 
1625
        return 1;
 
1626
}
 
1627
 
1534
1628
/*
1535
1629
 * Start health-check.
1536
1630
 * Returns 0 if OK, -1 if error, and prints the error in this case.
1540
1634
        struct proxy *px;
1541
1635
        struct server *s;
1542
1636
        struct task *t;
1543
 
        int nbchk=0, mininter=0, srvpos=0;
 
1637
        int nbcheck=0, mininter=0, srvpos=0;
1544
1638
 
1545
1639
        /* 1- count the checkers to run simultaneously.
1546
1640
         * We also determine the minimum interval among all of those which
1547
1641
         * have an interval larger than SRV_CHK_INTER_THRES. This interval
1548
1642
         * will be used to spread their start-up date. Those which have
1549
 
         * a shorter interval will start independantly and will not dictate
 
1643
         * a shorter interval will start independently and will not dictate
1550
1644
         * too short an interval for all others.
1551
1645
         */
1552
1646
        for (px = proxy; px; px = px->next) {
1565
1659
                                t->expire = TICK_ETERNITY;
1566
1660
                        }
1567
1661
 
1568
 
                        if (!(s->state & SRV_CHECKED))
1569
 
                                continue;
1570
 
 
1571
 
                        if ((srv_getinter(s) >= SRV_CHK_INTER_THRES) &&
1572
 
                            (!mininter || mininter > srv_getinter(s)))
1573
 
                                mininter = srv_getinter(s);
1574
 
 
1575
 
                        nbchk++;
 
1662
                        if (s->check.state & CHK_ST_CONFIGURED) {
 
1663
                                nbcheck++;
 
1664
                                if ((srv_getinter(&s->check) >= SRV_CHK_INTER_THRES) &&
 
1665
                                    (!mininter || mininter > srv_getinter(&s->check)))
 
1666
                                        mininter = srv_getinter(&s->check);
 
1667
                        }
 
1668
 
 
1669
                        if (s->agent.state & CHK_ST_CONFIGURED) {
 
1670
                                nbcheck++;
 
1671
                                if ((srv_getinter(&s->agent) >= SRV_CHK_INTER_THRES) &&
 
1672
                                    (!mininter || mininter > srv_getinter(&s->agent)))
 
1673
                                        mininter = srv_getinter(&s->agent);
 
1674
                        }
1576
1675
                }
1577
1676
        }
1578
1677
 
1579
 
        if (!nbchk)
 
1678
        if (!nbcheck)
1580
1679
                return 0;
1581
1680
 
1582
1681
        srand((unsigned)time(NULL));
1588
1687
         */
1589
1688
        for (px = proxy; px; px = px->next) {
1590
1689
                for (s = px->srv; s; s = s->next) {
1591
 
                        if (!(s->state & SRV_CHECKED))
1592
 
                                continue;
1593
 
 
1594
 
                        /* one task for the checks */
1595
 
                        if ((t = task_new()) == NULL) {
1596
 
                                Alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
1597
 
                                return -1;
1598
 
                        }
1599
 
 
1600
 
                        s->check = t;
1601
 
                        t->process = process_chk;
1602
 
                        t->context = s;
1603
 
 
1604
 
                        /* check this every ms */
1605
 
                        t->expire = tick_add(now_ms,
1606
 
                                             MS_TO_TICKS(((mininter && mininter >= srv_getinter(s)) ?
1607
 
                                                          mininter : srv_getinter(s)) * srvpos / nbchk));
1608
 
                        s->check_start = now;
1609
 
                        task_queue(t);
1610
 
 
1611
 
                        srvpos++;
 
1690
                        /* A task for the main check */
 
1691
                        if (s->check.state & CHK_ST_CONFIGURED) {
 
1692
                                if (!start_check_task(&s->check, mininter, nbcheck, srvpos))
 
1693
                                        return -1;
 
1694
                                srvpos++;
 
1695
                        }
 
1696
 
 
1697
                        /* A task for a auxiliary agent check */
 
1698
                        if (s->agent.state & CHK_ST_CONFIGURED) {
 
1699
                                if (!start_check_task(&s->agent, mininter, nbcheck, srvpos)) {
 
1700
                                        return -1;
 
1701
                                }
 
1702
                                srvpos++;
 
1703
                        }
1612
1704
                }
1613
1705
        }
1614
1706
        return 0;
1615
1707
}
1616
1708
 
1617
1709
/*
1618
 
 * Perform content verification check on data in s->check_data buffer.
 
1710
 * Perform content verification check on data in s->check.buffer buffer.
1619
1711
 * The buffer MUST be terminated by a null byte before calling this function.
1620
1712
 * Sets server status appropriately. The caller is responsible for ensuring
1621
1713
 * that the buffer contains at least 13 characters. If <done> is zero, we may
1632
1724
        switch (s->proxy->options2 & PR_O2_EXP_TYPE) {
1633
1725
        case PR_O2_EXP_STS:
1634
1726
        case PR_O2_EXP_RSTS:
1635
 
                memcpy(status_code, s->check_data + 9, 3);
1636
 
                memcpy(status_msg + strlen(status_msg) - 4, s->check_data + 9, 3);
 
1727
                memcpy(status_code, s->check.bi->data + 9, 3);
 
1728
                memcpy(status_msg + strlen(status_msg) - 4, s->check.bi->data + 9, 3);
1637
1729
 
1638
1730
                if ((s->proxy->options2 & PR_O2_EXP_TYPE) == PR_O2_EXP_STS)
1639
1731
                        ret = strncmp(s->proxy->expect_str, status_code, 3) == 0;
1640
1732
                else
1641
 
                        ret = regexec(s->proxy->expect_regex, status_code, MAX_MATCH, pmatch, 0) == 0;
 
1733
                        ret = regex_exec(s->proxy->expect_regex, status_code);
1642
1734
 
1643
1735
                /* we necessarily have the response, so there are no partial failures */
1644
1736
                if (s->proxy->options2 & PR_O2_EXP_INV)
1645
1737
                        ret = !ret;
1646
1738
 
1647
 
                set_server_check_status(s, ret ? HCHK_STATUS_L7OKD : HCHK_STATUS_L7STS, status_msg);
 
1739
                set_server_check_status(&s->check, ret ? HCHK_STATUS_L7OKD : HCHK_STATUS_L7STS, status_msg);
1648
1740
                break;
1649
1741
 
1650
1742
        case PR_O2_EXP_STR:
1654
1746
                 * to '\0' if crlf < 2.
1655
1747
                 */
1656
1748
                crlf = 0;
1657
 
                for (contentptr = s->check_data; *contentptr; contentptr++) {
 
1749
                for (contentptr = s->check.bi->data; *contentptr; contentptr++) {
1658
1750
                        if (crlf >= 2)
1659
1751
                                break;
1660
1752
                        if (*contentptr == '\r')
1670
1762
                        if (!done)
1671
1763
                                return 0;
1672
1764
 
1673
 
                        set_server_check_status(s, HCHK_STATUS_L7RSP,
 
1765
                        set_server_check_status(&s->check, HCHK_STATUS_L7RSP,
1674
1766
                                                "HTTP content check could not find a response body");
1675
1767
                        return 1;
1676
1768
                }
1680
1772
                        if (!done)
1681
1773
                                return 0;
1682
1774
 
1683
 
                        set_server_check_status(s, HCHK_STATUS_L7RSP,
 
1775
                        set_server_check_status(&s->check, HCHK_STATUS_L7RSP,
1684
1776
                                                "HTTP content check found empty response body");
1685
1777
                        return 1;
1686
1778
                }
1690
1782
                if ((s->proxy->options2 & PR_O2_EXP_TYPE) == PR_O2_EXP_STR)
1691
1783
                        ret = strstr(contentptr, s->proxy->expect_str) != NULL;
1692
1784
                else
1693
 
                        ret = regexec(s->proxy->expect_regex, contentptr, MAX_MATCH, pmatch, 0) == 0;
 
1785
                        ret = regex_exec(s->proxy->expect_regex, contentptr);
1694
1786
 
1695
1787
                /* if we don't match, we may need to wait more */
1696
1788
                if (!ret && !done)
1699
1791
                if (ret) {
1700
1792
                        /* content matched */
1701
1793
                        if (s->proxy->options2 & PR_O2_EXP_INV)
1702
 
                                set_server_check_status(s, HCHK_STATUS_L7RSP,
 
1794
                                set_server_check_status(&s->check, HCHK_STATUS_L7RSP,
1703
1795
                                                        "HTTP check matched unwanted content");
1704
1796
                        else
1705
 
                                set_server_check_status(s, HCHK_STATUS_L7OKD,
 
1797
                                set_server_check_status(&s->check, HCHK_STATUS_L7OKD,
1706
1798
                                                        "HTTP content check matched");
1707
1799
                }
1708
1800
                else {
1709
1801
                        if (s->proxy->options2 & PR_O2_EXP_INV)
1710
 
                                set_server_check_status(s, HCHK_STATUS_L7OKD,
 
1802
                                set_server_check_status(&s->check, HCHK_STATUS_L7OKD,
1711
1803
                                                        "HTTP check did not match unwanted content");
1712
1804
                        else
1713
 
                                set_server_check_status(s, HCHK_STATUS_L7RSP,
 
1805
                                set_server_check_status(&s->check, HCHK_STATUS_L7RSP,
1714
1806
                                                        "HTTP content check did not match");
1715
1807
                }
1716
1808
                break;
1719
1811
}
1720
1812
 
1721
1813
/*
 
1814
 * return the id of a step in a send/expect session
 
1815
 */
 
1816
static int tcpcheck_get_step_id(struct server *s)
 
1817
{
 
1818
        struct tcpcheck_rule *cur = NULL, *next = NULL;
 
1819
        int i = 0;
 
1820
 
 
1821
        cur = s->check.last_started_step;
 
1822
 
 
1823
        /* no step => first step */
 
1824
        if (cur == NULL)
 
1825
                return 1;
 
1826
 
 
1827
        /* increment i until current step */
 
1828
        list_for_each_entry(next, &s->proxy->tcpcheck_rules, list) {
 
1829
                if (next->list.p == &cur->list)
 
1830
                        break;
 
1831
                ++i;
 
1832
        }
 
1833
 
 
1834
        return i;
 
1835
}
 
1836
 
 
1837
static void tcpcheck_main(struct connection *conn)
 
1838
{
 
1839
        char *contentptr;
 
1840
        struct list *head = NULL;
 
1841
        struct tcpcheck_rule *cur = NULL;
 
1842
        int done = 0, ret = 0;
 
1843
 
 
1844
        struct check *check = conn->owner;
 
1845
        struct server *s = check->server;
 
1846
        struct task *t = check->task;
 
1847
 
 
1848
        /*
 
1849
         * don't do anything until the connection is established but if we're running
 
1850
         * first step which must be a connect
 
1851
         */
 
1852
        if (check->current_step && (!(conn->flags & CO_FL_CONNECTED))) {
 
1853
                /* update expire time, should be done by process_chk */
 
1854
                /* we allow up to min(inter, timeout.connect) for a connection
 
1855
                 * to establish but only when timeout.check is set
 
1856
                 * as it may be to short for a full check otherwise
 
1857
                 */
 
1858
                while (tick_is_expired(t->expire, now_ms)) {
 
1859
                        int t_con;
 
1860
 
 
1861
                        t_con = tick_add(t->expire, s->proxy->timeout.connect);
 
1862
                        t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
 
1863
 
 
1864
                        if (s->proxy->timeout.check)
 
1865
                                t->expire = tick_first(t->expire, t_con);
 
1866
                }
 
1867
                return;
 
1868
        }
 
1869
 
 
1870
        /* here, we know that the connection is established */
 
1871
        if (check->result != CHK_RES_UNKNOWN)
 
1872
                goto out_end_tcpcheck;
 
1873
 
 
1874
        /* head is be the first element of the double chained list */
 
1875
        head = &s->proxy->tcpcheck_rules;
 
1876
 
 
1877
        /* no step means first step
 
1878
         * initialisation */
 
1879
        if (check->current_step == NULL) {
 
1880
                check->bo->p = check->bo->data;
 
1881
                check->bo->o = 0;
 
1882
                check->bi->p = check->bi->data;
 
1883
                check->bi->i = 0;
 
1884
                cur = check->current_step = LIST_ELEM(head->n, struct tcpcheck_rule *, list);
 
1885
                t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
 
1886
                if (s->proxy->timeout.check)
 
1887
                        t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);
 
1888
        }
 
1889
        /* keep on processing step */
 
1890
        else {
 
1891
                cur = check->current_step;
 
1892
        }
 
1893
 
 
1894
        if (conn->flags & CO_FL_HANDSHAKE)
 
1895
                return;
 
1896
 
 
1897
        /* It's only the rules which will enable send/recv */
 
1898
        __conn_data_stop_both(conn);
 
1899
 
 
1900
        while (1) {
 
1901
                /* we have to try to flush the output buffer before reading, at the end,
 
1902
                 * or if we're about to send a string that does not fit in the remaining space.
 
1903
                 */
 
1904
                if (check->bo->o &&
 
1905
                    (&cur->list == head ||
 
1906
                     check->current_step->action != TCPCHK_ACT_SEND ||
 
1907
                     check->current_step->string_len >= buffer_total_space(check->bo))) {
 
1908
 
 
1909
                        if (conn->xprt->snd_buf(conn, check->bo, 0) <= 0) {
 
1910
                                if (conn->flags & CO_FL_ERROR) {
 
1911
                                        chk_report_conn_err(conn, errno, 0);
 
1912
                                        __conn_data_stop_both(conn);
 
1913
                                        goto out_end_tcpcheck;
 
1914
                                }
 
1915
                                goto out_need_io;
 
1916
                        }
 
1917
                }
 
1918
 
 
1919
                /* did we reach the end ? If so, let's check that everything was sent */
 
1920
                if (&cur->list == head) {
 
1921
                        if (check->bo->o)
 
1922
                                goto out_need_io;
 
1923
                        break;
 
1924
                }
 
1925
 
 
1926
                if (check->current_step->action == TCPCHK_ACT_CONNECT) {
 
1927
                        struct protocol *proto;
 
1928
                        struct xprt_ops *xprt;
 
1929
 
 
1930
                        /* mark the step as started */
 
1931
                        check->last_started_step = check->current_step;
 
1932
                        /* first, shut existing connection */
 
1933
                        conn_force_close(conn);
 
1934
 
 
1935
                        /* prepare new connection */
 
1936
                        /* initialization */
 
1937
                        conn_init(conn);
 
1938
                        conn_attach(conn, check, &check_conn_cb);
 
1939
                        conn->target = &s->obj_type;
 
1940
 
 
1941
                        /* no client address */
 
1942
                        clear_addr(&conn->addr.from);
 
1943
 
 
1944
                        if (is_addr(&s->check_common.addr)) {
 
1945
                                /* we'll connect to the check addr specified on the server */
 
1946
                                conn->addr.to = s->check_common.addr;
 
1947
                                proto = s->check_common.proto;
 
1948
                        }
 
1949
                        else {
 
1950
                                /* we'll connect to the addr on the server */
 
1951
                                conn->addr.to = s->addr;
 
1952
                                proto = s->proto;
 
1953
                        }
 
1954
 
 
1955
                        /* port */
 
1956
                        if (check->current_step->port)
 
1957
                                set_host_port(&conn->addr.to, check->current_step->port);
 
1958
                        else if (check->port)
 
1959
                                set_host_port(&conn->addr.to, check->port);
 
1960
 
 
1961
#ifdef USE_OPENSSL
 
1962
                        if (check->current_step->conn_opts & TCPCHK_OPT_SSL) {
 
1963
                                xprt = &ssl_sock;
 
1964
                        }
 
1965
                        else {
 
1966
                                xprt = &raw_sock;
 
1967
                        }
 
1968
#else  /* USE_OPENSSL */
 
1969
                        xprt = &raw_sock;
 
1970
#endif /* USE_OPENSSL */
 
1971
                        conn_prepare(conn, proto, xprt);
 
1972
 
 
1973
                        ret = SN_ERR_INTERNAL;
 
1974
                        if (proto->connect)
 
1975
                                ret = proto->connect(conn, check->type, (check->type) ? 0 : 2);
 
1976
                        conn->flags |= CO_FL_WAKE_DATA;
 
1977
                        if (check->current_step->conn_opts & TCPCHK_OPT_SEND_PROXY) {
 
1978
                                conn->send_proxy_ofs = 1;
 
1979
                                conn->flags |= CO_FL_SEND_PROXY;
 
1980
                        }
 
1981
 
 
1982
                        /* It can return one of :
 
1983
                         *  - SN_ERR_NONE if everything's OK
 
1984
                         *  - SN_ERR_SRVTO if there are no more servers
 
1985
                         *  - SN_ERR_SRVCL if the connection was refused by the server
 
1986
                         *  - SN_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
 
1987
                         *  - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
 
1988
                         *  - SN_ERR_INTERNAL for any other purely internal errors
 
1989
                         * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
 
1990
                         * Note that we try to prevent the network stack from sending the ACK during the
 
1991
                         * connect() when a pure TCP check is used (without PROXY protocol).
 
1992
                         */
 
1993
                        switch (ret) {
 
1994
                        case SN_ERR_NONE:
 
1995
                                /* we allow up to min(inter, timeout.connect) for a connection
 
1996
                                 * to establish but only when timeout.check is set
 
1997
                                 * as it may be to short for a full check otherwise
 
1998
                                 */
 
1999
                                t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
 
2000
 
 
2001
                                if (s->proxy->timeout.check && s->proxy->timeout.connect) {
 
2002
                                        int t_con = tick_add(now_ms, s->proxy->timeout.connect);
 
2003
                                        t->expire = tick_first(t->expire, t_con);
 
2004
                                }
 
2005
                                break;
 
2006
                        case SN_ERR_SRVTO: /* ETIMEDOUT */
 
2007
                        case SN_ERR_SRVCL: /* ECONNREFUSED, ENETUNREACH, ... */
 
2008
                                chunk_printf(&trash, "TCPCHK error establishing connection at step %d: %s",
 
2009
                                                tcpcheck_get_step_id(s), strerror(errno));
 
2010
                                set_server_check_status(check, HCHK_STATUS_L4CON, trash.str);
 
2011
                                goto out_end_tcpcheck;
 
2012
                        case SN_ERR_PRXCOND:
 
2013
                        case SN_ERR_RESOURCE:
 
2014
                        case SN_ERR_INTERNAL:
 
2015
                                chunk_printf(&trash, "TCPCHK error establishing connection at step %d",
 
2016
                                                tcpcheck_get_step_id(s));
 
2017
                                set_server_check_status(check, HCHK_STATUS_SOCKERR, trash.str);
 
2018
                                goto out_end_tcpcheck;
 
2019
                        }
 
2020
 
 
2021
                        /* allow next rule */
 
2022
                        cur = (struct tcpcheck_rule *)cur->list.n;
 
2023
                        check->current_step = cur;
 
2024
 
 
2025
                        /* don't do anything until the connection is established */
 
2026
                        if (!(conn->flags & CO_FL_CONNECTED)) {
 
2027
                                /* update expire time, should be done by process_chk */
 
2028
                                /* we allow up to min(inter, timeout.connect) for a connection
 
2029
                                 * to establish but only when timeout.check is set
 
2030
                                 * as it may be to short for a full check otherwise
 
2031
                                 */
 
2032
                                while (tick_is_expired(t->expire, now_ms)) {
 
2033
                                        int t_con;
 
2034
 
 
2035
                                        t_con = tick_add(t->expire, s->proxy->timeout.connect);
 
2036
                                        t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
 
2037
 
 
2038
                                        if (s->proxy->timeout.check)
 
2039
                                                t->expire = tick_first(t->expire, t_con);
 
2040
                                }
 
2041
                                return;
 
2042
                        }
 
2043
 
 
2044
                } /* end 'connect' */
 
2045
                else if (check->current_step->action == TCPCHK_ACT_SEND) {
 
2046
                        /* mark the step as started */
 
2047
                        check->last_started_step = check->current_step;
 
2048
 
 
2049
                        /* reset the read buffer */
 
2050
                        if (*check->bi->data != '\0') {
 
2051
                                *check->bi->data = '\0';
 
2052
                                check->bi->i = 0;
 
2053
                        }
 
2054
 
 
2055
                        if (conn->flags & (CO_FL_SOCK_WR_SH | CO_FL_DATA_WR_SH)) {
 
2056
                                conn->flags |= CO_FL_ERROR;
 
2057
                                chk_report_conn_err(conn, 0, 0);
 
2058
                                goto out_end_tcpcheck;
 
2059
                        }
 
2060
 
 
2061
                        if (check->current_step->string_len >= check->bo->size) {
 
2062
                                chunk_printf(&trash, "tcp-check send : string too large (%d) for buffer size (%d) at step %d",
 
2063
                                             check->current_step->string_len, check->bo->size,
 
2064
                                             tcpcheck_get_step_id(s));
 
2065
                                set_server_check_status(check, HCHK_STATUS_L7RSP, trash.str);
 
2066
                                goto out_end_tcpcheck;
 
2067
                        }
 
2068
 
 
2069
                        /* do not try to send if there is no space */
 
2070
                        if (check->current_step->string_len >= buffer_total_space(check->bo))
 
2071
                                continue;
 
2072
 
 
2073
                        bo_putblk(check->bo, check->current_step->string, check->current_step->string_len);
 
2074
                        *check->bo->p = '\0'; /* to make gdb output easier to read */
 
2075
 
 
2076
                        /* go to next rule and try to send */
 
2077
                        cur = (struct tcpcheck_rule *)cur->list.n;
 
2078
                        check->current_step = cur;
 
2079
                } /* end 'send' */
 
2080
                else if (check->current_step->action == TCPCHK_ACT_EXPECT) {
 
2081
                        if (unlikely(check->result == CHK_RES_FAILED))
 
2082
                                goto out_end_tcpcheck;
 
2083
 
 
2084
                        if (conn->xprt->rcv_buf(conn, check->bi, check->bi->size) <= 0) {
 
2085
                                if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH)) {
 
2086
                                        done = 1;
 
2087
                                        if ((conn->flags & CO_FL_ERROR) && !check->bi->i) {
 
2088
                                                /* Report network errors only if we got no other data. Otherwise
 
2089
                                                 * we'll let the upper layers decide whether the response is OK
 
2090
                                                 * or not. It is very common that an RST sent by the server is
 
2091
                                                 * reported as an error just after the last data chunk.
 
2092
                                                 */
 
2093
                                                chk_report_conn_err(conn, errno, 0);
 
2094
                                                goto out_end_tcpcheck;
 
2095
                                        }
 
2096
                                }
 
2097
                                else
 
2098
                                        goto out_need_io;
 
2099
                        }
 
2100
 
 
2101
                        /* mark the step as started */
 
2102
                        check->last_started_step = check->current_step;
 
2103
 
 
2104
 
 
2105
                        /* Intermediate or complete response received.
 
2106
                         * Terminate string in check->bi->data buffer.
 
2107
                         */
 
2108
                        if (check->bi->i < check->bi->size) {
 
2109
                                check->bi->data[check->bi->i] = '\0';
 
2110
                        }
 
2111
                        else {
 
2112
                                check->bi->data[check->bi->i - 1] = '\0';
 
2113
                                done = 1; /* buffer full, don't wait for more data */
 
2114
                        }
 
2115
 
 
2116
                        contentptr = check->bi->data;
 
2117
 
 
2118
                        /* Check that response body is not empty... */
 
2119
                        if (!check->bi->i) {
 
2120
                                if (!done)
 
2121
                                        continue;
 
2122
 
 
2123
                                /* empty response */
 
2124
                                chunk_printf(&trash, "TCPCHK got an empty response at step %d",
 
2125
                                                tcpcheck_get_step_id(s));
 
2126
                                set_server_check_status(check, HCHK_STATUS_L7RSP, trash.str);
 
2127
 
 
2128
                                goto out_end_tcpcheck;
 
2129
                        }
 
2130
 
 
2131
                        if (!done && (cur->string != NULL) && (check->bi->i < cur->string_len) )
 
2132
                                continue; /* try to read more */
 
2133
 
 
2134
                tcpcheck_expect:
 
2135
                        if (cur->string != NULL)
 
2136
                                ret = my_memmem(contentptr, check->bi->i, cur->string, cur->string_len) != NULL;
 
2137
                        else if (cur->expect_regex != NULL)
 
2138
                                ret = regex_exec(cur->expect_regex, contentptr);
 
2139
 
 
2140
                        if (!ret && !done)
 
2141
                                continue; /* try to read more */
 
2142
 
 
2143
                        /* matched */
 
2144
                        if (ret) {
 
2145
                                /* matched but we did not want to => ERROR */
 
2146
                                if (cur->inverse) {
 
2147
                                        /* we were looking for a string */
 
2148
                                        if (cur->string != NULL) {
 
2149
                                                chunk_printf(&trash, "TCPCHK matched unwanted content '%s' at step %d",
 
2150
                                                                cur->string, tcpcheck_get_step_id(s));
 
2151
                                        }
 
2152
                                        else {
 
2153
                                        /* we were looking for a regex */
 
2154
                                                chunk_printf(&trash, "TCPCHK matched unwanted content (regex) at step %d",
 
2155
                                                                tcpcheck_get_step_id(s));
 
2156
                                        }
 
2157
                                        set_server_check_status(check, HCHK_STATUS_L7RSP, trash.str);
 
2158
                                        goto out_end_tcpcheck;
 
2159
                                }
 
2160
                                /* matched and was supposed to => OK, next step */
 
2161
                                else {
 
2162
                                        cur = (struct tcpcheck_rule*)cur->list.n;
 
2163
                                        check->current_step = cur;
 
2164
                                        if (check->current_step->action == TCPCHK_ACT_EXPECT)
 
2165
                                                goto tcpcheck_expect;
 
2166
                                        __conn_data_stop_recv(conn);
 
2167
                                }
 
2168
                        }
 
2169
                        else {
 
2170
                        /* not matched */
 
2171
                                /* not matched and was not supposed to => OK, next step */
 
2172
                                if (cur->inverse) {
 
2173
                                        cur = (struct tcpcheck_rule*)cur->list.n;
 
2174
                                        check->current_step = cur;
 
2175
                                        if (check->current_step->action == TCPCHK_ACT_EXPECT)
 
2176
                                                goto tcpcheck_expect;
 
2177
                                        __conn_data_stop_recv(conn);
 
2178
                                }
 
2179
                                /* not matched but was supposed to => ERROR */
 
2180
                                else {
 
2181
                                        /* we were looking for a string */
 
2182
                                        if (cur->string != NULL) {
 
2183
                                                chunk_printf(&trash, "TCPCHK did not match content '%s' at step %d",
 
2184
                                                                cur->string, tcpcheck_get_step_id(s));
 
2185
                                        }
 
2186
                                        else {
 
2187
                                        /* we were looking for a regex */
 
2188
                                                chunk_printf(&trash, "TCPCHK did not match content (regex) at step %d",
 
2189
                                                                tcpcheck_get_step_id(s));
 
2190
                                        }
 
2191
                                        set_server_check_status(check, HCHK_STATUS_L7RSP, trash.str);
 
2192
                                        goto out_end_tcpcheck;
 
2193
                                }
 
2194
                        }
 
2195
                } /* end expect */
 
2196
        } /* end loop over double chained step list */
 
2197
 
 
2198
        set_server_check_status(check, HCHK_STATUS_L7OKD, "(tcp-check)");
 
2199
        goto out_end_tcpcheck;
 
2200
 
 
2201
 out_need_io:
 
2202
        if (check->bo->o)
 
2203
                __conn_data_want_send(conn);
 
2204
 
 
2205
        if (check->current_step->action == TCPCHK_ACT_EXPECT)
 
2206
                __conn_data_want_recv(conn);
 
2207
        return;
 
2208
 
 
2209
 out_end_tcpcheck:
 
2210
        /* collect possible new errors */
 
2211
        if (conn->flags & CO_FL_ERROR)
 
2212
                chk_report_conn_err(conn, 0, 0);
 
2213
 
 
2214
        /* cleanup before leaving */
 
2215
        check->current_step = NULL;
 
2216
 
 
2217
        if (check->result == CHK_RES_FAILED)
 
2218
                conn->flags |= CO_FL_ERROR;
 
2219
 
 
2220
        __conn_data_stop_both(conn);
 
2221
 
 
2222
        return;
 
2223
}
 
2224
 
 
2225
 
 
2226
/*
1722
2227
 * Local variables:
1723
2228
 *  c-indent-level: 8
1724
2229
 *  c-basic-offset: 8