summaryrefslogtreecommitdiff
path: root/accel-pppd/ctrl/l2tp
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2014-03-28 21:09:58 +0100
committerDmitry Kozlov <xeb@mail.ru>2014-04-01 06:48:02 +0400
commitf6bad674803eb1a6205ed9c440992aa0af7e535a (patch)
treea567c01f1157f82fbdbc129ce777805386984b0a /accel-pppd/ctrl/l2tp
parenta801c89a0bfc83a7026f822e9b429cf6e331bcc8 (diff)
downloadaccel-ppp-f6bad674803eb1a6205ed9c440992aa0af7e535a.tar.gz
accel-ppp-f6bad674803eb1a6205ed9c440992aa0af7e535a.zip
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 <g.nault@alphalink.fr>
Diffstat (limited to 'accel-pppd/ctrl/l2tp')
-rw-r--r--accel-pppd/ctrl/l2tp/l2tp.c57
-rw-r--r--accel-pppd/ctrl/l2tp/l2tp.h1
2 files changed, 34 insertions, 24 deletions
diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c
index 925b643..dc11b42 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 91844c6..1b7e4ce 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 )