#define EXCLBUFFERS 4096
#endif /* TUNE_LARGE */
-#define MAX_TCP_TIMEOUT 65535
+/* RFC7828 defines timeout as 16-bit value specified in units of 100
+ * milliseconds, so the maximum and minimum advertised and keepalive
+ * timeouts are capped by the data type (it's ~109 minutes)
+ */
+#define MIN_INITIAL_TIMEOUT UINT32_C(2500) /* 2.5 seconds */
+#define MAX_INITIAL_TIMEOUT UINT32_C(120000) /* 2 minutes */
+#define MIN_IDLE_TIMEOUT UINT32_C(100) /* 0.1 seconds */
+#define MAX_IDLE_TIMEOUT UINT32_C(120000) /* 2 minutes */
+#define MIN_KEEPALIVE_TIMEOUT UINT32_C(100) /* 0.1 seconds */
+#define MAX_KEEPALIVE_TIMEOUT UINT32_C(UINT16_MAX * 100)
+#define MIN_ADVERTISED_TIMEOUT UINT32_C(0) /* No minimum */
+#define MAX_ADVERTISED_TIMEOUT UINT32_C(UINT16_MAX * 100)
/*%
* Check an operation for failure. Assumes that the function
unsigned int maxsocks;
uint32_t softquota = 0;
uint32_t max;
- unsigned int initial, idle, keepalive, advertised;
+ uint64_t initial, idle, keepalive, advertised;
dns_aclenv_t *env =
ns_interfacemgr_getaclenv(named_g_server->interfacemgr);
obj = NULL;
result = named_config_get(maps, "tcp-initial-timeout", &obj);
INSIST(result == ISC_R_SUCCESS);
- initial = cfg_obj_asuint32(obj);
- if (initial > 1200) {
+ initial = cfg_obj_asuint32(obj) * 100;
+ if (initial > MAX_INITIAL_TIMEOUT) {
cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
"tcp-initial-timeout value is out of range: "
- "lowering to 1200");
- initial = 1200;
- } else if (initial < 25) {
+ "lowering to %" PRIu32,
+ MAX_INITIAL_TIMEOUT / 100);
+ initial = MAX_INITIAL_TIMEOUT;
+ } else if (initial < MIN_INITIAL_TIMEOUT) {
cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
"tcp-initial-timeout value is out of range: "
- "raising to 25");
- initial = 25;
+ "raising to %" PRIu32,
+ MIN_INITIAL_TIMEOUT / 100);
+ initial = MIN_INITIAL_TIMEOUT;
}
obj = NULL;
result = named_config_get(maps, "tcp-idle-timeout", &obj);
INSIST(result == ISC_R_SUCCESS);
- idle = cfg_obj_asuint32(obj);
- if (idle > 1200) {
+ idle = cfg_obj_asuint32(obj) * 100;
+ if (idle > MAX_IDLE_TIMEOUT) {
cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
"tcp-idle-timeout value is out of range: "
- "lowering to 1200");
- idle = 1200;
- } else if (idle < 1) {
+ "lowering to %" PRIu32,
+ MAX_IDLE_TIMEOUT / 100);
+ idle = MAX_IDLE_TIMEOUT;
+ } else if (idle < MIN_IDLE_TIMEOUT) {
cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
"tcp-idle-timeout value is out of range: "
- "raising to 1");
- idle = 1;
+ "raising to %" PRIu32,
+ MIN_IDLE_TIMEOUT / 100);
+ idle = MIN_IDLE_TIMEOUT;
}
obj = NULL;
result = named_config_get(maps, "tcp-keepalive-timeout", &obj);
INSIST(result == ISC_R_SUCCESS);
- keepalive = cfg_obj_asuint32(obj);
- if (keepalive > MAX_TCP_TIMEOUT) {
+ keepalive = cfg_obj_asuint32(obj) * 100;
+ if (keepalive > MAX_KEEPALIVE_TIMEOUT) {
cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
"tcp-keepalive-timeout value is out of range: "
- "lowering to %u",
- MAX_TCP_TIMEOUT);
- keepalive = MAX_TCP_TIMEOUT;
- } else if (keepalive < 1) {
+ "lowering to %" PRIu32,
+ MAX_KEEPALIVE_TIMEOUT / 100);
+ keepalive = MAX_KEEPALIVE_TIMEOUT;
+ } else if (keepalive < MIN_KEEPALIVE_TIMEOUT) {
cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
"tcp-keepalive-timeout value is out of range: "
- "raising to 1");
- keepalive = 1;
+ "raising to %" PRIu32,
+ MIN_KEEPALIVE_TIMEOUT / 100);
+ keepalive = MIN_KEEPALIVE_TIMEOUT;
}
obj = NULL;
result = named_config_get(maps, "tcp-advertised-timeout", &obj);
INSIST(result == ISC_R_SUCCESS);
- advertised = cfg_obj_asuint32(obj);
- if (advertised > MAX_TCP_TIMEOUT) {
+ advertised = cfg_obj_asuint32(obj) * 100;
+ if (advertised > MAX_ADVERTISED_TIMEOUT) {
cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
"tcp-advertized-timeout value is out of range: "
- "lowering to %u",
- MAX_TCP_TIMEOUT);
- advertised = MAX_TCP_TIMEOUT;
+ "lowering to %" PRIu32,
+ MAX_ADVERTISED_TIMEOUT / 100);
+ advertised = MAX_ADVERTISED_TIMEOUT;
}
isc_nm_settimeouts(named_g_nm, initial, idle, keepalive, advertised);
named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) {
char *ptr;
isc_result_t result = ISC_R_SUCCESS;
- unsigned int initial, idle, keepalive, advertised;
+ uint32_t initial, idle, keepalive, advertised;
char msg[128];
/* Skip the command name. */
ptr = next_token(lex, NULL);
if (ptr != NULL) {
CHECK(isc_parse_uint32(&initial, ptr, 10));
- if (initial > 1200) {
+ initial *= 100;
+ if (initial > MAX_INITIAL_TIMEOUT) {
CHECK(ISC_R_RANGE);
}
- if (initial < 25) {
+ if (initial < MIN_INITIAL_TIMEOUT) {
CHECK(ISC_R_RANGE);
}
return (ISC_R_UNEXPECTEDEND);
}
CHECK(isc_parse_uint32(&idle, ptr, 10));
- if (idle > 1200) {
+ idle *= 100;
+ if (idle > MAX_IDLE_TIMEOUT) {
CHECK(ISC_R_RANGE);
}
- if (idle < 1) {
+ if (idle < MIN_IDLE_TIMEOUT) {
CHECK(ISC_R_RANGE);
}
return (ISC_R_UNEXPECTEDEND);
}
CHECK(isc_parse_uint32(&keepalive, ptr, 10));
- if (keepalive > MAX_TCP_TIMEOUT) {
+ keepalive *= 100;
+ if (keepalive > MAX_KEEPALIVE_TIMEOUT) {
CHECK(ISC_R_RANGE);
}
- if (keepalive < 1) {
+ if (keepalive < MIN_KEEPALIVE_TIMEOUT) {
CHECK(ISC_R_RANGE);
}
return (ISC_R_UNEXPECTEDEND);
}
CHECK(isc_parse_uint32(&advertised, ptr, 10));
- if (advertised > MAX_TCP_TIMEOUT) {
+ advertised *= 100;
+ if (advertised > MAX_ADVERTISED_TIMEOUT) {
CHECK(ISC_R_RANGE);
}
isc_task_endexclusive(named_g_server->task);
}
- snprintf(msg, sizeof(msg), "tcp-initial-timeout=%u\n", initial);
+ snprintf(msg, sizeof(msg), "tcp-initial-timeout=%u\n", initial / 100);
CHECK(putstr(text, msg));
- snprintf(msg, sizeof(msg), "tcp-idle-timeout=%u\n", idle);
+ snprintf(msg, sizeof(msg), "tcp-idle-timeout=%u\n", idle / 100);
CHECK(putstr(text, msg));
- snprintf(msg, sizeof(msg), "tcp-keepalive-timeout=%u\n", keepalive);
+ snprintf(msg, sizeof(msg), "tcp-keepalive-timeout=%u\n",
+ keepalive / 100);
CHECK(putstr(text, msg));
- snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u", advertised);
+ snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u",
+ advertised / 100);
CHECK(putstr(text, msg));
cleanup:
isc_nmhandle_cleartimeout(isc_nmhandle_t *handle);
/*%<
* Set/clear the read/recv timeout for the socket connected to 'handle'
- * to 'timeout', and reset the timer, in miliseconds.
+ * to 'timeout' (in milliseconds), and reset the timer.
*
* When this is called on a 'wrapper' socket handle (for example,
* a TCPDNS socket wrapping a TCP connection), the timer is set for
isc_nm_settimeouts(isc_nm_t *mgr, uint32_t init, uint32_t idle,
uint32_t keepalive, uint32_t advertised);
/*%<
- * Sets the initial, idle, and keepalive timeout values to use for
- * TCP connections, and the timeout value to advertise in responses using
+ * Sets the initial, idle, and keepalive timeout values (in milliseconds) to use
+ * for TCP connections, and the timeout value to advertise in responses using
* the EDNS TCP Keepalive option (which should ordinarily be the same
- * as 'keepalive'), in tenths of seconds.
+ * as 'keepalive').
*
* Requires:
* \li 'mgr' is a valid netmgr.
uint32_t *keepalive, uint32_t *advertised);
/*%<
* Gets the initial, idle, keepalive, or advertised timeout values,
- * in tenths of seconds.
+ * in milliseconds.
*
* Any integer pointer parameter not set to NULL will be updated to
* contain the corresponding timeout value.