Commit b79585f5 authored by James Chapman's avatar James Chapman Committed by David S. Miller

l2tp: pppol2tp_connect() handles ipv6 sockaddr variants

Userspace uses connect() to associate a pppol2tp socket with a tunnel
socket. This needs to allow the caller to supply the new IPv6
sockaddr_pppol2tp structures if IPv6 is used.
Signed-off-by: default avatarJames Chapman <jchapman@katalix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9d4ec1ae
...@@ -628,7 +628,6 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, ...@@ -628,7 +628,6 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr; struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr;
struct sockaddr_pppol2tpv3 *sp3 = (struct sockaddr_pppol2tpv3 *) uservaddr;
struct pppox_sock *po = pppox_sk(sk); struct pppox_sock *po = pppox_sk(sk);
struct l2tp_session *session = NULL; struct l2tp_session *session = NULL;
struct l2tp_tunnel *tunnel; struct l2tp_tunnel *tunnel;
...@@ -657,7 +656,13 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, ...@@ -657,7 +656,13 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
if (sk->sk_user_data) if (sk->sk_user_data)
goto end; /* socket is already attached */ goto end; /* socket is already attached */
/* Get params from socket address. Handle L2TPv2 and L2TPv3 */ /* Get params from socket address. Handle L2TPv2 and L2TPv3.
* This is nasty because there are different sockaddr_pppol2tp
* structs for L2TPv2, L2TPv3, over IPv4 and IPv6. We use
* the sockaddr size to determine which structure the caller
* is using.
*/
peer_tunnel_id = 0;
if (sockaddr_len == sizeof(struct sockaddr_pppol2tp)) { if (sockaddr_len == sizeof(struct sockaddr_pppol2tp)) {
fd = sp->pppol2tp.fd; fd = sp->pppol2tp.fd;
tunnel_id = sp->pppol2tp.s_tunnel; tunnel_id = sp->pppol2tp.s_tunnel;
...@@ -665,12 +670,31 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, ...@@ -665,12 +670,31 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
session_id = sp->pppol2tp.s_session; session_id = sp->pppol2tp.s_session;
peer_session_id = sp->pppol2tp.d_session; peer_session_id = sp->pppol2tp.d_session;
} else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpv3)) { } else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpv3)) {
struct sockaddr_pppol2tpv3 *sp3 =
(struct sockaddr_pppol2tpv3 *) sp;
ver = 3; ver = 3;
fd = sp3->pppol2tp.fd; fd = sp3->pppol2tp.fd;
tunnel_id = sp3->pppol2tp.s_tunnel; tunnel_id = sp3->pppol2tp.s_tunnel;
peer_tunnel_id = sp3->pppol2tp.d_tunnel; peer_tunnel_id = sp3->pppol2tp.d_tunnel;
session_id = sp3->pppol2tp.s_session; session_id = sp3->pppol2tp.s_session;
peer_session_id = sp3->pppol2tp.d_session; peer_session_id = sp3->pppol2tp.d_session;
} else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpin6)) {
struct sockaddr_pppol2tpin6 *sp6 =
(struct sockaddr_pppol2tpin6 *) sp;
fd = sp6->pppol2tp.fd;
tunnel_id = sp6->pppol2tp.s_tunnel;
peer_tunnel_id = sp6->pppol2tp.d_tunnel;
session_id = sp6->pppol2tp.s_session;
peer_session_id = sp6->pppol2tp.d_session;
} else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpv3in6)) {
struct sockaddr_pppol2tpv3in6 *sp6 =
(struct sockaddr_pppol2tpv3in6 *) sp;
ver = 3;
fd = sp6->pppol2tp.fd;
tunnel_id = sp6->pppol2tp.s_tunnel;
peer_tunnel_id = sp6->pppol2tp.d_tunnel;
session_id = sp6->pppol2tp.s_session;
peer_session_id = sp6->pppol2tp.d_session;
} else { } else {
error = -EINVAL; error = -EINVAL;
goto end; /* bad socket address */ goto end; /* bad socket address */
...@@ -711,12 +735,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, ...@@ -711,12 +735,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
if (tunnel->recv_payload_hook == NULL) if (tunnel->recv_payload_hook == NULL)
tunnel->recv_payload_hook = pppol2tp_recv_payload_hook; tunnel->recv_payload_hook = pppol2tp_recv_payload_hook;
if (tunnel->peer_tunnel_id == 0) { if (tunnel->peer_tunnel_id == 0)
if (ver == 2) tunnel->peer_tunnel_id = peer_tunnel_id;
tunnel->peer_tunnel_id = sp->pppol2tp.d_tunnel;
else
tunnel->peer_tunnel_id = sp3->pppol2tp.d_tunnel;
}
/* Create session if it doesn't already exist. We handle the /* Create session if it doesn't already exist. We handle the
* case where a session was previously created by the netlink * case where a session was previously created by the netlink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment