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 <stdarg.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <time.h>
23 #include <unistd.h>
24 #include <sys/resource.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <netinet/in.h>
29 #include <netinet/tcp.h>
30 #include <arpa/inet.h>
31 
32 #include <haproxy/action.h>
33 #include <haproxy/api.h>
34 #include <haproxy/arg.h>
35 #include <haproxy/cfgparse.h>
36 #include <haproxy/check.h>
37 #include <haproxy/chunk.h>
38 #include <haproxy/dgram.h>
39 #include <haproxy/dynbuf-t.h>
40 #include <haproxy/extcheck.h>
41 #include <haproxy/fd.h>
42 #include <haproxy/global.h>
43 #include <haproxy/h1.h>
44 #include <haproxy/http.h>
45 #include <haproxy/http_htx.h>
46 #include <haproxy/htx.h>
47 #include <haproxy/istbuf.h>
48 #include <haproxy/list.h>
49 #include <haproxy/log.h>
50 #include <haproxy/mailers.h>
51 #include <haproxy/port_range.h>
52 #include <haproxy/proto_tcp.h>
53 #include <haproxy/protocol.h>
54 #include <haproxy/proxy.h>
55 #include <haproxy/queue.h>
56 #include <haproxy/regex.h>
57 #include <haproxy/resolvers.h>
58 #include <haproxy/sample.h>
59 #include <haproxy/server.h>
60 #include <haproxy/ssl_sock.h>
61 #include <haproxy/stats-t.h>
62 #include <haproxy/stream_interface.h>
63 #include <haproxy/task.h>
64 #include <haproxy/tcpcheck.h>
65 #include <haproxy/thread.h>
66 #include <haproxy/time.h>
67 #include <haproxy/tools.h>
68 #include <haproxy/trace.h>
69 #include <haproxy/vars.h>
70 
71 /* trace source and events */
72 static void check_trace(enum trace_level level, uint64_t mask,
73 			const struct trace_source *src,
74 			const struct ist where, const struct ist func,
75 			const void *a1, const void *a2, const void *a3, const void *a4);
76 
77 /* The event representation is split like this :
78  *   check  - check
79  *
80  * CHECK_EV_* macros are defined in <haproxy/check.h>
81  */
82 static const struct trace_event check_trace_events[] = {
83 	{ .mask = CHK_EV_TASK_WAKE,   .name = "task_wake",        .desc = "Check task woken up" },
84 	{ .mask = CHK_EV_HCHK_START,  .name = "hchck_start",      .desc = "Health-check started" },
85 	{ .mask = CHK_EV_HCHK_WAKE,   .name = "hchck_wake",       .desc = "Health-check woken up" },
86 	{ .mask = CHK_EV_HCHK_RUN,    .name = "hchck_run",        .desc = "Health-check running" },
87 	{ .mask = CHK_EV_HCHK_END,    .name = "hchck_end",        .desc = "Health-check terminated" },
88 	{ .mask = CHK_EV_HCHK_SUCC,   .name = "hchck_succ",       .desc = "Health-check success" },
89 	{ .mask = CHK_EV_HCHK_ERR,    .name = "hchck_err",        .desc = "Health-check failure" },
90 
91 	{ .mask = CHK_EV_TCPCHK_EVAL, .name = "tcp_check_eval",   .desc = "tcp-check rules evaluation" },
92 	{ .mask = CHK_EV_TCPCHK_ERR,  .name = "tcp_check_err",    .desc = "tcp-check evaluation error" },
93 	{ .mask = CHK_EV_TCPCHK_CONN, .name = "tcp_check_conn",   .desc = "tcp-check connection rule" },
94 	{ .mask = CHK_EV_TCPCHK_SND,  .name = "tcp_check_send",   .desc = "tcp-check send rule" },
95 	{ .mask = CHK_EV_TCPCHK_EXP,  .name = "tcp_check_expect", .desc = "tcp-check expect rule" },
96 	{ .mask = CHK_EV_TCPCHK_ACT,  .name = "tcp_check_action", .desc = "tcp-check action rule" },
97 
98 	{ .mask = CHK_EV_RX_DATA,     .name = "rx_data",          .desc = "receipt of data" },
99 	{ .mask = CHK_EV_RX_BLK,      .name = "rx_blk",           .desc = "receipt blocked" },
100 	{ .mask = CHK_EV_RX_ERR,      .name = "rx_err",           .desc = "receipt error" },
101 
102 	{ .mask = CHK_EV_TX_DATA,     .name = "tx_data",          .desc = "transmission of data" },
103 	{ .mask = CHK_EV_TX_BLK,      .name = "tx_blk",           .desc = "transmission blocked" },
104 	{ .mask = CHK_EV_TX_ERR,      .name = "tx_err",           .desc = "transmission error" },
105 
106 	{}
107 };
108 
109 static const struct name_desc check_trace_lockon_args[4] = {
110 	/* arg1 */ { /* already used by the check */ },
111 	/* arg2 */ { },
112 	/* arg3 */ { },
113 	/* arg4 */ { }
114 };
115 
116 static const struct name_desc check_trace_decoding[] = {
117 #define CHK_VERB_CLEAN    1
118 	{ .name="clean",    .desc="only user-friendly stuff, generally suitable for level \"user\"" },
119 #define CHK_VERB_MINIMAL  2
120 	{ .name="minimal",  .desc="report info on stream and stream-interfaces" },
121 #define CHK_VERB_SIMPLE   3
122 	{ .name="simple",   .desc="add info on request and response channels" },
123 #define CHK_VERB_ADVANCED 4
124 	{ .name="advanced", .desc="add info on channel's buffer for data and developer levels only" },
125 #define CHK_VERB_COMPLETE 5
126 	{ .name="complete", .desc="add info on channel's buffer" },
127 	{ /* end */ }
128 };
129 
130 struct trace_source trace_check = {
131 	.name = IST("check"),
132 	.desc = "Health-check",
133 	.arg_def = TRC_ARG1_CHK,  // TRACE()'s first argument is always a stream
134 	.default_cb = check_trace,
135 	.known_events = check_trace_events,
136 	.lockon_args = check_trace_lockon_args,
137 	.decoding = check_trace_decoding,
138 	.report_events = ~0,  // report everything by default
139 };
140 
141 #define TRACE_SOURCE &trace_check
142 INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
143 
144 
145 static int wake_srv_chk(struct conn_stream *cs);
146 struct data_cb check_conn_cb = {
147 	.wake = wake_srv_chk,
148 	.name = "CHCK",
149 };
150 
151 
152 /* Dummy frontend used to create all checks sessions. */
153 struct proxy checks_fe;
154 
155 
check_trace_buf(const struct buffer * buf,size_t ofs,size_t len)156 static inline void check_trace_buf(const struct buffer *buf, size_t ofs, size_t len)
157 {
158 	size_t block1, block2;
159 	int line, ptr, newptr;
160 
161 	block1 = b_contig_data(buf, ofs);
162 	block2 = 0;
163 	if (block1 > len)
164 		block1 = len;
165 	block2 = len - block1;
166 
167 	ofs = b_peek_ofs(buf, ofs);
168 
169 	line = 0;
170 	ptr = ofs;
171 	while (ptr < ofs + block1) {
172 		newptr = dump_text_line(&trace_buf, b_orig(buf), b_size(buf), ofs + block1, &line, ptr);
173 		if (newptr == ptr)
174 			break;
175 		ptr = newptr;
176 	}
177 
178 	line = ptr = 0;
179 	while (ptr < block2) {
180 		newptr = dump_text_line(&trace_buf, b_orig(buf), b_size(buf), block2, &line, ptr);
181 		if (newptr == ptr)
182 			break;
183 		ptr = newptr;
184 	}
185 }
186 
187 /* trace source and events */
check_trace(enum trace_level level,uint64_t mask,const struct trace_source * src,const struct ist where,const struct ist func,const void * a1,const void * a2,const void * a3,const void * a4)188 static void check_trace(enum trace_level level, uint64_t mask,
189 			const struct trace_source *src,
190 			const struct ist where, const struct ist func,
191 			const void *a1, const void *a2, const void *a3, const void *a4)
192 {
193 	const struct check *check = a1;
194 	const struct server *srv = (check ? check->server : NULL);
195 	const size_t        *val = a4;
196 	const char *res;
197 
198 	if (!check || src->verbosity < CHK_VERB_CLEAN)
199 		return;
200 
201 	chunk_appendf(&trace_buf, " : [%c] SRV=%s",
202 		      ((check->type == PR_O2_EXT_CHK) ? 'E' : (check->state & CHK_ST_AGENT ? 'A' : 'H')),
203 		      srv->id);
204 
205 	chunk_appendf(&trace_buf, " status=%d/%d %s",
206 		      (check->health >= check->rise) ? check->health - check->rise + 1 : check->health,
207 		      (check->health >= check->rise) ? check->fall : check->rise,
208 		      (check->health >= check->rise) ? (srv->uweight ? "UP" : "DRAIN") : "DOWN");
209 
210 	switch (check->result) {
211 	case CHK_RES_NEUTRAL: res = "-";     break;
212 	case CHK_RES_FAILED:   res = "FAIL"; break;
213 	case CHK_RES_PASSED:   res = "PASS"; break;
214 	case CHK_RES_CONDPASS: res = "COND"; break;
215 	default:               res = "UNK";  break;
216 	}
217 
218 	if (src->verbosity == CHK_VERB_CLEAN)
219 		return;
220 
221 	chunk_appendf(&trace_buf, " - last=%s(%d)/%s(%d)",
222 		      get_check_status_info(check->status), check->status,
223 		      res, check->result);
224 
225 	/* Display the value to the 4th argument (level > STATE) */
226 	if (src->level > TRACE_LEVEL_STATE && val)
227 		chunk_appendf(&trace_buf, " - VAL=%lu", (long)*val);
228 
229 	chunk_appendf(&trace_buf, " check=%p(0x%08x)", check, check->state);
230 
231 	if (src->verbosity == CHK_VERB_MINIMAL)
232 		return;
233 
234 
235 	if (check->cs) {
236 		chunk_appendf(&trace_buf, " - conn=%p(0x%08x)", check->cs->conn, check->cs->conn->flags);
237 		chunk_appendf(&trace_buf, " cs=%p(0x%08x)", check->cs, check->cs->flags);
238 	}
239 
240 	if (mask & CHK_EV_TCPCHK) {
241 		const char *type;
242 
243 		switch (check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) {
244 			case TCPCHK_RULES_PGSQL_CHK: type = "PGSQL"; break;
245 			case TCPCHK_RULES_REDIS_CHK: type = "REDIS"; break;
246 			case TCPCHK_RULES_SMTP_CHK:  type = "SMTP";  break;
247 			case TCPCHK_RULES_HTTP_CHK:  type = "HTTP";  break;
248 			case TCPCHK_RULES_MYSQL_CHK: type = "MYSQL"; break;
249 			case TCPCHK_RULES_LDAP_CHK:  type = "LDAP";  break;
250 			case TCPCHK_RULES_SSL3_CHK:  type = "SSL3";  break;
251 			case TCPCHK_RULES_AGENT_CHK: type = "AGENT"; break;
252 			case TCPCHK_RULES_SPOP_CHK:  type = "SPOP";  break;
253 			case TCPCHK_RULES_TCP_CHK:   type = "TCP";   break;
254 			default:                     type = "???"; break;
255 		}
256 		if (check->current_step)
257 			chunk_appendf(&trace_buf, " - tcp-check=(%s,%d)", type, tcpcheck_get_step_id(check, NULL));
258 		else
259 			chunk_appendf(&trace_buf, " - tcp-check=(%s,-)", type);
260 	}
261 
262 	/* Display bi and bo buffer info (level > USER & verbosity > SIMPLE) */
263 	if (src->level > TRACE_LEVEL_USER) {
264 		const struct buffer *buf = NULL;
265 
266 		chunk_appendf(&trace_buf, " bi=%u@%p+%u/%u",
267 			      (unsigned int)b_data(&check->bi), b_orig(&check->bi),
268 			      (unsigned int)b_head_ofs(&check->bi), (unsigned int)b_size(&check->bi));
269 		chunk_appendf(&trace_buf, " bo=%u@%p+%u/%u",
270 			      (unsigned int)b_data(&check->bo), b_orig(&check->bo),
271 			      (unsigned int)b_head_ofs(&check->bo), (unsigned int)b_size(&check->bo));
272 
273 		if (src->verbosity >= CHK_VERB_ADVANCED && (mask & (CHK_EV_RX)))
274 			buf = (b_is_null(&check->bi) ? NULL : &check->bi);
275 		else if (src->verbosity >= CHK_VERB_ADVANCED && (mask & (CHK_EV_TX)))
276 			buf = (b_is_null(&check->bo) ? NULL : &check->bo);
277 
278 		if (buf) {
279 			if ((check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
280 				int full = (src->verbosity == CHK_VERB_COMPLETE);
281 
282 				chunk_memcat(&trace_buf, "\n\t", 2);
283 				htx_dump(&trace_buf, htxbuf(buf), full);
284 			}
285 			else {
286 				int max = ((src->verbosity == CHK_VERB_COMPLETE) ? 1024 : 256);
287 
288 				chunk_memcat(&trace_buf, "\n", 1);
289 				if (b_data(buf) > max) {
290 					check_trace_buf(buf, 0, max);
291 					chunk_memcat(&trace_buf, "  ...\n", 6);
292 				}
293 				else
294 					check_trace_buf(buf, 0, b_data(buf));
295 			}
296 
297 		}
298 	}
299 
300 }
301 
302 
303 /**************************************************************************/
304 /************************ Handle check results ****************************/
305 /**************************************************************************/
306 struct check_status {
307 	short result;			/* one of SRV_CHK_* */
308 	char *info;			/* human readable short info */
309 	char *desc;			/* long description */
310 };
311 
312 struct analyze_status {
313 	char *desc;				/* description */
314 	unsigned char lr[HANA_OBS_SIZE];	/* result for l4/l7: 0 = ignore, 1 - error, 2 - OK */
315 };
316 
317 static const struct check_status check_statuses[HCHK_STATUS_SIZE] = {
318 	[HCHK_STATUS_UNKNOWN]	= { CHK_RES_UNKNOWN,  "UNK",     "Unknown" },
319 	[HCHK_STATUS_INI]	= { CHK_RES_UNKNOWN,  "INI",     "Initializing" },
320 	[HCHK_STATUS_START]	= { /* SPECIAL STATUS*/ },
321 
322 	/* Below we have finished checks */
323 	[HCHK_STATUS_CHECKED]	= { CHK_RES_NEUTRAL,  "CHECKED", "No status change" },
324 	[HCHK_STATUS_HANA]	= { CHK_RES_FAILED,   "HANA",    "Health analyze" },
325 
326 	[HCHK_STATUS_SOCKERR]	= { CHK_RES_FAILED,   "SOCKERR", "Socket error" },
327 
328 	[HCHK_STATUS_L4OK]	= { CHK_RES_PASSED,   "L4OK",    "Layer4 check passed" },
329 	[HCHK_STATUS_L4TOUT]	= { CHK_RES_FAILED,   "L4TOUT",  "Layer4 timeout" },
330 	[HCHK_STATUS_L4CON]	= { CHK_RES_FAILED,   "L4CON",   "Layer4 connection problem" },
331 
332 	[HCHK_STATUS_L6OK]	= { CHK_RES_PASSED,   "L6OK",    "Layer6 check passed" },
333 	[HCHK_STATUS_L6TOUT]	= { CHK_RES_FAILED,   "L6TOUT",  "Layer6 timeout" },
334 	[HCHK_STATUS_L6RSP]	= { CHK_RES_FAILED,   "L6RSP",   "Layer6 invalid response" },
335 
336 	[HCHK_STATUS_L7TOUT]	= { CHK_RES_FAILED,   "L7TOUT",  "Layer7 timeout" },
337 	[HCHK_STATUS_L7RSP]	= { CHK_RES_FAILED,   "L7RSP",   "Layer7 invalid response" },
338 
339 	[HCHK_STATUS_L57DATA]	= { /* DUMMY STATUS */ },
340 
341 	[HCHK_STATUS_L7OKD]	= { CHK_RES_PASSED,   "L7OK",    "Layer7 check passed" },
342 	[HCHK_STATUS_L7OKCD]	= { CHK_RES_CONDPASS, "L7OKC",   "Layer7 check conditionally passed" },
343 	[HCHK_STATUS_L7STS]	= { CHK_RES_FAILED,   "L7STS",   "Layer7 wrong status" },
344 
345 	[HCHK_STATUS_PROCERR]	= { CHK_RES_FAILED,   "PROCERR",  "External check error" },
346 	[HCHK_STATUS_PROCTOUT]	= { CHK_RES_FAILED,   "PROCTOUT", "External check timeout" },
347 	[HCHK_STATUS_PROCOK]	= { CHK_RES_PASSED,   "PROCOK",   "External check passed" },
348 };
349 
350 static const struct analyze_status analyze_statuses[HANA_STATUS_SIZE] = {		/* 0: ignore, 1: error, 2: OK */
351 	[HANA_STATUS_UNKNOWN]		= { "Unknown",                         { 0, 0 }},
352 
353 	[HANA_STATUS_L4_OK]		= { "L4 successful connection",        { 2, 0 }},
354 	[HANA_STATUS_L4_ERR]		= { "L4 unsuccessful connection",      { 1, 1 }},
355 
356 	[HANA_STATUS_HTTP_OK]		= { "Correct http response",           { 0, 2 }},
357 	[HANA_STATUS_HTTP_STS]		= { "Wrong http response",             { 0, 1 }},
358 	[HANA_STATUS_HTTP_HDRRSP]	= { "Invalid http response (headers)", { 0, 1 }},
359 	[HANA_STATUS_HTTP_RSP]		= { "Invalid http response",           { 0, 1 }},
360 
361 	[HANA_STATUS_HTTP_READ_ERROR]	= { "Read error (http)",               { 0, 1 }},
362 	[HANA_STATUS_HTTP_READ_TIMEOUT]	= { "Read timeout (http)",             { 0, 1 }},
363 	[HANA_STATUS_HTTP_BROKEN_PIPE]	= { "Close from server (http)",        { 0, 1 }},
364 };
365 
366 /* checks if <err> is a real error for errno or one that can be ignored, and
367  * return 0 for these ones or <err> for real ones.
368  */
unclean_errno(int err)369 static inline int unclean_errno(int err)
370 {
371 	if (err == EAGAIN || err == EINPROGRESS ||
372 	    err == EISCONN || err == EALREADY)
373 		return 0;
374 	return err;
375 }
376 
377 /* Converts check_status code to result code */
get_check_status_result(short check_status)378 short get_check_status_result(short check_status)
379 {
380 	if (check_status < HCHK_STATUS_SIZE)
381 		return check_statuses[check_status].result;
382 	else
383 		return check_statuses[HCHK_STATUS_UNKNOWN].result;
384 }
385 
386 /* Converts check_status code to description */
get_check_status_description(short check_status)387 const char *get_check_status_description(short check_status) {
388 
389 	const char *desc;
390 
391 	if (check_status < HCHK_STATUS_SIZE)
392 		desc = check_statuses[check_status].desc;
393 	else
394 		desc = NULL;
395 
396 	if (desc && *desc)
397 		return desc;
398 	else
399 		return check_statuses[HCHK_STATUS_UNKNOWN].desc;
400 }
401 
402 /* Converts check_status code to short info */
get_check_status_info(short check_status)403 const char *get_check_status_info(short check_status)
404 {
405 	const char *info;
406 
407 	if (check_status < HCHK_STATUS_SIZE)
408 		info = check_statuses[check_status].info;
409 	else
410 		info = NULL;
411 
412 	if (info && *info)
413 		return info;
414 	else
415 		return check_statuses[HCHK_STATUS_UNKNOWN].info;
416 }
417 
418 /* Convert analyze_status to description */
get_analyze_status(short analyze_status)419 const char *get_analyze_status(short analyze_status) {
420 
421 	const char *desc;
422 
423 	if (analyze_status < HANA_STATUS_SIZE)
424 		desc = analyze_statuses[analyze_status].desc;
425 	else
426 		desc = NULL;
427 
428 	if (desc && *desc)
429 		return desc;
430 	else
431 		return analyze_statuses[HANA_STATUS_UNKNOWN].desc;
432 }
433 
434 /* Sets check->status, update check->duration and fill check->result with an
435  * adequate CHK_RES_* value. The new check->health is computed based on the
436  * result.
437  *
438  * Shows information in logs about failed health check if server is UP or
439  * succeeded health checks if server is DOWN.
440  */
set_server_check_status(struct check * check,short status,const char * desc)441 void set_server_check_status(struct check *check, short status, const char *desc)
442 {
443 	struct server *s = check->server;
444 	short prev_status = check->status;
445 	int report = 0;
446 
447 	TRACE_POINT(CHK_EV_HCHK_RUN, check);
448 
449 	if (status == HCHK_STATUS_START) {
450 		check->result = CHK_RES_UNKNOWN;	/* no result yet */
451 		check->desc[0] = '\0';
452 		check->start = now;
453 		return;
454 	}
455 
456 	if (!check->status)
457 		return;
458 
459 	if (desc && *desc) {
460 		strncpy(check->desc, desc, HCHK_DESC_LEN-1);
461 		check->desc[HCHK_DESC_LEN-1] = '\0';
462 	} else
463 		check->desc[0] = '\0';
464 
465 	check->status = status;
466 	if (check_statuses[status].result)
467 		check->result = check_statuses[status].result;
468 
469 	if (status == HCHK_STATUS_HANA)
470 		check->duration = -1;
471 	else if (!tv_iszero(&check->start)) {
472 		/* set_server_check_status() may be called more than once */
473 		check->duration = tv_ms_elapsed(&check->start, &now);
474 		tv_zero(&check->start);
475 	}
476 
477 	/* no change is expected if no state change occurred */
478 	if (check->result == CHK_RES_NEUTRAL)
479 		return;
480 
481 	/* If the check was really just sending a mail, it won't have an
482 	 * associated server, so we're done now.
483 	 */
484 	if (!s)
485 	    return;
486 	report = 0;
487 
488 
489 	switch (check->result) {
490 	case CHK_RES_FAILED:
491 		/* Failure to connect to the agent as a secondary check should not
492 		 * cause the server to be marked down.
493 		 */
494 		if ((!(check->state & CHK_ST_AGENT) ||
495 		    (check->status >= HCHK_STATUS_L57DATA)) &&
496 		    (check->health > 0)) {
497 			_HA_ATOMIC_INC(&s->counters.failed_checks);
498 			report = 1;
499 			check->health--;
500 			if (check->health < check->rise)
501 				check->health = 0;
502 		}
503 		break;
504 
505 	case CHK_RES_PASSED:
506 	case CHK_RES_CONDPASS:
507 		if (check->health < check->rise + check->fall - 1) {
508 			report = 1;
509 			check->health++;
510 
511 			if (check->health >= check->rise)
512 				check->health = check->rise + check->fall - 1; /* OK now */
513 		}
514 
515 		/* clear consecutive_errors if observing is enabled */
516 		if (s->onerror)
517 			s->consecutive_errors = 0;
518 		break;
519 
520 	default:
521 		break;
522 	}
523 
524 	if (s->proxy->options2 & PR_O2_LOGHCHKS &&
525 	    (status != prev_status || report)) {
526 		chunk_printf(&trash,
527 		             "%s check for %sserver %s/%s %s%s",
528 			     (check->state & CHK_ST_AGENT) ? "Agent" : "Health",
529 		             s->flags & SRV_F_BACKUP ? "backup " : "",
530 		             s->proxy->id, s->id,
531 		             (check->result == CHK_RES_CONDPASS) ? "conditionally ":"",
532 		             (check->result >= CHK_RES_PASSED)   ? "succeeded" : "failed");
533 
534 		srv_append_status(&trash, s, check, -1, 0);
535 
536 		chunk_appendf(&trash, ", status: %d/%d %s",
537 		             (check->health >= check->rise) ? check->health - check->rise + 1 : check->health,
538 		             (check->health >= check->rise) ? check->fall : check->rise,
539 			     (check->health >= check->rise) ? (s->uweight ? "UP" : "DRAIN") : "DOWN");
540 
541 		ha_warning("%s.\n", trash.area);
542 		send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.area);
543 		send_email_alert(s, LOG_INFO, "%s", trash.area);
544 	}
545 }
546 
547 /* Marks the check <check>'s server down if the current check is already failed
548  * and the server is not down yet nor in maintenance.
549  */
check_notify_failure(struct check * check)550 void check_notify_failure(struct check *check)
551 {
552 	struct server *s = check->server;
553 
554 	/* The agent secondary check should only cause a server to be marked
555 	 * as down if check->status is HCHK_STATUS_L7STS, which indicates
556 	 * that the agent returned "fail", "stopped" or "down".
557 	 * The implication here is that failure to connect to the agent
558 	 * as a secondary check should not cause the server to be marked
559 	 * down. */
560 	if ((check->state & CHK_ST_AGENT) && check->status != HCHK_STATUS_L7STS)
561 		return;
562 
563 	if (check->health > 0)
564 		return;
565 
566 	TRACE_STATE("health-check failed, set server DOWN", CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
567 	/* We only report a reason for the check if we did not do so previously */
568 	srv_set_stopped(s, NULL, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : NULL);
569 }
570 
571 /* Marks the check <check> as valid and tries to set its server up, provided
572  * it isn't in maintenance, it is not tracking a down server and other checks
573  * comply. The rule is simple : by default, a server is up, unless any of the
574  * following conditions is true :
575  *   - health check failed (check->health < rise)
576  *   - agent check failed (agent->health < rise)
577  *   - the server tracks a down server (track && track->state == STOPPED)
578  * Note that if the server has a slowstart, it will switch to STARTING instead
579  * of RUNNING. Also, only the health checks support the nolb mode, so the
580  * agent's success may not take the server out of this mode.
581  */
check_notify_success(struct check * check)582 void check_notify_success(struct check *check)
583 {
584 	struct server *s = check->server;
585 
586 	if (s->next_admin & SRV_ADMF_MAINT)
587 		return;
588 
589 	if (s->track && s->track->next_state == SRV_ST_STOPPED)
590 		return;
591 
592 	if ((s->check.state & CHK_ST_ENABLED) && (s->check.health < s->check.rise))
593 		return;
594 
595 	if ((s->agent.state & CHK_ST_ENABLED) && (s->agent.health < s->agent.rise))
596 		return;
597 
598 	if ((check->state & CHK_ST_AGENT) && s->next_state == SRV_ST_STOPPING)
599 		return;
600 
601 	TRACE_STATE("health-check succeeded, set server RUNNING", CHK_EV_HCHK_END|CHK_EV_HCHK_SUCC, check);
602 	srv_set_running(s, NULL, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : NULL);
603 }
604 
605 /* Marks the check <check> as valid and tries to set its server into stopping mode
606  * if it was running or starting, and provided it isn't in maintenance and other
607  * checks comply. The conditions for the server to be marked in stopping mode are
608  * the same as for it to be turned up. Also, only the health checks support the
609  * nolb mode.
610  */
check_notify_stopping(struct check * check)611 void check_notify_stopping(struct check *check)
612 {
613 	struct server *s = check->server;
614 
615 	if (s->next_admin & SRV_ADMF_MAINT)
616 		return;
617 
618 	if (check->state & CHK_ST_AGENT)
619 		return;
620 
621 	if (s->track && s->track->next_state == SRV_ST_STOPPED)
622 		return;
623 
624 	if ((s->check.state & CHK_ST_ENABLED) && (s->check.health < s->check.rise))
625 		return;
626 
627 	if ((s->agent.state & CHK_ST_ENABLED) && (s->agent.health < s->agent.rise))
628 		return;
629 
630 	TRACE_STATE("health-check condionnaly succeeded, set server STOPPING", CHK_EV_HCHK_END|CHK_EV_HCHK_SUCC, check);
631 	srv_set_stopping(s, NULL, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : NULL);
632 }
633 
634 /* note: use health_adjust() only, which first checks that the observe mode is
635  * enabled. This will take the server lock if needed.
636  */
__health_adjust(struct server * s,short status)637 void __health_adjust(struct server *s, short status)
638 {
639 	int failed;
640 	int expire;
641 
642 	if (s->observe >= HANA_OBS_SIZE)
643 		return;
644 
645 	if (status >= HANA_STATUS_SIZE || !analyze_statuses[status].desc)
646 		return;
647 
648 	switch (analyze_statuses[status].lr[s->observe - 1]) {
649 		case 1:
650 			failed = 1;
651 			break;
652 
653 		case 2:
654 			failed = 0;
655 			break;
656 
657 		default:
658 			return;
659 	}
660 
661 	if (!failed) {
662 		/* good: clear consecutive_errors */
663 		s->consecutive_errors = 0;
664 		return;
665 	}
666 
667 	_HA_ATOMIC_INC(&s->consecutive_errors);
668 
669 	if (s->consecutive_errors < s->consecutive_errors_limit)
670 		return;
671 
672 	chunk_printf(&trash, "Detected %d consecutive errors, last one was: %s",
673 	             s->consecutive_errors, get_analyze_status(status));
674 
675 	if (s->check.fastinter)
676 		expire = tick_add(now_ms, MS_TO_TICKS(s->check.fastinter));
677 	else
678 		expire = TICK_ETERNITY;
679 
680 	HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
681 
682 	switch (s->onerror) {
683 		case HANA_ONERR_FASTINTER:
684 		/* force fastinter - nothing to do here as all modes force it */
685 			break;
686 
687 		case HANA_ONERR_SUDDTH:
688 		/* simulate a pre-fatal failed health check */
689 			if (s->check.health > s->check.rise)
690 				s->check.health = s->check.rise + 1;
691 
692 			/* fall through */
693 
694 		case HANA_ONERR_FAILCHK:
695 		/* simulate a failed health check */
696 			set_server_check_status(&s->check, HCHK_STATUS_HANA,
697 						trash.area);
698 			check_notify_failure(&s->check);
699 			break;
700 
701 		case HANA_ONERR_MARKDWN:
702 		/* mark server down */
703 			s->check.health = s->check.rise;
704 			set_server_check_status(&s->check, HCHK_STATUS_HANA,
705 						trash.area);
706 			check_notify_failure(&s->check);
707 			break;
708 
709 		default:
710 			/* write a warning? */
711 			break;
712 	}
713 
714 	HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);
715 
716 	s->consecutive_errors = 0;
717 	_HA_ATOMIC_INC(&s->counters.failed_hana);
718 
719 	if (tick_isset(expire) && tick_is_lt(expire, s->check.task->expire)) {
720 		/* requeue check task with new expire */
721 		task_schedule(s->check.task, expire);
722 	}
723 }
724 
725 /* Checks the connection. If an error has already been reported or the socket is
726  * closed, keep errno intact as it is supposed to contain the valid error code.
727  * If no error is reported, check the socket's error queue using getsockopt().
728  * Warning, this must be done only once when returning from poll, and never
729  * after an I/O error was attempted, otherwise the error queue might contain
730  * inconsistent errors. If an error is detected, the CO_FL_ERROR is set on the
731  * socket. Returns non-zero if an error was reported, zero if everything is
732  * clean (including a properly closed socket).
733  */
retrieve_errno_from_socket(struct connection * conn)734 static int retrieve_errno_from_socket(struct connection *conn)
735 {
736 	int skerr;
737 	socklen_t lskerr = sizeof(skerr);
738 
739 	if (conn->flags & CO_FL_ERROR && (unclean_errno(errno) || !conn->ctrl))
740 		return 1;
741 
742 	if (!conn_ctrl_ready(conn))
743 		return 0;
744 
745 	if (getsockopt(conn->handle.fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr) == 0)
746 		errno = skerr;
747 
748 	errno = unclean_errno(errno);
749 
750 	if (!errno) {
751 		/* we could not retrieve an error, that does not mean there is
752 		 * none. Just don't change anything and only report the prior
753 		 * error if any.
754 		 */
755 		if (conn->flags & CO_FL_ERROR)
756 			return 1;
757 		else
758 			return 0;
759 	}
760 
761 	conn->flags |= CO_FL_ERROR | CO_FL_SOCK_WR_SH | CO_FL_SOCK_RD_SH;
762 	return 1;
763 }
764 
765 /* Tries to collect as much information as possible on the connection status,
766  * and adjust the server status accordingly. It may make use of <errno_bck>
767  * if non-null when the caller is absolutely certain of its validity (eg:
768  * checked just after a syscall). If the caller doesn't have a valid errno,
769  * it can pass zero, and retrieve_errno_from_socket() will be called to try
770  * to extract errno from the socket. If no error is reported, it will consider
771  * the <expired> flag. This is intended to be used when a connection error was
772  * reported in conn->flags or when a timeout was reported in <expired>. The
773  * function takes care of not updating a server status which was already set.
774  * All situations where at least one of <expired> or CO_FL_ERROR are set
775  * produce a status.
776  */
chk_report_conn_err(struct check * check,int errno_bck,int expired)777 void chk_report_conn_err(struct check *check, int errno_bck, int expired)
778 {
779 	struct conn_stream *cs = check->cs;
780 	struct connection *conn = cs_conn(cs);
781 	const char *err_msg;
782 	struct buffer *chk;
783 	int step;
784 
785 	if (check->result != CHK_RES_UNKNOWN) {
786 		return;
787 	}
788 
789 	errno = unclean_errno(errno_bck);
790 	if (conn && errno)
791 		retrieve_errno_from_socket(conn);
792 
793 	if (conn && !(conn->flags & CO_FL_ERROR) &&
794 	    !(cs->flags & CS_FL_ERROR) && !expired)
795 		return;
796 
797 	TRACE_ENTER(CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check, 0, 0, (size_t[]){expired});
798 
799 	/* we'll try to build a meaningful error message depending on the
800 	 * context of the error possibly present in conn->err_code, and the
801 	 * socket error possibly collected above. This is useful to know the
802 	 * exact step of the L6 layer (eg: SSL handshake).
803 	 */
804 	chk = get_trash_chunk();
805 
806 	if (check->type == PR_O2_TCPCHK_CHK &&
807 	    (check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_TCP_CHK) {
808 		step = tcpcheck_get_step_id(check, NULL);
809 		if (!step) {
810 			TRACE_DEVEL("initial connection failure", CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
811 			chunk_printf(chk, " at initial connection step of tcp-check");
812 		}
813 		else {
814 			chunk_printf(chk, " at step %d of tcp-check", step);
815 			/* we were looking for a string */
816 			if (check->current_step && check->current_step->action == TCPCHK_ACT_CONNECT) {
817 				if (check->current_step->connect.port)
818 					chunk_appendf(chk, " (connect port %d)" ,check->current_step->connect.port);
819 				else
820 					chunk_appendf(chk, " (connect)");
821 				TRACE_DEVEL("connection failure", CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
822 			}
823 			else if (check->current_step && check->current_step->action == TCPCHK_ACT_EXPECT) {
824 				struct tcpcheck_expect *expect = &check->current_step->expect;
825 
826 				switch (expect->type) {
827 				case TCPCHK_EXPECT_STRING:
828 					chunk_appendf(chk, " (expect string '%.*s')", (unsigned int)istlen(expect->data), istptr(expect->data));
829 					break;
830 				case TCPCHK_EXPECT_BINARY:
831 					chunk_appendf(chk, " (expect binary '%.*s')", (unsigned int)istlen(expect->data), istptr(expect->data));
832 					break;
833 				case TCPCHK_EXPECT_STRING_REGEX:
834 					chunk_appendf(chk, " (expect regex)");
835 					break;
836 				case TCPCHK_EXPECT_BINARY_REGEX:
837 					chunk_appendf(chk, " (expect binary regex)");
838 					break;
839 				case TCPCHK_EXPECT_STRING_LF:
840 					chunk_appendf(chk, " (expect log-format string)");
841 					break;
842 				case TCPCHK_EXPECT_BINARY_LF:
843 					chunk_appendf(chk, " (expect log-format binary)");
844 					break;
845 				case TCPCHK_EXPECT_HTTP_STATUS:
846 					chunk_appendf(chk, " (expect HTTP status codes)");
847 					break;
848 				case TCPCHK_EXPECT_HTTP_STATUS_REGEX:
849 					chunk_appendf(chk, " (expect HTTP status regex)");
850 					break;
851 				case TCPCHK_EXPECT_HTTP_HEADER:
852 					chunk_appendf(chk, " (expect HTTP header pattern)");
853 					break;
854 				case TCPCHK_EXPECT_HTTP_BODY:
855 					chunk_appendf(chk, " (expect HTTP body content '%.*s')", (unsigned int)istlen(expect->data), istptr(expect->data));
856 					break;
857 				case TCPCHK_EXPECT_HTTP_BODY_REGEX:
858 					chunk_appendf(chk, " (expect HTTP body regex)");
859 					break;
860 				case TCPCHK_EXPECT_HTTP_BODY_LF:
861 					chunk_appendf(chk, " (expect log-format HTTP body)");
862 					break;
863 				case TCPCHK_EXPECT_CUSTOM:
864 					chunk_appendf(chk, " (expect custom function)");
865 					break;
866 				case TCPCHK_EXPECT_UNDEF:
867 					chunk_appendf(chk, " (undefined expect!)");
868 					break;
869 				}
870 				TRACE_DEVEL("expect rule failed", CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
871 			}
872 			else if (check->current_step && check->current_step->action == TCPCHK_ACT_SEND) {
873 				chunk_appendf(chk, " (send)");
874 				TRACE_DEVEL("send rule failed", CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
875 			}
876 
877 			if (check->current_step && check->current_step->comment)
878 				chunk_appendf(chk, " comment: '%s'", check->current_step->comment);
879 		}
880 	}
881 
882 	if (conn && conn->err_code) {
883 		if (unclean_errno(errno))
884 			chunk_printf(&trash, "%s (%s)%s", conn_err_code_str(conn), strerror(errno),
885 				     chk->area);
886 		else
887 			chunk_printf(&trash, "%s%s", conn_err_code_str(conn),
888 				     chk->area);
889 		err_msg = trash.area;
890 	}
891 	else {
892 		if (unclean_errno(errno)) {
893 			chunk_printf(&trash, "%s%s", strerror(errno),
894 				     chk->area);
895 			err_msg = trash.area;
896 		}
897 		else {
898 			err_msg = chk->area;
899 		}
900 	}
901 
902 	if (check->state & CHK_ST_PORT_MISS) {
903 		/* NOTE: this is reported after <fall> tries */
904 		set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
905 	}
906 
907 	if (!conn || !conn->ctrl) {
908 		/* error before any connection attempt (connection allocation error or no control layer) */
909 		set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
910 	}
911 	else if (conn->flags & CO_FL_WAIT_L4_CONN) {
912 		/* L4 not established (yet) */
913 		if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
914 			set_server_check_status(check, HCHK_STATUS_L4CON, err_msg);
915 		else if (expired)
916 			set_server_check_status(check, HCHK_STATUS_L4TOUT, err_msg);
917 
918 		/*
919 		 * might be due to a server IP change.
920 		 * Let's trigger a DNS resolution if none are currently running.
921 		 */
922 		if (check->server)
923 			resolv_trigger_resolution(check->server->resolv_requester);
924 
925 	}
926 	else if (conn->flags & CO_FL_WAIT_L6_CONN) {
927 		/* L6 not established (yet) */
928 		if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
929 			set_server_check_status(check, HCHK_STATUS_L6RSP, err_msg);
930 		else if (expired)
931 			set_server_check_status(check, HCHK_STATUS_L6TOUT, err_msg);
932 	}
933 	else if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) {
934 		/* I/O error after connection was established and before we could diagnose */
935 		set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
936 	}
937 	else if (expired) {
938 		enum healthcheck_status tout = HCHK_STATUS_L7TOUT;
939 
940 		/* connection established but expired check */
941 		if (check->current_step && check->current_step->action == TCPCHK_ACT_EXPECT &&
942 		    check->current_step->expect.tout_status != HCHK_STATUS_UNKNOWN)
943 			tout = check->current_step->expect.tout_status;
944 		set_server_check_status(check, tout, err_msg);
945 	}
946 
947 	TRACE_LEAVE(CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
948 	return;
949 }
950 
951 
952 /* Builds the server state header used by HTTP health-checks */
httpchk_build_status_header(struct server * s,struct buffer * buf)953 int httpchk_build_status_header(struct server *s, struct buffer *buf)
954 {
955 	int sv_state;
956 	int ratio;
957 	char addr[46];
958 	char port[6];
959 	const char *srv_hlt_st[7] = { "DOWN", "DOWN %d/%d",
960 				      "UP %d/%d", "UP",
961 				      "NOLB %d/%d", "NOLB",
962 				      "no check" };
963 
964 	if (!(s->check.state & CHK_ST_ENABLED))
965 		sv_state = 6;
966 	else if (s->cur_state != SRV_ST_STOPPED) {
967 		if (s->check.health == s->check.rise + s->check.fall - 1)
968 			sv_state = 3; /* UP */
969 		else
970 			sv_state = 2; /* going down */
971 
972 		if (s->cur_state == SRV_ST_STOPPING)
973 			sv_state += 2;
974 	} else {
975 		if (s->check.health)
976 			sv_state = 1; /* going up */
977 		else
978 			sv_state = 0; /* DOWN */
979 	}
980 
981 	chunk_appendf(buf, srv_hlt_st[sv_state],
982 		      (s->cur_state != SRV_ST_STOPPED) ? (s->check.health - s->check.rise + 1) : (s->check.health),
983 		      (s->cur_state != SRV_ST_STOPPED) ? (s->check.fall) : (s->check.rise));
984 
985 	addr_to_str(&s->addr, addr, sizeof(addr));
986 	if (s->addr.ss_family == AF_INET || s->addr.ss_family == AF_INET6)
987 		snprintf(port, sizeof(port), "%u", s->svc_port);
988 	else
989 		*port = 0;
990 
991 	chunk_appendf(buf, "; address=%s; port=%s; name=%s/%s; node=%s; weight=%d/%d; scur=%d/%d; qcur=%d",
992 		      addr, port, s->proxy->id, s->id,
993 		      global.node,
994 		      (s->cur_eweight * s->proxy->lbprm.wmult + s->proxy->lbprm.wdiv - 1) / s->proxy->lbprm.wdiv,
995 		      (s->proxy->lbprm.tot_weight * s->proxy->lbprm.wmult + s->proxy->lbprm.wdiv - 1) / s->proxy->lbprm.wdiv,
996 		      s->cur_sess, s->proxy->beconn - s->proxy->nbpend,
997 		      s->nbpend);
998 
999 	if ((s->cur_state == SRV_ST_STARTING) &&
1000 	    now.tv_sec < s->last_change + s->slowstart &&
1001 	    now.tv_sec >= s->last_change) {
1002 		ratio = MAX(1, 100 * (now.tv_sec - s->last_change) / s->slowstart);
1003 		chunk_appendf(buf, "; throttle=%d%%", ratio);
1004 	}
1005 
1006 	return b_data(buf);
1007 }
1008 
1009 /**************************************************************************/
1010 /***************** Health-checks based on connections *********************/
1011 /**************************************************************************/
1012 /* This function is used only for server health-checks. It handles connection
1013  * status updates including errors. If necessary, it wakes the check task up.
1014  * It returns 0 on normal cases, <0 if at least one close() has happened on the
1015  * connection (eg: reconnect). It relies on tcpcheck_main().
1016  */
wake_srv_chk(struct conn_stream * cs)1017 static int wake_srv_chk(struct conn_stream *cs)
1018 {
1019 	struct connection *conn = cs->conn;
1020 	struct check *check = cs->data;
1021 	struct email_alertq *q = container_of(check, typeof(*q), check);
1022 	int ret = 0;
1023 
1024 	TRACE_ENTER(CHK_EV_HCHK_WAKE, check);
1025 	if (check->server)
1026 		HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
1027 	else
1028 		HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
1029 
1030 	/* we may have to make progress on the TCP checks */
1031 	ret = tcpcheck_main(check);
1032 
1033 	cs = check->cs;
1034 	conn = cs->conn;
1035 
1036 	if (unlikely(conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)) {
1037 		/* We may get error reports bypassing the I/O handlers, typically
1038 		 * the case when sending a pure TCP check which fails, then the I/O
1039 		 * handlers above are not called. This is completely handled by the
1040 		 * main processing task so let's simply wake it up. If we get here,
1041 		 * we expect errno to still be valid.
1042 		 */
1043 		TRACE_ERROR("report connection error", CHK_EV_HCHK_WAKE|CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
1044 		chk_report_conn_err(check, errno, 0);
1045 		task_wakeup(check->task, TASK_WOKEN_IO);
1046 	}
1047 
1048 	if (check->result != CHK_RES_UNKNOWN || ret == -1) {
1049 		/* Check complete or aborted. If connection not yet closed do it
1050 		 * now and wake the check task up to be sure the result is
1051 		 * handled ASAP. */
1052 		cs_drain_and_close(cs);
1053 		ret = -1;
1054 
1055 		if (check->wait_list.events)
1056 			cs->conn->mux->unsubscribe(cs, check->wait_list.events, &check->wait_list);
1057 
1058 		/* We may have been scheduled to run, and the
1059 		 * I/O handler expects to have a cs, so remove
1060 		 * the tasklet
1061 		 */
1062 		tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
1063 		task_wakeup(check->task, TASK_WOKEN_IO);
1064 	}
1065 
1066 	if (check->server)
1067 		HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
1068 	else
1069 		HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
1070 
1071 	TRACE_LEAVE(CHK_EV_HCHK_WAKE, check);
1072 	return ret;
1073 }
1074 
1075 /* 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 int state)1076 struct task *event_srv_chk_io(struct task *t, void *ctx, unsigned int state)
1077 {
1078 	struct check *check = ctx;
1079 	struct conn_stream *cs = check->cs;
1080 
1081 	wake_srv_chk(cs);
1082 	return NULL;
1083 }
1084 
1085 /* manages a server health-check that uses a connection. Returns
1086  * the time the task accepts to wait, or TIME_ETERNITY for infinity.
1087  *
1088  * Please do NOT place any return statement in this function and only leave
1089  * via the out_unlock label.
1090  */
process_chk_conn(struct task * t,void * context,unsigned int state)1091 struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
1092 {
1093 	struct check *check = context;
1094 	struct proxy *proxy = check->proxy;
1095 	struct conn_stream *cs;
1096 	struct connection *conn;
1097 	int rv;
1098 	int expired = tick_is_expired(t->expire, now_ms);
1099 
1100 	TRACE_ENTER(CHK_EV_TASK_WAKE, check);
1101 
1102 	if (check->server)
1103 		HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
1104 
1105 	if (!(check->state & CHK_ST_INPROGRESS)) {
1106 		/* no check currently running */
1107 		if (!expired) /* woke up too early */ {
1108 			TRACE_STATE("health-check wake up too early", CHK_EV_TASK_WAKE, check);
1109 			goto out_unlock;
1110 		}
1111 
1112 		/* we don't send any health-checks when the proxy is
1113 		 * stopped, the server should not be checked or the check
1114 		 * is disabled.
1115 		 */
1116 		if (((check->state & (CHK_ST_ENABLED | CHK_ST_PAUSED)) != CHK_ST_ENABLED) ||
1117 		    proxy->disabled) {
1118 			TRACE_STATE("health-check paused or disabled", CHK_EV_TASK_WAKE, check);
1119 			goto reschedule;
1120 		}
1121 
1122 		/* we'll initiate a new check */
1123 		set_server_check_status(check, HCHK_STATUS_START, NULL);
1124 
1125 		check->state |= CHK_ST_INPROGRESS;
1126 		TRACE_STATE("init new health-check", CHK_EV_TASK_WAKE|CHK_EV_HCHK_START, check);
1127 
1128 		task_set_affinity(t, tid_bit);
1129 
1130 		check->current_step = NULL;
1131 		tcpcheck_main(check);
1132 		expired = 0;
1133 	}
1134 
1135 	cs = check->cs;
1136 	conn = cs_conn(cs);
1137 
1138 	/* there was a test running.
1139 	 * First, let's check whether there was an uncaught error,
1140 	 * which can happen on connect timeout or error.
1141 	 */
1142 	if (check->result == CHK_RES_UNKNOWN) {
1143 		/* Here the connection must be defined. Otherwise the
1144 		 * error would have already been detected
1145 		 */
1146 		if ((conn && ((conn->flags & CO_FL_ERROR) || (cs->flags & CS_FL_ERROR))) || expired) {
1147 			TRACE_ERROR("report connection error", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
1148 			chk_report_conn_err(check, 0, expired);
1149 		}
1150 		else {
1151 			if (check->state & CHK_ST_CLOSE_CONN) {
1152 				TRACE_DEVEL("closing current connection", CHK_EV_TASK_WAKE|CHK_EV_HCHK_RUN, check);
1153 				cs_destroy(cs);
1154 				cs = NULL;
1155 				conn = NULL;
1156 				check->cs = NULL;
1157 				check->state &= ~CHK_ST_CLOSE_CONN;
1158 				tcpcheck_main(check);
1159 			}
1160 			if (check->result == CHK_RES_UNKNOWN) {
1161 				TRACE_DEVEL("health-check not expired", CHK_EV_TASK_WAKE|CHK_EV_HCHK_RUN, check);
1162 				goto out_unlock; /* timeout not reached, wait again */
1163 			}
1164 		}
1165 	}
1166 
1167 	/* check complete or aborted */
1168 	TRACE_STATE("health-check complete or aborted", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END, check);
1169 
1170 	check->current_step = NULL;
1171 
1172 	if (conn && conn->xprt) {
1173 		/* The check was aborted and the connection was not yet closed.
1174 		 * This can happen upon timeout, or when an external event such
1175 		 * as a failed response coupled with "observe layer7" caused the
1176 		 * server state to be suddenly changed.
1177 		 */
1178 		cs_drain_and_close(cs);
1179 	}
1180 
1181 	if (cs) {
1182 		if (check->wait_list.events)
1183 			cs->conn->mux->unsubscribe(cs, check->wait_list.events, &check->wait_list);
1184 		/* We may have been scheduled to run, and the
1185 		 * I/O handler expects to have a cs, so remove
1186 		 * the tasklet
1187 		 */
1188 		tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
1189 		cs_destroy(cs);
1190 		cs = check->cs = NULL;
1191 		conn = NULL;
1192 	}
1193 
1194 	if (check->sess != NULL) {
1195 		vars_prune(&check->vars, check->sess, NULL);
1196 		session_free(check->sess);
1197 		check->sess = NULL;
1198 	}
1199 
1200 	if (check->server) {
1201 		if (check->result == CHK_RES_FAILED) {
1202 			/* a failure or timeout detected */
1203 			TRACE_DEVEL("report failure", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
1204 			check_notify_failure(check);
1205 		}
1206 		else if (check->result == CHK_RES_CONDPASS) {
1207 			/* check is OK but asks for stopping mode */
1208 			TRACE_DEVEL("report conditional success", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END|CHK_EV_HCHK_SUCC, check);
1209 			check_notify_stopping(check);
1210 		}
1211 		else if (check->result == CHK_RES_PASSED) {
1212 			/* a success was detected */
1213 			TRACE_DEVEL("report success", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END|CHK_EV_HCHK_SUCC, check);
1214 			check_notify_success(check);
1215 		}
1216 	}
1217 	task_set_affinity(t, MAX_THREADS_MASK);
1218 	check_release_buf(check, &check->bi);
1219 	check_release_buf(check, &check->bo);
1220 	check->state &= ~(CHK_ST_INPROGRESS|CHK_ST_IN_ALLOC|CHK_ST_OUT_ALLOC);
1221 
1222 	if (check->server) {
1223 		rv = 0;
1224 		if (global.spread_checks > 0) {
1225 			rv = srv_getinter(check) * global.spread_checks / 100;
1226 			rv -= (int) (2 * rv * (ha_random32() / 4294967295.0));
1227 		}
1228 		t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(check) + rv));
1229 	}
1230 
1231  reschedule:
1232 	while (tick_is_expired(t->expire, now_ms))
1233 		t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
1234  out_unlock:
1235 	if (check->server)
1236 		HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
1237 
1238 	TRACE_LEAVE(CHK_EV_TASK_WAKE, check);
1239 	return t;
1240 }
1241 
1242 
1243 /**************************************************************************/
1244 /************************** Init/deinit checks ****************************/
1245 /**************************************************************************/
1246 /*
1247  * Tries to grab a buffer and to re-enables processing on check <target>. The
1248  * check flags are used to figure what buffer was requested. It returns 1 if the
1249  * allocation succeeds, in which case the I/O tasklet is woken up, or 0 if it's
1250  * impossible to wake up and we prefer to be woken up later.
1251  */
check_buf_available(void * target)1252 int check_buf_available(void *target)
1253 {
1254 	struct check *check = target;
1255 
1256 	if ((check->state & CHK_ST_IN_ALLOC) && b_alloc(&check->bi)) {
1257 		TRACE_STATE("unblocking check, input buffer allocated", CHK_EV_TCPCHK_EXP|CHK_EV_RX_BLK, check);
1258 		check->state &= ~CHK_ST_IN_ALLOC;
1259 		tasklet_wakeup(check->wait_list.tasklet);
1260 		return 1;
1261 	}
1262 	if ((check->state & CHK_ST_OUT_ALLOC) && b_alloc(&check->bo)) {
1263 		TRACE_STATE("unblocking check, output buffer allocated", CHK_EV_TCPCHK_SND|CHK_EV_TX_BLK, check);
1264 		check->state &= ~CHK_ST_OUT_ALLOC;
1265 		tasklet_wakeup(check->wait_list.tasklet);
1266 		return 1;
1267 	}
1268 
1269 	return 0;
1270 }
1271 
1272 /*
1273  * Allocate a buffer. If it fails, it adds the check in buffer wait queue.
1274  */
check_get_buf(struct check * check,struct buffer * bptr)1275 struct buffer *check_get_buf(struct check *check, struct buffer *bptr)
1276 {
1277 	struct buffer *buf = NULL;
1278 
1279 	if (likely(!LIST_INLIST(&check->buf_wait.list)) &&
1280 	    unlikely((buf = b_alloc(bptr)) == NULL)) {
1281 		check->buf_wait.target = check;
1282 		check->buf_wait.wakeup_cb = check_buf_available;
1283 		LIST_APPEND(&ti->buffer_wq, &check->buf_wait.list);
1284 	}
1285 	return buf;
1286 }
1287 
1288 /*
1289  * Release a buffer, if any, and try to wake up entities waiting in the buffer
1290  * wait queue.
1291  */
check_release_buf(struct check * check,struct buffer * bptr)1292 void check_release_buf(struct check *check, struct buffer *bptr)
1293 {
1294 	if (bptr->size) {
1295 		b_free(bptr);
1296 		offer_buffers(check->buf_wait.target, 1);
1297 	}
1298 }
1299 
init_check(struct check * check,int type)1300 const char *init_check(struct check *check, int type)
1301 {
1302 	check->type = type;
1303 
1304 	check->bi = BUF_NULL;
1305 	check->bo = BUF_NULL;
1306 	LIST_INIT(&check->buf_wait.list);
1307 
1308 	check->wait_list.tasklet = tasklet_new();
1309 	if (!check->wait_list.tasklet)
1310 		return "out of memory while allocating check tasklet";
1311 	check->wait_list.events = 0;
1312 	check->wait_list.tasklet->process = event_srv_chk_io;
1313 	check->wait_list.tasklet->context = check;
1314 	return NULL;
1315 }
1316 
free_check(struct check * check)1317 void free_check(struct check *check)
1318 {
1319 	task_destroy(check->task);
1320 	if (check->wait_list.tasklet)
1321 		tasklet_free(check->wait_list.tasklet);
1322 
1323 	check_release_buf(check, &check->bi);
1324 	check_release_buf(check, &check->bo);
1325 	if (check->cs) {
1326 		ha_free(&check->cs->conn);
1327 		cs_free(check->cs);
1328 		check->cs = NULL;
1329 	}
1330 }
1331 
1332 /* manages a server health-check. Returns the time the task accepts to wait, or
1333  * TIME_ETERNITY for infinity.
1334  */
process_chk(struct task * t,void * context,unsigned int state)1335 struct task *process_chk(struct task *t, void *context, unsigned int state)
1336 {
1337 	struct check *check = context;
1338 
1339 	if (check->type == PR_O2_EXT_CHK)
1340 		return process_chk_proc(t, context, state);
1341 	return process_chk_conn(t, context, state);
1342 
1343 }
1344 
1345 
start_check_task(struct check * check,int mininter,int nbcheck,int srvpos)1346 static int start_check_task(struct check *check, int mininter,
1347 			    int nbcheck, int srvpos)
1348 {
1349 	struct task *t;
1350 	unsigned long thread_mask = MAX_THREADS_MASK;
1351 
1352 	if (check->type == PR_O2_EXT_CHK)
1353 		thread_mask = 1;
1354 
1355 	/* task for the check */
1356 	if ((t = task_new(thread_mask)) == NULL) {
1357 		ha_alert("Starting [%s:%s] check: out of memory.\n",
1358 			 check->server->proxy->id, check->server->id);
1359 		return 0;
1360 	}
1361 
1362 	check->task = t;
1363 	t->process = process_chk;
1364 	t->context = check;
1365 
1366 	if (mininter < srv_getinter(check))
1367 		mininter = srv_getinter(check);
1368 
1369 	if (global.max_spread_checks && mininter > global.max_spread_checks)
1370 		mininter = global.max_spread_checks;
1371 
1372 	/* check this every ms */
1373 	t->expire = tick_add(now_ms, MS_TO_TICKS(mininter * srvpos / nbcheck));
1374 	check->start = now;
1375 	task_queue(t);
1376 
1377 	return 1;
1378 }
1379 
1380 /* updates the server's weight during a warmup stage. Once the final weight is
1381  * reached, the task automatically stops. Note that any server status change
1382  * must have updated s->last_change accordingly.
1383  */
server_warmup(struct task * t,void * context,unsigned int state)1384 struct task *server_warmup(struct task *t, void *context, unsigned int state)
1385 {
1386 	struct server *s = context;
1387 
1388 	/* by default, plan on stopping the task */
1389 	t->expire = TICK_ETERNITY;
1390 	if ((s->next_admin & SRV_ADMF_MAINT) ||
1391 	    (s->next_state != SRV_ST_STARTING))
1392 		return t;
1393 
1394 	HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
1395 
1396 	/* recalculate the weights and update the state */
1397 	server_recalc_eweight(s, 1);
1398 
1399 	/* probably that we can refill this server with a bit more connections */
1400 	pendconn_grab_from_px(s);
1401 
1402 	HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);
1403 
1404 	/* get back there in 1 second or 1/20th of the slowstart interval,
1405 	 * whichever is greater, resulting in small 5% steps.
1406 	 */
1407 	if (s->next_state == SRV_ST_STARTING)
1408 		t->expire = tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20)));
1409 	return t;
1410 }
1411 
1412 /*
1413  * Start health-check.
1414  * Returns 0 if OK, ERR_FATAL on error, and prints the error in this case.
1415  */
start_checks()1416 static int start_checks()
1417 {
1418 
1419 	struct proxy *px;
1420 	struct server *s;
1421 	struct task *t;
1422 	int nbcheck=0, mininter=0, srvpos=0;
1423 
1424 	/* 0- init the dummy frontend used to create all checks sessions */
1425 	init_new_proxy(&checks_fe);
1426 	checks_fe.id = strdup("CHECKS-FE");
1427 	checks_fe.cap = PR_CAP_FE | PR_CAP_BE;
1428         checks_fe.mode = PR_MODE_TCP;
1429 	checks_fe.maxconn = 0;
1430 	checks_fe.conn_retries = CONN_RETRIES;
1431 	checks_fe.options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
1432 	checks_fe.timeout.client = TICK_ETERNITY;
1433 
1434 	/* 1- count the checkers to run simultaneously.
1435 	 * We also determine the minimum interval among all of those which
1436 	 * have an interval larger than SRV_CHK_INTER_THRES. This interval
1437 	 * will be used to spread their start-up date. Those which have
1438 	 * a shorter interval will start independently and will not dictate
1439 	 * too short an interval for all others.
1440 	 */
1441 	for (px = proxies_list; px; px = px->next) {
1442 		for (s = px->srv; s; s = s->next) {
1443 			if (s->slowstart) {
1444 				if ((t = task_new(MAX_THREADS_MASK)) == NULL) {
1445 					ha_alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
1446 					return ERR_ALERT | ERR_FATAL;
1447 				}
1448 				/* We need a warmup task that will be called when the server
1449 				 * state switches from down to up.
1450 				 */
1451 				s->warmup = t;
1452 				t->process = server_warmup;
1453 				t->context = s;
1454 				/* server can be in this state only because of */
1455 				if (s->next_state == SRV_ST_STARTING)
1456 					task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, (now.tv_sec - s->last_change)) / 20)));
1457 			}
1458 
1459 			if (s->check.state & CHK_ST_CONFIGURED) {
1460 				nbcheck++;
1461 				if ((srv_getinter(&s->check) >= SRV_CHK_INTER_THRES) &&
1462 				    (!mininter || mininter > srv_getinter(&s->check)))
1463 					mininter = srv_getinter(&s->check);
1464 			}
1465 
1466 			if (s->agent.state & CHK_ST_CONFIGURED) {
1467 				nbcheck++;
1468 				if ((srv_getinter(&s->agent) >= SRV_CHK_INTER_THRES) &&
1469 				    (!mininter || mininter > srv_getinter(&s->agent)))
1470 					mininter = srv_getinter(&s->agent);
1471 			}
1472 		}
1473 	}
1474 
1475 	if (!nbcheck)
1476 		return ERR_NONE;
1477 
1478 	srand((unsigned)time(NULL));
1479 
1480 	/* 2- start them as far as possible from each other. For this, we will
1481 	 * start them after their interval is set to the min interval divided
1482 	 * by the number of servers, weighted by the server's position in the
1483 	 * list.
1484 	 */
1485 	for (px = proxies_list; px; px = px->next) {
1486 		if ((px->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
1487 			if (init_pid_list()) {
1488 				ha_alert("Starting [%s] check: out of memory.\n", px->id);
1489 				return ERR_ALERT | ERR_FATAL;
1490 			}
1491 		}
1492 
1493 		for (s = px->srv; s; s = s->next) {
1494 			/* A task for the main check */
1495 			if (s->check.state & CHK_ST_CONFIGURED) {
1496 				if (s->check.type == PR_O2_EXT_CHK) {
1497 					if (!prepare_external_check(&s->check))
1498 						return ERR_ALERT | ERR_FATAL;
1499 				}
1500 				if (!start_check_task(&s->check, mininter, nbcheck, srvpos))
1501 					return ERR_ALERT | ERR_FATAL;
1502 				srvpos++;
1503 			}
1504 
1505 			/* A task for a auxiliary agent check */
1506 			if (s->agent.state & CHK_ST_CONFIGURED) {
1507 				if (!start_check_task(&s->agent, mininter, nbcheck, srvpos)) {
1508 					return ERR_ALERT | ERR_FATAL;
1509 				}
1510 				srvpos++;
1511 			}
1512 		}
1513 	}
1514 	return ERR_NONE;
1515 }
1516 
1517 
1518 /*
1519  * Return value:
1520  *   the port to be used for the health check
1521  *   0 in case no port could be found for the check
1522  */
srv_check_healthcheck_port(struct check * chk)1523 static int srv_check_healthcheck_port(struct check *chk)
1524 {
1525 	int i = 0;
1526 	struct server *srv = NULL;
1527 
1528 	srv = chk->server;
1529 
1530 	/* by default, we use the health check port configured */
1531 	if (chk->port > 0)
1532 		return chk->port;
1533 
1534 	/* try to get the port from check_core.addr if check.port not set */
1535 	i = get_host_port(&chk->addr);
1536 	if (i > 0)
1537 		return i;
1538 
1539 	/* try to get the port from server address */
1540 	/* prevent MAPPORTS from working at this point, since checks could
1541 	 * not be performed in such case (MAPPORTS impose a relative ports
1542 	 * based on live traffic)
1543 	 */
1544 	if (srv->flags & SRV_F_MAPPORTS)
1545 		return 0;
1546 
1547 	i = srv->svc_port; /* by default */
1548 	if (i > 0)
1549 		return i;
1550 
1551 	return 0;
1552 }
1553 
1554 /* Initializes an health-check attached to the server <srv>. Non-zero is returned
1555  * if an error occurred.
1556  */
init_srv_check(struct server * srv)1557 static int init_srv_check(struct server *srv)
1558 {
1559 	const char *err;
1560 	struct tcpcheck_rule *r;
1561 	int ret = ERR_NONE;
1562 	int check_type;
1563 
1564 	if (!srv->do_check || !(srv->proxy->cap & PR_CAP_BE))
1565 		goto out;
1566 
1567 	check_type = srv->check.tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK;
1568 
1569 	/* If neither a port nor an addr was specified and no check transport
1570 	 * layer is forced, then the transport layer used by the checks is the
1571 	 * same as for the production traffic. Otherwise we use raw_sock by
1572 	 * default, unless one is specified.
1573 	 */
1574 	if (!srv->check.port && !is_addr(&srv->check.addr)) {
1575 		if (!srv->check.use_ssl && srv->use_ssl != -1) {
1576 			srv->check.use_ssl = srv->use_ssl;
1577 			srv->check.xprt    = srv->xprt;
1578 		}
1579 		else if (srv->check.use_ssl == 1)
1580 			srv->check.xprt = xprt_get(XPRT_SSL);
1581 		srv->check.send_proxy |= (srv->pp_opts);
1582 	}
1583 	else if (srv->check.use_ssl == 1)
1584 		srv->check.xprt = xprt_get(XPRT_SSL);
1585 
1586 	/* Inherit the mux protocol from the server if not already defined for
1587 	 * the check
1588 	 */
1589 	if (srv->mux_proto && !srv->check.mux_proto &&
1590 	    ((srv->mux_proto->mode == PROTO_MODE_HTTP && check_type == TCPCHK_RULES_HTTP_CHK) ||
1591 	     (srv->mux_proto->mode == PROTO_MODE_TCP && check_type != TCPCHK_RULES_HTTP_CHK))) {
1592 		srv->check.mux_proto = srv->mux_proto;
1593 	}
1594 	/* test that check proto is valid if explicitly defined */
1595 	else if (srv->check.mux_proto &&
1596 	         ((srv->check.mux_proto->mode == PROTO_MODE_HTTP && check_type != TCPCHK_RULES_HTTP_CHK) ||
1597 	          (srv->check.mux_proto->mode == PROTO_MODE_TCP && check_type == TCPCHK_RULES_HTTP_CHK))) {
1598 		ha_alert("config: %s '%s': server '%s' uses an incompatible MUX protocol for the selected check type\n",
1599 		         proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
1600 		ret |= ERR_ALERT | ERR_FATAL;
1601 		goto out;
1602 	}
1603 
1604 	/* validate <srv> server health-check settings */
1605 
1606 	/* We need at least a service port, a check port or the first tcp-check
1607 	 * rule must be a 'connect' one when checking an IPv4/IPv6 server.
1608 	 */
1609 	if ((srv_check_healthcheck_port(&srv->check) != 0) ||
1610 	    (!is_inet_addr(&srv->check.addr) && (is_addr(&srv->check.addr) || !is_inet_addr(&srv->addr))))
1611 		goto init;
1612 
1613 	if (!srv->proxy->tcpcheck_rules.list || LIST_ISEMPTY(srv->proxy->tcpcheck_rules.list)) {
1614 		ha_alert("config: %s '%s': server '%s' has neither service port nor check port.\n",
1615 			 proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
1616 		ret |= ERR_ALERT | ERR_ABORT;
1617 		goto out;
1618 	}
1619 
1620 	/* search the first action (connect / send / expect) in the list */
1621 	r = get_first_tcpcheck_rule(&srv->proxy->tcpcheck_rules);
1622 	if (!r || (r->action != TCPCHK_ACT_CONNECT) || (!r->connect.port && !get_host_port(&r->connect.addr))) {
1623 		ha_alert("config: %s '%s': server '%s' has neither service port nor check port "
1624 			 "nor tcp_check rule 'connect' with port information.\n",
1625 			 proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
1626 		ret |= ERR_ALERT | ERR_ABORT;
1627 		goto out;
1628 	}
1629 
1630 	/* scan the tcp-check ruleset to ensure a port has been configured */
1631 	list_for_each_entry(r, srv->proxy->tcpcheck_rules.list, list) {
1632 		if ((r->action == TCPCHK_ACT_CONNECT) && (!r->connect.port && !get_host_port(&r->connect.addr))) {
1633 			ha_alert("config: %s '%s': server '%s' has neither service port nor check port, "
1634 				 "and a tcp_check rule 'connect' with no port information.\n",
1635 				 proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
1636 			ret |= ERR_ALERT | ERR_ABORT;
1637 			goto out;
1638 		}
1639 	}
1640 
1641   init:
1642 	if (!(srv->proxy->options2 & PR_O2_CHK_ANY)) {
1643 		struct tcpcheck_ruleset *rs = NULL;
1644 		struct tcpcheck_rules *rules = &srv->proxy->tcpcheck_rules;
1645 		//char *errmsg = NULL;
1646 
1647 		srv->proxy->options2 &= ~PR_O2_CHK_ANY;
1648 		srv->proxy->options2 |= PR_O2_TCPCHK_CHK;
1649 
1650 		rs = find_tcpcheck_ruleset("*tcp-check");
1651 		if (!rs) {
1652 			rs = create_tcpcheck_ruleset("*tcp-check");
1653 			if (rs == NULL) {
1654 				ha_alert("config: %s '%s': out of memory.\n",
1655 					 proxy_type_str(srv->proxy), srv->proxy->id);
1656 				ret |= ERR_ALERT | ERR_FATAL;
1657 				goto out;
1658 			}
1659 		}
1660 
1661 		free_tcpcheck_vars(&rules->preset_vars);
1662 		rules->list = &rs->rules;
1663 		rules->flags = 0;
1664 	}
1665 
1666 	err = init_check(&srv->check, srv->proxy->options2 & PR_O2_CHK_ANY);
1667 	if (err) {
1668 		ha_alert("config: %s '%s': unable to init check for server '%s' (%s).\n",
1669 			 proxy_type_str(srv->proxy), srv->proxy->id, srv->id, err);
1670 		ret |= ERR_ALERT | ERR_ABORT;
1671 		goto out;
1672 	}
1673 	srv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
1674 	global.maxsock++;
1675 
1676   out:
1677 	return ret;
1678 }
1679 
1680 /* Initializes an agent-check attached to the server <srv>. Non-zero is returned
1681  * if an error occurred.
1682  */
init_srv_agent_check(struct server * srv)1683 static int init_srv_agent_check(struct server *srv)
1684 {
1685 	struct tcpcheck_rule *chk;
1686 	const char *err;
1687 	int ret = ERR_NONE;
1688 
1689 	if (!srv->do_agent || !(srv->proxy->cap & PR_CAP_BE))
1690 		goto out;
1691 
1692 	/* If there is no connect rule preceding all send / expect rules, an
1693 	 * implicit one is inserted before all others.
1694 	 */
1695 	chk = get_first_tcpcheck_rule(srv->agent.tcpcheck_rules);
1696 	if (!chk || chk->action != TCPCHK_ACT_CONNECT) {
1697 		chk = calloc(1, sizeof(*chk));
1698 		if (!chk) {
1699 			ha_alert("config : %s '%s': unable to add implicit tcp-check connect rule"
1700 				 " to agent-check for server '%s' (out of memory).\n",
1701 				 proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
1702 			ret |= ERR_ALERT | ERR_FATAL;
1703 			goto out;
1704 		}
1705 		chk->action = TCPCHK_ACT_CONNECT;
1706 		chk->connect.options = (TCPCHK_OPT_DEFAULT_CONNECT|TCPCHK_OPT_IMPLICIT);
1707 		LIST_INSERT(srv->agent.tcpcheck_rules->list, &chk->list);
1708 	}
1709 
1710 
1711 	err = init_check(&srv->agent, PR_O2_TCPCHK_CHK);
1712 	if (err) {
1713 		ha_alert("config: %s '%s': unable to init agent-check for server '%s' (%s).\n",
1714 			 proxy_type_str(srv->proxy), srv->proxy->id, srv->id, err);
1715 		ret |= ERR_ALERT | ERR_ABORT;
1716 		goto out;
1717 	}
1718 
1719 	if (!srv->agent.inter)
1720 		srv->agent.inter = srv->check.inter;
1721 
1722 	srv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
1723 	global.maxsock++;
1724 
1725   out:
1726 	return ret;
1727 }
1728 
deinit_srv_check(struct server * srv)1729 static void deinit_srv_check(struct server *srv)
1730 {
1731 	if (srv->check.state & CHK_ST_CONFIGURED)
1732 		free_check(&srv->check);
1733 	srv->check.state &= ~CHK_ST_CONFIGURED & ~CHK_ST_ENABLED;
1734 	srv->do_check = 0;
1735 }
1736 
1737 
deinit_srv_agent_check(struct server * srv)1738 static void deinit_srv_agent_check(struct server *srv)
1739 {
1740 	if (srv->agent.tcpcheck_rules) {
1741 		free_tcpcheck_vars(&srv->agent.tcpcheck_rules->preset_vars);
1742 		ha_free(&srv->agent.tcpcheck_rules);
1743 	}
1744 
1745 	if (srv->agent.state & CHK_ST_CONFIGURED)
1746 		free_check(&srv->agent);
1747 
1748 	srv->agent.state &= ~CHK_ST_CONFIGURED & ~CHK_ST_ENABLED & ~CHK_ST_AGENT;
1749 	srv->do_agent = 0;
1750 }
1751 
1752 REGISTER_POST_SERVER_CHECK(init_srv_check);
1753 REGISTER_POST_SERVER_CHECK(init_srv_agent_check);
1754 REGISTER_POST_CHECK(start_checks);
1755 
1756 REGISTER_SERVER_DEINIT(deinit_srv_check);
1757 REGISTER_SERVER_DEINIT(deinit_srv_agent_check);
1758 
1759 
1760 /**************************************************************************/
1761 /************************** Check sample fetches **************************/
1762 /**************************************************************************/
1763 
1764 static struct sample_fetch_kw_list smp_kws = {ILH, {
1765 	{ /* END */ },
1766 }};
1767 
1768 INITCALL1(STG_REGISTER, sample_register_fetches, &smp_kws);
1769 
1770 
1771 /**************************************************************************/
1772 /************************ Check's parsing functions ***********************/
1773 /**************************************************************************/
1774 /* Parse the "addr" server keyword */
srv_parse_addr(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)1775 static int srv_parse_addr(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
1776 			  char **errmsg)
1777 {
1778 	struct sockaddr_storage *sk;
1779 	int port1, port2, err_code = 0;
1780 
1781 
1782 	if (!*args[*cur_arg+1]) {
1783 		memprintf(errmsg, "'%s' expects <ipv4|ipv6> as argument.", args[*cur_arg]);
1784 		goto error;
1785 	}
1786 
1787 	sk = str2sa_range(args[*cur_arg+1], NULL, &port1, &port2, NULL, NULL, errmsg, NULL, NULL,
1788 	                  PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT);
1789 	if (!sk) {
1790 		memprintf(errmsg, "'%s' : %s", args[*cur_arg], *errmsg);
1791 		goto error;
1792 	}
1793 
1794 	srv->check.addr = *sk;
1795 	/* if agentaddr was never set, we can use addr */
1796 	if (!(srv->flags & SRV_F_AGENTADDR))
1797 		srv->agent.addr = *sk;
1798 
1799   out:
1800 	return err_code;
1801 
1802  error:
1803 	err_code |= ERR_ALERT | ERR_FATAL;
1804 	goto out;
1805 }
1806 
1807 /* Parse the "agent-addr" server keyword */
srv_parse_agent_addr(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)1808 static int srv_parse_agent_addr(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
1809 				char **errmsg)
1810 {
1811 	struct sockaddr_storage sk;
1812 	int err_code = 0;
1813 
1814 	if (!*(args[*cur_arg+1])) {
1815 		memprintf(errmsg, "'%s' expects an address as argument.", args[*cur_arg]);
1816 		goto error;
1817 	}
1818 	memset(&sk, 0, sizeof(sk));
1819 	if (str2ip(args[*cur_arg + 1], &sk) == NULL) {
1820 		memprintf(errmsg, "parsing agent-addr failed. Check if '%s' is correct address.", args[*cur_arg+1]);
1821 		goto error;
1822 	}
1823 	set_srv_agent_addr(srv, &sk);
1824 
1825   out:
1826 	return err_code;
1827 
1828   error:
1829 	err_code |= ERR_ALERT | ERR_FATAL;
1830 	goto out;
1831 }
1832 
1833 /* Parse the "agent-check" server keyword */
srv_parse_agent_check(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)1834 static int srv_parse_agent_check(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
1835 				 char **errmsg)
1836 {
1837 	struct tcpcheck_ruleset *rs = NULL;
1838 	struct tcpcheck_rules *rules = srv->agent.tcpcheck_rules;
1839 	struct tcpcheck_rule *chk;
1840 	int err_code = 0;
1841 
1842 	if (srv->do_agent)
1843 		goto out;
1844 
1845 	if (!(curpx->cap & PR_CAP_BE)) {
1846 		memprintf(errmsg, "'%s' ignored because %s '%s' has no backend capability",
1847 			  args[*cur_arg], proxy_type_str(curpx), curpx->id);
1848 		return ERR_WARN;
1849 	}
1850 
1851 	if (!rules) {
1852 		rules = calloc(1, sizeof(*rules));
1853 		if (!rules) {
1854 			memprintf(errmsg, "out of memory.");
1855 			goto error;
1856 		}
1857 		LIST_INIT(&rules->preset_vars);
1858 		srv->agent.tcpcheck_rules = rules;
1859 	}
1860 	rules->list  = NULL;
1861 	rules->flags = 0;
1862 
1863 	rs = find_tcpcheck_ruleset("*agent-check");
1864 	if (rs)
1865 		goto ruleset_found;
1866 
1867 	rs = create_tcpcheck_ruleset("*agent-check");
1868 	if (rs == NULL) {
1869 		memprintf(errmsg, "out of memory.");
1870 		goto error;
1871 	}
1872 
1873 	chk = parse_tcpcheck_send((char *[]){"tcp-check", "send-lf", "%[var(check.agent_string)]", ""},
1874 				  1, curpx, &rs->rules, srv->conf.file, srv->conf.line, errmsg);
1875 	if (!chk) {
1876 		memprintf(errmsg, "'%s': %s", args[*cur_arg], *errmsg);
1877 		goto error;
1878 	}
1879 	chk->index = 0;
1880 	LIST_APPEND(&rs->rules, &chk->list);
1881 
1882 	chk = parse_tcpcheck_expect((char *[]){"tcp-check", "expect", "custom", ""},
1883 		                    1, curpx, &rs->rules, TCPCHK_RULES_AGENT_CHK,
1884 				    srv->conf.file, srv->conf.line, errmsg);
1885 	if (!chk) {
1886 		memprintf(errmsg, "'%s': %s", args[*cur_arg], *errmsg);
1887 		goto error;
1888 	}
1889 	chk->expect.custom = tcpcheck_agent_expect_reply;
1890 	chk->index = 1;
1891 	LIST_APPEND(&rs->rules, &chk->list);
1892 
1893   ruleset_found:
1894 	rules->list = &rs->rules;
1895 	rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
1896 	rules->flags |= TCPCHK_RULES_AGENT_CHK;
1897 	srv->do_agent = 1;
1898 
1899   out:
1900 	return err_code;
1901 
1902   error:
1903 	deinit_srv_agent_check(srv);
1904 	free_tcpcheck_ruleset(rs);
1905 	err_code |= ERR_ALERT | ERR_FATAL;
1906 	goto out;
1907 }
1908 
1909 /* Parse the "agent-inter" server keyword */
srv_parse_agent_inter(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)1910 static int srv_parse_agent_inter(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
1911 				 char **errmsg)
1912 {
1913 	const char *err = NULL;
1914 	unsigned int delay;
1915 	int err_code = 0;
1916 
1917 	if (!*(args[*cur_arg+1])) {
1918 		memprintf(errmsg, "'%s' expects a delay as argument.", args[*cur_arg]);
1919 		goto error;
1920 	}
1921 
1922 	err = parse_time_err(args[*cur_arg+1], &delay, TIME_UNIT_MS);
1923 	if (err == PARSE_TIME_OVER) {
1924 		memprintf(errmsg, "timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).",
1925 			  args[*cur_arg+1], args[*cur_arg], srv->id);
1926 		goto error;
1927 	}
1928 	else if (err == PARSE_TIME_UNDER) {
1929 		memprintf(errmsg, "timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.",
1930 			  args[*cur_arg+1], args[*cur_arg], srv->id);
1931 		goto error;
1932 	}
1933 	else if (err) {
1934 		memprintf(errmsg, "unexpected character '%c' in 'agent-inter' argument of server %s.",
1935 			  *err, srv->id);
1936 		goto error;
1937 	}
1938 	if (delay <= 0) {
1939 		memprintf(errmsg, "invalid value %d for argument '%s' of server %s.",
1940 			  delay, args[*cur_arg], srv->id);
1941 		goto error;
1942 	}
1943 	srv->agent.inter = delay;
1944 
1945   out:
1946 	return err_code;
1947 
1948   error:
1949 	err_code |= ERR_ALERT | ERR_FATAL;
1950 	goto out;
1951 }
1952 
1953 /* Parse the "agent-port" server keyword */
srv_parse_agent_port(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)1954 static int srv_parse_agent_port(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
1955 				char **errmsg)
1956 {
1957 	int err_code = 0;
1958 
1959 	if (!*(args[*cur_arg+1])) {
1960 		memprintf(errmsg, "'%s' expects a port number as argument.", args[*cur_arg]);
1961 		goto error;
1962 	}
1963 
1964 	global.maxsock++;
1965 	set_srv_agent_port(srv, atol(args[*cur_arg + 1]));
1966 
1967   out:
1968 	return err_code;
1969 
1970   error:
1971 	err_code |= ERR_ALERT | ERR_FATAL;
1972 	goto out;
1973 }
1974 
set_srv_agent_send(struct server * srv,const char * send)1975 int set_srv_agent_send(struct server *srv, const char *send)
1976 {
1977 	struct tcpcheck_rules *rules = srv->agent.tcpcheck_rules;
1978 	struct tcpcheck_var *var = NULL;
1979 	char *str;
1980 
1981 	str = strdup(send);
1982 	var = create_tcpcheck_var(ist("check.agent_string"));
1983 	if (str == NULL || var == NULL)
1984 		goto error;
1985 
1986 	free_tcpcheck_vars(&rules->preset_vars);
1987 
1988 	var->data.type = SMP_T_STR;
1989 	var->data.u.str.area = str;
1990 	var->data.u.str.data = strlen(str);
1991 	LIST_INIT(&var->list);
1992 	LIST_APPEND(&rules->preset_vars, &var->list);
1993 
1994 	return 1;
1995 
1996   error:
1997 	free(str);
1998 	free(var);
1999 	return 0;
2000 }
2001 
2002 /* set agent addr and appropriate flag */
set_srv_agent_addr(struct server * srv,struct sockaddr_storage * sk)2003 inline void set_srv_agent_addr(struct server *srv, struct sockaddr_storage *sk)
2004 {
2005 	srv->agent.addr = *sk;
2006 	srv->flags |= SRV_F_AGENTADDR;
2007 }
2008 
2009 /* set agent port and appropriate flag */
set_srv_agent_port(struct server * srv,int port)2010 inline void set_srv_agent_port(struct server *srv, int port)
2011 {
2012 	srv->agent.port = port;
2013 	srv->flags |= SRV_F_AGENTPORT;
2014 }
2015 
2016 /* Parse the "agent-send" server keyword */
srv_parse_agent_send(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2017 static int srv_parse_agent_send(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2018 				char **errmsg)
2019 {
2020 	struct tcpcheck_rules *rules = srv->agent.tcpcheck_rules;
2021 	int err_code = 0;
2022 
2023 	if (!*(args[*cur_arg+1])) {
2024 		memprintf(errmsg, "'%s' expects a string as argument.", args[*cur_arg]);
2025 		goto error;
2026 	}
2027 
2028 	if (!rules) {
2029 		rules = calloc(1, sizeof(*rules));
2030 		if (!rules) {
2031 			memprintf(errmsg, "out of memory.");
2032 			goto error;
2033 		}
2034 		LIST_INIT(&rules->preset_vars);
2035 		srv->agent.tcpcheck_rules = rules;
2036 	}
2037 
2038 	if (!set_srv_agent_send(srv, args[*cur_arg+1])) {
2039 		memprintf(errmsg, "out of memory.");
2040 		goto error;
2041 	}
2042 
2043   out:
2044 	return err_code;
2045 
2046   error:
2047 	deinit_srv_agent_check(srv);
2048 	err_code |= ERR_ALERT | ERR_FATAL;
2049 	goto out;
2050 }
2051 
2052 /* Parse the "no-agent-send" server keyword */
srv_parse_no_agent_check(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2053 static int srv_parse_no_agent_check(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2054 				    char **errmsg)
2055 {
2056 	deinit_srv_agent_check(srv);
2057 	return 0;
2058 }
2059 
2060 /* Parse the "check" server keyword */
srv_parse_check(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2061 static int srv_parse_check(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2062 			   char **errmsg)
2063 {
2064 	if (!(curpx->cap & PR_CAP_BE)) {
2065 		memprintf(errmsg, "'%s' ignored because %s '%s' has no backend capability",
2066 			  args[*cur_arg], proxy_type_str(curpx), curpx->id);
2067 		return ERR_WARN;
2068 	}
2069 
2070 	srv->do_check = 1;
2071 	return 0;
2072 }
2073 
2074 /* Parse the "check-send-proxy" server keyword */
srv_parse_check_send_proxy(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2075 static int srv_parse_check_send_proxy(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2076 				      char **errmsg)
2077 {
2078 	srv->check.send_proxy = 1;
2079 	return 0;
2080 }
2081 
2082 /* Parse the "check-via-socks4" server keyword */
srv_parse_check_via_socks4(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2083 static int srv_parse_check_via_socks4(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2084 				      char **errmsg)
2085 {
2086 	srv->check.via_socks4 = 1;
2087 	return 0;
2088 }
2089 
2090 /* Parse the "no-check" server keyword */
srv_parse_no_check(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2091 static int srv_parse_no_check(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2092 			      char **errmsg)
2093 {
2094 	deinit_srv_check(srv);
2095 	return 0;
2096 }
2097 
2098 /* Parse the "no-check-send-proxy" server keyword */
srv_parse_no_check_send_proxy(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2099 static int srv_parse_no_check_send_proxy(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2100 					 char **errmsg)
2101 {
2102 	srv->check.send_proxy = 0;
2103 	return 0;
2104 }
2105 
2106 /* parse the "check-proto" server keyword */
srv_parse_check_proto(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)2107 static int srv_parse_check_proto(char **args, int *cur_arg,
2108 				 struct proxy *px, struct server *newsrv, char **err)
2109 {
2110 	int err_code = 0;
2111 
2112 	if (!*args[*cur_arg + 1]) {
2113 		memprintf(err, "'%s' : missing value", args[*cur_arg]);
2114 		goto error;
2115 	}
2116 	newsrv->check.mux_proto = get_mux_proto(ist(args[*cur_arg + 1]));
2117 	if (!newsrv->check.mux_proto) {
2118 		memprintf(err, "'%s' :  unknown MUX protocol '%s'", args[*cur_arg], args[*cur_arg+1]);
2119 		goto error;
2120 	}
2121 
2122   out:
2123 	return err_code;
2124 
2125   error:
2126 	err_code |= ERR_ALERT | ERR_FATAL;
2127 	goto out;
2128 }
2129 
2130 
2131 /* Parse the "rise" server keyword */
srv_parse_check_rise(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2132 static int srv_parse_check_rise(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2133 				char **errmsg)
2134 {
2135 	int err_code = 0;
2136 
2137 	if (!*args[*cur_arg + 1]) {
2138 		memprintf(errmsg, "'%s' expects an integer argument.", args[*cur_arg]);
2139 		goto error;
2140 	}
2141 
2142 	srv->check.rise = atol(args[*cur_arg+1]);
2143 	if (srv->check.rise <= 0) {
2144 		memprintf(errmsg, "'%s' has to be > 0.", args[*cur_arg]);
2145 		goto error;
2146 	}
2147 
2148 	if (srv->check.health)
2149 		srv->check.health = srv->check.rise;
2150 
2151   out:
2152 	return err_code;
2153 
2154   error:
2155 	deinit_srv_agent_check(srv);
2156 	err_code |= ERR_ALERT | ERR_FATAL;
2157 	goto out;
2158 }
2159 
2160 /* Parse the "fall" server keyword */
srv_parse_check_fall(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2161 static int srv_parse_check_fall(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2162 				char **errmsg)
2163 {
2164 	int err_code = 0;
2165 
2166 	if (!*args[*cur_arg + 1]) {
2167 		memprintf(errmsg, "'%s' expects an integer argument.", args[*cur_arg]);
2168 		goto error;
2169 	}
2170 
2171 	srv->check.fall = atol(args[*cur_arg+1]);
2172 	if (srv->check.fall <= 0) {
2173 		memprintf(errmsg, "'%s' has to be > 0.", args[*cur_arg]);
2174 		goto error;
2175 	}
2176 
2177   out:
2178 	return err_code;
2179 
2180   error:
2181 	deinit_srv_agent_check(srv);
2182 	err_code |= ERR_ALERT | ERR_FATAL;
2183 	goto out;
2184 }
2185 
2186 /* Parse the "inter" server keyword */
srv_parse_check_inter(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2187 static int srv_parse_check_inter(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2188 				 char **errmsg)
2189 {
2190 	const char *err = NULL;
2191 	unsigned int delay;
2192 	int err_code = 0;
2193 
2194 	if (!*(args[*cur_arg+1])) {
2195 		memprintf(errmsg, "'%s' expects a delay as argument.", args[*cur_arg]);
2196 		goto error;
2197 	}
2198 
2199 	err = parse_time_err(args[*cur_arg+1], &delay, TIME_UNIT_MS);
2200 	if (err == PARSE_TIME_OVER) {
2201 		memprintf(errmsg, "timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).",
2202 			  args[*cur_arg+1], args[*cur_arg], srv->id);
2203 		goto error;
2204 	}
2205 	else if (err == PARSE_TIME_UNDER) {
2206 		memprintf(errmsg, "timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.",
2207 			  args[*cur_arg+1], args[*cur_arg], srv->id);
2208 		goto error;
2209 	}
2210 	else if (err) {
2211 		memprintf(errmsg, "unexpected character '%c' in 'agent-inter' argument of server %s.",
2212 			  *err, srv->id);
2213 		goto error;
2214 	}
2215 	if (delay <= 0) {
2216 		memprintf(errmsg, "invalid value %d for argument '%s' of server %s.",
2217 			  delay, args[*cur_arg], srv->id);
2218 		goto error;
2219 	}
2220 	srv->check.inter = delay;
2221 
2222   out:
2223 	return err_code;
2224 
2225   error:
2226 	err_code |= ERR_ALERT | ERR_FATAL;
2227 	goto out;
2228 }
2229 
2230 
2231 /* Parse the "fastinter" server keyword */
srv_parse_check_fastinter(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2232 static int srv_parse_check_fastinter(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2233 				     char **errmsg)
2234 {
2235 	const char *err = NULL;
2236 	unsigned int delay;
2237 	int err_code = 0;
2238 
2239 	if (!*(args[*cur_arg+1])) {
2240 		memprintf(errmsg, "'%s' expects a delay as argument.", args[*cur_arg]);
2241 		goto error;
2242 	}
2243 
2244 	err = parse_time_err(args[*cur_arg+1], &delay, TIME_UNIT_MS);
2245 	if (err == PARSE_TIME_OVER) {
2246 		memprintf(errmsg, "timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).",
2247 			  args[*cur_arg+1], args[*cur_arg], srv->id);
2248 		goto error;
2249 	}
2250 	else if (err == PARSE_TIME_UNDER) {
2251 		memprintf(errmsg, "timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.",
2252 			  args[*cur_arg+1], args[*cur_arg], srv->id);
2253 		goto error;
2254 	}
2255 	else if (err) {
2256 		memprintf(errmsg, "unexpected character '%c' in 'agent-inter' argument of server %s.",
2257 			  *err, srv->id);
2258 		goto error;
2259 	}
2260 	if (delay <= 0) {
2261 		memprintf(errmsg, "invalid value %d for argument '%s' of server %s.",
2262 			  delay, args[*cur_arg], srv->id);
2263 		goto error;
2264 	}
2265 	srv->check.fastinter = delay;
2266 
2267   out:
2268 	return err_code;
2269 
2270   error:
2271 	err_code |= ERR_ALERT | ERR_FATAL;
2272 	goto out;
2273 }
2274 
2275 
2276 /* Parse the "downinter" server keyword */
srv_parse_check_downinter(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2277 static int srv_parse_check_downinter(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2278 				     char **errmsg)
2279 {
2280 	const char *err = NULL;
2281 	unsigned int delay;
2282 	int err_code = 0;
2283 
2284 	if (!*(args[*cur_arg+1])) {
2285 		memprintf(errmsg, "'%s' expects a delay as argument.", args[*cur_arg]);
2286 		goto error;
2287 	}
2288 
2289 	err = parse_time_err(args[*cur_arg+1], &delay, TIME_UNIT_MS);
2290 	if (err == PARSE_TIME_OVER) {
2291 		memprintf(errmsg, "timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).",
2292 			  args[*cur_arg+1], args[*cur_arg], srv->id);
2293 		goto error;
2294 	}
2295 	else if (err == PARSE_TIME_UNDER) {
2296 		memprintf(errmsg, "timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.",
2297 			  args[*cur_arg+1], args[*cur_arg], srv->id);
2298 		goto error;
2299 	}
2300 	else if (err) {
2301 		memprintf(errmsg, "unexpected character '%c' in 'agent-inter' argument of server %s.",
2302 			  *err, srv->id);
2303 		goto error;
2304 	}
2305 	if (delay <= 0) {
2306 		memprintf(errmsg, "invalid value %d for argument '%s' of server %s.",
2307 			  delay, args[*cur_arg], srv->id);
2308 		goto error;
2309 	}
2310 	srv->check.downinter = delay;
2311 
2312   out:
2313 	return err_code;
2314 
2315   error:
2316 	err_code |= ERR_ALERT | ERR_FATAL;
2317 	goto out;
2318 }
2319 
2320 /* Parse the "port" server keyword */
srv_parse_check_port(char ** args,int * cur_arg,struct proxy * curpx,struct server * srv,char ** errmsg)2321 static int srv_parse_check_port(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
2322 				char **errmsg)
2323 {
2324 	int err_code = 0;
2325 
2326 	if (!*(args[*cur_arg+1])) {
2327 		memprintf(errmsg, "'%s' expects a port number as argument.", args[*cur_arg]);
2328 		goto error;
2329 	}
2330 
2331 	global.maxsock++;
2332 	srv->check.port = atol(args[*cur_arg+1]);
2333 	/* if agentport was never set, we can use port */
2334 	if (!(srv->flags & SRV_F_AGENTPORT))
2335 		srv->agent.port = srv->check.port;
2336 
2337   out:
2338 	return err_code;
2339 
2340   error:
2341 	err_code |= ERR_ALERT | ERR_FATAL;
2342 	goto out;
2343 }
2344 
2345 static struct srv_kw_list srv_kws = { "CHK", { }, {
2346 	{ "addr",                srv_parse_addr,                1,  1,  0 }, /* IP address to send health to or to probe from agent-check */
2347 	{ "agent-addr",          srv_parse_agent_addr,          1,  1,  0 }, /* Enable an auxiliary agent check */
2348 	{ "agent-check",         srv_parse_agent_check,         0,  1,  0 }, /* Enable agent checks */
2349 	{ "agent-inter",         srv_parse_agent_inter,         1,  1,  0 }, /* Set the interval between two agent checks */
2350 	{ "agent-port",          srv_parse_agent_port,          1,  1,  0 }, /* Set the TCP port used for agent checks. */
2351 	{ "agent-send",          srv_parse_agent_send,          1,  1,  0 }, /* Set string to send to agent. */
2352 	{ "check",               srv_parse_check,               0,  1,  0 }, /* Enable health checks */
2353 	{ "check-proto",         srv_parse_check_proto,         1,  1,  0 }, /* Set the mux protocol for health checks  */
2354 	{ "check-send-proxy",    srv_parse_check_send_proxy,    0,  1,  0 }, /* Enable PROXY protocol for health checks */
2355 	{ "check-via-socks4",    srv_parse_check_via_socks4,    0,  1,  0 }, /* Enable socks4 proxy for health checks */
2356 	{ "no-agent-check",      srv_parse_no_agent_check,      0,  1,  0 }, /* Do not enable any auxiliary agent check */
2357 	{ "no-check",            srv_parse_no_check,            0,  1,  0 }, /* Disable health checks */
2358 	{ "no-check-send-proxy", srv_parse_no_check_send_proxy, 0,  1,  0 }, /* Disable PROXY protocol for health checks */
2359 	{ "rise",                srv_parse_check_rise,          1,  1,  0 }, /* Set rise value for health checks */
2360 	{ "fall",                srv_parse_check_fall,          1,  1,  0 }, /* Set fall value for health checks */
2361 	{ "inter",               srv_parse_check_inter,         1,  1,  0 }, /* Set inter value for health checks */
2362 	{ "fastinter",           srv_parse_check_fastinter,     1,  1,  0 }, /* Set fastinter value for health checks */
2363 	{ "downinter",           srv_parse_check_downinter,     1,  1,  0 }, /* Set downinter value for health checks */
2364 	{ "port",                srv_parse_check_port,          1,  1,  0 }, /* Set the TCP port used for health checks. */
2365 	{ NULL, NULL, 0 },
2366 }};
2367 
2368 INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
2369 
2370 /*
2371  * Local variables:
2372  *  c-indent-level: 8
2373  *  c-basic-offset: 8
2374  * End:
2375  */
2376