summaryrefslogtreecommitdiff
path: root/accel-pppd/ctrl/l2tp/l2tp.c
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2013-02-11 21:02:58 +0100
committerKozlov Dmitry <xeb@mail.ru>2013-02-12 00:12:48 +0400
commitf478f82d91e7344a59363c409c778dc12133ecb7 (patch)
treed45d60495d9e9e95f4fb934f9b829ef11d268e24 /accel-pppd/ctrl/l2tp/l2tp.c
parentc7a7743845a5d00f4609e7a61e6261564e2c3acf (diff)
downloadaccel-ppp-xebd-f478f82d91e7344a59363c409c778dc12133ecb7.tar.gz
accel-ppp-xebd-f478f82d91e7344a59363c409c778dc12133ecb7.zip
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 <g.nault@alphalink.fr>
Diffstat (limited to 'accel-pppd/ctrl/l2tp/l2tp.c')
-rw-r--r--accel-pppd/ctrl/l2tp/l2tp.c22
1 files 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:"