Added the mobile-dpd configuration option.

This option allows setting a different DPD value for
mobile clients to allow them going to sleep for longer time.
This commit is contained in:
Nikos Mavrogiannopoulos
2014-02-17 22:17:09 +01:00
parent 821f56f5e1
commit 2bd6f5a6a1
5 changed files with 69 additions and 37 deletions
+2
View File
@@ -57,6 +57,7 @@ static struct cfg_options available_options[] = {
{ .name = "udp-port", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "udp-port", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "keepalive", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "keepalive", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "dpd", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "dpd", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "mobile-dpd", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "rate-limit-ms", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "rate-limit-ms", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "ocsp-response", .type = OPTION_STRING, .mandatory = 0 }, { .name = "ocsp-response", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "server-cert", .type = OPTION_STRING, .mandatory = 1 }, { .name = "server-cert", .type = OPTION_STRING, .mandatory = 1 },
@@ -322,6 +323,7 @@ unsigned force_cert_auth;
READ_NUMERIC("udp-port", config->udp_port); READ_NUMERIC("udp-port", config->udp_port);
READ_NUMERIC("keepalive", config->keepalive); READ_NUMERIC("keepalive", config->keepalive);
READ_NUMERIC("dpd", config->dpd); READ_NUMERIC("dpd", config->dpd);
READ_NUMERIC("mobile-dpd", config->mobile_dpd);
READ_NUMERIC("rate-limit-ms", config->rate_limit_ms); READ_NUMERIC("rate-limit-ms", config->rate_limit_ms);
READ_STRING("ocsp-response", config->ocsp_response); READ_STRING("ocsp-response", config->ocsp_response);
+9 -1
View File
@@ -110,9 +110,17 @@ udp-port = 3333
# Keepalive in seconds # Keepalive in seconds
keepalive = 32400 keepalive = 32400
# Dead peer detection in seconds # Dead peer detection in seconds. Set to zero
# to disable.
dpd = 240 dpd = 240
# Dead peer detection for mobile clients. The needs to
# be much higher (or even disabled by setting to zero),
# to prevent such clients being awaken too often by the DPD
# messages, and save battery.
# (clients that send the X-AnyConnect-Identifier-DeviceType)
mobile-dpd = 1800
# MTU discovery (DPD must be enabled) # MTU discovery (DPD must be enabled)
try-mtu-discovery = false try-mtu-discovery = false
+1
View File
@@ -202,6 +202,7 @@ struct cfg_st {
unsigned auth_timeout; /* timeout of HTTP auth */ unsigned auth_timeout; /* timeout of HTTP auth */
unsigned keepalive; unsigned keepalive;
unsigned dpd; unsigned dpd;
unsigned mobile_dpd;
unsigned foreground; unsigned foreground;
unsigned debug; unsigned debug;
unsigned max_clients; unsigned max_clients;
+42 -36
View File
@@ -172,16 +172,6 @@ int url_cb(http_parser * parser, const char *at, size_t length)
return 0; return 0;
} }
#define STR_HDR_COOKIE "Cookie"
#define STR_HDR_USER_AGENT "User-Agent"
#define STR_HDR_CONNECTION "Connection"
#define STR_HDR_MS "X-DTLS-Master-Secret"
#define STR_HDR_CS "X-DTLS-CipherSuite"
#define STR_HDR_DMTU "X-DTLS-MTU"
#define STR_HDR_CMTU "X-CSTP-MTU"
#define STR_HDR_ATYPE "X-CSTP-Address-Type"
#define STR_HDR_HOST "X-CSTP-Hostname"
#define STR_HDR_FULL_IPV6 "X-CSTP-Full-IPv6-Capability"
#define CS_ESALSA20 "OC-DTLS1_2-ESALSA20-SHA" #define CS_ESALSA20 "OC-DTLS1_2-ESALSA20-SHA"
#define CS_SALSA20 "OC-DTLS1_2-SALSA20-SHA" #define CS_SALSA20 "OC-DTLS1_2-SALSA20-SHA"
@@ -290,6 +280,9 @@ static void value_check(struct worker_st *ws, struct http_req_st *req)
memcpy(req->hostname, value, value_length); memcpy(req->hostname, value, value_length);
req->hostname[value_length] = 0; req->hostname[value_length] = 0;
break; break;
case HEADER_DEVICE_TYPE:
req->is_mobile = 1;
break;
case HEADER_USER_AGENT: case HEADER_USER_AGENT:
if (value_length + 1 > MAX_AGENT_NAME) { if (value_length + 1 > MAX_AGENT_NAME) {
req->user_agent[0] = 0; req->user_agent[0] = 0;
@@ -413,6 +406,7 @@ int header_field_cb(http_parser * parser, const char *at, size_t length)
static void header_check(struct http_req_st *req) static void header_check(struct http_req_st *req)
{ {
/* FIXME: move this mess to a table */
if (req->header.length == sizeof(STR_HDR_COOKIE) - 1 && if (req->header.length == sizeof(STR_HDR_COOKIE) - 1 &&
strncmp((char *)req->header.data, STR_HDR_COOKIE, strncmp((char *)req->header.data, STR_HDR_COOKIE,
req->header.length) == 0) { req->header.length) == 0) {
@@ -437,6 +431,10 @@ static void header_check(struct http_req_st *req)
strncmp((char *)req->header.data, STR_HDR_CS, strncmp((char *)req->header.data, STR_HDR_CS,
req->header.length) == 0) { req->header.length) == 0) {
req->next_header = HEADER_DTLS_CIPHERSUITE; req->next_header = HEADER_DTLS_CIPHERSUITE;
} else if (req->header.length == sizeof(STR_HDR_DEVICE_TYPE) - 1 &&
strncmp((char *)req->header.data, STR_HDR_DEVICE_TYPE,
req->header.length) == 0) {
req->next_header = HEADER_DEVICE_TYPE;
} else if (req->header.length == sizeof(STR_HDR_ATYPE) - 1 && } else if (req->header.length == sizeof(STR_HDR_ATYPE) - 1 &&
strncmp((char *)req->header.data, STR_HDR_ATYPE, strncmp((char *)req->header.data, STR_HDR_ATYPE,
req->header.length) == 0) { req->header.length) == 0) {
@@ -898,7 +896,7 @@ void mtu_ok(worker_st * ws)
} }
static static
int periodic_check(worker_st * ws, unsigned mtu_overhead, time_t now) int periodic_check(worker_st * ws, unsigned mtu_overhead, time_t now, unsigned dpd)
{ {
socklen_t sl; socklen_t sl;
int max, e, ret; int max, e, ret;
@@ -907,22 +905,23 @@ int periodic_check(worker_st * ws, unsigned mtu_overhead, time_t now)
return 0; return 0;
/* check DPD. Otherwise exit */ /* check DPD. Otherwise exit */
if (ws->udp_state == UP_ACTIVE if (ws->udp_state == UP_ACTIVE &&
&& now - ws->last_msg_udp > DPD_TRIES * ws->config->dpd) { now - ws->last_msg_udp > DPD_TRIES * dpd &&
dpd > 0) {
oclog(ws, LOG_ERR, oclog(ws, LOG_ERR,
"have not received UDP any message or DPD for long (%d secs)", "have not received UDP any message or DPD for long (%d secs, DPD is %d)",
(int)(now - ws->last_msg_udp)); (int)(now - ws->last_msg_udp), dpd);
ws->buffer[0] = AC_PKT_DPD_OUT; ws->buffer[0] = AC_PKT_DPD_OUT;
tls_send(ws->dtls_session, ws->buffer, 1); tls_send(ws->dtls_session, ws->buffer, 1);
if (now - ws->last_msg_udp > DPD_MAX_TRIES * ws->config->dpd) { if (now - ws->last_msg_udp > DPD_MAX_TRIES * dpd) {
oclog(ws, LOG_ERR, oclog(ws, LOG_ERR,
"have not received UDP message or DPD for very long; disabling UDP port"); "have not received UDP message or DPD for very long; disabling UDP port");
ws->udp_state = UP_INACTIVE; ws->udp_state = UP_INACTIVE;
} }
} }
if (now - ws->last_msg_tcp > DPD_TRIES * ws->config->dpd) { if (dpd > 0 && now - ws->last_msg_tcp > DPD_TRIES * dpd) {
oclog(ws, LOG_ERR, oclog(ws, LOG_ERR,
"have not received TCP DPD for long (%d secs)", "have not received TCP DPD for long (%d secs)",
(int)(now - ws->last_msg_tcp)); (int)(now - ws->last_msg_tcp));
@@ -937,7 +936,7 @@ int periodic_check(worker_st * ws, unsigned mtu_overhead, time_t now)
tls_send(ws->session, ws->buffer, 8); tls_send(ws->session, ws->buffer, 8);
if (now - ws->last_msg_tcp > DPD_MAX_TRIES * ws->config->dpd) { if (now - ws->last_msg_tcp > DPD_MAX_TRIES * dpd) {
oclog(ws, LOG_ERR, oclog(ws, LOG_ERR,
"have not received TCP DPD for very long; tearing down connection"); "have not received TCP DPD for very long; tearing down connection");
return -1; return -1;
@@ -1018,7 +1017,8 @@ static int connect_handler(worker_st * ws)
{ {
struct http_req_st *req = &ws->req; struct http_req_st *req = &ws->req;
fd_set rfds; fd_set rfds;
int l, e, max, ret, overhead; int l, e, max, ret, overhead, t;
int dpd;
unsigned tls_retry, dtls_mtu, cstp_mtu; unsigned tls_retry, dtls_mtu, cstp_mtu;
char *p; char *p;
#ifdef HAVE_PSELECT #ifdef HAVE_PSELECT
@@ -1030,7 +1030,6 @@ static int connect_handler(worker_st * ws)
time_t udp_recv_time = 0, now; time_t udp_recv_time = 0, now;
struct timespec tnow; struct timespec tnow;
unsigned mtu_overhead = 0, ip6; unsigned mtu_overhead = 0, ip6;
int sndbuf;
socklen_t sl; socklen_t sl;
bandwidth_st b_tx; bandwidth_st b_tx;
bandwidth_st b_rx; bandwidth_st b_rx;
@@ -1110,8 +1109,16 @@ static int connect_handler(worker_st * ws)
ret = tls_puts(ws->session, "X-CSTP-Version: 1\r\n"); ret = tls_puts(ws->session, "X-CSTP-Version: 1\r\n");
SEND_ERR(ret); SEND_ERR(ret);
ret = tls_printf(ws->session, "X-CSTP-DPD: %u\r\n", ws->config->dpd); if (req->is_mobile)
SEND_ERR(ret); dpd = ws->config->mobile_dpd;
else
dpd = ws->config->dpd;
oclog(ws, LOG_DEBUG, "suggesting DPD of %d secs", dpd);
if (dpd > 0) {
ret = tls_printf(ws->session, "X-CSTP-DPD: %u\r\n", dpd);
SEND_ERR(ret);
}
if (ws->config->default_domain) { if (ws->config->default_domain) {
ret = ret =
@@ -1310,14 +1317,14 @@ static int connect_handler(worker_st * ws)
/* set TCP socket options */ /* set TCP socket options */
if (ws->config->output_buffer > 0) { if (ws->config->output_buffer > 0) {
sndbuf = ws->conn_mtu * ws->config->output_buffer; t = ws->conn_mtu * ws->config->output_buffer;
ret = ret =
setsockopt(ws->conn_fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, setsockopt(ws->conn_fd, SOL_SOCKET, SO_SNDBUF, &t,
sizeof(sndbuf)); sizeof(t));
if (ret == -1) if (ret == -1)
oclog(ws, LOG_DEBUG, oclog(ws, LOG_DEBUG,
"setsockopt(TCP, SO_SNDBUF) to %u, failed.", "setsockopt(TCP, SO_SNDBUF) to %u, failed.",
sndbuf); t);
} }
set_net_priority(ws, ws->conn_fd, ws->config->net_priority); set_net_priority(ws, ws->conn_fd, ws->config->net_priority);
@@ -1334,10 +1341,10 @@ static int connect_handler(worker_st * ws)
ws->buffer); ws->buffer);
SEND_ERR(ret); SEND_ERR(ret);
ret = if (dpd > 0) {
tls_printf(ws->session, "X-DTLS-DPD: %u\r\n", ret = tls_printf(ws->session, "X-DTLS-DPD: %u\r\n", dpd);
ws->config->dpd); SEND_ERR(ret);
SEND_ERR(ret); }
ret = ret =
tls_printf(ws->session, "X-DTLS-Port: %u\r\n", tls_printf(ws->session, "X-DTLS-Port: %u\r\n",
@@ -1397,13 +1404,12 @@ static int connect_handler(worker_st * ws)
oclog(ws, LOG_DEBUG, "suggesting DTLS MTU %u", dtls_mtu); oclog(ws, LOG_DEBUG, "suggesting DTLS MTU %u", dtls_mtu);
if (ws->config->output_buffer > 0) { if (ws->config->output_buffer > 0) {
sndbuf = MIN(2048, dtls_mtu * ws->config->output_buffer); t = MIN(2048, dtls_mtu * ws->config->output_buffer);
setsockopt(ws->udp_fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, setsockopt(ws->udp_fd, SOL_SOCKET, SO_SNDBUF, &t,
sizeof(sndbuf)); sizeof(t));
if (ret == -1) if (ret == -1)
oclog(ws, LOG_DEBUG, oclog(ws, LOG_DEBUG,
"setsockopt(UDP, SO_SNDBUF) to %u, failed.", "setsockopt(UDP, SO_SNDBUF) to %u, failed.", t);
sndbuf);
} }
set_net_priority(ws, ws->udp_fd, ws->config->net_priority); set_net_priority(ws, ws->udp_fd, ws->config->net_priority);
@@ -1517,7 +1523,7 @@ static int connect_handler(worker_st * ws)
gettime(&tnow); gettime(&tnow);
now = tnow.tv_sec; now = tnow.tv_sec;
if (periodic_check(ws, mtu_overhead, now) < 0) if (periodic_check(ws, mtu_overhead, now, dpd) < 0)
goto exit; goto exit;
if (FD_ISSET(ws->tun_fd, &rfds)) { if (FD_ISSET(ws->tun_fd, &rfds)) {
+15
View File
@@ -42,6 +42,18 @@ typedef enum {
UP_ACTIVE UP_ACTIVE
} udp_port_state_t; } udp_port_state_t;
#define STR_HDR_COOKIE "Cookie"
#define STR_HDR_USER_AGENT "User-Agent"
#define STR_HDR_CONNECTION "Connection"
#define STR_HDR_MS "X-DTLS-Master-Secret"
#define STR_HDR_CS "X-DTLS-CipherSuite"
#define STR_HDR_DMTU "X-DTLS-MTU"
#define STR_HDR_CMTU "X-CSTP-MTU"
#define STR_HDR_ATYPE "X-CSTP-Address-Type"
#define STR_HDR_HOST "X-CSTP-Hostname"
#define STR_HDR_FULL_IPV6 "X-CSTP-Full-IPv6-Capability"
#define STR_HDR_DEVICE_TYPE "X-AnyConnect-Identifier-DeviceType"
enum { enum {
HEADER_COOKIE = 1, HEADER_COOKIE = 1,
HEADER_MASTER_SECRET, HEADER_MASTER_SECRET,
@@ -49,6 +61,7 @@ enum {
HEADER_CSTP_MTU, HEADER_CSTP_MTU,
HEADER_CSTP_ATYPE, HEADER_CSTP_ATYPE,
HEADER_DTLS_MTU, HEADER_DTLS_MTU,
HEADER_DEVICE_TYPE,
HEADER_DTLS_CIPHERSUITE, HEADER_DTLS_CIPHERSUITE,
HEADER_CONNECTION, HEADER_CONNECTION,
HEADER_FULL_IPV6, HEADER_FULL_IPV6,
@@ -94,6 +107,8 @@ struct http_req_st {
uint8_t sid_cookie[SID_SIZE]; uint8_t sid_cookie[SID_SIZE];
unsigned int sid_cookie_set; unsigned int sid_cookie_set;
unsigned int is_mobile;
unsigned char master_secret[TLS_MASTER_SIZE]; unsigned char master_secret[TLS_MASTER_SIZE];
unsigned int master_secret_set; unsigned int master_secret_set;