1 /*
2  * Health-checks functions.
3  *
4  * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
5  * Copyright 2007-2009 Krzysztof Piotr Oledzki <ole@ans.pl>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version
10  * 2 of the License, or (at your option) any later version.
11  *
12  */
13 
14 #include <assert.h>
15 #include <ctype.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <signal.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24 #include <unistd.h>
25 #include <sys/resource.h>
26 #include <sys/socket.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <netinet/in.h>
30 #include <netinet/tcp.h>
31 #include <arpa/inet.h>
32 
33 #include <common/chunk.h>
34 #include <common/compat.h>
35 #include <common/config.h>
36 #include <common/mini-clist.h>
37 #include <common/net_helper.h>
38 #include <common/standard.h>
39 #include <common/time.h>
40 #include <common/hathreads.h>
41 
42 #include <types/global.h>
43 #include <types/dns.h>
44 #include <types/stats.h>
45 
46 #include <proto/backend.h>
47 #include <proto/checks.h>
48 #include <proto/stats.h>
49 #include <proto/fd.h>
50 #include <proto/log.h>
51 #include <proto/mux_pt.h>
52 #include <proto/queue.h>
53 #include <proto/port_range.h>
54 #include <proto/proto_tcp.h>
55 #include <proto/protocol.h>
56 #include <proto/proxy.h>
57 #include <proto/server.h>
58 #include <proto/signal.h>
59 #include <proto/stream_interface.h>
60 #include <proto/task.h>
61 #include <proto/log.h>
62 #include <proto/dns.h>
63 #include <proto/proto_udp.h>
64 #include <proto/ssl_sock.h>
65 
66 static int httpchk_expect(struct server *s, int done);
67 static int tcpcheck_get_step_id(struct check *);
68 static char * tcpcheck_get_step_comment(struct check *, int);
69 static int tcpcheck_main(struct check *);
70 static void __event_srv_chk_w(struct conn_stream *cs);
71 static int wake_srv_chk(struct conn_stream *cs);
72 static void __event_srv_chk_r(struct conn_stream *cs);
73 
74 DECLARE_STATIC_POOL(pool_head_email_alert,   "email_alert",   sizeof(struct email_alert));
75 DECLARE_STATIC_POOL(pool_head_tcpcheck_rule, "tcpcheck_rule", sizeof(struct tcpcheck_rule));
76 
77 
78 static const struct check_status check_statuses[HCHK_STATUS_SIZE] = {
79 	[HCHK_STATUS_UNKNOWN]	= { CHK_RES_UNKNOWN,  "UNK",     "Unknown" },
80 	[HCHK_STATUS_INI]	= { CHK_RES_UNKNOWN,  "INI",     "Initializing" },
81 	[HCHK_STATUS_START]	= { /* SPECIAL STATUS*/ },
82 
83 	/* Below we have finished checks */
84 	[HCHK_STATUS_CHECKED]	= { CHK_RES_NEUTRAL,  "CHECKED", "No status change" },
85 	[HCHK_STATUS_HANA]	= { CHK_RES_FAILED,   "HANA",    "Health analyze" },
86 
87 	[HCHK_STATUS_SOCKERR]	= { CHK_RES_FAILED,   "SOCKERR", "Socket error" },
88 
89 	[HCHK_STATUS_L4OK]	= { CHK_RES_PASSED,   "L4OK",    "Layer4 check passed" },
90 	[HCHK_STATUS_L4TOUT]	= { CHK_RES_FAILED,   "L4TOUT",  "Layer4 timeout" },
91 	[HCHK_STATUS_L4CON]	= { CHK_RES_FAILED,   "L4CON",   "Layer4 connection problem" },
92 
93 	[HCHK_STATUS_L6OK]	= { CHK_RES_PASSED,   "L6OK",    "Layer6 check passed" },
94 	[HCHK_STATUS_L6TOUT]	= { CHK_RES_FAILED,   "L6TOUT",  "Layer6 timeout" },
95 	[HCHK_STATUS_L6RSP]	= { CHK_RES_FAILED,   "L6RSP",   "Layer6 invalid response" },
96 
97 	[HCHK_STATUS_L7TOUT]	= { CHK_RES_FAILED,   "L7TOUT",  "Layer7 timeout" },
98 	[HCHK_STATUS_L7RSP]	= { CHK_RES_FAILED,   "L7RSP",   "Layer7 invalid response" },
99 
100 	[HCHK_STATUS_L57DATA]	= { /* DUMMY STATUS */ },
101 
102 	[HCHK_STATUS_L7OKD]	= { CHK_RES_PASSED,   "L7OK",    "Layer7 check passed" },
103 	[HCHK_STATUS_L7OKCD]	= { CHK_RES_CONDPASS, "L7OKC",   "Layer7 check conditionally passed" },
104 	[HCHK_STATUS_L7STS]	= { CHK_RES_FAILED,   "L7STS",   "Layer7 wrong status" },
105 
106 	[HCHK_STATUS_PROCERR]	= { CHK_RES_FAILED,   "PROCERR",  "External check error" },
107 	[HCHK_STATUS_PROCTOUT]	= { CHK_RES_FAILED,   "PROCTOUT", "External check timeout" },
108 	[HCHK_STATUS_PROCOK]	= { CHK_RES_PASSED,   "PROCOK",   "External check passed" },
109 };
110 
111 const struct extcheck_env extcheck_envs[EXTCHK_SIZE] = {
112 	[EXTCHK_PATH]                   = { "PATH",                   EXTCHK_SIZE_EVAL_INIT },
113 	[EXTCHK_HAPROXY_PROXY_NAME]     = { "HAPROXY_PROXY_NAME",     EXTCHK_SIZE_EVAL_INIT },
114 	[EXTCHK_HAPROXY_PROXY_ID]       = { "HAPROXY_PROXY_ID",       EXTCHK_SIZE_EVAL_INIT },
115 	[EXTCHK_HAPROXY_PROXY_ADDR]     = { "HAPROXY_PROXY_ADDR",     EXTCHK_SIZE_EVAL_INIT },
116 	[EXTCHK_HAPROXY_PROXY_PORT]     = { "HAPROXY_PROXY_PORT",     EXTCHK_SIZE_EVAL_INIT },
117 	[EXTCHK_HAPROXY_SERVER_NAME]    = { "HAPROXY_SERVER_NAME",    EXTCHK_SIZE_EVAL_INIT },
118 	[EXTCHK_HAPROXY_SERVER_ID]      = { "HAPROXY_SERVER_ID",      EXTCHK_SIZE_EVAL_INIT },
119 	[EXTCHK_HAPROXY_SERVER_ADDR]    = { "HAPROXY_SERVER_ADDR",    EXTCHK_SIZE_ADDR },
120 	[EXTCHK_HAPROXY_SERVER_PORT]    = { "HAPROXY_SERVER_PORT",    EXTCHK_SIZE_UINT },
121 	[EXTCHK_HAPROXY_SERVER_MAXCONN] = { "HAPROXY_SERVER_MAXCONN", EXTCHK_SIZE_EVAL_INIT },
122 	[EXTCHK_HAPROXY_SERVER_CURCONN] = { "HAPROXY_SERVER_CURCONN", EXTCHK_SIZE_ULONG },
123 };
124 
125 static const struct analyze_status analyze_statuses[HANA_STATUS_SIZE] = {		/* 0: ignore, 1: error, 2: OK */
126 	[HANA_STATUS_UNKNOWN]		= { "Unknown",                         { 0, 0 }},
127 
128 	[HANA_STATUS_L4_OK]		= { "L4 successful connection",        { 2, 0 }},
129 	[HANA_STATUS_L4_ERR]		= { "L4 unsuccessful connection",      { 1, 1 }},
130 
131 	[HANA_STATUS_HTTP_OK]		= { "Correct http response",           { 0, 2 }},
132 	[HANA_STATUS_HTTP_STS]		= { "Wrong http response",             { 0, 1 }},
133 	[HANA_STATUS_HTTP_HDRRSP]	= { "Invalid http response (headers)", { 0, 1 }},
134 	[HANA_STATUS_HTTP_RSP]		= { "Invalid http response",           { 0, 1 }},
135 
136 	[HANA_STATUS_HTTP_READ_ERROR]	= { "Read error (http)",               { 0, 1 }},
137 	[HANA_STATUS_HTTP_READ_TIMEOUT]	= { "Read timeout (http)",             { 0, 1 }},
138 	[HANA_STATUS_HTTP_BROKEN_PIPE]	= { "Close from server (http)",        { 0, 1 }},
139 };
140 
141 /* checks if <err> is a real error for errno or one that can be ignored, and
142  * return 0 for these ones or <err> for real ones.
143  */
unclean_errno(int err)144 static inline int unclean_errno(int err)
145 {
146 	if (err == EAGAIN || err == EINPROGRESS ||
147 	    err == EISCONN || err == EALREADY)
148 		return 0;
149 	return err;
150 }
151 
152 /*
153  * Convert check_status code to description
154  */
get_check_status_description(short check_status)155 const char *get_check_status_description(short check_status) {
156 
157 	const char *desc;
158 
159 	if (check_status < HCHK_STATUS_SIZE)
160 		desc = check_statuses[check_status].desc;
161 	else
162 		desc = NULL;
163 
164 	if (desc && *desc)
165 		return desc;
166 	else
167 		return check_statuses[HCHK_STATUS_UNKNOWN].desc;
168 }
169 
170 /*
171  * Convert check_status code to short info
172  */
get_check_status_info(short check_status)173 const char *get_check_status_info(short check_status) {
174 
175 	const char *info;
176 
177 	if (check_status < HCHK_STATUS_SIZE)
178 		info = check_statuses[check_status].info;
179 	else
180 		info = NULL;
181 
182 	if (info && *info)
183 		return info;
184 	else
185 		return check_statuses[HCHK_STATUS_UNKNOWN].info;
186 }
187 
get_analyze_status(short analyze_status)188 const char *get_analyze_status(short analyze_status) {
189 
190 	const char *desc;
191 
192 	if (analyze_status < HANA_STATUS_SIZE)
193 		desc = analyze_statuses[analyze_status].desc;
194 	else
195 		desc = NULL;
196 
197 	if (desc && *desc)
198 		return desc;
199 	else
200 		return analyze_statuses[HANA_STATUS_UNKNOWN].desc;
201 }
202 
203 /*
204  * Set check->status, update check->duration and fill check->result with
205  * an adequate CHK_RES_* value. The new check->health is computed based
206  * on the result.
207  *
208  * Show information in logs about failed health check if server is UP
209  * or succeeded health checks if server is DOWN.
210  */
set_server_check_status(struct check * check,short status,const char * desc)211 static void set_server_check_status(struct check *check, short status, const char *desc)
212 {
213 	struct server *s = check->server;
214 	short prev_status = check->status;
215 	int report = 0;
216 
217 	if (status == HCHK_STATUS_START) {
218 		check->result = CHK_RES_UNKNOWN;	/* no result yet */
219 		check->desc[0] = '\0';
220 		check->start = now;
221 		return;
222 	}
223 
224 	if (!check->status)
225 		return;
226 
227 	if (desc && *desc) {
228 		strncpy(check->desc, desc, HCHK_DESC_LEN-1);
229 		check->desc[HCHK_DESC_LEN-1] = '\0';
230 	} else
231 		check->desc[0] = '\0';
232 
233 	check->status = status;
234 	if (check_statuses[status].result)
235 		check->result = check_statuses[status].result;
236 
237 	if (status == HCHK_STATUS_HANA)
238 		check->duration = -1;
239 	else if (!tv_iszero(&check->start)) {
240 		/* set_server_check_status() may be called more than once */
241 		check->duration = tv_ms_elapsed(&check->start, &now);
242 		tv_zero(&check->start);
243 	}
244 
245 	/* no change is expected if no state change occurred */
246 	if (check->result == CHK_RES_NEUTRAL)
247 		return;
248 
249 	/* If the check was really just sending a mail, it won't have an
250 	 * associated server, so we're done now.
251 	 */
252 	if (!s)
253 	    return;
254 	report = 0;
255 
256 	switch (check->result) {
257 	case CHK_RES_FAILED:
258 		/* Failure to connect to the agent as a secondary check should not
259 		 * cause the server to be marked down.
260 		 */
261 		if ((!(check->state & CHK_ST_AGENT) ||
262 		    (check->status >= HCHK_STATUS_L57DATA)) &&
263 		    (check->health > 0)) {
264 			_HA_ATOMIC_ADD(&s->counters.failed_checks, 1);
265 			report = 1;
266 			check->health--;
267 			if (check->health < check->rise)
268 				check->health = 0;
269 		}
270 		break;
271 
272 	case CHK_RES_PASSED:
273 	case CHK_RES_CONDPASS:	/* "condpass" cannot make the first step but it OK after a "passed" */
274 		if ((check->health < check->rise + check->fall - 1) &&
275 		    (check->result == CHK_RES_PASSED || check->health > 0)) {
276 			report = 1;
277 			check->health++;
278 
279 			if (check->health >= check->rise)
280 				check->health = check->rise + check->fall - 1; /* OK now */
281 		}
282 
283 		/* clear consecutive_errors if observing is enabled */
284 		if (s->onerror)
285 			s->consecutive_errors = 0;
286 		break;
287 
288 	default:
289 		break;
290 	}
291 
292 	if (s->proxy->options2 & PR_O2_LOGHCHKS &&
293 	    (status != prev_status || report)) {
294 		chunk_printf(&trash,
295 		             "%s check for %sserver %s/%s %s%s",
296 			     (check->state & CHK_ST_AGENT) ? "Agent" : "Health",
297 		             s->flags & SRV_F_BACKUP ? "backup " : "",
298 		             s->proxy->id, s->id,
299 		             (check->result == CHK_RES_CONDPASS) ? "conditionally ":"",
300 		             (check->result >= CHK_RES_PASSED)   ? "succeeded" : "failed");
301 
302 		srv_append_status(&trash, s, check, -1, 0);
303 
304 		chunk_appendf(&trash, ", status: %d/%d %s",
305 		             (check->health >= check->rise) ? check->health - check->rise + 1 : check->health,
306 		             (check->health >= check->rise) ? check->fall : check->rise,
307 			     (check->health >= check->rise) ? (s->uweight ? "UP" : "DRAIN") : "DOWN");
308 
309 		ha_warning("%s.\n", trash.area);
310 		send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.area);
311 		send_email_alert(s, LOG_INFO, "%s", trash.area);
312 	}
313 }
314 
315 /* Marks the check <check>'s server down if the current check is already failed
316  * and the server is not down yet nor in maintenance.
317  */
check_notify_failure(struct check * check)318 static void check_notify_failure(struct check *check)
319 {
320 	struct server *s = check->server;
321 
322 	/* The agent secondary check should only cause a server to be marked
323 	 * as down if check->status is HCHK_STATUS_L7STS, which indicates
324 	 * that the agent returned "fail", "stopped" or "down".
325 	 * The implication here is that failure to connect to the agent
326 	 * as a secondary check should not cause the server to be marked
327 	 * down. */
328 	if ((check->state & CHK_ST_AGENT) && check->status != HCHK_STATUS_L7STS)
329 		return;
330 
331 	if (check->health > 0)
332 		return;
333 
334 	/* We only report a reason for the check if we did not do so previously */
335 	srv_set_stopped(s, NULL, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : NULL);
336 }
337 
338 /* Marks the check <check> as valid and tries to set its server up, provided
339  * it isn't in maintenance, it is not tracking a down server and other checks
340  * comply. The rule is simple : by default, a server is up, unless any of the
341  * following conditions is true :
342  *   - health check failed (check->health < rise)
343  *   - agent check failed (agent->health < rise)
344  *   - the server tracks a down server (track && track->state == STOPPED)
345  * Note that if the server has a slowstart, it will switch to STARTING instead
346  * of RUNNING. Also, only the health checks support the nolb mode, so the
347  * agent's success may not take the server out of this mode.
348  */
check_notify_success(struct check * check)349 static void check_notify_success(struct check *check)
350 {
351 	struct server *s = check->server;
352 
353 	if (s->next_admin & SRV_ADMF_MAINT)
354 		return;
355 
356 	if (s->track && s->track->next_state == SRV_ST_STOPPED)
357 		return;
358 
359 	if ((s->check.state & CHK_ST_ENABLED) && (s->check.health < s->check.rise))
360 		return;
361 
362 	if ((s->agent.state & CHK_ST_ENABLED) && (s->agent.health < s->agent.rise))
363 		return;
364 
365 	if ((check->state & CHK_ST_AGENT) && s->next_state == SRV_ST_STOPPING)
366 		return;
367 
368 	srv_set_running(s, NULL, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : NULL);
369 }
370 
371 /* Marks the check <check> as valid and tries to set its server into stopping mode
372  * if it was running or starting, and provided it isn't in maintenance and other
373  * checks comply. The conditions for the server to be marked in stopping mode are
374  * the same as for it to be turned up. Also, only the health checks support the
375  * nolb mode.
376  */
check_notify_stopping(struct check * check)377 static void check_notify_stopping(struct check *check)
378 {
379 	struct server *s = check->server;
380 
381 	if (s->next_admin & SRV_ADMF_MAINT)
382 		return;
383 
384 	if (check->state & CHK_ST_AGENT)
385 		return;
386 
387 	if (s->track && s->track->next_state == SRV_ST_STOPPED)
388 		return;
389 
390 	if ((s->check.state & CHK_ST_ENABLED) && (s->check.health < s->check.rise))
391 		return;
392 
393 	if ((s->agent.state & CHK_ST_ENABLED) && (s->agent.health < s->agent.rise))
394 		return;
395 
396 	srv_set_stopping(s, NULL, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : NULL);
397 }
398 
399 /* note: use health_adjust() only, which first checks that the observe mode is
400  * enabled.
401  */
__health_adjust(struct server * s,short status)402 void __health_adjust(struct server *s, short status)
403 {
404 	int failed;
405 	int expire;
406 
407 	if (s->observe >= HANA_OBS_SIZE)
408 		return;
409 
410 	if (status >= HANA_STATUS_SIZE || !analyze_statuses[status].desc)
411 		return;
412 
413 	switch (analyze_statuses[status].lr[s->observe - 1]) {
414 		case 1:
415 			failed = 1;
416 			break;
417 
418 		case 2:
419 			failed = 0;
420 			break;
421 
422 		default:
423 			return;
424 	}
425 
426 	if (!failed) {
427 		/* good: clear consecutive_errors */
428 		s->consecutive_errors = 0;
429 		return;
430 	}
431 
432 	_HA_ATOMIC_ADD(&s->consecutive_errors, 1);
433 
434 	if (s->consecutive_errors < s->consecutive_errors_limit)
435 		return;
436 
437 	chunk_printf(&trash, "Detected %d consecutive errors, last one was: %s",
438 	             s->consecutive_errors, get_analyze_status(status));
439 
440 	switch (s->onerror) {
441 		case HANA_ONERR_FASTINTER:
442 		/* force fastinter - nothing to do here as all modes force it */
443 			break;
444 
445 		case HANA_ONERR_SUDDTH:
446 		/* simulate a pre-fatal failed health check */
447 			if (s->check.health > s->check.rise)
448 				s->check.health = s->check.rise + 1;
449 
450 			/* no break - fall through */
451 
452 		case HANA_ONERR_FAILCHK:
453 		/* simulate a failed health check */
454 			set_server_check_status(&s->check, HCHK_STATUS_HANA,
455 						trash.area);
456 			check_notify_failure(&s->check);
457 			break;
458 
459 		case HANA_ONERR_MARKDWN:
460 		/* mark server down */
461 			s->check.health = s->check.rise;
462 			set_server_check_status(&s->check, HCHK_STATUS_HANA,
463 						trash.area);
464 			check_notify_failure(&s->check);
465 			break;
466 
467 		default:
468 			/* write a warning? */
469 			break;
470 	}
471 
472 	s->consecutive_errors = 0;
473 	_HA_ATOMIC_ADD(&s->counters.failed_hana, 1);
474 
475 	if (s->check.fastinter) {
476 		expire = tick_add(now_ms, MS_TO_TICKS(s->check.fastinter));
477 		if (tick_is_lt(expire, s->check.task->expire)) {
478 			s->check.task->expire = expire;
479 			/* requeue check task with new expire */
480 			task_queue(s->check.task);
481 		}
482 	}
483 }
484 
httpchk_build_status_header(struct server * s,char * buffer,int size)485 static int httpchk_build_status_header(struct server *s, char *buffer, int size)
486 {
487 	int sv_state;
488 	int ratio;
489 	int hlen = 0;
490 	char addr[46];
491 	char port[6];
492 	const char *srv_hlt_st[7] = { "DOWN", "DOWN %d/%d",
493 				      "UP %d/%d", "UP",
494 				      "NOLB %d/%d", "NOLB",
495 				      "no check" };
496 
497 	memcpy(buffer + hlen, "X-Haproxy-Server-State: ", 24);
498 	hlen += 24;
499 
500 	if (!(s->check.state & CHK_ST_ENABLED))
501 		sv_state = 6;
502 	else if (s->cur_state != SRV_ST_STOPPED) {
503 		if (s->check.health == s->check.rise + s->check.fall - 1)
504 			sv_state = 3; /* UP */
505 		else
506 			sv_state = 2; /* going down */
507 
508 		if (s->cur_state == SRV_ST_STOPPING)
509 			sv_state += 2;
510 	} else {
511 		if (s->check.health)
512 			sv_state = 1; /* going up */
513 		else
514 			sv_state = 0; /* DOWN */
515 	}
516 
517 	hlen += snprintf(buffer + hlen, size - hlen,
518 			     srv_hlt_st[sv_state],
519 			     (s->cur_state != SRV_ST_STOPPED) ? (s->check.health - s->check.rise + 1) : (s->check.health),
520 			     (s->cur_state != SRV_ST_STOPPED) ? (s->check.fall) : (s->check.rise));
521 
522 	addr_to_str(&s->addr, addr, sizeof(addr));
523 	if (s->addr.ss_family == AF_INET || s->addr.ss_family == AF_INET6)
524 		snprintf(port, sizeof(port), "%u", s->svc_port);
525 	else
526 		*port = 0;
527 
528 	hlen += snprintf(buffer + hlen,  size - hlen, "; address=%s; port=%s; name=%s/%s; node=%s; weight=%d/%d; scur=%d/%d; qcur=%d",
529 			     addr, port, s->proxy->id, s->id,
530 			     global.node,
531 			     (s->cur_eweight * s->proxy->lbprm.wmult + s->proxy->lbprm.wdiv - 1) / s->proxy->lbprm.wdiv,
532 			     (s->proxy->lbprm.tot_weight * s->proxy->lbprm.wmult + s->proxy->lbprm.wdiv - 1) / s->proxy->lbprm.wdiv,
533 			     s->cur_sess, s->proxy->beconn - s->proxy->nbpend,
534 			     s->nbpend);
535 
536 	if ((s->cur_state == SRV_ST_STARTING) &&
537 	    now.tv_sec < s->last_change + s->slowstart &&
538 	    now.tv_sec >= s->last_change) {
539 		ratio = MAX(1, 100 * (now.tv_sec - s->last_change) / s->slowstart);
540 		hlen += snprintf(buffer + hlen, size - hlen, "; throttle=%d%%", ratio);
541 	}
542 
543 	buffer[hlen++] = '\r';
544 	buffer[hlen++] = '\n';
545 
546 	return hlen;
547 }
548 
549 /* Check the connection. If an error has already been reported or the socket is
550  * closed, keep errno intact as it is supposed to contain the valid error code.
551  * If no error is reported, check the socket's error queue using getsockopt().
552  * Warning, this must be done only once when returning from poll, and never
553  * after an I/O error was attempted, otherwise the error queue might contain
554  * inconsistent errors. If an error is detected, the CO_FL_ERROR is set on the
555  * socket. Returns non-zero if an error was reported, zero if everything is
556  * clean (including a properly closed socket).
557  */
retrieve_errno_from_socket(struct connection * conn)558 static int retrieve_errno_from_socket(struct connection *conn)
559 {
560 	int skerr;
561 	socklen_t lskerr = sizeof(skerr);
562 
563 	if (conn->flags & CO_FL_ERROR && (unclean_errno(errno) || !conn->ctrl))
564 		return 1;
565 
566 	if (!conn_ctrl_ready(conn))
567 		return 0;
568 
569 	if (getsockopt(conn->handle.fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr) == 0)
570 		errno = skerr;
571 
572 	errno = unclean_errno(errno);
573 
574 	if (!errno) {
575 		/* we could not retrieve an error, that does not mean there is
576 		 * none. Just don't change anything and only report the prior
577 		 * error if any.
578 		 */
579 		if (conn->flags & CO_FL_ERROR)
580 			return 1;
581 		else
582 			return 0;
583 	}
584 
585 	conn->flags |= CO_FL_ERROR | CO_FL_SOCK_WR_SH | CO_FL_SOCK_RD_SH;
586 	return 1;
587 }
588 
589 /* Try to collect as much information as possible on the connection status,
590  * and adjust the server status accordingly. It may make use of <errno_bck>
591  * if non-null when the caller is absolutely certain of its validity (eg:
592  * checked just after a syscall). If the caller doesn't have a valid errno,
593  * it can pass zero, and retrieve_errno_from_socket() will be called to try
594  * to extract errno from the socket. If no error is reported, it will consider
595  * the <expired> flag. This is intended to be used when a connection error was
596  * reported in conn->flags or when a timeout was reported in <expired>. The
597  * function takes care of not updating a server status which was already set.
598  * All situations where at least one of <expired> or CO_FL_ERROR are set
599  * produce a status.
600  */
chk_report_conn_err(struct check * check,int errno_bck,int expired)601 static void chk_report_conn_err(struct check *check, int errno_bck, int expired)
602 {
603 	struct conn_stream *cs = check->cs;
604 	struct connection *conn = cs_conn(cs);
605 	const char *err_msg;
606 	struct buffer *chk;
607 	int step;
608 	char *comment;
609 
610 	if (check->result != CHK_RES_UNKNOWN)
611 		return;
612 
613 	errno = unclean_errno(errno_bck);
614 	if (conn && errno)
615 		retrieve_errno_from_socket(conn);
616 
617 	if (conn && !(conn->flags & CO_FL_ERROR) &&
618 	    !(cs->flags & CS_FL_ERROR) && !expired)
619 		return;
620 
621 	/* we'll try to build a meaningful error message depending on the
622 	 * context of the error possibly present in conn->err_code, and the
623 	 * socket error possibly collected above. This is useful to know the
624 	 * exact step of the L6 layer (eg: SSL handshake).
625 	 */
626 	chk = get_trash_chunk();
627 
628 	if (check->type == PR_O2_TCPCHK_CHK) {
629 		step = tcpcheck_get_step_id(check);
630 		if (!step)
631 			chunk_printf(chk, " at initial connection step of tcp-check");
632 		else {
633 			chunk_printf(chk, " at step %d of tcp-check", step);
634 			/* we were looking for a string */
635 			if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_CONNECT) {
636 				if (check->last_started_step->port)
637 					chunk_appendf(chk, " (connect port %d)" ,check->last_started_step->port);
638 				else
639 					chunk_appendf(chk, " (connect)");
640 			}
641 			else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_EXPECT) {
642 				if (check->last_started_step->string)
643 					chunk_appendf(chk, " (expect string '%s')", check->last_started_step->string);
644 				else if (check->last_started_step->expect_regex)
645 					chunk_appendf(chk, " (expect regex)");
646 			}
647 			else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_SEND) {
648 				chunk_appendf(chk, " (send)");
649 			}
650 
651 			comment = tcpcheck_get_step_comment(check, step);
652 			if (comment)
653 				chunk_appendf(chk, " comment: '%s'", comment);
654 		}
655 	}
656 
657 	if (conn && conn->err_code) {
658 		if (unclean_errno(errno))
659 			chunk_printf(&trash, "%s (%s)%s", conn_err_code_str(conn), strerror(errno),
660 				     chk->area);
661 		else
662 			chunk_printf(&trash, "%s%s", conn_err_code_str(conn),
663 				     chk->area);
664 		err_msg = trash.area;
665 	}
666 	else {
667 		if (unclean_errno(errno)) {
668 			chunk_printf(&trash, "%s%s", strerror(errno),
669 				     chk->area);
670 			err_msg = trash.area;
671 		}
672 		else {
673 			err_msg = chk->area;
674 		}
675 	}
676 
677 	if (check->state & CHK_ST_PORT_MISS) {
678 		/* NOTE: this is reported after <fall> tries */
679 		chunk_printf(chk, "No port available for the TCP connection");
680 		set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
681 	}
682 
683 	if (!conn) {
684 		/* connection allocation error before the connection was established */
685 		set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
686 	}
687 	else if ((conn->flags & (CO_FL_CONNECTED|CO_FL_WAIT_L4_CONN)) == CO_FL_WAIT_L4_CONN) {
688 		/* L4 not established (yet) */
689 		if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
690 			set_server_check_status(check, HCHK_STATUS_L4CON, err_msg);
691 		else if (expired)
692 			set_server_check_status(check, HCHK_STATUS_L4TOUT, err_msg);
693 
694 		/*
695 		 * might be due to a server IP change.
696 		 * Let's trigger a DNS resolution if none are currently running.
697 		 */
698 		if (check->server)
699 			dns_trigger_resolution(check->server->dns_requester);
700 
701 	}
702 	else if ((conn->flags & (CO_FL_CONNECTED|CO_FL_WAIT_L6_CONN)) == CO_FL_WAIT_L6_CONN) {
703 		/* L6 not established (yet) */
704 		if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
705 			set_server_check_status(check, HCHK_STATUS_L6RSP, err_msg);
706 		else if (expired)
707 			set_server_check_status(check, HCHK_STATUS_L6TOUT, err_msg);
708 	}
709 	else if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) {
710 		/* I/O error after connection was established and before we could diagnose */
711 		set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
712 	}
713 	else if (expired) {
714 		/* connection established but expired check */
715 		if (check->type == PR_O2_SSL3_CHK)
716 			set_server_check_status(check, HCHK_STATUS_L6TOUT, err_msg);
717 		else	/* HTTP, SMTP, ... */
718 			set_server_check_status(check, HCHK_STATUS_L7TOUT, err_msg);
719 	}
720 
721 	return;
722 }
723 
724 /* This function checks if any I/O is wanted, and if so, attempts to do so */
event_srv_chk_io(struct task * t,void * ctx,unsigned short state)725 static struct task *event_srv_chk_io(struct task *t, void *ctx, unsigned short state)
726 {
727 	struct check *check = ctx;
728 	struct conn_stream *cs = check->cs;
729 	struct email_alertq *q = container_of(check, typeof(*q), check);
730 	int ret = 0;
731 
732 	if (!(check->wait_list.events & SUB_RETRY_SEND))
733 		ret = wake_srv_chk(cs);
734 	if (ret == 0 && !(check->wait_list.events & SUB_RETRY_RECV)) {
735 		if (check->server)
736 			HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
737 		else
738 			HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
739 		__event_srv_chk_r(cs);
740 		if (check->server)
741 			HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
742 		else
743 			HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
744 	}
745 	return NULL;
746 }
747 
748 /* same as above but protected by the server lock.
749  *
750  * Please do NOT place any return statement in this function and only leave
751  * via the out label. NOTE THAT THIS FUNCTION DOESN'T LOCK, YOU PROBABLY WANT
752  * TO USE event_srv_chk_w() instead.
753  */
__event_srv_chk_w(struct conn_stream * cs)754 static void __event_srv_chk_w(struct conn_stream *cs)
755 {
756 	struct connection *conn = cs->conn;
757 	struct check *check = cs->data;
758 	struct server *s = check->server;
759 	struct task *t = check->task;
760 
761 	if (unlikely(check->result == CHK_RES_FAILED))
762 		goto out_wakeup;
763 
764 	if (conn->flags & CO_FL_HANDSHAKE) {
765 		if (!(conn->flags & CO_FL_ERROR))
766 			cs->conn->mux->subscribe(cs, SUB_RETRY_SEND, &check->wait_list);
767 		goto out;
768 	}
769 
770 	if (retrieve_errno_from_socket(conn)) {
771 		chk_report_conn_err(check, errno, 0);
772 		goto out_wakeup;
773 	}
774 
775 	if (conn->flags & CO_FL_SOCK_WR_SH) {
776 		/* if the output is closed, we can't do anything */
777 		conn->flags |= CO_FL_ERROR;
778 		chk_report_conn_err(check, 0, 0);
779 		goto out_wakeup;
780 	}
781 
782 	/* here, we know that the connection is established. That's enough for
783 	 * a pure TCP check.
784 	 */
785 	if (!check->type)
786 		goto out_wakeup;
787 
788 	/* wake() will take care of calling tcpcheck_main() */
789 	if (check->type == PR_O2_TCPCHK_CHK)
790 		goto out;
791 
792 	if (b_data(&check->bo)) {
793 		cs->conn->mux->snd_buf(cs, &check->bo, b_data(&check->bo), 0);
794 		b_realign_if_empty(&check->bo);
795 		if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) {
796 			chk_report_conn_err(check, errno, 0);
797 			goto out_wakeup;
798 		}
799 		if (b_data(&check->bo)) {
800 			conn->mux->subscribe(cs, SUB_RETRY_SEND, &check->wait_list);
801 			goto out;
802 		}
803 	}
804 
805 	if (!b_data(&check->bo))
806 		conn_xprt_stop_send(conn);
807 
808 	/* full request sent, we allow up to <timeout.check> if nonzero for a response */
809 	if (s->proxy->timeout.check) {
810 		t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);
811 		task_queue(t);
812 	}
813 	goto out;
814 
815  out_wakeup:
816 	task_wakeup(t, TASK_WOKEN_IO);
817  out:
818 	return;
819 }
820 
821 /*
822  * This function is used only for server health-checks. It handles the server's
823  * reply to an HTTP request, SSL HELLO or MySQL client Auth. It calls
824  * set_server_check_status() to update check->status, check->duration
825  * and check->result.
826 
827  * The set_server_check_status function is called with HCHK_STATUS_L7OKD if
828  * an HTTP server replies HTTP 2xx or 3xx (valid responses), if an SMTP server
829  * returns 2xx, HCHK_STATUS_L6OK if an SSL server returns at least 5 bytes in
830  * response to an SSL HELLO (the principle is that this is enough to
831  * distinguish between an SSL server and a pure TCP relay). All other cases will
832  * call it with a proper error status like HCHK_STATUS_L7STS, HCHK_STATUS_L6RSP,
833  * etc.
834  *
835  * Please do NOT place any return statement in this function and only leave
836  * via the out label.
837  *
838  * This must be called with the server lock held.
839  */
__event_srv_chk_r(struct conn_stream * cs)840 static void __event_srv_chk_r(struct conn_stream *cs)
841 {
842 	struct connection *conn = cs->conn;
843 	struct check *check = cs->data;
844 	struct server *s = check->server;
845 	struct task *t = check->task;
846 	char *desc;
847 	int done;
848 
849 	if (unlikely(check->result == CHK_RES_FAILED))
850 		goto out_wakeup;
851 
852 	if (conn->flags & CO_FL_HANDSHAKE) {
853 		if (!(conn->flags & CO_FL_ERROR))
854 			cs->conn->mux->subscribe(cs, SUB_RETRY_RECV, &check->wait_list);
855 		goto out;
856 	}
857 
858 	/* wake() will take care of calling tcpcheck_main() */
859 	if (check->type == PR_O2_TCPCHK_CHK)
860 		goto out;
861 
862 	/* Warning! Linux returns EAGAIN on SO_ERROR if data are still available
863 	 * but the connection was closed on the remote end. Fortunately, recv still
864 	 * works correctly and we don't need to do the getsockopt() on linux.
865 	 */
866 
867 	/* Set buffer to point to the end of the data already read, and check
868 	 * that there is free space remaining. If the buffer is full, proceed
869 	 * with running the checks without attempting another socket read.
870 	 */
871 
872 	done = 0;
873 
874 	cs->conn->mux->rcv_buf(cs, &check->bi, b_size(&check->bi), 0);
875 	if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH) || cs->flags & CS_FL_ERROR) {
876 		done = 1;
877 		if ((conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) && !b_data(&check->bi)) {
878 			/* Report network errors only if we got no other data. Otherwise
879 			 * we'll let the upper layers decide whether the response is OK
880 			 * or not. It is very common that an RST sent by the server is
881 			 * reported as an error just after the last data chunk.
882 			 */
883 			chk_report_conn_err(check, errno, 0);
884 			goto out_wakeup;
885 		}
886 	}
887 
888 	/* the rest of the code below expects the connection to be ready! */
889 	if (!(conn->flags & CO_FL_CONNECTED) && !done)
890 		goto wait_more_data;
891 
892 	/* Intermediate or complete response received.
893 	 * Terminate string in b_head(&check->bi) buffer.
894 	 */
895 	if (b_data(&check->bi) < b_size(&check->bi))
896 		b_head(&check->bi)[b_data(&check->bi)] = '\0';
897 	else {
898 		b_head(&check->bi)[b_data(&check->bi) - 1] = '\0';
899 		done = 1; /* buffer full, don't wait for more data */
900 	}
901 
902 	/* Run the checks... */
903 	switch (check->type) {
904 	case PR_O2_HTTP_CHK:
905 		if (!done && b_data(&check->bi) < strlen("HTTP/1.0 000\r"))
906 			goto wait_more_data;
907 
908 		/* Check if the server speaks HTTP 1.X */
909 		if ((b_data(&check->bi) < strlen("HTTP/1.0 000\r")) ||
910 		    (memcmp(b_head(&check->bi), "HTTP/1.", 7) != 0 ||
911 		    (*(b_head(&check->bi) + 12) != ' ' && *(b_head(&check->bi) + 12) != '\r')) ||
912 		    !isdigit((unsigned char) *(b_head(&check->bi) + 9)) || !isdigit((unsigned char) *(b_head(&check->bi) + 10)) ||
913 		    !isdigit((unsigned char) *(b_head(&check->bi) + 11))) {
914 			cut_crlf(b_head(&check->bi));
915 			set_server_check_status(check, HCHK_STATUS_L7RSP, b_head(&check->bi));
916 
917 			goto out_wakeup;
918 		}
919 
920 		check->code = str2uic(b_head(&check->bi) + 9);
921 		desc = ltrim(b_head(&check->bi) + 12, ' ');
922 
923 		if ((s->proxy->options & PR_O_DISABLE404) &&
924 			 (s->next_state != SRV_ST_STOPPED) && (check->code == 404)) {
925 			/* 404 may be accepted as "stopping" only if the server was up */
926 			cut_crlf(desc);
927 			set_server_check_status(check, HCHK_STATUS_L7OKCD, desc);
928 		}
929 		else if (s->proxy->options2 & PR_O2_EXP_TYPE) {
930 			/* Run content verification check... We know we have at least 13 chars */
931 			if (!httpchk_expect(s, done))
932 				goto wait_more_data;
933 		}
934 		/* check the reply : HTTP/1.X 2xx and 3xx are OK */
935 		else if (*(b_head(&check->bi) + 9) == '2' || *(b_head(&check->bi) + 9) == '3') {
936 			cut_crlf(desc);
937 			set_server_check_status(check,  HCHK_STATUS_L7OKD, desc);
938 		}
939 		else {
940 			cut_crlf(desc);
941 			set_server_check_status(check, HCHK_STATUS_L7STS, desc);
942 		}
943 		break;
944 
945 	case PR_O2_SSL3_CHK:
946 		if (!done && b_data(&check->bi) < 5)
947 			goto wait_more_data;
948 
949 		/* Check for SSLv3 alert or handshake */
950 		if ((b_data(&check->bi) >= 5) && (*b_head(&check->bi) == 0x15 || *b_head(&check->bi) == 0x16))
951 			set_server_check_status(check, HCHK_STATUS_L6OK, NULL);
952 		else
953 			set_server_check_status(check, HCHK_STATUS_L6RSP, NULL);
954 		break;
955 
956 	case PR_O2_SMTP_CHK:
957 		if (!done && b_data(&check->bi) < strlen("000\r"))
958 			goto wait_more_data;
959 
960 		/* do not reset when closing, servers don't like this */
961 		if (conn_ctrl_ready(cs->conn))
962 			fdtab[cs->conn->handle.fd].linger_risk = 0;
963 
964 		/* Check if the server speaks SMTP */
965 		if ((b_data(&check->bi) < strlen("000\r")) ||
966 		    (*(b_head(&check->bi) + 3) != ' ' && *(b_head(&check->bi) + 3) != '\r') ||
967 		    !isdigit((unsigned char) *b_head(&check->bi)) || !isdigit((unsigned char) *(b_head(&check->bi) + 1)) ||
968 		    !isdigit((unsigned char) *(b_head(&check->bi) + 2))) {
969 			cut_crlf(b_head(&check->bi));
970 			set_server_check_status(check, HCHK_STATUS_L7RSP, b_head(&check->bi));
971 			goto out_wakeup;
972 		}
973 
974 		check->code = str2uic(b_head(&check->bi));
975 
976 		desc = ltrim(b_head(&check->bi) + 3, ' ');
977 		cut_crlf(desc);
978 
979 		/* Check for SMTP code 2xx (should be 250) */
980 		if (*b_head(&check->bi) == '2')
981 			set_server_check_status(check, HCHK_STATUS_L7OKD, desc);
982 		else
983 			set_server_check_status(check, HCHK_STATUS_L7STS, desc);
984 		break;
985 
986 	case PR_O2_LB_AGENT_CHK: {
987 		int status = HCHK_STATUS_CHECKED;
988 		const char *hs = NULL; /* health status      */
989 		const char *as = NULL; /* admin status */
990 		const char *ps = NULL; /* performance status */
991 		const char *cs = NULL; /* maxconn */
992 		const char *err = NULL; /* first error to report */
993 		const char *wrn = NULL; /* first warning to report */
994 		char *cmd, *p;
995 
996 		/* We're getting an agent check response. The agent could
997 		 * have been disabled in the mean time with a long check
998 		 * still pending. It is important that we ignore the whole
999 		 * response.
1000 		 */
1001 		if (!(check->server->agent.state & CHK_ST_ENABLED))
1002 			break;
1003 
1004 		/* The agent supports strings made of a single line ended by the
1005 		 * first CR ('\r') or LF ('\n'). This line is composed of words
1006 		 * delimited by spaces (' '), tabs ('\t'), or commas (','). The
1007 		 * line may optionally contained a description of a state change
1008 		 * after a sharp ('#'), which is only considered if a health state
1009 		 * is announced.
1010 		 *
1011 		 * Words may be composed of :
1012 		 *   - a numeric weight suffixed by the percent character ('%').
1013 		 *   - a health status among "up", "down", "stopped", and "fail".
1014 		 *   - an admin status among "ready", "drain", "maint".
1015 		 *
1016 		 * These words may appear in any order. If multiple words of the
1017 		 * same category appear, the last one wins.
1018 		 */
1019 
1020 		p = b_head(&check->bi);
1021 		while (*p && *p != '\n' && *p != '\r')
1022 			p++;
1023 
1024 		if (!*p) {
1025 			if (!done)
1026 				goto wait_more_data;
1027 
1028 			/* at least inform the admin that the agent is mis-behaving */
1029 			set_server_check_status(check, check->status, "Ignoring incomplete line from agent");
1030 			break;
1031 		}
1032 
1033 		*p = 0;
1034 		cmd = b_head(&check->bi);
1035 
1036 		while (*cmd) {
1037 			/* look for next word */
1038 			if (*cmd == ' ' || *cmd == '\t' || *cmd == ',') {
1039 				cmd++;
1040 				continue;
1041 			}
1042 
1043 			if (*cmd == '#') {
1044 				/* this is the beginning of a health status description,
1045 				 * skip the sharp and blanks.
1046 				 */
1047 				cmd++;
1048 				while (*cmd == '\t' || *cmd == ' ')
1049 					cmd++;
1050 				break;
1051 			}
1052 
1053 			/* find the end of the word so that we have a null-terminated
1054 			 * word between <cmd> and <p>.
1055 			 */
1056 			p = cmd + 1;
1057 			while (*p && *p != '\t' && *p != ' ' && *p != '\n' && *p != ',')
1058 				p++;
1059 			if (*p)
1060 				*p++ = 0;
1061 
1062 			/* first, health statuses */
1063 			if (strcasecmp(cmd, "up") == 0) {
1064 				check->health = check->rise + check->fall - 1;
1065 				status = HCHK_STATUS_L7OKD;
1066 				hs = cmd;
1067 			}
1068 			else if (strcasecmp(cmd, "down") == 0) {
1069 				check->health = 0;
1070 				status = HCHK_STATUS_L7STS;
1071 				hs = cmd;
1072 			}
1073 			else if (strcasecmp(cmd, "stopped") == 0) {
1074 				check->health = 0;
1075 				status = HCHK_STATUS_L7STS;
1076 				hs = cmd;
1077 			}
1078 			else if (strcasecmp(cmd, "fail") == 0) {
1079 				check->health = 0;
1080 				status = HCHK_STATUS_L7STS;
1081 				hs = cmd;
1082 			}
1083 			/* admin statuses */
1084 			else if (strcasecmp(cmd, "ready") == 0) {
1085 				as = cmd;
1086 			}
1087 			else if (strcasecmp(cmd, "drain") == 0) {
1088 				as = cmd;
1089 			}
1090 			else if (strcasecmp(cmd, "maint") == 0) {
1091 				as = cmd;
1092 			}
1093 			/* try to parse a weight here and keep the last one */
1094 			else if (isdigit((unsigned char)*cmd) && strchr(cmd, '%') != NULL) {
1095 				ps = cmd;
1096 			}
1097 			/* try to parse a maxconn here */
1098 			else if (strncasecmp(cmd, "maxconn:", strlen("maxconn:")) == 0) {
1099 				cs = cmd;
1100 			}
1101 			else {
1102 				/* keep a copy of the first error */
1103 				if (!err)
1104 					err = cmd;
1105 			}
1106 			/* skip to next word */
1107 			cmd = p;
1108 		}
1109 		/* here, cmd points either to \0 or to the beginning of a
1110 		 * description. Skip possible leading spaces.
1111 		 */
1112 		while (*cmd == ' ' || *cmd == '\n')
1113 			cmd++;
1114 
1115 		/* First, update the admin status so that we avoid sending other
1116 		 * possibly useless warnings and can also update the health if
1117 		 * present after going back up.
1118 		 */
1119 		if (as) {
1120 			if (strcasecmp(as, "drain") == 0)
1121 				srv_adm_set_drain(check->server);
1122 			else if (strcasecmp(as, "maint") == 0)
1123 				srv_adm_set_maint(check->server);
1124 			else
1125 				srv_adm_set_ready(check->server);
1126 		}
1127 
1128 		/* now change weights */
1129 		if (ps) {
1130 			const char *msg;
1131 
1132 			msg = server_parse_weight_change_request(s, ps);
1133 			if (!wrn || !*wrn)
1134 				wrn = msg;
1135 		}
1136 
1137 		if (cs) {
1138 			const char *msg;
1139 
1140 			cs += strlen("maxconn:");
1141 
1142 			msg = server_parse_maxconn_change_request(s, cs);
1143 			if (!wrn || !*wrn)
1144 				wrn = msg;
1145 		}
1146 
1147 		/* and finally health status */
1148 		if (hs) {
1149 			/* We'll report some of the warnings and errors we have
1150 			 * here. Down reports are critical, we leave them untouched.
1151 			 * Lack of report, or report of 'UP' leaves the room for
1152 			 * ERR first, then WARN.
1153 			 */
1154 			const char *msg = cmd;
1155 			struct buffer *t;
1156 
1157 			if (!*msg || status == HCHK_STATUS_L7OKD) {
1158 				if (err && *err)
1159 					msg = err;
1160 				else if (wrn && *wrn)
1161 					msg = wrn;
1162 			}
1163 
1164 			t = get_trash_chunk();
1165 			chunk_printf(t, "via agent : %s%s%s%s",
1166 				     hs, *msg ? " (" : "",
1167 				     msg, *msg ? ")" : "");
1168 
1169 			set_server_check_status(check, status, t->area);
1170 		}
1171 		else if (err && *err) {
1172 			/* No status change but we'd like to report something odd.
1173 			 * Just report the current state and copy the message.
1174 			 */
1175 			chunk_printf(&trash, "agent reports an error : %s", err);
1176 			set_server_check_status(check, status/*check->status*/,
1177                                                 trash.area);
1178 
1179 		}
1180 		else if (wrn && *wrn) {
1181 			/* No status change but we'd like to report something odd.
1182 			 * Just report the current state and copy the message.
1183 			 */
1184 			chunk_printf(&trash, "agent warns : %s", wrn);
1185 			set_server_check_status(check, status/*check->status*/,
1186                                                 trash.area);
1187 		}
1188 		else
1189 			set_server_check_status(check, status, NULL);
1190 		break;
1191 	}
1192 
1193 	case PR_O2_PGSQL_CHK:
1194 		if (!done && b_data(&check->bi) < 9)
1195 			goto wait_more_data;
1196 
1197 		/* do not reset when closing, servers don't like this */
1198 		if (conn_ctrl_ready(cs->conn))
1199 			fdtab[cs->conn->handle.fd].linger_risk = 0;
1200 
1201 		if (b_head(&check->bi)[0] == 'R') {
1202 			set_server_check_status(check, HCHK_STATUS_L7OKD, "PostgreSQL server is ok");
1203 		}
1204 		else {
1205 			if ((b_head(&check->bi)[0] == 'E') && (b_head(&check->bi)[5]!=0) && (b_head(&check->bi)[6]!=0))
1206 				desc = &b_head(&check->bi)[6];
1207 			else
1208 				desc = "PostgreSQL unknown error";
1209 
1210 			set_server_check_status(check, HCHK_STATUS_L7STS, desc);
1211 		}
1212 		break;
1213 
1214 	case PR_O2_REDIS_CHK:
1215 		if (!done && b_data(&check->bi) < 7)
1216 			goto wait_more_data;
1217 
1218 		if (strcmp(b_head(&check->bi), "+PONG\r\n") == 0) {
1219 			set_server_check_status(check, HCHK_STATUS_L7OKD, "Redis server is ok");
1220 		}
1221 		else {
1222 			set_server_check_status(check, HCHK_STATUS_L7STS, b_head(&check->bi));
1223 		}
1224 		break;
1225 
1226 	case PR_O2_MYSQL_CHK:
1227 		if (!done && b_data(&check->bi) < 5)
1228 			goto wait_more_data;
1229 
1230 		/* do not reset when closing, servers don't like this */
1231 		if (conn_ctrl_ready(cs->conn))
1232 			fdtab[cs->conn->handle.fd].linger_risk = 0;
1233 
1234 		if (s->proxy->check_len == 0) { // old mode
1235 			if (*(b_head(&check->bi) + 4) != '\xff') {
1236 				/* We set the MySQL Version in description for information purpose
1237 				 * FIXME : it can be cool to use MySQL Version for other purpose,
1238 				 * like mark as down old MySQL server.
1239 				 */
1240 				if (b_data(&check->bi) > 51) {
1241 					desc = ltrim(b_head(&check->bi) + 5, ' ');
1242 					set_server_check_status(check, HCHK_STATUS_L7OKD, desc);
1243 				}
1244 				else {
1245 					if (!done)
1246 						goto wait_more_data;
1247 
1248 					/* it seems we have a OK packet but without a valid length,
1249 					 * it must be a protocol error
1250 					 */
1251 					set_server_check_status(check, HCHK_STATUS_L7RSP, b_head(&check->bi));
1252 				}
1253 			}
1254 			else {
1255 				/* An error message is attached in the Error packet */
1256 				desc = ltrim(b_head(&check->bi) + 7, ' ');
1257 				set_server_check_status(check, HCHK_STATUS_L7STS, desc);
1258 			}
1259 		} else {
1260 			unsigned int first_packet_len = ((unsigned int) *b_head(&check->bi)) +
1261 			                                (((unsigned int) *(b_head(&check->bi) + 1)) << 8) +
1262 			                                (((unsigned int) *(b_head(&check->bi) + 2)) << 16);
1263 
1264 			if (b_data(&check->bi) == first_packet_len + 4) {
1265 				/* MySQL Error packet always begin with field_count = 0xff */
1266 				if (*(b_head(&check->bi) + 4) != '\xff') {
1267 					/* We have only one MySQL packet and it is a Handshake Initialization packet
1268 					* but we need to have a second packet to know if it is alright
1269 					*/
1270 					if (!done && b_data(&check->bi) < first_packet_len + 5)
1271 						goto wait_more_data;
1272 				}
1273 				else {
1274 					/* We have only one packet and it is an Error packet,
1275 					* an error message is attached, so we can display it
1276 					*/
1277 					desc = &b_head(&check->bi)[7];
1278 					//ha_warning("onlyoneERR: %s\n", desc);
1279 					set_server_check_status(check, HCHK_STATUS_L7STS, desc);
1280 				}
1281 			} else if (b_data(&check->bi) > first_packet_len + 4) {
1282 				unsigned int second_packet_len = ((unsigned int) *(b_head(&check->bi) + first_packet_len + 4)) +
1283 				                                 (((unsigned int) *(b_head(&check->bi) + first_packet_len + 5)) << 8) +
1284 				                                 (((unsigned int) *(b_head(&check->bi) + first_packet_len + 6)) << 16);
1285 
1286 				if (b_data(&check->bi) == first_packet_len + 4 + second_packet_len + 4 ) {
1287 					/* We have 2 packets and that's good */
1288 					/* Check if the second packet is a MySQL Error packet or not */
1289 					if (*(b_head(&check->bi) + first_packet_len + 8) != '\xff') {
1290 						/* No error packet */
1291 						/* We set the MySQL Version in description for information purpose */
1292 						desc = &b_head(&check->bi)[5];
1293 						//ha_warning("2packetOK: %s\n", desc);
1294 						set_server_check_status(check, HCHK_STATUS_L7OKD, desc);
1295 					}
1296 					else {
1297 						/* An error message is attached in the Error packet
1298 						* so we can display it ! :)
1299 						*/
1300 						desc = &b_head(&check->bi)[first_packet_len+11];
1301 						//ha_warning("2packetERR: %s\n", desc);
1302 						set_server_check_status(check, HCHK_STATUS_L7STS, desc);
1303 					}
1304 				}
1305 			}
1306 			else {
1307 				if (!done)
1308 					goto wait_more_data;
1309 
1310 				/* it seems we have a Handshake Initialization packet but without a valid length,
1311 				 * it must be a protocol error
1312 				 */
1313 				desc = &b_head(&check->bi)[5];
1314 				//ha_warning("protoerr: %s\n", desc);
1315 				set_server_check_status(check, HCHK_STATUS_L7RSP, desc);
1316 			}
1317 		}
1318 		break;
1319 
1320 	case PR_O2_LDAP_CHK: {
1321 		char *ptr;
1322 		unsigned short nbytes = 0;
1323 		size_t msglen = 0;
1324 
1325 		if (!done && b_data(&check->bi) < 14)
1326 			goto wait_more_data;
1327 
1328 		/* Check if the server speaks LDAP (ASN.1/BER)
1329 		 * http://en.wikipedia.org/wiki/Basic_Encoding_Rules
1330 		 * http://tools.ietf.org/html/rfc4511
1331 		 */
1332 
1333 		/* http://tools.ietf.org/html/rfc4511#section-4.1.1
1334 		 *   LDAPMessage: 0x30: SEQUENCE
1335 		 */
1336 		if ((b_data(&check->bi) < 14) || (*(b_head(&check->bi)) != '\x30')) {
1337 			set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
1338 			goto out_wakeup;
1339 		}
1340 
1341 		ptr = b_head(&check->bi) + 1;
1342 		if (*ptr & 0x80) {
1343 			/* For message size encoded on several bytes, we only handle
1344 			 * size encoded on 2 or 4 bytes. There is no reason to make this
1345 			 * part to complex because only Active Directory is known to
1346 			 * encode BindReponse length on 4 bytes.
1347 			 */
1348 			nbytes = (*ptr & 0x7f);
1349 			if (b_data(&check->bi) < 1 + nbytes) {
1350 				if (done) {
1351 					set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
1352 					goto out_wakeup;
1353 				}
1354 				goto wait_more_data;
1355 			}
1356 			switch (nbytes) {
1357 			case 4: msglen = read_n32(ptr+1); break;
1358 			case 2: msglen = read_n16(ptr+1); break;
1359 			default:
1360 				set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
1361 				goto out_wakeup;
1362 			}
1363 		}
1364 		else
1365 			msglen = *ptr;
1366 		ptr += 1 + nbytes;
1367 
1368 		if (b_data(&check->bi) < 2 + nbytes + msglen) {
1369 			if (done) {
1370 				set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
1371 				goto out_wakeup;
1372 			}
1373 			goto wait_more_data;
1374 		}
1375 
1376 		/* http://tools.ietf.org/html/rfc4511#section-4.2.2
1377 		 *   messageID: 0x02 0x01 0x01: INTEGER 1
1378 		 *   protocolOp: 0x61: bindResponse
1379 		 */
1380 		if (memcmp(ptr, "\x02\x01\x01\x61", 4) != 0) {
1381 			set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
1382 			goto out_wakeup;
1383 		}
1384 		ptr += 4;
1385 
1386 		/* skip size of bindResponse */
1387 		nbytes = 0;
1388 		if (*ptr & 0x80)
1389 			nbytes = (*ptr & 0x7f);
1390 		ptr += 1 + nbytes;
1391 
1392 		/* http://tools.ietf.org/html/rfc4511#section-4.1.9
1393 		 *   ldapResult: 0x0a 0x01: ENUMERATION
1394 		 */
1395 		if (memcmp(ptr, "\x0a\x01", 2) != 0) {
1396 			set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
1397 			goto out_wakeup;
1398 		}
1399 		ptr += 2;
1400 
1401 		/* http://tools.ietf.org/html/rfc4511#section-4.1.9
1402 		 *   resultCode
1403 		 */
1404 		check->code = *ptr;
1405 		if (check->code) {
1406 			set_server_check_status(check, HCHK_STATUS_L7STS, "See RFC: http://tools.ietf.org/html/rfc4511#section-4.1.9");
1407 		} else {
1408 			set_server_check_status(check, HCHK_STATUS_L7OKD, "Success");
1409 		}
1410 		break;
1411 	}
1412 
1413 	case PR_O2_SPOP_CHK: {
1414 		unsigned int framesz;
1415 		char	     err[HCHK_DESC_LEN];
1416 
1417 		if (!done && b_data(&check->bi) < 4)
1418 			goto wait_more_data;
1419 
1420 		memcpy(&framesz, b_head(&check->bi), 4);
1421 		framesz = ntohl(framesz);
1422 
1423 		if (!done && b_data(&check->bi) < (4+framesz))
1424 		    goto wait_more_data;
1425 
1426 		if (!spoe_handle_healthcheck_response(b_head(&check->bi)+4, framesz, err, HCHK_DESC_LEN-1))
1427 			set_server_check_status(check, HCHK_STATUS_L7OKD, "SPOA server is ok");
1428 		else
1429 			set_server_check_status(check, HCHK_STATUS_L7STS, err);
1430 		break;
1431 	}
1432 
1433 	default:
1434 		/* good connection is enough for pure TCP check */
1435 		if ((conn->flags & CO_FL_CONNECTED) && !check->type) {
1436 			if (check->use_ssl == 1)
1437 				set_server_check_status(check, HCHK_STATUS_L6OK, NULL);
1438 			else
1439 				set_server_check_status(check, HCHK_STATUS_L4OK, NULL);
1440 		}
1441 		break;
1442 	} /* switch */
1443 
1444  out_wakeup:
1445 	/* collect possible new errors */
1446 	if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
1447 		chk_report_conn_err(check, 0, 0);
1448 
1449 	/* Reset the check buffer... */
1450 	*b_head(&check->bi) = '\0';
1451 	b_reset(&check->bi);
1452 
1453 	/* Close the connection... We still attempt to nicely close if,
1454 	 * for instance, SSL needs to send a "close notify." Later, we perform
1455 	 * a hard close and reset the connection if some data are pending,
1456 	 * otherwise we end up with many TIME_WAITs and eat all the source port
1457 	 * range quickly.  To avoid sending RSTs all the time, we first try to
1458 	 * drain pending data.
1459 	 */
1460 	/* Call cs_shutr() first, to add the CO_FL_SOCK_RD_SH flag on the
1461 	 * connection, to make sure cs_shutw() will not lead to a shutdown()
1462 	 * that would provoke TIME_WAITs.
1463 	 */
1464 	cs_shutr(cs, CS_SHR_DRAIN);
1465 	cs_shutw(cs, CS_SHW_NORMAL);
1466 
1467 	/* OK, let's not stay here forever */
1468 	if (check->result == CHK_RES_FAILED)
1469 		conn->flags |= CO_FL_ERROR;
1470 
1471 	task_wakeup(t, TASK_WOKEN_IO);
1472 out:
1473 	return;
1474 
1475  wait_more_data:
1476 	cs->conn->mux->subscribe(cs, SUB_RETRY_RECV, &check->wait_list);
1477         goto out;
1478 }
1479 
1480 /*
1481  * This function is used only for server health-checks. It handles connection
1482  * status updates including errors. If necessary, it wakes the check task up.
1483  * It returns 0 on normal cases, <0 if at least one close() has happened on the
1484  * connection (eg: reconnect).
1485  */
wake_srv_chk(struct conn_stream * cs)1486 static int wake_srv_chk(struct conn_stream *cs)
1487 {
1488 	struct connection *conn = cs->conn;
1489 	struct check *check = cs->data;
1490 	struct email_alertq *q = container_of(check, typeof(*q), check);
1491 	int ret = 0;
1492 
1493 	if (check->server)
1494 		HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
1495 	else
1496 		HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
1497 
1498 	/* we may have to make progress on the TCP checks */
1499 	if (check->type == PR_O2_TCPCHK_CHK) {
1500 		ret = tcpcheck_main(check);
1501 		cs = check->cs;
1502 		conn = cs->conn;
1503 	} else {
1504 		if (!(check->wait_list.events & SUB_RETRY_SEND))
1505 			__event_srv_chk_w(cs);
1506 		if (!(check->wait_list.events & SUB_RETRY_RECV))
1507 			__event_srv_chk_r(cs);
1508 	}
1509 
1510 	if (unlikely(conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)) {
1511 		/* We may get error reports bypassing the I/O handlers, typically
1512 		 * the case when sending a pure TCP check which fails, then the I/O
1513 		 * handlers above are not called. This is completely handled by the
1514 		 * main processing task so let's simply wake it up. If we get here,
1515 		 * we expect errno to still be valid.
1516 		 */
1517 		chk_report_conn_err(check, errno, 0);
1518 		task_wakeup(check->task, TASK_WOKEN_IO);
1519 	}
1520 	else if (!(conn->flags & CO_FL_HANDSHAKE) && !check->type) {
1521 		/* we may get here if only a connection probe was required : we
1522 		 * don't have any data to send nor anything expected in response,
1523 		 * so the completion of the connection establishment is enough.
1524 		 */
1525 		task_wakeup(check->task, TASK_WOKEN_IO);
1526 	}
1527 
1528 	if (check->result != CHK_RES_UNKNOWN) {
1529 		/* Check complete or aborted. If connection not yet closed do it
1530 		 * now and wake the check task up to be sure the result is
1531 		 * handled ASAP. */
1532 		conn_sock_drain(conn);
1533 		cs_close(cs);
1534 		ret = -1;
1535 		/* We may have been scheduled to run, and the
1536 		 * I/O handler expects to have a cs, so remove
1537 		 * the tasklet
1538 		 */
1539 		tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
1540 		task_wakeup(check->task, TASK_WOKEN_IO);
1541 	}
1542 
1543 	if (check->server)
1544 		HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
1545 	else
1546 		HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
1547 
1548 	/* if a connection got replaced, we must absolutely prevent the connection
1549 	 * handler from touching its fd, and perform the FD polling updates ourselves
1550 	 */
1551 	if (ret < 0)
1552 		conn_cond_update_polling(conn);
1553 
1554 	return ret;
1555 }
1556 
1557 struct data_cb check_conn_cb = {
1558 	.wake = wake_srv_chk,
1559 	.name = "CHCK",
1560 };
1561 
1562 /*
1563  * updates the server's weight during a warmup stage. Once the final weight is
1564  * reached, the task automatically stops. Note that any server status change
1565  * must have updated s->last_change accordingly.
1566  */
server_warmup(struct task * t,void * context,unsigned short state)1567 static struct task *server_warmup(struct task *t, void *context, unsigned short state)
1568 {
1569 	struct server *s = context;
1570 
1571 	/* by default, plan on stopping the task */
1572 	t->expire = TICK_ETERNITY;
1573 	if ((s->next_admin & SRV_ADMF_MAINT) ||
1574 	    (s->next_state != SRV_ST_STARTING))
1575 		return t;
1576 
1577 	HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
1578 
1579 	/* recalculate the weights and update the state */
1580 	server_recalc_eweight(s, 1);
1581 
1582 	/* probably that we can refill this server with a bit more connections */
1583 	pendconn_grab_from_px(s);
1584 
1585 	HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);
1586 
1587 	/* get back there in 1 second or 1/20th of the slowstart interval,
1588 	 * whichever is greater, resulting in small 5% steps.
1589 	 */
1590 	if (s->next_state == SRV_ST_STARTING)
1591 		t->expire = tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20)));
1592 	return t;
1593 }
1594 
1595 /* returns the first NON-COMMENT tcp-check rule from list <list> or NULL if
1596  * none was found.
1597  */
get_first_tcpcheck_rule(struct list * list)1598 static struct tcpcheck_rule *get_first_tcpcheck_rule(struct list *list)
1599 {
1600 	struct tcpcheck_rule *r;
1601 
1602 	list_for_each_entry(r, list, list) {
1603 		if (r->action != TCPCHK_ACT_COMMENT)
1604 			return r;
1605 	}
1606 	return NULL;
1607 }
1608 
1609 /*
1610  * establish a server health-check that makes use of a connection.
1611  *
1612  * It can return one of :
1613  *  - SF_ERR_NONE if everything's OK and tcpcheck_main() was not called
1614  *  - SF_ERR_UP if if everything's OK and tcpcheck_main() was called
1615  *  - SF_ERR_SRVTO if there are no more servers
1616  *  - SF_ERR_SRVCL if the connection was refused by the server
1617  *  - SF_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
1618  *  - SF_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
1619  *  - SF_ERR_INTERNAL for any other purely internal errors
1620  *  - SF_ERR_CHK_PORT if no port could be found to run a health check on an AF_INET* socket
1621  * Additionally, in the case of SF_ERR_RESOURCE, an emergency log will be emitted.
1622  * Note that we try to prevent the network stack from sending the ACK during the
1623  * connect() when a pure TCP check is used (without PROXY protocol).
1624  */
connect_conn_chk(struct task * t)1625 static int connect_conn_chk(struct task *t)
1626 {
1627 	struct check *check = t->context;
1628 	struct server *s = check->server;
1629 	struct conn_stream *cs = check->cs;
1630 	struct connection *conn = cs_conn(cs);
1631 	struct protocol *proto;
1632 	struct tcpcheck_rule *tcp_rule = NULL;
1633 	int ret;
1634 	int connflags = 0;
1635 
1636 	/* we cannot have a connection here */
1637 	if (conn)
1638 		return SF_ERR_INTERNAL;
1639 
1640 	/* tcpcheck send/expect initialisation */
1641 	if (check->type == PR_O2_TCPCHK_CHK) {
1642 		check->current_step = NULL;
1643 		tcp_rule = get_first_tcpcheck_rule(check->tcpcheck_rules);
1644 	}
1645 
1646 	/* prepare the check buffer.
1647 	 * This should not be used if check is the secondary agent check
1648 	 * of a server as s->proxy->check_req will relate to the
1649 	 * configuration of the primary check. Similarly, tcp-check uses
1650 	 * its own strings.
1651 	 */
1652 	if (check->type && check->type != PR_O2_TCPCHK_CHK && !(check->state & CHK_ST_AGENT)) {
1653 		b_putblk(&check->bo, s->proxy->check_req, s->proxy->check_len);
1654 
1655 		/* we want to check if this host replies to HTTP or SSLv3 requests
1656 		 * so we'll send the request, and won't wake the checker up now.
1657 		 */
1658 		if ((check->type) == PR_O2_SSL3_CHK) {
1659 			/* SSL requires that we put Unix time in the request */
1660 			int gmt_time = htonl(date.tv_sec);
1661 			memcpy(b_head(&check->bo) + 11, &gmt_time, 4);
1662 		}
1663 		else if ((check->type) == PR_O2_HTTP_CHK) {
1664 			/* prevent HTTP keep-alive when "http-check expect" is used */
1665 			if (s->proxy->options2 & PR_O2_EXP_TYPE)
1666 				b_putist(&check->bo, ist("Connection: close\r\n"));
1667 
1668 			/* If there is a body, add its content-length */
1669 			if (s->proxy->check_body_len)
1670 				chunk_appendf(&check->bo, "Content-Length: %s\r\n", ultoa(s->proxy->check_body_len));
1671 
1672 			/* Add configured headers */
1673 			if (s->proxy->check_hdrs)
1674 				b_putblk(&check->bo, s->proxy->check_hdrs, s->proxy->check_hdrs_len);
1675 
1676 			/* Add send-state header */
1677 			if (s->proxy->options2 & PR_O2_CHK_SNDST)
1678 				b_putblk(&check->bo, trash.area,
1679 					 httpchk_build_status_header(s, trash.area, trash.size));
1680 
1681 			/* end-of-header */
1682 			b_putist(&check->bo, ist("\r\n"));
1683 
1684 			/* Add the body */
1685 			if (s->proxy->check_body)
1686 				b_putblk(&check->bo, s->proxy->check_body, s->proxy->check_body_len);
1687 
1688 			*b_tail(&check->bo) = '\0'; /* to make gdb output easier to read */
1689 		}
1690 	}
1691 
1692 	if ((check->type & PR_O2_LB_AGENT_CHK) && check->send_string_len) {
1693 		b_putblk(&check->bo, check->send_string, check->send_string_len);
1694 	}
1695 
1696 	/* for tcp-checks, the initial connection setup is handled separately as
1697 	 * it may be sent to a specific port and not to the server's.
1698 	 */
1699 	if (tcp_rule && tcp_rule->action == TCPCHK_ACT_CONNECT) {
1700 		tcpcheck_main(check);
1701 		return SF_ERR_UP;
1702 	}
1703 
1704 	/* prepare a new connection */
1705 	cs = check->cs = cs_new(NULL);
1706 	if (!check->cs)
1707 		return SF_ERR_RESOURCE;
1708 	conn = cs->conn;
1709 	/* Maybe there were an older connection we were waiting on */
1710 	check->wait_list.events = 0;
1711 
1712 	if (is_addr(&check->addr)) {
1713 		/* we'll connect to the check addr specified on the server */
1714 		conn->addr.to = check->addr;
1715 	}
1716 	else {
1717 		/* we'll connect to the addr on the server */
1718 		conn->addr.to = s->addr;
1719 	}
1720 
1721 	if (s->check.via_socks4 &&  (s->flags & SRV_F_SOCKS4_PROXY)) {
1722 		conn->send_proxy_ofs = 1;
1723 		conn->flags |= CO_FL_SOCKS4;
1724 	}
1725 
1726 	proto = protocol_by_family(conn->addr.to.ss_family);
1727 	conn->target = &s->obj_type;
1728 
1729 	if ((conn->addr.to.ss_family == AF_INET) || (conn->addr.to.ss_family == AF_INET6)) {
1730 		int i = 0;
1731 
1732 		i = srv_check_healthcheck_port(check);
1733 		if (i == 0)
1734 			return SF_ERR_CHK_PORT;
1735 
1736 		set_host_port(&conn->addr.to, i);
1737 	}
1738 
1739 	/* no client address */
1740 	clear_addr(&conn->addr.from);
1741 
1742 	conn_prepare(conn, proto, check->xprt);
1743 	if (conn_install_mux(conn, &mux_pt_ops, cs, s->proxy, NULL) < 0)
1744 		return SF_ERR_RESOURCE;
1745 	cs_attach(cs, check, &check_conn_cb);
1746 
1747 	/* only plain tcp-check supports quick ACK */
1748 	if (check->type != 0)
1749 		connflags |= CONNECT_HAS_DATA;
1750 	if ((check->type == 0 || check->type == PR_O2_TCPCHK_CHK) &&
1751 	    (!tcp_rule || tcp_rule->action != TCPCHK_ACT_EXPECT))
1752 		connflags |= CONNECT_DELACK_ALWAYS;
1753 
1754 	ret = SF_ERR_INTERNAL;
1755 	if (proto && proto->connect)
1756 		ret = proto->connect(conn, connflags);
1757 
1758 
1759 #ifdef USE_OPENSSL
1760 	if (ret == SF_ERR_NONE) {
1761 		if (s->check.sni)
1762 			ssl_sock_set_servername(conn, s->check.sni);
1763 		if (s->check.alpn_str)
1764 			ssl_sock_set_alpn(conn, (unsigned char *)s->check.alpn_str,
1765 			    s->check.alpn_len);
1766 	}
1767 #endif
1768 	if (s->check.send_proxy && !(check->state & CHK_ST_AGENT)) {
1769 		conn->send_proxy_ofs = 1;
1770 		conn->flags |= CO_FL_SEND_PROXY;
1771 	}
1772 	if (conn->flags & (CO_FL_SEND_PROXY | CO_FL_SOCKS4) &&
1773 	    conn_ctrl_ready(conn)) {
1774 		if (xprt_add_hs(conn) < 0)
1775 			ret = SF_ERR_RESOURCE;
1776 	}
1777 
1778 	return ret;
1779 }
1780 
1781 static struct list pid_list = LIST_HEAD_INIT(pid_list);
1782 static struct pool_head *pool_head_pid_list;
1783 __decl_spinlock(pid_list_lock);
1784 
block_sigchld(void)1785 void block_sigchld(void)
1786 {
1787 	sigset_t set;
1788 	sigemptyset(&set);
1789 	sigaddset(&set, SIGCHLD);
1790 	assert(ha_sigmask(SIG_BLOCK, &set, NULL) == 0);
1791 }
1792 
unblock_sigchld(void)1793 void unblock_sigchld(void)
1794 {
1795 	sigset_t set;
1796 	sigemptyset(&set);
1797 	sigaddset(&set, SIGCHLD);
1798 	assert(ha_sigmask(SIG_UNBLOCK, &set, NULL) == 0);
1799 }
1800 
pid_list_add(pid_t pid,struct task * t)1801 static struct pid_list *pid_list_add(pid_t pid, struct task *t)
1802 {
1803 	struct pid_list *elem;
1804 	struct check *check = t->context;
1805 
1806 	elem = pool_alloc(pool_head_pid_list);
1807 	if (!elem)
1808 		return NULL;
1809 	elem->pid = pid;
1810 	elem->t = t;
1811 	elem->exited = 0;
1812 	check->curpid = elem;
1813 	LIST_INIT(&elem->list);
1814 
1815 	HA_SPIN_LOCK(PID_LIST_LOCK, &pid_list_lock);
1816 	LIST_ADD(&pid_list, &elem->list);
1817 	HA_SPIN_UNLOCK(PID_LIST_LOCK, &pid_list_lock);
1818 
1819 	return elem;
1820 }
1821 
pid_list_del(struct pid_list * elem)1822 static void pid_list_del(struct pid_list *elem)
1823 {
1824 	struct check *check;
1825 
1826 	if (!elem)
1827 		return;
1828 
1829 	HA_SPIN_LOCK(PID_LIST_LOCK, &pid_list_lock);
1830 	LIST_DEL(&elem->list);
1831 	HA_SPIN_UNLOCK(PID_LIST_LOCK, &pid_list_lock);
1832 
1833 	if (!elem->exited)
1834 		kill(elem->pid, SIGTERM);
1835 
1836 	check = elem->t->context;
1837 	check->curpid = NULL;
1838 	pool_free(pool_head_pid_list, elem);
1839 }
1840 
1841 /* Called from inside SIGCHLD handler, SIGCHLD is blocked */
pid_list_expire(pid_t pid,int status)1842 static void pid_list_expire(pid_t pid, int status)
1843 {
1844 	struct pid_list *elem;
1845 
1846 	HA_SPIN_LOCK(PID_LIST_LOCK, &pid_list_lock);
1847 	list_for_each_entry(elem, &pid_list, list) {
1848 		if (elem->pid == pid) {
1849 			elem->t->expire = now_ms;
1850 			elem->status = status;
1851 			elem->exited = 1;
1852 			task_wakeup(elem->t, TASK_WOKEN_IO);
1853 			break;
1854 		}
1855 	}
1856 	HA_SPIN_UNLOCK(PID_LIST_LOCK, &pid_list_lock);
1857 }
1858 
sigchld_handler(struct sig_handler * sh)1859 static void sigchld_handler(struct sig_handler *sh)
1860 {
1861 	pid_t pid;
1862 	int status;
1863 
1864 	while ((pid = waitpid(0, &status, WNOHANG)) > 0)
1865 		pid_list_expire(pid, status);
1866 }
1867 
init_pid_list(void)1868 static int init_pid_list(void)
1869 {
1870 	if (pool_head_pid_list != NULL)
1871 		/* Nothing to do */
1872 		return 0;
1873 
1874 	if (!signal_register_fct(SIGCHLD, sigchld_handler, SIGCHLD)) {
1875 		ha_alert("Failed to set signal handler for external health checks: %s. Aborting.\n",
1876 			 strerror(errno));
1877 		return 1;
1878 	}
1879 
1880 	pool_head_pid_list = create_pool("pid_list", sizeof(struct pid_list), MEM_F_SHARED);
1881 	if (pool_head_pid_list == NULL) {
1882 		ha_alert("Failed to allocate memory pool for external health checks: %s. Aborting.\n",
1883 			 strerror(errno));
1884 		return 1;
1885 	}
1886 
1887 	return 0;
1888 }
1889 
1890 /* helper macro to set an environment variable and jump to a specific label on failure. */
1891 #define EXTCHK_SETENV(check, envidx, value, fail) { if (extchk_setenv(check, envidx, value)) goto fail; }
1892 
1893 /*
1894  * helper function to allocate enough memory to store an environment variable.
1895  * It will also check that the environment variable is updatable, and silently
1896  * fail if not.
1897  */
extchk_setenv(struct check * check,int idx,const char * value)1898 static int extchk_setenv(struct check *check, int idx, const char *value)
1899 {
1900 	int len, ret;
1901 	char *envname;
1902 	int vmaxlen;
1903 
1904 	if (idx < 0 || idx >= EXTCHK_SIZE) {
1905 		ha_alert("Illegal environment variable index %d. Aborting.\n", idx);
1906 		return 1;
1907 	}
1908 
1909 	envname = extcheck_envs[idx].name;
1910 	vmaxlen = extcheck_envs[idx].vmaxlen;
1911 
1912 	/* Check if the environment variable is already set, and silently reject
1913 	 * the update if this one is not updatable. */
1914 	if ((vmaxlen == EXTCHK_SIZE_EVAL_INIT) && (check->envp[idx]))
1915 		return 0;
1916 
1917 	/* Instead of sending NOT_USED, sending an empty value is preferable */
1918 	if (strcmp(value, "NOT_USED") == 0) {
1919 		value = "";
1920 	}
1921 
1922 	len = strlen(envname) + 1;
1923 	if (vmaxlen == EXTCHK_SIZE_EVAL_INIT)
1924 		len += strlen(value);
1925 	else
1926 		len += vmaxlen;
1927 
1928 	if (!check->envp[idx])
1929 		check->envp[idx] = malloc(len + 1);
1930 
1931 	if (!check->envp[idx]) {
1932 		ha_alert("Failed to allocate memory for the environment variable '%s'. Aborting.\n", envname);
1933 		return 1;
1934 	}
1935 	ret = snprintf(check->envp[idx], len + 1, "%s=%s", envname, value);
1936 	if (ret < 0) {
1937 		ha_alert("Failed to store the environment variable '%s'. Reason : %s. Aborting.\n", envname, strerror(errno));
1938 		return 1;
1939 	}
1940 	else if (ret > len) {
1941 		ha_alert("Environment variable '%s' was truncated. Aborting.\n", envname);
1942 		return 1;
1943 	}
1944 	return 0;
1945 }
1946 
prepare_external_check(struct check * check)1947 static int prepare_external_check(struct check *check)
1948 {
1949 	struct server *s = check->server;
1950 	struct proxy *px = s->proxy;
1951 	struct listener *listener = NULL, *l;
1952 	int i;
1953 	const char *path = px->check_path ? px->check_path : DEF_CHECK_PATH;
1954 	char buf[256];
1955 
1956 	list_for_each_entry(l, &px->conf.listeners, by_fe)
1957 		/* Use the first INET, INET6 or UNIX listener */
1958 		if (l->addr.ss_family == AF_INET ||
1959 		    l->addr.ss_family == AF_INET6 ||
1960 		    l->addr.ss_family == AF_UNIX) {
1961 			listener = l;
1962 			break;
1963 		}
1964 
1965 	check->curpid = NULL;
1966 	check->envp = calloc((EXTCHK_SIZE + 1), sizeof(char *));
1967 	if (!check->envp) {
1968 		ha_alert("Failed to allocate memory for environment variables. Aborting\n");
1969 		goto err;
1970 	}
1971 
1972 	check->argv = calloc(6, sizeof(char *));
1973 	if (!check->argv) {
1974 		ha_alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
1975 		goto err;
1976 	}
1977 
1978 	check->argv[0] = px->check_command;
1979 
1980 	if (!listener) {
1981 		check->argv[1] = strdup("NOT_USED");
1982 		check->argv[2] = strdup("NOT_USED");
1983 	}
1984 	else if (listener->addr.ss_family == AF_INET ||
1985 	    listener->addr.ss_family == AF_INET6) {
1986 		addr_to_str(&listener->addr, buf, sizeof(buf));
1987 		check->argv[1] = strdup(buf);
1988 		port_to_str(&listener->addr, buf, sizeof(buf));
1989 		check->argv[2] = strdup(buf);
1990 	}
1991 	else if (listener->addr.ss_family == AF_UNIX) {
1992 		const struct sockaddr_un *un;
1993 
1994 		un = (struct sockaddr_un *)&listener->addr;
1995 		check->argv[1] = strdup(un->sun_path);
1996 		check->argv[2] = strdup("NOT_USED");
1997 	}
1998 	else {
1999 		ha_alert("Starting [%s:%s] check: unsupported address family.\n", px->id, s->id);
2000 		goto err;
2001 	}
2002 
2003 	if (!check->argv[1] || !check->argv[2]) {
2004 		ha_alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
2005 		goto err;
2006 	}
2007 
2008 	check->argv[3] = calloc(EXTCHK_SIZE_ADDR, sizeof(*check->argv[3]));
2009 	check->argv[4] = calloc(EXTCHK_SIZE_UINT, sizeof(*check->argv[4]));
2010 	if (!check->argv[3] || !check->argv[4]) {
2011 		ha_alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
2012 		goto err;
2013 	}
2014 
2015 	addr_to_str(&s->addr, check->argv[3], EXTCHK_SIZE_ADDR);
2016 	if (s->addr.ss_family == AF_INET || s->addr.ss_family == AF_INET6)
2017 		snprintf(check->argv[4], EXTCHK_SIZE_UINT, "%u", s->svc_port);
2018 
2019 	for (i = 0; i < 5; i++) {
2020 		if (!check->argv[i]) {
2021 			ha_alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
2022 			goto err;
2023 		}
2024 	}
2025 
2026 	EXTCHK_SETENV(check, EXTCHK_PATH, path, err);
2027 	/* Add proxy environment variables */
2028 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_PROXY_NAME, px->id, err);
2029 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_PROXY_ID, ultoa_r(px->uuid, buf, sizeof(buf)), err);
2030 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_PROXY_ADDR, check->argv[1], err);
2031 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_PROXY_PORT, check->argv[2], err);
2032 	/* Add server environment variables */
2033 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_NAME, s->id, err);
2034 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_ID, ultoa_r(s->puid, buf, sizeof(buf)), err);
2035 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_ADDR, check->argv[3], err);
2036 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_PORT, check->argv[4], err);
2037 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_MAXCONN, ultoa_r(s->maxconn, buf, sizeof(buf)), err);
2038 	EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->cur_sess, buf, sizeof(buf)), err);
2039 
2040 	/* Ensure that we don't leave any hole in check->envp */
2041 	for (i = 0; i < EXTCHK_SIZE; i++)
2042 		if (!check->envp[i])
2043 			EXTCHK_SETENV(check, i, "", err);
2044 
2045 	return 1;
2046 err:
2047 	if (check->envp) {
2048 		for (i = 0; i < EXTCHK_SIZE; i++)
2049 			free(check->envp[i]);
2050 		free(check->envp);
2051 		check->envp = NULL;
2052 	}
2053 
2054 	if (check->argv) {
2055 		for (i = 1; i < 5; i++)
2056 			free(check->argv[i]);
2057 		free(check->argv);
2058 		check->argv = NULL;
2059 	}
2060 	return 0;
2061 }
2062 
2063 /*
2064  * establish a server health-check that makes use of a process.
2065  *
2066  * It can return one of :
2067  *  - SF_ERR_NONE if everything's OK
2068  *  - SF_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
2069  * Additionally, in the case of SF_ERR_RESOURCE, an emergency log will be emitted.
2070  *
2071  * Blocks and then unblocks SIGCHLD
2072  */
connect_proc_chk(struct task * t)2073 static int connect_proc_chk(struct task *t)
2074 {
2075 	char buf[256];
2076 	struct check *check = t->context;
2077 	struct server *s = check->server;
2078 	struct proxy *px = s->proxy;
2079 	int status;
2080 	pid_t pid;
2081 
2082 	status = SF_ERR_RESOURCE;
2083 
2084 	block_sigchld();
2085 
2086 	pid = fork();
2087 	if (pid < 0) {
2088 		ha_alert("Failed to fork process for external health check: %s. Aborting.\n",
2089 			 strerror(errno));
2090 		set_server_check_status(check, HCHK_STATUS_SOCKERR, strerror(errno));
2091 		goto out;
2092 	}
2093 	if (pid == 0) {
2094 		/* Child */
2095 		extern char **environ;
2096 		struct rlimit limit;
2097 		int fd;
2098 
2099 		/* close all FDs. Keep stdin/stdout/stderr in verbose mode */
2100 		fd = (global.mode & (MODE_QUIET|MODE_VERBOSE)) == MODE_QUIET ? 0 : 3;
2101 
2102 		my_closefrom(fd);
2103 
2104 		/* restore the initial FD limits */
2105 		limit.rlim_cur = rlim_fd_cur_at_boot;
2106 		limit.rlim_max = rlim_fd_max_at_boot;
2107 		if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
2108 			getrlimit(RLIMIT_NOFILE, &limit);
2109 			ha_warning("External check: failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
2110 				   rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
2111 				   (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
2112 		}
2113 
2114 		environ = check->envp;
2115 
2116 		/* Update some environment variables and command args: curconn, server addr and server port */
2117 		EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->cur_sess, buf, sizeof(buf)), fail);
2118 
2119 		addr_to_str(&s->addr, check->argv[3], EXTCHK_SIZE_ADDR);
2120 		EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_ADDR, check->argv[3], fail);
2121 
2122 		*check->argv[4] = 0;
2123 		if (s->addr.ss_family == AF_INET || s->addr.ss_family == AF_INET6)
2124 			snprintf(check->argv[4], EXTCHK_SIZE_UINT, "%u", s->svc_port);
2125 		EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_PORT, check->argv[4], fail);
2126 
2127 		haproxy_unblock_signals();
2128 		execvp(px->check_command, check->argv);
2129 		ha_alert("Failed to exec process for external health check: %s. Aborting.\n",
2130 			 strerror(errno));
2131 	fail:
2132 		exit(-1);
2133 	}
2134 
2135 	/* Parent */
2136 	if (check->result == CHK_RES_UNKNOWN) {
2137 		if (pid_list_add(pid, t) != NULL) {
2138 			t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
2139 
2140 			if (px->timeout.check && px->timeout.connect) {
2141 				int t_con = tick_add(now_ms, px->timeout.connect);
2142 				t->expire = tick_first(t->expire, t_con);
2143 			}
2144 			status = SF_ERR_NONE;
2145 			goto out;
2146 		}
2147 		else {
2148 			set_server_check_status(check, HCHK_STATUS_SOCKERR, strerror(errno));
2149 		}
2150 		kill(pid, SIGTERM); /* process creation error */
2151 	}
2152 	else
2153 		set_server_check_status(check, HCHK_STATUS_SOCKERR, strerror(errno));
2154 
2155 out:
2156 	unblock_sigchld();
2157 	return status;
2158 }
2159 
2160 /*
2161  * manages a server health-check that uses an external process. Returns
2162  * the time the task accepts to wait, or TIME_ETERNITY for infinity.
2163  *
2164  * Please do NOT place any return statement in this function and only leave
2165  * via the out_unlock label.
2166  */
process_chk_proc(struct task * t,void * context,unsigned short state)2167 static struct task *process_chk_proc(struct task *t, void *context, unsigned short state)
2168 {
2169 	struct check *check = context;
2170 	struct server *s = check->server;
2171 	int rv;
2172 	int ret;
2173 	int expired = tick_is_expired(t->expire, now_ms);
2174 
2175 	HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
2176 	if (!(check->state & CHK_ST_INPROGRESS)) {
2177 		/* no check currently running */
2178 		if (!expired) /* woke up too early */
2179 			goto out_unlock;
2180 
2181 		/* we don't send any health-checks when the proxy is
2182 		 * stopped, the server should not be checked or the check
2183 		 * is disabled.
2184 		 */
2185 		if (((check->state & (CHK_ST_ENABLED | CHK_ST_PAUSED)) != CHK_ST_ENABLED) ||
2186 		    s->proxy->state == PR_STSTOPPED)
2187 			goto reschedule;
2188 
2189 		/* we'll initiate a new check */
2190 		set_server_check_status(check, HCHK_STATUS_START, NULL);
2191 
2192 		check->state |= CHK_ST_INPROGRESS;
2193 
2194 		ret = connect_proc_chk(t);
2195 		if (ret == SF_ERR_NONE) {
2196 			/* the process was forked, we allow up to min(inter,
2197 			 * timeout.connect) for it to report its status, but
2198 			 * only when timeout.check is set as it may be to short
2199 			 * for a full check otherwise.
2200 			 */
2201 			t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
2202 
2203 			if (s->proxy->timeout.check && s->proxy->timeout.connect) {
2204 				int t_con = tick_add(now_ms, s->proxy->timeout.connect);
2205 				t->expire = tick_first(t->expire, t_con);
2206 			}
2207 			task_set_affinity(t, tid_bit);
2208 			goto reschedule;
2209 		}
2210 
2211 		/* here, we failed to start the check */
2212 
2213 		check->state &= ~CHK_ST_INPROGRESS;
2214 		check_notify_failure(check);
2215 
2216 		/* we allow up to min(inter, timeout.connect) for a connection
2217 		 * to establish but only when timeout.check is set
2218 		 * as it may be to short for a full check otherwise
2219 		 */
2220 		while (tick_is_expired(t->expire, now_ms)) {
2221 			int t_con;
2222 
2223 			t_con = tick_add(t->expire, s->proxy->timeout.connect);
2224 			t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
2225 
2226 			if (s->proxy->timeout.check)
2227 				t->expire = tick_first(t->expire, t_con);
2228 		}
2229 	}
2230 	else {
2231 		/* there was a test running.
2232 		 * First, let's check whether there was an uncaught error,
2233 		 * which can happen on connect timeout or error.
2234 		 */
2235 		if (check->result == CHK_RES_UNKNOWN) {
2236 			/* good connection is enough for pure TCP check */
2237 			struct pid_list *elem = check->curpid;
2238 			int status = HCHK_STATUS_UNKNOWN;
2239 
2240 			if (elem->exited) {
2241 				status = elem->status; /* Save in case the process exits between use below */
2242 				if (!WIFEXITED(status))
2243 					check->code = -1;
2244 				else
2245 					check->code = WEXITSTATUS(status);
2246 				if (!WIFEXITED(status) || WEXITSTATUS(status))
2247 					status = HCHK_STATUS_PROCERR;
2248 				else
2249 					status = HCHK_STATUS_PROCOK;
2250 			} else if (expired) {
2251 				status = HCHK_STATUS_PROCTOUT;
2252 				ha_warning("kill %d\n", (int)elem->pid);
2253 				kill(elem->pid, SIGTERM);
2254 			}
2255 			set_server_check_status(check, status, NULL);
2256 		}
2257 
2258 		if (check->result == CHK_RES_FAILED) {
2259 			/* a failure or timeout detected */
2260 			check_notify_failure(check);
2261 		}
2262 		else if (check->result == CHK_RES_CONDPASS) {
2263 			/* check is OK but asks for stopping mode */
2264 			check_notify_stopping(check);
2265 		}
2266 		else if (check->result == CHK_RES_PASSED) {
2267 			/* a success was detected */
2268 			check_notify_success(check);
2269 		}
2270 		task_set_affinity(t, 1);
2271 		check->state &= ~CHK_ST_INPROGRESS;
2272 
2273 		pid_list_del(check->curpid);
2274 
2275 		rv = 0;
2276 		if (global.spread_checks > 0) {
2277 			rv = srv_getinter(check) * global.spread_checks / 100;
2278 			rv -= (int) (2 * rv * (ha_random32() / 4294967295.0));
2279 		}
2280 		t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(check) + rv));
2281 	}
2282 
2283  reschedule:
2284 	while (tick_is_expired(t->expire, now_ms))
2285 		t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
2286 
2287  out_unlock:
2288 	HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
2289 	return t;
2290 }
2291 
2292 /*
2293  * manages a server health-check that uses a connection. Returns
2294  * the time the task accepts to wait, or TIME_ETERNITY for infinity.
2295  *
2296  * Please do NOT place any return statement in this function and only leave
2297  * via the out_unlock label.
2298  */
process_chk_conn(struct task * t,void * context,unsigned short state)2299 static struct task *process_chk_conn(struct task *t, void *context, unsigned short state)
2300 {
2301 	struct check *check = context;
2302 	struct proxy *proxy = check->proxy;
2303 	struct conn_stream *cs = check->cs;
2304 	struct connection *conn = cs_conn(cs);
2305 	int rv;
2306 	int ret;
2307 	int expired = tick_is_expired(t->expire, now_ms);
2308 
2309 	if (check->server)
2310 		HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
2311 	if (!(check->state & CHK_ST_INPROGRESS)) {
2312 		/* no check currently running */
2313 		if (!expired) /* woke up too early */
2314 			goto out_unlock;
2315 
2316 		/* we don't send any health-checks when the proxy is
2317 		 * stopped, the server should not be checked or the check
2318 		 * is disabled.
2319 		 */
2320 		if (((check->state & (CHK_ST_ENABLED | CHK_ST_PAUSED)) != CHK_ST_ENABLED) ||
2321 		    proxy->state == PR_STSTOPPED)
2322 			goto reschedule;
2323 
2324 		/* we'll initiate a new check */
2325 		set_server_check_status(check, HCHK_STATUS_START, NULL);
2326 
2327 		check->state |= CHK_ST_INPROGRESS;
2328 		b_reset(&check->bi);
2329 		b_reset(&check->bo);
2330 
2331 		task_set_affinity(t, tid_bit);
2332 		ret = connect_conn_chk(t);
2333 		cs = check->cs;
2334 		conn = cs_conn(cs);
2335 
2336 		switch (ret) {
2337 		case SF_ERR_UP:
2338 			goto out_unlock;
2339 
2340 		case SF_ERR_NONE:
2341 			/* we allow up to min(inter, timeout.connect) for a connection
2342 			 * to establish but only when timeout.check is set
2343 			 * as it may be to short for a full check otherwise
2344 			 */
2345 			t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
2346 
2347 			if (proxy->timeout.check && proxy->timeout.connect) {
2348 				int t_con = tick_add(now_ms, proxy->timeout.connect);
2349 				t->expire = tick_first(t->expire, t_con);
2350 			}
2351 
2352 			if (check->type) {
2353 				/* send the request if we have one. We avoid receiving
2354 				 * if not connected, unless we didn't subscribe for
2355 				 * sending since otherwise we won't be woken up.
2356 				 */
2357 				__event_srv_chk_w(cs);
2358 				if (!(conn->flags & CO_FL_WAIT_L4_CONN) ||
2359 				    !(check->wait_list.events & SUB_RETRY_SEND))
2360 					__event_srv_chk_r(cs);
2361 			}
2362 
2363 			goto reschedule;
2364 
2365 		case SF_ERR_SRVTO: /* ETIMEDOUT */
2366 		case SF_ERR_SRVCL: /* ECONNREFUSED, ENETUNREACH, ... */
2367 			if (conn)
2368 				conn->flags |= CO_FL_ERROR;
2369 			chk_report_conn_err(check, errno, 0);
2370 			break;
2371 		/* should share same code than cases below */
2372 		case SF_ERR_CHK_PORT:
2373 			check->state |= CHK_ST_PORT_MISS;
2374 		case SF_ERR_PRXCOND:
2375 		case SF_ERR_RESOURCE:
2376 		case SF_ERR_INTERNAL:
2377 			if (conn)
2378 				conn->flags |= CO_FL_ERROR;
2379 			chk_report_conn_err(check, conn ? 0 : ENOMEM, 0);
2380 			break;
2381 		}
2382 
2383 		/* here, we have seen a synchronous error, no fd was allocated */
2384 		task_set_affinity(t, MAX_THREADS_MASK);
2385 		if (cs) {
2386 			if (check->wait_list.events)
2387 				cs->conn->xprt->unsubscribe(cs->conn,
2388 				                            cs->conn->xprt_ctx,
2389 							    check->wait_list.events,
2390 							    &check->wait_list);
2391 			/* We may have been scheduled to run, and the
2392 			 * I/O handler expects to have a cs, so remove
2393 			 * the tasklet
2394 			 */
2395 			tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
2396 			cs_destroy(cs);
2397 			cs = check->cs = NULL;
2398 			conn = NULL;
2399 		}
2400 
2401 		check->state &= ~CHK_ST_INPROGRESS;
2402 		check_notify_failure(check);
2403 
2404 		/* we allow up to min(inter, timeout.connect) for a connection
2405 		 * to establish but only when timeout.check is set
2406 		 * as it may be to short for a full check otherwise
2407 		 */
2408 		while (tick_is_expired(t->expire, now_ms)) {
2409 			int t_con;
2410 
2411 			t_con = tick_add(t->expire, proxy->timeout.connect);
2412 			t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
2413 
2414 			if (proxy->timeout.check)
2415 				t->expire = tick_first(t->expire, t_con);
2416 		}
2417 	}
2418 	else {
2419 		/* there was a test running.
2420 		 * First, let's check whether there was an uncaught error,
2421 		 * which can happen on connect timeout or error.
2422 		 */
2423 		if (check->result == CHK_RES_UNKNOWN) {
2424 			/* good connection is enough for pure TCP check */
2425 			if ((conn->flags & CO_FL_CONNECTED) && !check->type) {
2426 				if (check->use_ssl == 1)
2427 					set_server_check_status(check, HCHK_STATUS_L6OK, NULL);
2428 				else
2429 					set_server_check_status(check, HCHK_STATUS_L4OK, NULL);
2430 			}
2431 			else if ((conn->flags & CO_FL_ERROR) || cs->flags & CS_FL_ERROR || expired) {
2432 				chk_report_conn_err(check, 0, expired);
2433 			}
2434 			else
2435 				goto out_unlock; /* timeout not reached, wait again */
2436 		}
2437 
2438 		/* check complete or aborted */
2439 		if (conn && conn->xprt) {
2440 			/* The check was aborted and the connection was not yet closed.
2441 			 * This can happen upon timeout, or when an external event such
2442 			 * as a failed response coupled with "observe layer7" caused the
2443 			 * server state to be suddenly changed.
2444 			 */
2445 			conn_sock_drain(conn);
2446 			cs_close(cs);
2447 		}
2448 
2449 		if (cs) {
2450 			if (check->wait_list.events)
2451 				cs->conn->xprt->unsubscribe(cs->conn,
2452 				    cs->conn->xprt_ctx,
2453 				    check->wait_list.events,
2454 				    &check->wait_list);
2455 			/* We may have been scheduled to run, and the
2456 			 * I/O handler expects to have a cs, so remove
2457 			 * the tasklet
2458 			 */
2459 			tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
2460 			cs_destroy(cs);
2461 			cs = check->cs = NULL;
2462 			conn = NULL;
2463 		}
2464 
2465 		if (check->server) {
2466 			if (check->result == CHK_RES_FAILED) {
2467 				/* a failure or timeout detected */
2468 				check_notify_failure(check);
2469 			}
2470 			else if (check->result == CHK_RES_CONDPASS) {
2471 				/* check is OK but asks for stopping mode */
2472 				check_notify_stopping(check);
2473 			}
2474 			else if (check->result == CHK_RES_PASSED) {
2475 				/* a success was detected */
2476 				check_notify_success(check);
2477 			}
2478 		}
2479 		task_set_affinity(t, MAX_THREADS_MASK);
2480 		check->state &= ~CHK_ST_INPROGRESS;
2481 
2482 		if (check->server) {
2483 			rv = 0;
2484 			if (global.spread_checks > 0) {
2485 				rv = srv_getinter(check) * global.spread_checks / 100;
2486 				rv -= (int) (2 * rv * (ha_random32() / 4294967295.0));
2487 			}
2488 			t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(check) + rv));
2489 		}
2490 	}
2491 
2492  reschedule:
2493 	while (tick_is_expired(t->expire, now_ms))
2494 		t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
2495  out_unlock:
2496 	if (check->server)
2497 		HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
2498 	return t;
2499 }
2500 
2501 /*
2502  * manages a server health-check. Returns
2503  * the time the task accepts to wait, or TIME_ETERNITY for infinity.
2504  */
process_chk(struct task * t,void * context,unsigned short state)2505 static struct task *process_chk(struct task *t, void *context, unsigned short state)
2506 {
2507 	struct check *check = context;
2508 
2509 	if (check->type == PR_O2_EXT_CHK)
2510 		return process_chk_proc(t, context, state);
2511 	return process_chk_conn(t, context, state);
2512 
2513 }
2514 
start_check_task(struct check * check,int mininter,int nbcheck,int srvpos)2515 static int start_check_task(struct check *check, int mininter,
2516 			    int nbcheck, int srvpos)
2517 {
2518 	struct task *t;
2519 	unsigned long thread_mask = MAX_THREADS_MASK;
2520 
2521 	if (check->type == PR_O2_EXT_CHK)
2522 		thread_mask = 1;
2523 
2524 	/* task for the check */
2525 	if ((t = task_new(thread_mask)) == NULL) {
2526 		ha_alert("Starting [%s:%s] check: out of memory.\n",
2527 			 check->server->proxy->id, check->server->id);
2528 		return 0;
2529 	}
2530 
2531 	check->task = t;
2532 	t->process = process_chk;
2533 	t->context = check;
2534 
2535 	if (mininter < srv_getinter(check))
2536 		mininter = srv_getinter(check);
2537 
2538 	if (global.max_spread_checks && mininter > global.max_spread_checks)
2539 		mininter = global.max_spread_checks;
2540 
2541 	/* check this every ms */
2542 	t->expire = tick_add(now_ms, MS_TO_TICKS(mininter * srvpos / nbcheck));
2543 	check->start = now;
2544 	task_queue(t);
2545 
2546 	return 1;
2547 }
2548 
2549 /*
2550  * Start health-check.
2551  * Returns 0 if OK, ERR_FATAL on error, and prints the error in this case.
2552  */
start_checks()2553 static int start_checks()
2554 {
2555 
2556 	struct proxy *px;
2557 	struct server *s;
2558 	struct task *t;
2559 	int nbcheck=0, mininter=0, srvpos=0;
2560 
2561 	/* 1- count the checkers to run simultaneously.
2562 	 * We also determine the minimum interval among all of those which
2563 	 * have an interval larger than SRV_CHK_INTER_THRES. This interval
2564 	 * will be used to spread their start-up date. Those which have
2565 	 * a shorter interval will start independently and will not dictate
2566 	 * too short an interval for all others.
2567 	 */
2568 	for (px = proxies_list; px; px = px->next) {
2569 		for (s = px->srv; s; s = s->next) {
2570 			if (s->slowstart) {
2571 				if ((t = task_new(MAX_THREADS_MASK)) == NULL) {
2572 					ha_alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
2573 					return ERR_ALERT | ERR_FATAL;
2574 				}
2575 				/* We need a warmup task that will be called when the server
2576 				 * state switches from down to up.
2577 				 */
2578 				s->warmup = t;
2579 				t->process = server_warmup;
2580 				t->context = s;
2581 				/* server can be in this state only because of */
2582 				if (s->next_state == SRV_ST_STARTING)
2583 					task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, (now.tv_sec - s->last_change)) / 20)));
2584 			}
2585 
2586 			if (s->check.state & CHK_ST_CONFIGURED) {
2587 				nbcheck++;
2588 				if ((srv_getinter(&s->check) >= SRV_CHK_INTER_THRES) &&
2589 				    (!mininter || mininter > srv_getinter(&s->check)))
2590 					mininter = srv_getinter(&s->check);
2591 			}
2592 
2593 			if (s->agent.state & CHK_ST_CONFIGURED) {
2594 				nbcheck++;
2595 				if ((srv_getinter(&s->agent) >= SRV_CHK_INTER_THRES) &&
2596 				    (!mininter || mininter > srv_getinter(&s->agent)))
2597 					mininter = srv_getinter(&s->agent);
2598 			}
2599 		}
2600 	}
2601 
2602 	if (!nbcheck)
2603 		return 0;
2604 
2605 	srand((unsigned)time(NULL));
2606 
2607 	/*
2608 	 * 2- start them as far as possible from each others. For this, we will
2609 	 * start them after their interval set to the min interval divided by
2610 	 * the number of servers, weighted by the server's position in the list.
2611 	 */
2612 	for (px = proxies_list; px; px = px->next) {
2613 		if ((px->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
2614 			if (init_pid_list()) {
2615 				ha_alert("Starting [%s] check: out of memory.\n", px->id);
2616 				return ERR_ALERT | ERR_FATAL;
2617 			}
2618 		}
2619 
2620 		for (s = px->srv; s; s = s->next) {
2621 			/* A task for the main check */
2622 			if (s->check.state & CHK_ST_CONFIGURED) {
2623 				if (s->check.type == PR_O2_EXT_CHK) {
2624 					if (!prepare_external_check(&s->check))
2625 						return ERR_ALERT | ERR_FATAL;
2626 				}
2627 				if (!start_check_task(&s->check, mininter, nbcheck, srvpos))
2628 					return ERR_ALERT | ERR_FATAL;
2629 				srvpos++;
2630 			}
2631 
2632 			/* A task for a auxiliary agent check */
2633 			if (s->agent.state & CHK_ST_CONFIGURED) {
2634 				if (!start_check_task(&s->agent, mininter, nbcheck, srvpos)) {
2635 					return ERR_ALERT | ERR_FATAL;
2636 				}
2637 				srvpos++;
2638 			}
2639 		}
2640 	}
2641 	return 0;
2642 }
2643 
2644 /*
2645  * Perform content verification check on data in s->check.buffer buffer.
2646  * The buffer MUST be terminated by a null byte before calling this function.
2647  * Sets server status appropriately. The caller is responsible for ensuring
2648  * that the buffer contains at least 13 characters. If <done> is zero, we may
2649  * return 0 to indicate that data is required to decide of a match.
2650  */
httpchk_expect(struct server * s,int done)2651 static int httpchk_expect(struct server *s, int done)
2652 {
2653 	static THREAD_LOCAL char status_msg[] = "HTTP status check returned code <000>";
2654 	char status_code[] = "000";
2655 	char *contentptr;
2656 	int crlf;
2657 	int ret;
2658 
2659 	switch (s->proxy->options2 & PR_O2_EXP_TYPE) {
2660 	case PR_O2_EXP_STS:
2661 	case PR_O2_EXP_RSTS:
2662 		memcpy(status_code, b_head(&s->check.bi) + 9, 3);
2663 		memcpy(status_msg + strlen(status_msg) - 4, b_head(&s->check.bi) + 9, 3);
2664 
2665 		if ((s->proxy->options2 & PR_O2_EXP_TYPE) == PR_O2_EXP_STS)
2666 			ret = strncmp(s->proxy->expect_str, status_code, 3) == 0;
2667 		else
2668 			ret = regex_exec(s->proxy->expect_regex, status_code);
2669 
2670 		/* we necessarily have the response, so there are no partial failures */
2671 		if (s->proxy->options2 & PR_O2_EXP_INV)
2672 			ret = !ret;
2673 
2674 		set_server_check_status(&s->check, ret ? HCHK_STATUS_L7OKD : HCHK_STATUS_L7STS, status_msg);
2675 		break;
2676 
2677 	case PR_O2_EXP_STR:
2678 	case PR_O2_EXP_RSTR:
2679 		/* very simple response parser: ignore CR and only count consecutive LFs,
2680 		 * stop with contentptr pointing to first char after the double CRLF or
2681 		 * to '\0' if crlf < 2.
2682 		 */
2683 		crlf = 0;
2684 		for (contentptr = b_head(&s->check.bi); *contentptr; contentptr++) {
2685 			if (crlf >= 2)
2686 				break;
2687 			if (*contentptr == '\r')
2688 				continue;
2689 			else if (*contentptr == '\n')
2690 				crlf++;
2691 			else
2692 				crlf = 0;
2693 		}
2694 
2695 		/* Check that response contains a body... */
2696 		if (crlf < 2) {
2697 			if (!done)
2698 				return 0;
2699 
2700 			set_server_check_status(&s->check, HCHK_STATUS_L7RSP,
2701 						"HTTP content check could not find a response body");
2702 			return 1;
2703 		}
2704 
2705 		/* Check that response body is not empty... */
2706 		if (*contentptr == '\0') {
2707 			if (!done)
2708 				return 0;
2709 
2710 			set_server_check_status(&s->check, HCHK_STATUS_L7RSP,
2711 						"HTTP content check found empty response body");
2712 			return 1;
2713 		}
2714 
2715 		/* Check the response content against the supplied string
2716 		 * or regex... */
2717 		if ((s->proxy->options2 & PR_O2_EXP_TYPE) == PR_O2_EXP_STR)
2718 			ret = strstr(contentptr, s->proxy->expect_str) != NULL;
2719 		else
2720 			ret = regex_exec(s->proxy->expect_regex, contentptr);
2721 
2722 		/* if we don't match, we may need to wait more */
2723 		if (!ret && !done)
2724 			return 0;
2725 
2726 		if (ret) {
2727 			/* content matched */
2728 			if (s->proxy->options2 & PR_O2_EXP_INV)
2729 				set_server_check_status(&s->check, HCHK_STATUS_L7RSP,
2730 							"HTTP check matched unwanted content");
2731 			else
2732 				set_server_check_status(&s->check, HCHK_STATUS_L7OKD,
2733 							"HTTP content check matched");
2734 		}
2735 		else {
2736 			if (s->proxy->options2 & PR_O2_EXP_INV)
2737 				set_server_check_status(&s->check, HCHK_STATUS_L7OKD,
2738 							"HTTP check did not match unwanted content");
2739 			else
2740 				set_server_check_status(&s->check, HCHK_STATUS_L7RSP,
2741 							"HTTP content check did not match");
2742 		}
2743 		break;
2744 	}
2745 	return 1;
2746 }
2747 
2748 /*
2749  * return the id of a step in a send/expect session
2750  */
tcpcheck_get_step_id(struct check * check)2751 static int tcpcheck_get_step_id(struct check *check)
2752 {
2753 	struct tcpcheck_rule *cur = NULL, *next = NULL;
2754 	int i = 0;
2755 
2756 	/* not even started anything yet => step 0 = initial connect */
2757 	if (!check->current_step)
2758 		return 0;
2759 
2760 	cur = check->last_started_step;
2761 
2762 	/* no step => first step */
2763 	if (cur == NULL)
2764 		return 1;
2765 
2766 	/* increment i until current step */
2767 	list_for_each_entry(next, check->tcpcheck_rules, list) {
2768 		if (next->list.p == &cur->list)
2769 			break;
2770 		++i;
2771 	}
2772 
2773 	return i;
2774 }
2775 
2776 /*
2777  * return the latest known comment before (including) the given stepid
2778  * returns NULL if no comment found
2779  */
tcpcheck_get_step_comment(struct check * check,int stepid)2780 static char * tcpcheck_get_step_comment(struct check *check, int stepid)
2781 {
2782 	struct tcpcheck_rule *cur = NULL;
2783 	char *ret = NULL;
2784 	int i = 0;
2785 
2786 	/* not even started anything yet, return latest comment found before any action */
2787 	if (!check->current_step) {
2788 		list_for_each_entry(cur, check->tcpcheck_rules, list) {
2789 			if (cur->action == TCPCHK_ACT_COMMENT)
2790 				ret = cur->comment;
2791 			else
2792 				goto return_comment;
2793 		}
2794 	}
2795 
2796 	i = 1;
2797 	list_for_each_entry(cur, check->tcpcheck_rules, list) {
2798 		if (cur->comment)
2799 			ret = cur->comment;
2800 
2801 		if (i >= stepid)
2802 			goto return_comment;
2803 
2804 		++i;
2805 	}
2806 
2807  return_comment:
2808 	return ret;
2809 }
2810 
2811 /* proceed with next steps for the TCP checks <check>. Note that this is called
2812  * both from the connection's wake() callback and from the check scheduling task.
2813  * It returns 0 on normal cases, or <0 if a close() has happened on an existing
2814  * connection, presenting the risk of an fd replacement.
2815  *
2816  * Please do NOT place any return statement in this function and only leave
2817  * via the out_end_tcpcheck label after setting retcode.
2818  */
tcpcheck_main(struct check * check)2819 static int tcpcheck_main(struct check *check)
2820 {
2821 	char *contentptr, *comment;
2822 	struct tcpcheck_rule *next;
2823 	int done = 0, ret = 0, step = 0;
2824 	struct conn_stream *cs = check->cs;
2825 	struct connection *conn = cs_conn(cs);
2826 	struct server *s = check->server;
2827 	struct proxy *proxy = check->proxy;
2828 	struct task *t = check->task;
2829 	struct list *head = check->tcpcheck_rules;
2830 	int retcode = 0;
2831 
2832 	/* here, we know that the check is complete or that it failed */
2833 	if (check->result != CHK_RES_UNKNOWN)
2834 		goto out_end_tcpcheck;
2835 
2836 	/* We have 4 possibilities here :
2837 	 *   1. we've not yet attempted step 1, and step 1 is a connect, so no
2838 	 *      connection attempt was made yet ; conn==NULL;current_step==NULL.
2839 	 *   2. we've not yet attempted step 1, and step 1 is a not connect or
2840 	 *      does not exist (no rule), so a connection attempt was made
2841 	 *      before coming here, conn!=NULL.
2842 	 *   3. we're coming back after having started with step 1, so we may
2843 	 *      be waiting for a connection attempt to complete. conn!=NULL.
2844 	 *   4. the connection + handshake are complete. conn!=NULL.
2845 	 *
2846 	 * #2 and #3 are quite similar, we want both the connection and the
2847 	 * handshake to complete before going any further. Thus we must always
2848 	 * wait for a connection to complete unless we're before and existing
2849 	 * step 1.
2850 	 */
2851 
2852 	/* find first rule and skip comments */
2853 	next = LIST_NEXT(head, struct tcpcheck_rule *, list);
2854 	while (&next->list != head && next->action == TCPCHK_ACT_COMMENT)
2855 		next = LIST_NEXT(&next->list, struct tcpcheck_rule *, list);
2856 
2857 	if ((check->current_step || &next->list == head) &&
2858 	    (!(conn->flags & CO_FL_CONNECTED) || (conn->flags & CO_FL_HANDSHAKE))) {
2859 		/* we allow up to min(inter, timeout.connect) for a connection
2860 		 * to establish but only when timeout.check is set
2861 		 * as it may be to short for a full check otherwise
2862 		 */
2863 		while (tick_is_expired(t->expire, now_ms)) {
2864 			int t_con;
2865 
2866 			t_con = tick_add(t->expire, proxy->timeout.connect);
2867 			t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
2868 
2869 			if (proxy->timeout.check)
2870 				t->expire = tick_first(t->expire, t_con);
2871 		}
2872 		goto out;
2873 	}
2874 
2875 	/* special case: option tcp-check with no rule, a connect is enough */
2876 	if (&next->list == head) {
2877 		set_server_check_status(check, HCHK_STATUS_L4OK, NULL);
2878 		goto out_end_tcpcheck;
2879 	}
2880 
2881 	/* no step means first step initialisation */
2882 	if (check->current_step == NULL) {
2883 		check->last_started_step = NULL;
2884 		b_reset(&check->bo);
2885 		b_reset(&check->bi);
2886 		check->current_step = next;
2887 		t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
2888 		if (proxy->timeout.check)
2889 			t->expire = tick_add_ifset(now_ms, proxy->timeout.check);
2890 	}
2891 
2892 	while (1) {
2893 		/* We have to try to flush the output buffer before reading, at
2894 		 * the end, or if we're about to send a string that does not fit
2895 		 * in the remaining space. That explains why we break out of the
2896 		 * loop after this control. If we have data, conn is valid.
2897 		 */
2898 		if (b_data(&check->bo) &&
2899 		    (&check->current_step->list == head ||
2900 		     check->current_step->action != TCPCHK_ACT_SEND ||
2901 		     check->current_step->string_len >= b_room(&check->bo))) {
2902 			int ret;
2903 
2904 			ret = cs->conn->mux->snd_buf(cs, &check->bo, b_data(&check->bo), 0);
2905 			b_realign_if_empty(&check->bo);
2906 
2907 			if (ret <= 0) {
2908 				if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) {
2909 					chk_report_conn_err(check, errno, 0);
2910 					goto out_end_tcpcheck;
2911 				}
2912 				break;
2913 			}
2914 			if (b_data(&check->bo)) {
2915 				cs->conn->mux->subscribe(cs, SUB_RETRY_SEND, &check->wait_list);
2916 				goto out;
2917 			}
2918 		}
2919 
2920 		if (&check->current_step->list == head)
2921 			break;
2922 
2923 		/* have 'next' point to the next rule or NULL if we're on the
2924 		 * last one, connect() needs this.
2925 		 */
2926 		next = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
2927 
2928 		/* bypass all comment rules */
2929 		while (&next->list != head && next->action == TCPCHK_ACT_COMMENT)
2930 			next = LIST_NEXT(&next->list, struct tcpcheck_rule *, list);
2931 
2932 		/* NULL if we're on the last rule */
2933 		if (&next->list == head)
2934 			next = NULL;
2935 
2936 		if (check->current_step->action == TCPCHK_ACT_CONNECT) {
2937 			struct protocol *proto;
2938 			struct xprt_ops *xprt;
2939 
2940 			/* For a connect action we'll create a new connection.
2941 			 * We may also have to kill a previous one. But we don't
2942 			 * want to leave *without* a connection if we came here
2943 			 * from the connection layer, hence with a connection.
2944 			 * Thus we'll proceed in the following order :
2945 			 *   1: close but not release previous connection
2946 			 *   2: try to get a new connection
2947 			 *   3: release and replace the old one on success
2948 			 */
2949 			if (check->cs) {
2950 				cs_close(check->cs);
2951 				retcode = -1; /* do not reuse the fd in the caller! */
2952 			}
2953 
2954 			/* mark the step as started */
2955 			check->last_started_step = check->current_step;
2956 
2957 			/* prepare new connection */
2958 			cs = cs_new(NULL);
2959 			if (!cs) {
2960 				step = tcpcheck_get_step_id(check);
2961 				chunk_printf(&trash, "TCPCHK error allocating connection at step %d", step);
2962 				comment = tcpcheck_get_step_comment(check, step);
2963 				if (comment)
2964 					chunk_appendf(&trash, " comment: '%s'", comment);
2965 				set_server_check_status(check, HCHK_STATUS_SOCKERR,
2966 							trash.area);
2967 				check->current_step = NULL;
2968 				goto out;
2969 			}
2970 
2971 			if (check->cs) {
2972 				if (check->wait_list.events)
2973 					cs->conn->xprt->unsubscribe(cs->conn,
2974 					                            cs->conn->xprt_ctx,
2975 								    check->wait_list.events,
2976 								    &check->wait_list);
2977 				/* We may have been scheduled to run, and the
2978 				 * I/O handler expects to have a cs, so remove
2979 				 * the tasklet
2980 				 */
2981 				tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
2982 				cs_destroy(check->cs);
2983 			}
2984 
2985 			check->cs = cs;
2986 			conn = cs->conn;
2987 			/* Maybe there were an older connection we were waiting on */
2988 			check->wait_list.events = 0;
2989 			conn->target = s ? &s->obj_type : &proxy->obj_type;
2990 
2991 			/* no client address */
2992 			clear_addr(&conn->addr.from);
2993 
2994 			if (is_addr(&check->addr)) {
2995 				/* we'll connect to the check addr specified on the server */
2996 				conn->addr.to = check->addr;
2997 			}
2998 			else {
2999 				/* we'll connect to the addr on the server */
3000 				conn->addr.to = s->addr;
3001 			}
3002 			proto = protocol_by_family(conn->addr.to.ss_family);
3003 
3004 			/* port */
3005 			if (check->current_step->port)
3006 				set_host_port(&conn->addr.to, check->current_step->port);
3007 			else if (check->port)
3008 				set_host_port(&conn->addr.to, check->port);
3009 			else if (s->svc_port)
3010 				set_host_port(&conn->addr.to, s->svc_port);
3011 
3012 			if (check->current_step->conn_opts & TCPCHK_OPT_SSL) {
3013 				xprt = xprt_get(XPRT_SSL);
3014 			}
3015 			else {
3016 				xprt = xprt_get(XPRT_RAW);
3017 			}
3018 
3019 			conn_prepare(conn, proto, xprt);
3020 
3021 			if (conn_install_mux(conn, &mux_pt_ops, cs, proxy, NULL) < 0) {
3022 				ret = SF_ERR_RESOURCE;
3023 				goto fail_check;
3024 			}
3025 
3026 			cs_attach(cs, check, &check_conn_cb);
3027 
3028 			ret = SF_ERR_INTERNAL;
3029 			if (proto && proto->connect)
3030 				ret = proto->connect(conn,
3031 						     CONNECT_HAS_DATA /* I/O polling is always needed */ | ((next && next->action == TCPCHK_ACT_EXPECT) ? 0 : CONNECT_DELACK_ALWAYS));
3032 			if (conn_ctrl_ready(conn) &&
3033 				check->current_step->conn_opts & TCPCHK_OPT_SEND_PROXY) {
3034 				conn->send_proxy_ofs = 1;
3035 				conn->flags |= CO_FL_SEND_PROXY;
3036 				if (xprt_add_hs(conn) < 0)
3037 					ret = SF_ERR_RESOURCE;
3038 			}
3039 
3040 			/* It can return one of :
3041 			 *  - SF_ERR_NONE if everything's OK
3042 			 *  - SF_ERR_SRVTO if there are no more servers
3043 			 *  - SF_ERR_SRVCL if the connection was refused by the server
3044 			 *  - SF_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
3045 			 *  - SF_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
3046 			 *  - SF_ERR_INTERNAL for any other purely internal errors
3047 			 * Additionally, in the case of SF_ERR_RESOURCE, an emergency log will be emitted.
3048 			 * Note that we try to prevent the network stack from sending the ACK during the
3049 			 * connect() when a pure TCP check is used (without PROXY protocol).
3050 			 */
3051 		fail_check:
3052 			switch (ret) {
3053 			case SF_ERR_NONE:
3054 				/* we allow up to min(inter, timeout.connect) for a connection
3055 				 * to establish but only when timeout.check is set
3056 				 * as it may be to short for a full check otherwise
3057 				 */
3058 				t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
3059 
3060 				if (proxy->timeout.check && proxy->timeout.connect) {
3061 					int t_con = tick_add(now_ms, proxy->timeout.connect);
3062 					t->expire = tick_first(t->expire, t_con);
3063 				}
3064 				break;
3065 			case SF_ERR_SRVTO: /* ETIMEDOUT */
3066 			case SF_ERR_SRVCL: /* ECONNREFUSED, ENETUNREACH, ... */
3067 				step = tcpcheck_get_step_id(check);
3068 				chunk_printf(&trash, "TCPCHK error establishing connection at step %d: %s",
3069 						step, strerror(errno));
3070 				comment = tcpcheck_get_step_comment(check, step);
3071 				if (comment)
3072 					chunk_appendf(&trash, " comment: '%s'", comment);
3073 				set_server_check_status(check, HCHK_STATUS_L4CON,
3074 							trash.area);
3075 				goto out_end_tcpcheck;
3076 			case SF_ERR_PRXCOND:
3077 			case SF_ERR_RESOURCE:
3078 			case SF_ERR_INTERNAL:
3079 				step = tcpcheck_get_step_id(check);
3080 				chunk_printf(&trash, "TCPCHK error establishing connection at step %d", step);
3081 				comment = tcpcheck_get_step_comment(check, step);
3082 				if (comment)
3083 					chunk_appendf(&trash, " comment: '%s'", comment);
3084 				set_server_check_status(check, HCHK_STATUS_SOCKERR,
3085 							trash.area);
3086 				goto out_end_tcpcheck;
3087 			}
3088 
3089 			/* allow next rule */
3090 			check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
3091 
3092 			/* bypass all comment rules */
3093 			while (&check->current_step->list != head &&
3094 				check->current_step->action == TCPCHK_ACT_COMMENT)
3095 				check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
3096 
3097 			if (&check->current_step->list == head)
3098 				break;
3099 
3100 			/* don't do anything until the connection is established */
3101 			if (!(conn->flags & CO_FL_CONNECTED))
3102 				break;
3103 
3104 		} /* end 'connect' */
3105 		else if (check->current_step->action == TCPCHK_ACT_SEND) {
3106 			/* mark the step as started */
3107 			check->last_started_step = check->current_step;
3108 
3109 			/* reset the read buffer */
3110 			if (*b_head(&check->bi) != '\0') {
3111 				*b_head(&check->bi) = '\0';
3112 				b_reset(&check->bi);
3113 			}
3114 
3115 			if (conn->flags & CO_FL_SOCK_WR_SH) {
3116 				conn->flags |= CO_FL_ERROR;
3117 				chk_report_conn_err(check, 0, 0);
3118 				goto out_end_tcpcheck;
3119 			}
3120 
3121 			if (check->current_step->string_len >= b_size(&check->bo)) {
3122 				chunk_printf(&trash, "tcp-check send : string too large (%d) for buffer size (%u) at step %d",
3123 					     check->current_step->string_len, (unsigned int)b_size(&check->bo),
3124 					     tcpcheck_get_step_id(check));
3125 				set_server_check_status(check, HCHK_STATUS_L7RSP,
3126 							trash.area);
3127 				goto out_end_tcpcheck;
3128 			}
3129 
3130 			/* do not try to send if there is no space */
3131 			if (check->current_step->string_len >= b_room(&check->bo))
3132 				continue;
3133 
3134 			b_putblk(&check->bo, check->current_step->string, check->current_step->string_len);
3135 			*b_tail(&check->bo) = '\0'; /* to make gdb output easier to read */
3136 
3137 			/* go to next rule and try to send */
3138 			check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
3139 
3140 			/* bypass all comment rules */
3141 			while (&check->current_step->list != head &&
3142 				check->current_step->action == TCPCHK_ACT_COMMENT)
3143 				check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
3144 
3145 		} /* end 'send' */
3146 		else if (check->current_step->action == TCPCHK_ACT_EXPECT) {
3147 			if (unlikely(check->result == CHK_RES_FAILED))
3148 				goto out_end_tcpcheck;
3149 
3150 			/* If we already subscribed, then we tried to received
3151 			 * and failed, so there's no point trying again.
3152 			 */
3153 			if (check->wait_list.events & SUB_RETRY_RECV)
3154 				break;
3155 			if (cs->conn->mux->rcv_buf(cs, &check->bi, b_size(&check->bi), 0) <= 0) {
3156 				if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH) || cs->flags & CS_FL_ERROR) {
3157 					done = 1;
3158 					if ((conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) && !b_data(&check->bi)) {
3159 						/* Report network errors only if we got no other data. Otherwise
3160 						 * we'll let the upper layers decide whether the response is OK
3161 						 * or not. It is very common that an RST sent by the server is
3162 						 * reported as an error just after the last data chunk.
3163 						 */
3164 						chk_report_conn_err(check, errno, 0);
3165 						goto out_end_tcpcheck;
3166 					}
3167 				}
3168 				else {
3169 					conn->mux->subscribe(cs, SUB_RETRY_RECV, &check->wait_list);
3170 					break;
3171 				}
3172 			}
3173 
3174 			/* mark the step as started */
3175 			check->last_started_step = check->current_step;
3176 
3177 
3178 			/* Intermediate or complete response received.
3179 			 * Terminate string in b_head(&check->bi) buffer.
3180 			 */
3181 			if (b_data(&check->bi) < b_size(&check->bi)) {
3182 				b_head(&check->bi)[b_data(&check->bi)] = '\0';
3183 			}
3184 			else {
3185 				b_head(&check->bi)[b_data(&check->bi) - 1] = '\0';
3186 				done = 1; /* buffer full, don't wait for more data */
3187 			}
3188 
3189 			contentptr = b_head(&check->bi);
3190 
3191 			/* Check that response body is not empty... */
3192 			if (!b_data(&check->bi)) {
3193 				if (!done)
3194 					continue;
3195 
3196 				/* empty response */
3197 				step = tcpcheck_get_step_id(check);
3198 				chunk_printf(&trash, "TCPCHK got an empty response at step %d", step);
3199 				comment = tcpcheck_get_step_comment(check, step);
3200 				if (comment)
3201 					chunk_appendf(&trash, " comment: '%s'", comment);
3202 				set_server_check_status(check, HCHK_STATUS_L7RSP,
3203 							trash.area);
3204 
3205 				goto out_end_tcpcheck;
3206 			}
3207 
3208 		tcpcheck_expect:
3209 			if (!done && (check->current_step->string != NULL) && (b_data(&check->bi) < check->current_step->string_len) )
3210 				continue; /* try to read more */
3211 
3212 			if (check->current_step->string != NULL)
3213 				ret = my_memmem(contentptr, b_data(&check->bi), check->current_step->string, check->current_step->string_len) != NULL;
3214 			else if (check->current_step->expect_regex != NULL)
3215 				ret = regex_exec(check->current_step->expect_regex, contentptr);
3216 
3217 			if (!ret && !done)
3218 				continue; /* try to read more */
3219 
3220 			/* matched */
3221 			step = tcpcheck_get_step_id(check);
3222 			if (ret) {
3223 				/* matched but we did not want to => ERROR */
3224 				if (check->current_step->inverse) {
3225 					/* we were looking for a string */
3226 					if (check->current_step->string != NULL) {
3227 						chunk_printf(&trash, "TCPCHK matched unwanted content '%s' at step %d",
3228 						             check->current_step->string, step);
3229 					}
3230 					else {
3231 					/* we were looking for a regex */
3232 						chunk_printf(&trash, "TCPCHK matched unwanted content (regex) at step %d", step);
3233 					}
3234 					comment = tcpcheck_get_step_comment(check, step);
3235 					if (comment)
3236 						chunk_appendf(&trash, " comment: '%s'", comment);
3237 					set_server_check_status(check, HCHK_STATUS_L7RSP,
3238 								trash.area);
3239 					goto out_end_tcpcheck;
3240 				}
3241 				/* matched and was supposed to => OK, next step */
3242 				else {
3243 					/* allow next rule */
3244 					check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
3245 
3246 					/* bypass all comment rules */
3247 					while (&check->current_step->list != head &&
3248 					       check->current_step->action == TCPCHK_ACT_COMMENT)
3249 						check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
3250 
3251 					if (&check->current_step->list == head)
3252 						break;
3253 
3254 					if (check->current_step->action == TCPCHK_ACT_EXPECT)
3255 						goto tcpcheck_expect;
3256 				}
3257 			}
3258 			else {
3259 			/* not matched */
3260 				/* not matched and was not supposed to => OK, next step */
3261 				if (check->current_step->inverse) {
3262 					/* allow next rule */
3263 					check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
3264 
3265 					/* bypass all comment rules */
3266 					while (&check->current_step->list != head &&
3267 					       check->current_step->action == TCPCHK_ACT_COMMENT)
3268 						check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
3269 
3270 					if (&check->current_step->list == head)
3271 						break;
3272 
3273 					if (check->current_step->action == TCPCHK_ACT_EXPECT)
3274 						goto tcpcheck_expect;
3275 				}
3276 				/* not matched but was supposed to => ERROR */
3277 				else {
3278 					/* we were looking for a string */
3279 					if (check->current_step->string != NULL) {
3280 						chunk_printf(&trash, "TCPCHK did not match content '%s' at step %d",
3281 						             check->current_step->string, step);
3282 					}
3283 					else {
3284 					/* we were looking for a regex */
3285 						chunk_printf(&trash, "TCPCHK did not match content (regex) at step %d",
3286 								step);
3287 					}
3288 					comment = tcpcheck_get_step_comment(check, step);
3289 					if (comment)
3290 						chunk_appendf(&trash, " comment: '%s'", comment);
3291 					set_server_check_status(check, HCHK_STATUS_L7RSP,
3292 								trash.area);
3293 					goto out_end_tcpcheck;
3294 				}
3295 			}
3296 		} /* end expect */
3297 	} /* end loop over double chained step list */
3298 
3299 	/* don't do anything until the connection is established */
3300 	if (!(conn->flags & CO_FL_CONNECTED)) {
3301 		/* update expire time, should be done by process_chk */
3302 		/* we allow up to min(inter, timeout.connect) for a connection
3303 		 * to establish but only when timeout.check is set
3304 		 * as it may be to short for a full check otherwise
3305 		 */
3306 		while (tick_is_expired(t->expire, now_ms)) {
3307 			int t_con;
3308 
3309 			t_con = tick_add(t->expire, proxy->timeout.connect);
3310 			t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
3311 
3312 			if (proxy->timeout.check)
3313 				t->expire = tick_first(t->expire, t_con);
3314 		}
3315 		goto out;
3316 	}
3317 
3318 	/* We're waiting for some I/O to complete, we've reached the end of the
3319 	 * rules, or both. Do what we have to do, otherwise we're done.
3320 	 */
3321 	if (&check->current_step->list == head && !b_data(&check->bo)) {
3322 		set_server_check_status(check, HCHK_STATUS_L7OKD, "(tcp-check)");
3323 		goto out_end_tcpcheck;
3324 	}
3325 
3326 	if (&check->current_step->list != head &&
3327 	    check->current_step->action == TCPCHK_ACT_EXPECT)
3328 		__event_srv_chk_r(cs);
3329 	goto out;
3330 
3331  out_end_tcpcheck:
3332 	/* collect possible new errors */
3333 	if ((conn && conn->flags & CO_FL_ERROR) || (cs && cs->flags & CS_FL_ERROR))
3334 		chk_report_conn_err(check, 0, 0);
3335 
3336 	/* cleanup before leaving */
3337 	check->current_step = NULL;
3338 
3339 	if (conn && check->result == CHK_RES_FAILED)
3340 		conn->flags |= CO_FL_ERROR;
3341 
3342  out:
3343 	return retcode;
3344 }
3345 
init_check(struct check * check,int type)3346 const char *init_check(struct check *check, int type)
3347 {
3348 	check->type = type;
3349 
3350 	b_reset(&check->bi); check->bi.size = global.tune.chksize;
3351 	b_reset(&check->bo); check->bo.size = global.tune.chksize;
3352 
3353 	check->bi.area = calloc(check->bi.size, sizeof(char));
3354 	check->bo.area = calloc(check->bo.size, sizeof(char));
3355 
3356 	if (!check->bi.area || !check->bo.area)
3357 		return "out of memory while allocating check buffer";
3358 
3359 	check->wait_list.tasklet = tasklet_new();
3360 	if (!check->wait_list.tasklet)
3361 		return "out of memroy while allocating check tasklet";
3362 	check->wait_list.events = 0;
3363 	check->wait_list.tasklet->process = event_srv_chk_io;
3364 	check->wait_list.tasklet->context = check;
3365 	return NULL;
3366 }
3367 
free_check(struct check * check)3368 void free_check(struct check *check)
3369 {
3370 	task_destroy(check->task);
3371 	if (check->wait_list.tasklet)
3372 		tasklet_free(check->wait_list.tasklet);
3373 
3374 	free(check->bi.area);
3375 	free(check->bo.area);
3376 	if (check->cs) {
3377 		free(check->cs->conn);
3378 		check->cs->conn = NULL;
3379 		cs_free(check->cs);
3380 		check->cs = NULL;
3381 	}
3382 }
3383 
email_alert_free(struct email_alert * alert)3384 void email_alert_free(struct email_alert *alert)
3385 {
3386 	struct tcpcheck_rule *rule, *back;
3387 
3388 	if (!alert)
3389 		return;
3390 
3391 	list_for_each_entry_safe(rule, back, &alert->tcpcheck_rules, list) {
3392 		LIST_DEL(&rule->list);
3393 		free(rule->comment);
3394 		free(rule->string);
3395 		regex_free(rule->expect_regex);
3396 		pool_free(pool_head_tcpcheck_rule, rule);
3397 	}
3398 	pool_free(pool_head_email_alert, alert);
3399 }
3400 
process_email_alert(struct task * t,void * context,unsigned short state)3401 static struct task *process_email_alert(struct task *t, void *context, unsigned short state)
3402 {
3403 	struct check        *check = context;
3404 	struct email_alertq *q;
3405 	struct email_alert  *alert;
3406 
3407 	q = container_of(check, typeof(*q), check);
3408 
3409 	HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
3410 	while (1) {
3411 		if (!(check->state & CHK_ST_ENABLED)) {
3412 			if (LIST_ISEMPTY(&q->email_alerts)) {
3413 				/* All alerts processed, queue the task */
3414 				t->expire = TICK_ETERNITY;
3415 				task_queue(t);
3416 				goto end;
3417 			}
3418 
3419 			alert = LIST_NEXT(&q->email_alerts, typeof(alert), list);
3420 			LIST_DEL(&alert->list);
3421 			t->expire             = now_ms;
3422 			check->tcpcheck_rules = &alert->tcpcheck_rules;
3423 			check->status         = HCHK_STATUS_INI;
3424 			check->state         |= CHK_ST_ENABLED;
3425 		}
3426 
3427 		process_chk(t, context, state);
3428 		if (check->state & CHK_ST_INPROGRESS)
3429 			break;
3430 
3431 		alert = container_of(check->tcpcheck_rules, typeof(*alert), tcpcheck_rules);
3432 		email_alert_free(alert);
3433 		check->tcpcheck_rules = NULL;
3434 		check->server         = NULL;
3435 		check->state         &= ~CHK_ST_ENABLED;
3436 	}
3437   end:
3438 	HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
3439 	return t;
3440 }
3441 
3442 /* Initializes mailer alerts for the proxy <p> using <mls> parameters.
3443  *
3444  * The function returns 1 in success case, otherwise, it returns 0 and err is
3445  * filled.
3446  */
init_email_alert(struct mailers * mls,struct proxy * p,char ** err)3447 int init_email_alert(struct mailers *mls, struct proxy *p, char **err)
3448 {
3449 	struct mailer       *mailer;
3450 	struct email_alertq *queues;
3451 	const char          *err_str;
3452 	int                  i = 0;
3453 
3454 	if ((queues = calloc(mls->count, sizeof(*queues))) == NULL) {
3455 		memprintf(err, "out of memory while allocating mailer alerts queues");
3456 		goto fail_no_queue;
3457 	}
3458 
3459 	for (mailer = mls->mailer_list; mailer; i++, mailer = mailer->next) {
3460 		struct email_alertq *q     = &queues[i];
3461 		struct check        *check = &q->check;
3462 		struct task         *t;
3463 
3464 		LIST_INIT(&q->email_alerts);
3465 		HA_SPIN_INIT(&q->lock);
3466 		check->inter = mls->timeout.mail;
3467 		check->rise = DEF_AGENT_RISETIME;
3468 		check->proxy = p;
3469 		check->fall = DEF_AGENT_FALLTIME;
3470 		if ((err_str = init_check(check, PR_O2_TCPCHK_CHK))) {
3471 			memprintf(err, "%s", err_str);
3472 			goto error;
3473 		}
3474 
3475 		check->xprt = mailer->xprt;
3476 		check->addr = mailer->addr;
3477 		check->port = get_host_port(&mailer->addr);
3478 
3479 		if ((t = task_new(MAX_THREADS_MASK)) == NULL) {
3480 			memprintf(err, "out of memory while allocating mailer alerts task");
3481 			goto error;
3482 		}
3483 
3484 		check->task = t;
3485 		t->process = process_email_alert;
3486 		t->context = check;
3487 
3488 		/* check this in one ms */
3489 		t->expire    = TICK_ETERNITY;
3490 		check->start = now;
3491 		task_queue(t);
3492 	}
3493 
3494 	mls->users++;
3495 	free(p->email_alert.mailers.name);
3496 	p->email_alert.mailers.m = mls;
3497 	p->email_alert.queues    = queues;
3498 	return 0;
3499 
3500   error:
3501 	for (i = 0; i < mls->count; i++) {
3502 		struct email_alertq *q     = &queues[i];
3503 		struct check        *check = &q->check;
3504 
3505 		free_check(check);
3506 	}
3507 	free(queues);
3508   fail_no_queue:
3509 	return 1;
3510 }
3511 
3512 
add_tcpcheck_expect_str(struct list * list,const char * str)3513 static int add_tcpcheck_expect_str(struct list *list, const char *str)
3514 {
3515 	struct tcpcheck_rule *tcpcheck;
3516 
3517 	if ((tcpcheck = pool_alloc(pool_head_tcpcheck_rule)) == NULL)
3518 		return 0;
3519 	memset(tcpcheck, 0, sizeof(*tcpcheck));
3520 	tcpcheck->action       = TCPCHK_ACT_EXPECT;
3521 	tcpcheck->string       = strdup(str);
3522 	tcpcheck->expect_regex = NULL;
3523 	tcpcheck->comment      = NULL;
3524 	if (!tcpcheck->string) {
3525 		pool_free(pool_head_tcpcheck_rule, tcpcheck);
3526 		return 0;
3527 	}
3528 
3529 	LIST_ADDQ(list, &tcpcheck->list);
3530 	return 1;
3531 }
3532 
add_tcpcheck_send_strs(struct list * list,const char * const * strs)3533 static int add_tcpcheck_send_strs(struct list *list, const char * const *strs)
3534 {
3535 	struct tcpcheck_rule *tcpcheck;
3536 	const char *in;
3537 	char *dst;
3538 	int i;
3539 
3540 	if ((tcpcheck = pool_alloc(pool_head_tcpcheck_rule)) == NULL)
3541 		return 0;
3542 	memset(tcpcheck, 0, sizeof(*tcpcheck));
3543 	tcpcheck->action       = TCPCHK_ACT_SEND;
3544 	tcpcheck->expect_regex = NULL;
3545 	tcpcheck->comment      = NULL;
3546 	tcpcheck->string_len = 0;
3547 	for (i = 0; strs[i]; i++)
3548 		tcpcheck->string_len += strlen(strs[i]);
3549 
3550 	tcpcheck->string = malloc(tcpcheck->string_len + 1);
3551 	if (!tcpcheck->string) {
3552 		pool_free(pool_head_tcpcheck_rule, tcpcheck);
3553 		return 0;
3554 	}
3555 
3556 	dst = tcpcheck->string;
3557 	for (i = 0; strs[i]; i++)
3558 		for (in = strs[i]; (*dst = *in++); dst++);
3559 	*dst = 0;
3560 
3561 	LIST_ADDQ(list, &tcpcheck->list);
3562 	return 1;
3563 }
3564 
enqueue_one_email_alert(struct proxy * p,struct server * s,struct email_alertq * q,const char * msg)3565 static int enqueue_one_email_alert(struct proxy *p, struct server *s,
3566 				   struct email_alertq *q, const char *msg)
3567 {
3568 	struct email_alert   *alert;
3569 	struct tcpcheck_rule *tcpcheck;
3570 	struct check *check = &q->check;
3571 
3572 	if ((alert = pool_alloc(pool_head_email_alert)) == NULL)
3573 		goto error;
3574 	LIST_INIT(&alert->list);
3575 	LIST_INIT(&alert->tcpcheck_rules);
3576 	alert->srv = s;
3577 
3578 	if ((tcpcheck = pool_alloc(pool_head_tcpcheck_rule)) == NULL)
3579 		goto error;
3580 	memset(tcpcheck, 0, sizeof(*tcpcheck));
3581 	tcpcheck->action       = TCPCHK_ACT_CONNECT;
3582 	tcpcheck->comment      = NULL;
3583 	tcpcheck->string       = NULL;
3584 	tcpcheck->expect_regex = NULL;
3585 	LIST_ADDQ(&alert->tcpcheck_rules, &tcpcheck->list);
3586 
3587 	if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "220 "))
3588 		goto error;
3589 
3590 	{
3591 		const char * const strs[4] = { "EHLO ", p->email_alert.myhostname, "\r\n" };
3592 		if (!add_tcpcheck_send_strs(&alert->tcpcheck_rules, strs))
3593 			goto error;
3594 	}
3595 
3596 	if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "250 "))
3597 		goto error;
3598 
3599 	{
3600 		const char * const strs[4] = { "MAIL FROM:<", p->email_alert.from, ">\r\n" };
3601 		if (!add_tcpcheck_send_strs(&alert->tcpcheck_rules, strs))
3602 			goto error;
3603 	}
3604 
3605 	if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "250 "))
3606 		goto error;
3607 
3608 	{
3609 		const char * const strs[4] = { "RCPT TO:<", p->email_alert.to, ">\r\n" };
3610 		if (!add_tcpcheck_send_strs(&alert->tcpcheck_rules, strs))
3611 			goto error;
3612 	}
3613 
3614 	if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "250 "))
3615 		goto error;
3616 
3617 	{
3618 		const char * const strs[2] = { "DATA\r\n" };
3619 		if (!add_tcpcheck_send_strs(&alert->tcpcheck_rules, strs))
3620 			goto error;
3621 	}
3622 
3623 	if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "354 "))
3624 		goto error;
3625 
3626 	{
3627 		struct tm tm;
3628 		char datestr[48];
3629 		const char * const strs[18] = {
3630 			"From: ", p->email_alert.from, "\r\n",
3631 			"To: ", p->email_alert.to, "\r\n",
3632 			"Date: ", datestr, "\r\n",
3633 			"Subject: [HAproxy Alert] ", msg, "\r\n",
3634 			"\r\n",
3635 			msg, "\r\n",
3636 			"\r\n",
3637 			".\r\n",
3638 			NULL
3639 		};
3640 
3641 		get_localtime(date.tv_sec, &tm);
3642 
3643 		if (strftime(datestr, sizeof(datestr), "%a, %d %b %Y %T %z (%Z)", &tm) == 0) {
3644 			goto error;
3645 		}
3646 
3647 		if (!add_tcpcheck_send_strs(&alert->tcpcheck_rules, strs))
3648 			goto error;
3649 	}
3650 
3651 	if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "250 "))
3652 		goto error;
3653 
3654 	{
3655 		const char * const strs[2] = { "QUIT\r\n" };
3656 		if (!add_tcpcheck_send_strs(&alert->tcpcheck_rules, strs))
3657 			goto error;
3658 	}
3659 
3660 	if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "221 "))
3661 		goto error;
3662 
3663 	HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
3664 	task_wakeup(check->task, TASK_WOKEN_MSG);
3665 	LIST_ADDQ(&q->email_alerts, &alert->list);
3666 	HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
3667 	return 1;
3668 
3669 error:
3670 	email_alert_free(alert);
3671 	return 0;
3672 }
3673 
enqueue_email_alert(struct proxy * p,struct server * s,const char * msg)3674 static void enqueue_email_alert(struct proxy *p, struct server *s, const char *msg)
3675 {
3676 	int i;
3677 	struct mailer *mailer;
3678 
3679 	for (i = 0, mailer = p->email_alert.mailers.m->mailer_list;
3680 	     i < p->email_alert.mailers.m->count; i++, mailer = mailer->next) {
3681 		if (!enqueue_one_email_alert(p, s, &p->email_alert.queues[i], msg)) {
3682 			ha_alert("Email alert [%s] could not be enqueued: out of memory\n", p->id);
3683 			return;
3684 		}
3685 	}
3686 
3687 	return;
3688 }
3689 
3690 /*
3691  * Send email alert if configured.
3692  */
send_email_alert(struct server * s,int level,const char * format,...)3693 void send_email_alert(struct server *s, int level, const char *format, ...)
3694 {
3695 	va_list argp;
3696 	char buf[1024];
3697 	int len;
3698 	struct proxy *p = s->proxy;
3699 
3700 	if (!p->email_alert.mailers.m || level > p->email_alert.level || format == NULL)
3701 		return;
3702 
3703 	va_start(argp, format);
3704 	len = vsnprintf(buf, sizeof(buf), format, argp);
3705 	va_end(argp);
3706 
3707 	if (len < 0 || len >= sizeof(buf)) {
3708 		ha_alert("Email alert [%s] could not format message\n", p->id);
3709 		return;
3710 	}
3711 
3712 	enqueue_email_alert(p, s, buf);
3713 }
3714 
3715 /*
3716  * Return value:
3717  *   the port to be used for the health check
3718  *   0 in case no port could be found for the check
3719  */
srv_check_healthcheck_port(struct check * chk)3720 int srv_check_healthcheck_port(struct check *chk)
3721 {
3722 	int i = 0;
3723 	struct server *srv = NULL;
3724 
3725 	srv = chk->server;
3726 
3727 	/* by default, we use the health check port ocnfigured */
3728 	if (chk->port > 0)
3729 		return chk->port;
3730 
3731 	/* try to get the port from check_core.addr if check.port not set */
3732 	i = get_host_port(&chk->addr);
3733 	if (i > 0)
3734 		return i;
3735 
3736 	/* try to get the port from server address */
3737 	/* prevent MAPPORTS from working at this point, since checks could
3738 	 * not be performed in such case (MAPPORTS impose a relative ports
3739 	 * based on live traffic)
3740 	 */
3741 	if (srv->flags & SRV_F_MAPPORTS)
3742 		return 0;
3743 
3744 	i = srv->svc_port; /* by default */
3745 	if (i > 0)
3746 		return i;
3747 
3748 	return 0;
3749 }
3750 
init_srv_check(struct server * srv)3751 static int init_srv_check(struct server *srv)
3752 {
3753 	const char *err;
3754 	struct tcpcheck_rule *r;
3755 	int ret = 0;
3756 
3757 	if (!srv->do_check)
3758 		goto out;
3759 
3760 
3761 	/* If neither a port nor an addr was specified and no check transport
3762 	 * layer is forced, then the transport layer used by the checks is the
3763 	 * same as for the production traffic. Otherwise we use raw_sock by
3764 	 * default, unless one is specified.
3765 	 */
3766 	if (!srv->check.port && !is_addr(&srv->check.addr)) {
3767 		if (!srv->check.use_ssl && srv->use_ssl != -1) {
3768 			srv->check.use_ssl = srv->use_ssl;
3769 			srv->check.xprt    = srv->xprt;
3770 		}
3771 		else if (srv->check.use_ssl == 1)
3772 			srv->check.xprt = xprt_get(XPRT_SSL);
3773 
3774 		srv->check.send_proxy |= (srv->pp_opts);
3775 	}
3776 	else if (srv->check.use_ssl == 1)
3777 		srv->check.xprt = xprt_get(XPRT_SSL);
3778 
3779 	/* validate <srv> server health-check settings */
3780 
3781 	/* We need at least a service port, a check port or the first tcp-check
3782 	 * rule must be a 'connect' one when checking an IPv4/IPv6 server.
3783 	 */
3784 	if ((srv_check_healthcheck_port(&srv->check) != 0) ||
3785 	    (!is_inet_addr(&srv->check.addr) && (is_addr(&srv->check.addr) || !is_inet_addr(&srv->addr))))
3786 		goto init;
3787 
3788 	if (!LIST_ISEMPTY(&srv->proxy->tcpcheck_rules)) {
3789 		ha_alert("config: %s '%s': server '%s' has neither service port nor check port.\n",
3790 			 proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
3791 		ret |= ERR_ALERT | ERR_ABORT;
3792 		goto out;
3793 	}
3794 
3795 	/* search the first action (connect / send / expect) in the list */
3796 	r = get_first_tcpcheck_rule(&srv->proxy->tcpcheck_rules);
3797 	if (!r || (r->action != TCPCHK_ACT_CONNECT) || !r->port) {
3798 		ha_alert("config: %s '%s': server '%s' has neither service port nor check port "
3799 			 "nor tcp_check rule 'connect' with port information.\n",
3800 			 proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
3801 		ret |= ERR_ALERT | ERR_ABORT;
3802 		goto out;
3803 	}
3804 
3805 	/* scan the tcp-check ruleset to ensure a port has been configured */
3806 	list_for_each_entry(r, &srv->proxy->tcpcheck_rules, list) {
3807 		if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
3808 			ha_alert("config: %s '%s': server '%s' has neither service port nor check port, "
3809 				 "and a tcp_check rule 'connect' with no port information.\n",
3810 				 proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
3811 			ret |= ERR_ALERT | ERR_ABORT;
3812 			goto out;
3813 		}
3814 	}
3815 
3816   init:
3817 	err = init_check(&srv->check, srv->proxy->options2 & PR_O2_CHK_ANY);
3818 	if (err) {
3819 		ha_alert("config: %s '%s': unable to init check for server '%s' (%s).\n",
3820 			 proxy_type_str(srv->proxy), srv->proxy->id, srv->id, err);
3821 		ret |= ERR_ALERT | ERR_ABORT;
3822 		goto out;
3823 	}
3824 	srv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
3825 	global.maxsock++;
3826 
3827   out:
3828 	return ret;
3829 }
3830 
init_srv_agent_check(struct server * srv)3831 static int init_srv_agent_check(struct server *srv)
3832 {
3833 	const char *err;
3834 	int ret = 0;
3835 
3836 	if (!srv->do_agent)
3837 		goto out;
3838 
3839 	err = init_check(&srv->agent, PR_O2_LB_AGENT_CHK);
3840 	if (err) {
3841 		ha_alert("config: %s '%s': unable to init agent-check for server '%s' (%s).\n",
3842 			 proxy_type_str(srv->proxy), srv->proxy->id, srv->id, err);
3843 		ret |= ERR_ALERT | ERR_ABORT;
3844 		goto out;
3845 	}
3846 
3847 	if (!srv->agent.inter)
3848 		srv->agent.inter = srv->check.inter;
3849 
3850 	srv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
3851 	global.maxsock++;
3852 
3853   out:
3854 	return ret;
3855 }
3856 
deinit_srv_check(struct server * srv)3857 void deinit_srv_check(struct server *srv)
3858 {
3859 	if (srv->do_check)
3860 		free_check(&srv->check);
3861 }
3862 
3863 
deinit_srv_agent_check(struct server * srv)3864 void deinit_srv_agent_check(struct server *srv)
3865 {
3866 	if (srv->do_agent)
3867 		free_check(&srv->agent);
3868 	free(srv->agent.send_string);
3869 }
3870 
init_servers_checks()3871 static int init_servers_checks()
3872 {
3873 	struct proxy *px;
3874 	struct server *s;
3875 	int ret = 0;
3876 
3877 	for (px = proxies_list; px; px = px->next) {
3878 		for (s = px->srv; s; s = s->next) {
3879 			ret |= init_srv_check(s);
3880 			if (ret & (ERR_ABORT|ERR_FATAL))
3881 				goto end;
3882 			ret |= init_srv_agent_check(s);
3883 			if (ret & (ERR_ABORT|ERR_FATAL))
3884 				goto end;
3885 		}
3886 	}
3887 	ret = start_checks();
3888   end:
3889 	return ret;
3890 }
3891 
3892 REGISTER_POST_CHECK(init_servers_checks);
3893 
3894 /*
3895  * Local variables:
3896  *  c-indent-level: 8
3897  *  c-basic-offset: 8
3898  * End:
3899  */
3900