From a801c89a0bfc83a7026f822e9b429cf6e331bcc8 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Fri, 28 Mar 2014 21:09:24 +0100 Subject: l2tp: try generating Session IDs harder Don't give up immediately when generating a new Session ID fails. Keep trying until a valid Session ID is found. Abort when the number of attempts exceeds the number of valid Session IDs. This is derived from algorithm 3 of RFC 6056 (Port Randomization Recommendations). Other algorithms may be used later on if need be. Signed-off-by: Guillaume Nault --- accel-pppd/ctrl/l2tp/l2tp.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index 83136641..925b6434 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -1057,6 +1057,7 @@ static struct l2tp_sess_t *l2tp_tunnel_new_session(struct l2tp_conn_t *conn) struct l2tp_sess_t *sess = NULL; struct l2tp_sess_t **sess_search = NULL; ssize_t rdlen = 0; + uint16_t count; sess = mempool_alloc(l2tp_sess_pool); if (sess == NULL) { @@ -1067,23 +1068,27 @@ static struct l2tp_sess_t *l2tp_tunnel_new_session(struct l2tp_conn_t *conn) } memset(sess, 0, sizeof(*sess)); - rdlen = read(urandom_fd, &sess->sid, sizeof(sess->sid)); - if (rdlen != sizeof(sess->sid)) { - log_tunnel(log_error, conn, - "impossible to allocate new session:" - " reading from urandom failed: %s\n", - (rdlen < 0) ? strerror(errno) : "short read"); - goto out_err; - } - if (sess->sid == 0) { - log_tunnel(log_error, conn, - "impossible to allocate new session:" - " session ID generation failed\n"); - goto out_err; + for (count = UINT16_MAX; count > 0; --count) { + rdlen = read(urandom_fd, &sess->sid, sizeof(sess->sid)); + if (rdlen != sizeof(sess->sid)) { + log_tunnel(log_error, conn, + "impossible to allocate new session:" + " reading from urandom failed: %s\n", + (rdlen < 0) ? strerror(errno) : "short read"); + goto out_err; + } + + if (sess->sid == 0) + continue; + + sess_search = tsearch(sess, &conn->sessions, sess_cmp); + if (*sess_search != sess) + continue; + + break; } - sess_search = tsearch(sess, &conn->sessions, sess_cmp); - if (*sess_search != sess) { + if (count == 0) { log_tunnel(log_error, conn, "impossible to allocate new session:" " could not find any unused session ID\n"); -- cgit v1.2.3