From 24d4a04aa76c87898f9d0b16ad43fc8d667432ae Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Fri, 7 Sep 2012 12:34:08 +0200 Subject: L2TP: Separate session and tunnel connection code Establish tunnel and session connections upon reception of SCCCN and ICCN messages respectively. Signed-off-by: Guillaume Nault --- accel-pppd/ctrl/l2tp/l2tp.c | 94 ++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 36 deletions(-) (limited to 'accel-pppd') diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index 7faf951c..d436de0e 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -406,37 +406,12 @@ out_err: return -1; } -static int l2tp_connect(struct l2tp_conn_t *conn) +static int l2tp_session_connect(struct l2tp_conn_t *conn) { struct sockaddr_pppol2tp pppox_addr; int arg = 1; int flg; - memset(&pppox_addr, 0, sizeof(pppox_addr)); - pppox_addr.sa_family = AF_PPPOX; - pppox_addr.sa_protocol = PX_PROTO_OL2TP; - pppox_addr.pppol2tp.fd = conn->hnd.fd; - memcpy(&pppox_addr.pppol2tp.addr, &conn->lac_addr, sizeof(conn->lac_addr)); - pppox_addr.pppol2tp.s_tunnel = conn->tid; - pppox_addr.pppol2tp.d_tunnel = conn->peer_tid; - - conn->tunnel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); - if (conn->tunnel_fd < 0) { - log_ppp_error("l2tp: socket(AF_PPPOX): %s\n", strerror(errno)); - goto out_err; - } - - flg = fcntl(conn->tunnel_fd, F_GETFD); - if (flg < 0) { - log_ppp_error("l2tp: fcntl(F_GETFD): %s\n", strerror(errno)); - goto out_err; - } - flg = fcntl(conn->tunnel_fd, F_SETFD, flg | FD_CLOEXEC); - if (flg < 0) { - log_ppp_error("l2tp: fcntl(F_SETFD): %s\n", strerror(errno)); - goto out_err; - } - conn->sess.ppp.fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); if (conn->sess.ppp.fd < 0) { log_ppp_error("l2tp: socket(AF_PPPOX): %s\n", strerror(errno)); @@ -454,11 +429,13 @@ static int l2tp_connect(struct l2tp_conn_t *conn) goto out_err; } - if (connect(conn->tunnel_fd, (struct sockaddr *)&pppox_addr, sizeof(pppox_addr)) < 0) { - log_ppp_error("l2tp: connect(tunnel): %s\n", strerror(errno)); - goto out_err; - } - + memset(&pppox_addr, 0, sizeof(pppox_addr)); + pppox_addr.sa_family = AF_PPPOX; + pppox_addr.sa_protocol = PX_PROTO_OL2TP; + pppox_addr.pppol2tp.fd = conn->hnd.fd; + memcpy(&pppox_addr.pppol2tp.addr, &conn->lac_addr, sizeof(conn->lac_addr)); + pppox_addr.pppol2tp.s_tunnel = conn->tid; + pppox_addr.pppol2tp.d_tunnel = conn->peer_tid; pppox_addr.pppol2tp.s_session = conn->sess.sid; pppox_addr.pppol2tp.d_session = conn->sess.peer_sid; @@ -487,10 +464,6 @@ static int l2tp_connect(struct l2tp_conn_t *conn) return 0; out_err: - if (conn->tunnel_fd >= 0) { - close(conn->tunnel_fd); - conn->tunnel_fd = -1; - } if (conn->sess.ppp.fd >= 0) { close(conn->sess.ppp.fd); conn->sess.ppp.fd = -1; @@ -498,6 +471,51 @@ out_err: return -1; } +static int l2tp_tunnel_connect(struct l2tp_conn_t *conn) +{ + struct sockaddr_pppol2tp pppox_addr; + int flg; + + memset(&pppox_addr, 0, sizeof(pppox_addr)); + pppox_addr.sa_family = AF_PPPOX; + pppox_addr.sa_protocol = PX_PROTO_OL2TP; + pppox_addr.pppol2tp.fd = conn->hnd.fd; + memcpy(&pppox_addr.pppol2tp.addr, &conn->lac_addr, sizeof(conn->lac_addr)); + pppox_addr.pppol2tp.s_tunnel = conn->tid; + pppox_addr.pppol2tp.d_tunnel = conn->peer_tid; + + conn->tunnel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); + if (conn->tunnel_fd < 0) { + log_ppp_error("l2tp: socket(AF_PPPOX): %s\n", strerror(errno)); + goto out_err; + } + + flg = fcntl(conn->tunnel_fd, F_GETFD); + if (flg < 0) { + log_ppp_error("l2tp: fcntl(F_GETFD): %s\n", strerror(errno)); + goto out_err; + } + flg = fcntl(conn->tunnel_fd, F_SETFD, flg | FD_CLOEXEC); + if (flg < 0) { + log_ppp_error("l2tp: fcntl(F_SETFD): %s\n", strerror(errno)); + goto out_err; + } + + if (connect(conn->tunnel_fd, (struct sockaddr *)&pppox_addr, sizeof(pppox_addr)) < 0) { + log_ppp_error("l2tp: connect(tunnel): %s\n", strerror(errno)); + goto out_err; + } + + return 0; + +out_err: + if (conn->tunnel_fd >= 0) { + close(conn->tunnel_fd); + conn->tunnel_fd = -1; + } + return -1; +} + static void l2tp_rtimeout(struct triton_timer_t *t) { struct l2tp_conn_t *conn = container_of(t, typeof(*conn), rtimeout_timer); @@ -793,6 +811,10 @@ static int l2tp_recv_SCCCN(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack) { if (conn->state == STATE_WAIT_SCCCN) { triton_timer_mod(&conn->timeout_timer, 0); + if (l2tp_tunnel_connect(conn) < 0) { + l2tp_terminate(conn, 2, 0); + return -1; + } conn->state = STATE_ESTB; conn->sess.state1 = STATE_WAIT_ICRQ; } @@ -878,7 +900,7 @@ static int l2tp_recv_ICCN(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack) conn->sess.state1 = STATE_ESTB; - if (l2tp_connect(conn)) { + if (l2tp_session_connect(conn)) { if (l2tp_terminate(conn, 2, 0)) return -1; return 0; -- cgit v1.2.3