From f478f82d91e7344a59363c409c778dc12133ecb7 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Mon, 11 Feb 2013 21:02:58 +0100 Subject: l2tp: Add l2tp mode flag (LAC or LNS) Define the lns_mode flag for tunnels and sessions to keep track of their operating state. A session's mode is inherited from its parent tunnel. The session's mode is used to set the PPPOL2TP_SO_LNSMODE socket option to its PPP socket. For tunnels, the mode is used to define how new sessions may be created: -In LNS mode, new sessions may be created by accepting incomming calls (ICRQ) or by placing outgoing calls (OCRQ). -In LAC mode, tunnels will create sessions by accepting outgoing calls or by placing incomming calls. Signed-off-by: Guillaume Nault --- accel-pppd/ctrl/l2tp/l2tp.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index 2102826..cbf712c 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -76,6 +76,7 @@ struct l2tp_sess_t uint16_t peer_sid; int state1; + uint16_t lns_mode:1; struct triton_context_t sctx; struct triton_timer_t timeout_timer; @@ -98,6 +99,7 @@ struct l2tp_conn_t uint16_t tid; uint16_t peer_tid; uint32_t framing_cap; + uint16_t lns_mode:1; uint16_t challenge_len; uint8_t *challenge; @@ -729,6 +731,7 @@ static struct l2tp_sess_t *l2tp_tunnel_alloc_session(struct l2tp_conn_t *conn) sess->paren_conn = conn; sess->peer_sid = 0; sess->state1 = STATE_CLOSE; + sess->lns_mode = conn->lns_mode; sess->sctx.before_switch = log_switch; sess->sctx.close = l2tp_sess_close; @@ -815,7 +818,8 @@ out_err: static struct l2tp_conn_t *l2tp_tunnel_alloc(const struct sockaddr_in *peer, const struct sockaddr_in *host, - uint32_t framing_cap) + uint32_t framing_cap, + int lns_mode) { struct l2tp_conn_t *conn; socklen_t lnsaddrlen = sizeof(conn->lns_addr); @@ -924,6 +928,7 @@ static struct l2tp_conn_t *l2tp_tunnel_alloc(const struct sockaddr_in *peer, conn->sessions = NULL; conn->sess_count = 0; + conn->lns_mode = lns_mode; return conn; @@ -937,7 +942,7 @@ static int l2tp_session_connect(struct l2tp_sess_t *sess) { struct sockaddr_pppol2tp pppox_addr; struct l2tp_conn_t *conn = sess->paren_conn; - int arg = 1; + int lns_mode = sess->lns_mode; int flg; char addr[17]; char chan_name[64]; @@ -974,7 +979,8 @@ static int l2tp_session_connect(struct l2tp_sess_t *sess) goto out_err; } - if (setsockopt(sess->ppp.fd, SOL_PPPOL2TP, PPPOL2TP_SO_LNSMODE, &arg, sizeof(arg))) { + if (setsockopt(sess->ppp.fd, SOL_PPPOL2TP, PPPOL2TP_SO_LNSMODE, + &lns_mode, sizeof(lns_mode))) { log_ppp_error("l2tp: setsockopt: %s\n", strerror(errno)); goto out_err; } @@ -1350,7 +1356,7 @@ static int l2tp_recv_SCCRQ(struct l2tp_serv_t *serv, struct l2tp_packet_t *pack, host_addr.sin_port = 0; conn = l2tp_tunnel_alloc(&pack->addr, &host_addr, - framing_cap->val.uint32); + framing_cap->val.uint32, 1); if (conn == NULL) return -1; @@ -1460,7 +1466,7 @@ static int l2tp_recv_ICRQ(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack) uint16_t res = 0; uint16_t err = 0; - if (conn->state != STATE_ESTB) { + if (conn->state != STATE_ESTB && conn->lns_mode) { log_ppp_warn("l2tp: unexpected ICRQ\n"); return 0; } @@ -1691,6 +1697,12 @@ static void l2tp_tunnel_create_session(void *data) return; } + if (!conn->lns_mode) { + log_ppp_error("l2tp: impossible to place call: feature not" + " supported for tunnels operating as LAC\n"); + return; + } + sess = l2tp_tunnel_alloc_session(conn); if (sess == NULL) { log_ppp_error("l2tp: impossible to place call:" -- cgit v1.2.3