Commit | Line | Data |
---|---|---|
f056029c | 1 | /* |
ab5be9fa | 2 | * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> |
f056029c | 3 | * |
ab5be9fa | 4 | * SPDX-License-Identifier: GPL-2.0-only |
f056029c | 5 | * |
f056029c JR |
6 | */ |
7 | ||
28ab034a | 8 | #include "tcp_keep_alive.hpp" |
f056029c | 9 | |
c9e313bc | 10 | #include <common/compat/getenv.hpp> |
c9e313bc SM |
11 | #include <common/defaults.hpp> |
12 | #include <common/ini-config/ini-config.hpp> | |
28ab034a | 13 | #include <common/time.hpp> |
f056029c | 14 | |
28ab034a JG |
15 | #include <limits.h> |
16 | #include <netinet/tcp.h> | |
17 | #include <stdbool.h> | |
18 | #include <sys/socket.h> | |
19 | #include <sys/types.h> | |
f056029c | 20 | |
28ab034a JG |
21 | #define SOLARIS_IDLE_TIME_MIN_S 10 |
22 | #define SOLARIS_IDLE_TIME_MAX_S 864000 /* 10 days */ | |
f056029c JR |
23 | #define SOLARIS_ABORT_THRESHOLD_MIN_S 1 |
24 | #define SOLARIS_ABORT_THRESHOLD_MAX_S 480 /* 8 minutes */ | |
25 | ||
26 | /* Per-platform definitions of TCP socket options. */ | |
28ab034a | 27 | #if defined(__linux__) |
f056029c | 28 | |
28ab034a | 29 | #define COMPAT_TCP_LEVEL SOL_TCP |
f056029c | 30 | #define COMPAT_TCP_ABORT_THRESHOLD 0 /* Does not exist on linux. */ |
28ab034a JG |
31 | #define COMPAT_TCP_KEEPIDLE TCP_KEEPIDLE |
32 | #define COMPAT_TCP_KEEPINTVL TCP_KEEPINTVL | |
33 | #define COMPAT_TCP_KEEPCNT TCP_KEEPCNT | |
f056029c | 34 | |
28ab034a | 35 | #elif defined(__sun__) /* ! defined (__linux__) */ |
f056029c | 36 | |
f056029c JR |
37 | #define COMPAT_TCP_LEVEL IPPROTO_TCP |
38 | ||
39 | #ifdef TCP_KEEPALIVE_THRESHOLD | |
40 | #define COMPAT_TCP_KEEPIDLE TCP_KEEPALIVE_THRESHOLD | |
41 | #else /* ! defined (TCP_KEEPALIVE_THRESHOLD) */ | |
42 | #define COMPAT_TCP_KEEPIDLE 0 | |
43 | #endif /* TCP_KEEPALIVE_THRESHOLD */ | |
44 | ||
45 | #ifdef TCP_KEEPALIVE_ABORT_THRESHOLD | |
46 | #define COMPAT_TCP_ABORT_THRESHOLD TCP_KEEPALIVE_ABORT_THRESHOLD | |
47 | #else /* ! defined (TCP_KEEPALIVE_ABORT_THRESHOLD) */ | |
48 | #define COMPAT_TCP_ABORT_THRESHOLD 0 | |
49 | #endif /* TCP_KEEPALIVE_ABORT_THRESHOLD */ | |
50 | ||
51 | #define COMPAT_TCP_KEEPINTVL 0 /* Does not exist on Solaris. */ | |
28ab034a | 52 | #define COMPAT_TCP_KEEPCNT 0 /* Does not exist on Solaris. */ |
f056029c JR |
53 | |
54 | #else /* ! defined (__linux__) && ! defined (__sun__) */ | |
55 | ||
28ab034a | 56 | #define COMPAT_TCP_LEVEL 0 |
f056029c | 57 | #define COMPAT_TCP_ABORT_THRESHOLD 0 |
28ab034a JG |
58 | #define COMPAT_TCP_KEEPIDLE 0 |
59 | #define COMPAT_TCP_KEEPINTVL 0 | |
60 | #define COMPAT_TCP_KEEPCNT 0 | |
f056029c JR |
61 | |
62 | #endif /* ! defined (__linux__) && ! defined (__sun__) */ | |
63 | ||
f1494934 | 64 | namespace { |
f056029c JR |
65 | struct tcp_keep_alive_support { |
66 | /* TCP keep-alive is supported by this platform. */ | |
67 | bool supported; | |
68 | /* Overriding idle-time per socket is supported by this platform. */ | |
69 | bool idle_time_supported; | |
70 | /* | |
71 | * Overriding probe interval per socket is supported by this | |
72 | * platform. | |
73 | */ | |
74 | bool probe_interval_supported; | |
75 | /* | |
76 | * Configuring max probe count per socket is supported by this | |
77 | * platform. | |
78 | */ | |
79 | bool max_probe_count_supported; | |
80 | /* Overriding on a per-socket basis is supported by this platform. */ | |
81 | bool abort_threshold_supported; | |
82 | }; | |
83 | ||
84 | struct tcp_keep_alive_config { | |
85 | /* Maps to the LTTNG_RELAYD_TCP_KEEP_ALIVE_ENV environment variable. */ | |
86 | bool enabled; | |
87 | /* | |
88 | * Maps to the LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME_ENV environment | |
89 | * variable. | |
90 | */ | |
91 | int idle_time; | |
92 | /* | |
93 | * Maps to the LTTNG_RELAYD_TCP_KEEP_ALIVE_PROBE_INTERVAL_ENV | |
94 | * environment variable. | |
95 | */ | |
96 | int probe_interval; | |
97 | /* | |
98 | * Maps to the LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT_ENV | |
99 | * environment variable. | |
100 | */ | |
101 | int max_probe_count; | |
102 | /* | |
103 | * Maps to the LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD_ENV | |
104 | * environment variable. | |
105 | */ | |
106 | int abort_threshold; | |
107 | }; | |
108 | ||
28ab034a JG |
109 | struct tcp_keep_alive_config the_config = { .enabled = false, |
110 | .idle_time = -1, | |
111 | .probe_interval = -1, | |
112 | .max_probe_count = -1, | |
113 | .abort_threshold = -1 }; | |
114 | ||
115 | struct tcp_keep_alive_support the_support = { .supported = false, | |
116 | .idle_time_supported = false, | |
117 | .probe_interval_supported = false, | |
118 | .max_probe_count_supported = false, | |
119 | .abort_threshold_supported = false }; | |
f1494934 | 120 | } /* namespace */ |
f056029c JR |
121 | |
122 | /* | |
123 | * Common parser for string to positive int conversion where the value must be | |
124 | * in range [-1, INT_MAX]. | |
125 | * | |
126 | * Returns -2 on invalid value. | |
127 | */ | |
28ab034a | 128 | static int get_env_int(const char *env_var, const char *value) |
f056029c JR |
129 | { |
130 | int ret; | |
131 | long tmp; | |
cd9adb8b | 132 | char *endptr = nullptr; |
f056029c JR |
133 | |
134 | errno = 0; | |
135 | tmp = strtol(value, &endptr, 0); | |
136 | if (errno != 0) { | |
137 | ERR("%s cannot be parsed.", env_var); | |
138 | PERROR("errno for previous parsing failure"); | |
139 | ret = -2; | |
140 | goto end; | |
141 | } | |
142 | ||
143 | if (endptr == value || *endptr != '\0') { | |
28ab034a JG |
144 | ERR("%s is not a valid number", env_var); |
145 | ret = -1; | |
146 | goto end; | |
f056029c JR |
147 | } |
148 | ||
149 | if (tmp < -1) { | |
150 | ERR("%s must be greater or equal to -1", env_var); | |
151 | ret = -2; | |
152 | goto end; | |
153 | } | |
28ab034a | 154 | if (tmp > INT_MAX) { |
f056029c JR |
155 | ERR("%s is too big. Maximum value is %d", env_var, INT_MAX); |
156 | ret = -2; | |
157 | goto end; | |
158 | } | |
159 | ||
160 | ret = (int) tmp; | |
161 | end: | |
162 | return ret; | |
163 | } | |
164 | ||
165 | /* | |
166 | * Per-platform implementation of tcp_keep_alive_idle_time_modifier. | |
167 | * Returns -2 on invalid value. | |
168 | */ | |
169 | #ifdef __sun__ | |
170 | ||
28ab034a | 171 | static int convert_idle_time(int value) |
f056029c JR |
172 | { |
173 | int ret; | |
174 | unsigned int tmp_ms; | |
175 | ||
176 | if (value == -1 || value == 0) { | |
177 | /* Use system defaults */ | |
178 | ret = value; | |
179 | goto end; | |
180 | } | |
181 | ||
182 | if (value < 0) { | |
183 | ERR("Invalid tcp keep-alive idle time (%i)", value); | |
184 | ret = -2; | |
185 | goto end; | |
186 | } | |
187 | ||
188 | /* | |
189 | * Additional constraints for Solaris 11. | |
190 | * Minimum 10s, maximum 10 days. Defined by | |
191 | * https://docs.oracle.com/cd/E23824_01/html/821-1475/tcp-7p.html#REFMAN7tcp-7p | |
192 | */ | |
28ab034a | 193 | if ((value < SOLARIS_IDLE_TIME_MIN_S || value > SOLARIS_IDLE_TIME_MAX_S)) { |
f056029c | 194 | ERR("%s must be comprised between %d and %d inclusively on Solaris", |
28ab034a JG |
195 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME_ENV, |
196 | SOLARIS_IDLE_TIME_MIN_S, | |
197 | SOLARIS_IDLE_TIME_MAX_S); | |
f056029c JR |
198 | ret = -2; |
199 | goto end; | |
200 | } | |
201 | ||
202 | /* On Solaris idle time is given in milliseconds. */ | |
203 | tmp_ms = ((unsigned int) value) * MSEC_PER_SEC; | |
28ab034a | 204 | if ((value != 0 && (tmp_ms / ((unsigned int) value)) != MSEC_PER_SEC) || tmp_ms > INT_MAX) { |
f056029c JR |
205 | /* Overflow. */ |
206 | const int max_value = INT_MAX / MSEC_PER_SEC; | |
207 | ||
208 | ERR("%s is too big: maximum supported value is %d", | |
28ab034a JG |
209 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME_ENV, |
210 | max_value); | |
f056029c JR |
211 | ret = -2; |
212 | goto end; | |
213 | } | |
214 | ||
215 | /* tmp_ms is >= 0 and <= INT_MAX. Cast is safe. */ | |
216 | ret = (int) tmp_ms; | |
217 | end: | |
218 | return ret; | |
219 | } | |
220 | ||
221 | #else /* ! defined(__sun__) */ | |
222 | ||
28ab034a | 223 | static int convert_idle_time(int value) |
f056029c JR |
224 | { |
225 | return value; | |
226 | } | |
227 | ||
228 | #endif /* ! defined(__sun__) */ | |
229 | ||
230 | /* Per-platform support of tcp_keep_alive functionality. */ | |
28ab034a | 231 | #if defined(__linux__) |
f056029c | 232 | |
28ab034a | 233 | static void tcp_keep_alive_init_support(struct tcp_keep_alive_support *support) |
f056029c JR |
234 | { |
235 | support->supported = true; | |
236 | support->idle_time_supported = true; | |
237 | support->probe_interval_supported = true; | |
238 | support->max_probe_count_supported = true; | |
239 | /* Solaris specific */ | |
240 | support->abort_threshold_supported = false; | |
241 | } | |
242 | ||
243 | #elif defined(__sun__) /* ! defined (__linux__) */ | |
244 | ||
28ab034a | 245 | static void tcp_keep_alive_init_support(struct tcp_keep_alive_support *support) |
f056029c JR |
246 | { |
247 | support->supported = true; | |
248 | #ifdef TCP_KEEPALIVE_THRESHOLD | |
249 | support->idle_time_supported = true; | |
250 | #else | |
28ab034a JG |
251 | support->idle_time_supported = false; |
252 | ; | |
f056029c JR |
253 | #endif /* TCP_KEEPALIVE_THRESHOLD */ |
254 | ||
255 | /* | |
256 | * Solaris does not support either tcp_keepalive_probes or | |
257 | * tcp_keepalive_intvl. | |
258 | * Inferring a value for TCP_KEEP_ALIVE_ABORT_THRESHOLD using | |
259 | * (tcp_keepalive_probes * tcp_keepalive_intvl) could yield a good | |
260 | * alternative, but Solaris does not detail the algorithm used (such as | |
261 | * constant time retry like Linux). | |
262 | * | |
263 | * Ignore those settings on Solaris 11. We prefer exposing an | |
264 | * environment variable only used on Solaris for the abort threshold. | |
265 | */ | |
266 | support->probe_interval_supported = false; | |
267 | support->max_probe_count_supported = false; | |
268 | #ifdef TCP_KEEPALIVE_ABORT_THRESHOLD | |
269 | support->abort_threshold_supported = true; | |
270 | #else | |
271 | support->abort_threshold_supported = false; | |
272 | #endif /* TCP_KEEPALIVE_THRESHOLD */ | |
273 | } | |
274 | ||
275 | #else /* ! defined(__sun__) && ! defined(__linux__) */ | |
276 | ||
277 | /* Assume nothing is supported on other platforms. */ | |
28ab034a | 278 | static void tcp_keep_alive_init_support(struct tcp_keep_alive_support *support) |
f056029c JR |
279 | { |
280 | support->supported = false; | |
281 | support->idle_time_supported = false; | |
282 | support->probe_interval_supported = false; | |
283 | support->max_probe_count_supported = false; | |
284 | support->abort_threshold_supported = false; | |
285 | } | |
286 | ||
287 | #endif /* ! defined(__sun__) && ! defined(__linux__) */ | |
288 | ||
289 | #ifdef __sun__ | |
290 | ||
291 | /* | |
292 | * Solaris specific modifier for abort threshold. | |
293 | * Return -2 on error. | |
294 | */ | |
28ab034a | 295 | static int convert_abort_threshold(int value) |
f056029c JR |
296 | { |
297 | int ret; | |
298 | unsigned int tmp_ms; | |
299 | ||
300 | if (value == -1) { | |
301 | /* Use system defaults */ | |
302 | ret = value; | |
303 | goto end; | |
304 | } | |
305 | ||
306 | if (value < 0) { | |
307 | ERR("Invalid tcp keep-alive abort threshold (%i)", value); | |
308 | ret = -2; | |
309 | goto end; | |
310 | } | |
311 | ||
312 | /* | |
313 | * Additional constraints for Solaris 11. | |
314 | * | |
315 | * Between 0 and 8 minutes. | |
316 | * https://docs.oracle.com/cd/E19120-01/open.solaris/819-2724/fsvdh/index.html | |
317 | * | |
318 | * Restrict from 1 seconds to 8 minutes sice the 0 value goes against | |
319 | * the purpose of dead peers detection by never timing out when probing. | |
320 | * It does NOT mean that the connection times out immediately. | |
321 | */ | |
322 | if ((value < SOLARIS_ABORT_THRESHOLD_MIN_S || value > SOLARIS_ABORT_THRESHOLD_MAX_S)) { | |
323 | ERR("%s must be comprised between %d and %d inclusively on Solaris", | |
28ab034a JG |
324 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD_ENV, |
325 | SOLARIS_ABORT_THRESHOLD_MIN_S, | |
326 | SOLARIS_ABORT_THRESHOLD_MAX_S); | |
f056029c JR |
327 | ret = -2; |
328 | goto end; | |
329 | } | |
330 | ||
331 | /* Abort threshold is given in milliseconds. */ | |
332 | tmp_ms = ((unsigned int) value) * MSEC_PER_SEC; | |
28ab034a | 333 | if ((value != 0 && (tmp_ms / ((unsigned int) value)) != MSEC_PER_SEC) || tmp_ms > INT_MAX) { |
f056029c JR |
334 | /* Overflow */ |
335 | const int max_value = INT_MAX / MSEC_PER_SEC; | |
336 | ||
337 | ERR("%s is too big: maximum supported value is %d", | |
28ab034a JG |
338 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD_ENV, |
339 | max_value); | |
f056029c JR |
340 | ret = -2; |
341 | goto end; | |
342 | } | |
343 | ||
344 | /* tmp_ms is >= 0 and <= INT_MAX. Cast is safe. */ | |
345 | ret = (int) tmp_ms; | |
346 | end: | |
347 | return ret; | |
348 | } | |
349 | ||
350 | #else | |
351 | ||
28ab034a | 352 | static int convert_abort_threshold(int value) |
f056029c JR |
353 | { |
354 | return value; | |
355 | } | |
356 | ||
357 | #endif /* defined (__sun__) */ | |
358 | ||
359 | /* | |
360 | * Retrieve settings from environment variables and warn for settings not | |
361 | * supported by the platform. | |
362 | */ | |
28ab034a JG |
363 | static int tcp_keep_alive_init_config(struct tcp_keep_alive_support *support, |
364 | struct tcp_keep_alive_config *config) | |
f056029c JR |
365 | { |
366 | int ret; | |
367 | const char *value; | |
368 | ||
369 | value = lttng_secure_getenv(DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ENV); | |
370 | if (!support->supported) { | |
371 | if (value) { | |
372 | WARN("Using per-socket TCP keep-alive mechanism is not supported by this platform. Ignoring the %s environment variable.", | |
28ab034a | 373 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ENV); |
f056029c JR |
374 | } |
375 | config->enabled = false; | |
376 | } else if (value) { | |
377 | ret = config_parse_value(value); | |
378 | if (ret < 0 || ret > 1) { | |
379 | ERR("Invalid value for %s", DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ENV); | |
380 | ret = 1; | |
381 | goto error; | |
382 | } | |
383 | config->enabled = ret; | |
384 | } | |
28ab034a | 385 | DBG("TCP keep-alive mechanism %s", config->enabled ? "enabled" : "disabled"); |
f056029c JR |
386 | |
387 | /* Get value for tcp_keepalive_time in seconds. */ | |
388 | value = lttng_secure_getenv(DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME_ENV); | |
389 | if (!support->idle_time_supported && value) { | |
390 | WARN("Overriding the TCP keep-alive idle time threshold per-socket is not supported by this platform. Ignoring the %s environment variable.", | |
28ab034a | 391 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME_ENV); |
f056029c JR |
392 | config->idle_time = -1; |
393 | } else if (value) { | |
394 | int idle_time_platform; | |
395 | int idle_time_seconds; | |
396 | ||
28ab034a JG |
397 | idle_time_seconds = |
398 | get_env_int(DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME_ENV, value); | |
f056029c JR |
399 | if (idle_time_seconds < -1) { |
400 | ret = 1; | |
401 | goto error; | |
402 | } | |
403 | ||
404 | idle_time_platform = convert_idle_time(idle_time_seconds); | |
405 | if (idle_time_platform < -1) { | |
406 | ret = 1; | |
407 | goto error; | |
408 | } | |
409 | ||
410 | config->idle_time = idle_time_platform; | |
411 | DBG("Overriding %s to %d", | |
28ab034a JG |
412 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME_ENV, |
413 | idle_time_seconds); | |
f056029c JR |
414 | } |
415 | ||
416 | /* Get value for tcp_keepalive_intvl in seconds. */ | |
28ab034a | 417 | value = lttng_secure_getenv(DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_PROBE_INTERVAL_ENV); |
f056029c JR |
418 | if (!support->probe_interval_supported && value) { |
419 | WARN("Overriding the TCP keep-alive probe interval time per-socket is not supported by this platform. Ignoring the %s environment variable.", | |
28ab034a | 420 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_PROBE_INTERVAL_ENV); |
f056029c JR |
421 | config->probe_interval = -1; |
422 | } else if (value) { | |
423 | int probe_interval; | |
424 | ||
28ab034a JG |
425 | probe_interval = |
426 | get_env_int(DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_PROBE_INTERVAL_ENV, value); | |
f056029c JR |
427 | if (probe_interval < -1) { |
428 | ret = 1; | |
429 | goto error; | |
430 | } | |
431 | ||
432 | config->probe_interval = probe_interval; | |
433 | DBG("Overriding %s to %d", | |
28ab034a JG |
434 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_PROBE_INTERVAL_ENV, |
435 | config->probe_interval); | |
f056029c JR |
436 | } |
437 | ||
438 | /* Get value for tcp_keepalive_probes. */ | |
439 | value = lttng_secure_getenv(DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT_ENV); | |
440 | if (!support->max_probe_count_supported && value) { | |
441 | WARN("Overriding the TCP keep-alive maximum probe count per-socket is not supported by this platform. Ignoring the %s environment variable.", | |
28ab034a | 442 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT_ENV); |
f056029c JR |
443 | config->max_probe_count = -1; |
444 | } else if (value) { | |
445 | int max_probe_count; | |
446 | ||
28ab034a JG |
447 | max_probe_count = |
448 | get_env_int(DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT_ENV, value); | |
f056029c JR |
449 | if (max_probe_count < -1) { |
450 | ret = 1; | |
451 | goto error; | |
452 | } | |
453 | ||
454 | config->max_probe_count = max_probe_count; | |
455 | DBG("Overriding %s to %d", | |
28ab034a JG |
456 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT_ENV, |
457 | config->max_probe_count); | |
f056029c JR |
458 | } |
459 | ||
460 | /* Get value for tcp_keepalive_abort_interval. */ | |
28ab034a | 461 | value = lttng_secure_getenv(DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD_ENV); |
f056029c JR |
462 | if (!support->abort_threshold_supported && value) { |
463 | WARN("Overriding the TCP keep-alive abort threshold per-socket is not supported by this platform. Ignoring the %s environment variable.", | |
28ab034a | 464 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD_ENV); |
f056029c JR |
465 | config->abort_threshold = -1; |
466 | } else if (value) { | |
467 | int abort_threshold_platform; | |
468 | int abort_threshold_seconds; | |
469 | ||
28ab034a JG |
470 | abort_threshold_seconds = |
471 | get_env_int(DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT_ENV, value); | |
f056029c JR |
472 | if (abort_threshold_seconds < -1) { |
473 | ret = 1; | |
474 | goto error; | |
475 | } | |
476 | ||
28ab034a | 477 | abort_threshold_platform = convert_abort_threshold(abort_threshold_seconds); |
f056029c JR |
478 | if (abort_threshold_platform < -1) { |
479 | ret = 1; | |
480 | goto error; | |
481 | } | |
482 | ||
483 | config->abort_threshold = abort_threshold_platform; | |
484 | DBG("Overriding %s to %d", | |
28ab034a JG |
485 | DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD_ENV, |
486 | config->abort_threshold); | |
f056029c JR |
487 | } |
488 | ||
489 | ret = 0; | |
490 | ||
491 | error: | |
492 | return ret; | |
493 | } | |
494 | ||
495 | /* Initialize the TCP keep-alive configuration. */ | |
cd9adb8b | 496 | __attribute__((constructor)) static void tcp_keep_alive_init() |
f056029c | 497 | { |
3d16a92d SM |
498 | tcp_keep_alive_init_support(&the_support); |
499 | (void) tcp_keep_alive_init_config(&the_support, &the_config); | |
f056029c JR |
500 | } |
501 | ||
502 | /* | |
503 | * Set the socket options regarding TCP keep-alive. | |
504 | */ | |
f056029c JR |
505 | int socket_apply_keep_alive_config(int socket_fd) |
506 | { | |
507 | int ret; | |
508 | int val = 1; | |
509 | ||
510 | /* TCP keep-alive */ | |
3d16a92d | 511 | if (!the_support.supported || !the_config.enabled) { |
f056029c JR |
512 | ret = 0; |
513 | goto end; | |
514 | } | |
515 | ||
cbfbb78f | 516 | DBG("TCP keep-alive enabled for socket %d", socket_fd); |
28ab034a | 517 | ret = setsockopt(socket_fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)); |
f056029c JR |
518 | if (ret < 0) { |
519 | PERROR("setsockopt so_keepalive"); | |
520 | goto end; | |
521 | } | |
522 | ||
523 | /* TCP keep-alive idle time */ | |
3d16a92d SM |
524 | if (the_support.idle_time_supported && the_config.idle_time > 0) { |
525 | DBG("TCP keep-alive keep idle: %d enabled for socket %d", | |
28ab034a JG |
526 | the_config.idle_time, |
527 | socket_fd); | |
528 | ret = setsockopt(socket_fd, | |
529 | COMPAT_TCP_LEVEL, | |
530 | COMPAT_TCP_KEEPIDLE, | |
531 | &the_config.idle_time, | |
532 | sizeof(the_config.idle_time)); | |
f056029c JR |
533 | if (ret < 0) { |
534 | PERROR("setsockopt TCP_KEEPIDLE"); | |
535 | goto end; | |
536 | } | |
537 | } | |
538 | /* TCP keep-alive probe interval */ | |
28ab034a | 539 | if (the_support.probe_interval_supported && the_config.probe_interval > 0) { |
3d16a92d | 540 | DBG("TCP keep-alive probe_interval: %d enabled for socket %d", |
28ab034a JG |
541 | the_config.probe_interval, |
542 | socket_fd); | |
543 | ret = setsockopt(socket_fd, | |
544 | COMPAT_TCP_LEVEL, | |
545 | COMPAT_TCP_KEEPINTVL, | |
546 | &the_config.probe_interval, | |
547 | sizeof(the_config.probe_interval)); | |
f056029c JR |
548 | if (ret < 0) { |
549 | PERROR("setsockopt TCP_KEEPINTVL"); | |
550 | goto end; | |
551 | } | |
552 | } | |
553 | ||
554 | /* TCP keep-alive max probe count */ | |
28ab034a | 555 | if (the_support.max_probe_count_supported && the_config.max_probe_count > 0) { |
3d16a92d | 556 | DBG("TCP keep-alive max_probe: %d enabled for socket %d", |
28ab034a JG |
557 | the_config.max_probe_count, |
558 | socket_fd); | |
559 | ret = setsockopt(socket_fd, | |
560 | COMPAT_TCP_LEVEL, | |
561 | COMPAT_TCP_KEEPCNT, | |
562 | &the_config.max_probe_count, | |
563 | sizeof(the_config.max_probe_count)); | |
f056029c JR |
564 | if (ret < 0) { |
565 | PERROR("setsockopt TCP_KEEPCNT"); | |
566 | goto end; | |
567 | } | |
568 | } | |
569 | ||
570 | /* TCP keep-alive abort threshold */ | |
28ab034a | 571 | if (the_support.abort_threshold_supported && the_config.abort_threshold > 0) { |
3d16a92d | 572 | DBG("TCP keep-alive abort threshold: %d enabled for socket %d", |
28ab034a JG |
573 | the_config.abort_threshold, |
574 | socket_fd); | |
575 | ret = setsockopt(socket_fd, | |
576 | COMPAT_TCP_LEVEL, | |
577 | COMPAT_TCP_ABORT_THRESHOLD, | |
578 | &the_config.abort_threshold, | |
579 | sizeof(the_config.max_probe_count)); | |
f056029c JR |
580 | if (ret < 0) { |
581 | PERROR("setsockopt TCP_KEEPALIVE_ABORT_THRESHOLD"); | |
582 | goto end; | |
583 | } | |
584 | } | |
585 | end: | |
586 | return ret; | |
587 | } |