diff options
author | James Chapman <jchapman@katalix.com> | 2012-04-29 17:48:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-01 09:30:55 -0400 |
commit | b79585f537ba9631c9b6aafb54a8040c8d515fee (patch) | |
tree | a0de8558ab9af6339573408bb2d5a1b4a3f51a20 | |
parent | 9d4ec1aeda4a2754681a93029adf89f8f41b9a4d (diff) |
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: James Chapman <jchapman@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/l2tp/l2tp_ppp.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 27b9dec9d254..9f2c421aa307 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
@@ -628,7 +628,6 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
628 | { | 628 | { |
629 | struct sock *sk = sock->sk; | 629 | struct sock *sk = sock->sk; |
630 | struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr; | 630 | struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr; |
631 | struct sockaddr_pppol2tpv3 *sp3 = (struct sockaddr_pppol2tpv3 *) uservaddr; | ||
632 | struct pppox_sock *po = pppox_sk(sk); | 631 | struct pppox_sock *po = pppox_sk(sk); |
633 | struct l2tp_session *session = NULL; | 632 | struct l2tp_session *session = NULL; |
634 | struct l2tp_tunnel *tunnel; | 633 | struct l2tp_tunnel *tunnel; |
@@ -657,7 +656,13 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
657 | if (sk->sk_user_data) | 656 | if (sk->sk_user_data) |
658 | goto end; /* socket is already attached */ | 657 | goto end; /* socket is already attached */ |
659 | 658 | ||
660 | /* Get params from socket address. Handle L2TPv2 and L2TPv3 */ | 659 | /* Get params from socket address. Handle L2TPv2 and L2TPv3. |
660 | * This is nasty because there are different sockaddr_pppol2tp | ||
661 | * structs for L2TPv2, L2TPv3, over IPv4 and IPv6. We use | ||
662 | * the sockaddr size to determine which structure the caller | ||
663 | * is using. | ||
664 | */ | ||
665 | peer_tunnel_id = 0; | ||
661 | if (sockaddr_len == sizeof(struct sockaddr_pppol2tp)) { | 666 | if (sockaddr_len == sizeof(struct sockaddr_pppol2tp)) { |
662 | fd = sp->pppol2tp.fd; | 667 | fd = sp->pppol2tp.fd; |
663 | tunnel_id = sp->pppol2tp.s_tunnel; | 668 | tunnel_id = sp->pppol2tp.s_tunnel; |
@@ -665,12 +670,31 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
665 | session_id = sp->pppol2tp.s_session; | 670 | session_id = sp->pppol2tp.s_session; |
666 | peer_session_id = sp->pppol2tp.d_session; | 671 | peer_session_id = sp->pppol2tp.d_session; |
667 | } else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpv3)) { | 672 | } else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpv3)) { |
673 | struct sockaddr_pppol2tpv3 *sp3 = | ||
674 | (struct sockaddr_pppol2tpv3 *) sp; | ||
668 | ver = 3; | 675 | ver = 3; |
669 | fd = sp3->pppol2tp.fd; | 676 | fd = sp3->pppol2tp.fd; |
670 | tunnel_id = sp3->pppol2tp.s_tunnel; | 677 | tunnel_id = sp3->pppol2tp.s_tunnel; |
671 | peer_tunnel_id = sp3->pppol2tp.d_tunnel; | 678 | peer_tunnel_id = sp3->pppol2tp.d_tunnel; |
672 | session_id = sp3->pppol2tp.s_session; | 679 | session_id = sp3->pppol2tp.s_session; |
673 | peer_session_id = sp3->pppol2tp.d_session; | 680 | peer_session_id = sp3->pppol2tp.d_session; |
681 | } else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpin6)) { | ||
682 | struct sockaddr_pppol2tpin6 *sp6 = | ||
683 | (struct sockaddr_pppol2tpin6 *) sp; | ||
684 | fd = sp6->pppol2tp.fd; | ||
685 | tunnel_id = sp6->pppol2tp.s_tunnel; | ||
686 | peer_tunnel_id = sp6->pppol2tp.d_tunnel; | ||
687 | session_id = sp6->pppol2tp.s_session; | ||
688 | peer_session_id = sp6->pppol2tp.d_session; | ||
689 | } else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpv3in6)) { | ||
690 | struct sockaddr_pppol2tpv3in6 *sp6 = | ||
691 | (struct sockaddr_pppol2tpv3in6 *) sp; | ||
692 | ver = 3; | ||
693 | fd = sp6->pppol2tp.fd; | ||
694 | tunnel_id = sp6->pppol2tp.s_tunnel; | ||
695 | peer_tunnel_id = sp6->pppol2tp.d_tunnel; | ||
696 | session_id = sp6->pppol2tp.s_session; | ||
697 | peer_session_id = sp6->pppol2tp.d_session; | ||
674 | } else { | 698 | } else { |
675 | error = -EINVAL; | 699 | error = -EINVAL; |
676 | goto end; /* bad socket address */ | 700 | goto end; /* bad socket address */ |
@@ -711,12 +735,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
711 | if (tunnel->recv_payload_hook == NULL) | 735 | if (tunnel->recv_payload_hook == NULL) |
712 | tunnel->recv_payload_hook = pppol2tp_recv_payload_hook; | 736 | tunnel->recv_payload_hook = pppol2tp_recv_payload_hook; |
713 | 737 | ||
714 | if (tunnel->peer_tunnel_id == 0) { | 738 | if (tunnel->peer_tunnel_id == 0) |
715 | if (ver == 2) | 739 | tunnel->peer_tunnel_id = peer_tunnel_id; |
716 | tunnel->peer_tunnel_id = sp->pppol2tp.d_tunnel; | ||
717 | else | ||
718 | tunnel->peer_tunnel_id = sp3->pppol2tp.d_tunnel; | ||
719 | } | ||
720 | 740 | ||
721 | /* Create session if it doesn't already exist. We handle the | 741 | /* Create session if it doesn't already exist. We handle the |
722 | * case where a session was previously created by the netlink | 742 | * case where a session was previously created by the netlink |