From f6bad674803eb1a6205ed9c440992aa0af7e535a Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Fri, 28 Mar 2014 21:09:58 +0100 Subject: l2tp: use random Tunnel IDs Re-use the Session ID selection algorithm for generating Tunnel IDs. When a peer always uses the same source port for establishing tunnels, and if ephemeral ports aren't activated (default), then Tunnel IDs are the only way to identify tunnels. Using ramdom Tunnel IDs then minimises the risk of re-using IDs of half-closed tunnels (i.e. tunnels closed locally, but still existing on the peer side). As a minor side effect, the maximum value of a Tunnel ID is now 2^16 - 1. Signed-off-by: Guillaume Nault --- accel-pppd/ctrl/l2tp/l2tp.c | 57 +++++++++++++++++++++++++++------------------ accel-pppd/ctrl/l2tp/l2tp.h | 1 - 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index 925b6434..dc11b424 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -151,7 +151,6 @@ struct l2tp_conn_t static pthread_mutex_t l2tp_lock = PTHREAD_MUTEX_INITIALIZER; static struct l2tp_conn_t **l2tp_conn; -static uint16_t l2tp_tid; static mempool_t l2tp_conn_pool; static mempool_t l2tp_sess_pool; @@ -1197,7 +1196,8 @@ static struct l2tp_conn_t *l2tp_tunnel_alloc(const struct sockaddr_in *peer, { struct l2tp_conn_t *conn; socklen_t hostaddrlen = sizeof(conn->host_addr); - uint16_t tid; + uint16_t count; + ssize_t rdlen; int flag; conn = mempool_alloc(l2tp_conn_pool); @@ -1274,24 +1274,6 @@ static struct l2tp_conn_t *l2tp_tunnel_alloc(const struct sockaddr_in *peer, goto out_err; } - pthread_mutex_lock(&l2tp_lock); - for (tid = l2tp_tid + 1; tid != l2tp_tid; tid++) { - if (tid == L2TP_MAX_TID) - tid = 1; - if (!l2tp_conn[tid]) { - l2tp_conn[tid] = conn; - conn->tid = tid; - break; - } - } - pthread_mutex_unlock(&l2tp_lock); - - if (!conn->tid) { - log_error("l2tp: impossible to allocate new tunnel:" - " no more tunnel available\n"); - goto out_err; - } - if (getsockname(conn->hnd.fd, &conn->host_addr, &hostaddrlen) < 0) { log_error("l2tp: impossible to allocate new tunnel:" " getsockname() failed: %s\n", strerror(errno)); @@ -1305,6 +1287,35 @@ static struct l2tp_conn_t *l2tp_tunnel_alloc(const struct sockaddr_in *peer, goto out_err; } + for (count = UINT16_MAX; count > 0; --count) { + rdlen = read(urandom_fd, &conn->tid, sizeof(conn->tid)); + if (rdlen != sizeof(conn->tid)) { + log_error("l2tp: impossible to allocate new tunnel:" + " reading from urandom failed: %s\n", + (rdlen < 0) ? strerror(errno) : "short read"); + goto out_err; + } + + if (conn->tid == 0) + continue; + + pthread_mutex_lock(&l2tp_lock); + if (l2tp_conn[conn->tid]) { + pthread_mutex_unlock(&l2tp_lock); + continue; + } + l2tp_conn[conn->tid] = conn; + pthread_mutex_unlock(&l2tp_lock); + + break; + } + + if (count == 0) { + log_error("l2tp: impossible to allocate new tunnel:" + " could not find any unused tunnel ID\n"); + goto out_err; + } + conn->state = STATE_INIT; conn->framing_cap = framing_cap; @@ -4149,7 +4160,7 @@ static int l2tp_create_session_exec(const char *cmd, char * const *fields, return CLI_CMD_SYNTAX; } - if (u_readlong(&tid, fields[4], 1, L2TP_MAX_TID - 1) < 0) { + if (u_readlong(&tid, fields[4], 1, UINT16_MAX) < 0) { cli_sendv(client, "invalid Tunnel ID: \"%s\"\r\n", fields[4]); return CLI_CMD_INVAL; } @@ -4307,8 +4318,8 @@ static void l2tp_init(void) else if (system("modprobe -q pppol2tp || modprobe -q l2tp_ppp")) log_warn("unable to load l2tp kernel module\n"); - l2tp_conn = _malloc(L2TP_MAX_TID * sizeof(void *)); - memset(l2tp_conn, 0, L2TP_MAX_TID * sizeof(void *)); + l2tp_conn = _malloc((UINT16_MAX + 1) * sizeof(struct l2tp_conn_t *)); + memset(l2tp_conn, 0, (UINT16_MAX + 1) * sizeof(struct l2tp_conn_t *)); l2tp_conn_pool = mempool_create(sizeof(struct l2tp_conn_t)); l2tp_sess_pool = mempool_create(sizeof(struct l2tp_sess_t)); diff --git a/accel-pppd/ctrl/l2tp/l2tp.h b/accel-pppd/ctrl/l2tp/l2tp.h index 91844c6c..1b7e4cea 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.h +++ b/accel-pppd/ctrl/l2tp/l2tp.h @@ -14,7 +14,6 @@ #define ATTR_TYPE_STRING 5 #define L2TP_MAX_PACKET_SIZE 65536 -#define L2TP_MAX_TID 65534 #define L2TP_V2_PROTOCOL_VERSION ( 1 << 8 | 0 ) -- cgit v1.2.3