aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJames Chapman <jchapman@katalix.com>2010-04-02 02:18:54 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-03 17:56:04 -0400
commite0d4435f93905f517003cfa7328a36ea19788147 (patch)
treecdf858e601d993405d3fd1f318446dddbf9e6fcb /net
parentf7faffa3ff8ef6ae712ef16312b8a2aa7a1c95fe (diff)
l2tp: Update PPP-over-L2TP driver to work over L2TPv3
This patch makes changes to the L2TP PPP code for L2TPv3. The existing code has some assumptions about the L2TP header which are broken by L2TPv3. Also the sockaddr_pppol2tp structure of the original code is too small to support the increased size of the L2TPv3 tunnel and session id, so a new sockaddr_pppol2tpv3 structure is needed. In the socket calls, the size of this structure is used to tell if the operation is for L2TPv2 or L2TPv3. Signed-off-by: James Chapman <jchapman@katalix.com> Reviewed-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/l2tp/l2tp_ppp.c120
1 files changed, 74 insertions, 46 deletions
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index bee5b1413ec0..e5b531266541 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -291,17 +291,6 @@ static void pppol2tp_session_sock_put(struct l2tp_session *session)
291 * Transmit handling 291 * Transmit handling
292 ***********************************************************************/ 292 ***********************************************************************/
293 293
294/* Tell how big L2TP headers are for a particular session. This
295 * depends on whether sequence numbers are being used.
296 */
297static inline int pppol2tp_l2tp_header_len(struct l2tp_session *session)
298{
299 if (session->send_seq)
300 return PPPOL2TP_L2TP_HDR_SIZE_SEQ;
301
302 return PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
303}
304
305/* This is the sendmsg for the PPPoL2TP pppol2tp_session socket. We come here 294/* This is the sendmsg for the PPPoL2TP pppol2tp_session socket. We come here
306 * when a user application does a sendmsg() on the session socket. L2TP and 295 * when a user application does a sendmsg() on the session socket. L2TP and
307 * PPP headers must be inserted into the user's data. 296 * PPP headers must be inserted into the user's data.
@@ -394,7 +383,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
394 static const u8 ppph[2] = { 0xff, 0x03 }; 383 static const u8 ppph[2] = { 0xff, 0x03 };
395 struct sock *sk = (struct sock *) chan->private; 384 struct sock *sk = (struct sock *) chan->private;
396 struct sock *sk_tun; 385 struct sock *sk_tun;
397 int hdr_len;
398 struct l2tp_session *session; 386 struct l2tp_session *session;
399 struct l2tp_tunnel *tunnel; 387 struct l2tp_tunnel *tunnel;
400 struct pppol2tp_session *ps; 388 struct pppol2tp_session *ps;
@@ -417,9 +405,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
417 if (tunnel == NULL) 405 if (tunnel == NULL)
418 goto abort_put_sess; 406 goto abort_put_sess;
419 407
420 /* What header length is configured for this session? */
421 hdr_len = pppol2tp_l2tp_header_len(session);
422
423 old_headroom = skb_headroom(skb); 408 old_headroom = skb_headroom(skb);
424 if (skb_cow_head(skb, sizeof(ppph))) 409 if (skb_cow_head(skb, sizeof(ppph)))
425 goto abort_put_sess_tun; 410 goto abort_put_sess_tun;
@@ -432,7 +417,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
432 skb->data[0] = ppph[0]; 417 skb->data[0] = ppph[0];
433 skb->data[1] = ppph[1]; 418 skb->data[1] = ppph[1];
434 419
435 l2tp_xmit_skb(session, skb, hdr_len); 420 l2tp_xmit_skb(session, skb, session->hdr_len);
436 421
437 sock_put(sk_tun); 422 sock_put(sk_tun);
438 sock_put(sk); 423 sock_put(sk);
@@ -615,6 +600,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
615{ 600{
616 struct sock *sk = sock->sk; 601 struct sock *sk = sock->sk;
617 struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr; 602 struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr;
603 struct sockaddr_pppol2tpv3 *sp3 = (struct sockaddr_pppol2tpv3 *) uservaddr;
618 struct pppox_sock *po = pppox_sk(sk); 604 struct pppox_sock *po = pppox_sk(sk);
619 struct l2tp_session *session = NULL; 605 struct l2tp_session *session = NULL;
620 struct l2tp_tunnel *tunnel; 606 struct l2tp_tunnel *tunnel;
@@ -622,6 +608,10 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
622 struct dst_entry *dst; 608 struct dst_entry *dst;
623 struct l2tp_session_cfg cfg = { 0, }; 609 struct l2tp_session_cfg cfg = { 0, };
624 int error = 0; 610 int error = 0;
611 u32 tunnel_id, peer_tunnel_id;
612 u32 session_id, peer_session_id;
613 int ver = 2;
614 int fd;
625 615
626 lock_sock(sk); 616 lock_sock(sk);
627 617
@@ -639,21 +629,40 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
639 if (sk->sk_user_data) 629 if (sk->sk_user_data)
640 goto end; /* socket is already attached */ 630 goto end; /* socket is already attached */
641 631
642 /* Don't bind if s_tunnel is 0 */ 632 /* Get params from socket address. Handle L2TPv2 and L2TPv3 */
633 if (sockaddr_len == sizeof(struct sockaddr_pppol2tp)) {
634 fd = sp->pppol2tp.fd;
635 tunnel_id = sp->pppol2tp.s_tunnel;
636 peer_tunnel_id = sp->pppol2tp.d_tunnel;
637 session_id = sp->pppol2tp.s_session;
638 peer_session_id = sp->pppol2tp.d_session;
639 } else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpv3)) {
640 ver = 3;
641 fd = sp3->pppol2tp.fd;
642 tunnel_id = sp3->pppol2tp.s_tunnel;
643 peer_tunnel_id = sp3->pppol2tp.d_tunnel;
644 session_id = sp3->pppol2tp.s_session;
645 peer_session_id = sp3->pppol2tp.d_session;
646 } else {
647 error = -EINVAL;
648 goto end; /* bad socket address */
649 }
650
651 /* Don't bind if tunnel_id is 0 */
643 error = -EINVAL; 652 error = -EINVAL;
644 if (sp->pppol2tp.s_tunnel == 0) 653 if (tunnel_id == 0)
645 goto end; 654 goto end;
646 655
647 /* Special case: create tunnel context if s_session and 656 /* Special case: create tunnel context if session_id and
648 * d_session is 0. Otherwise look up tunnel using supplied 657 * peer_session_id is 0. Otherwise look up tunnel using supplied
649 * tunnel id. 658 * tunnel id.
650 */ 659 */
651 if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) { 660 if ((session_id == 0) && (peer_session_id == 0)) {
652 error = l2tp_tunnel_create(sock_net(sk), sp->pppol2tp.fd, 2, sp->pppol2tp.s_tunnel, sp->pppol2tp.d_tunnel, NULL, &tunnel); 661 error = l2tp_tunnel_create(sock_net(sk), fd, ver, tunnel_id, peer_tunnel_id, NULL, &tunnel);
653 if (error < 0) 662 if (error < 0)
654 goto end; 663 goto end;
655 } else { 664 } else {
656 tunnel = l2tp_tunnel_find(sock_net(sk), sp->pppol2tp.s_tunnel); 665 tunnel = l2tp_tunnel_find(sock_net(sk), tunnel_id);
657 666
658 /* Error if we can't find the tunnel */ 667 /* Error if we can't find the tunnel */
659 error = -ENOENT; 668 error = -ENOENT;
@@ -670,20 +679,21 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
670 679
671 /* Check that this session doesn't already exist */ 680 /* Check that this session doesn't already exist */
672 error = -EEXIST; 681 error = -EEXIST;
673 session = l2tp_session_find(sock_net(sk), tunnel, sp->pppol2tp.s_session); 682 session = l2tp_session_find(sock_net(sk), tunnel, session_id);
674 if (session != NULL) 683 if (session != NULL)
675 goto end; 684 goto end;
676 685
677 /* Default MTU must allow space for UDP/L2TP/PPP 686 /* Default MTU values. */
678 * headers. 687 if (cfg.mtu == 0)
679 */ 688 cfg.mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD;
680 cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD; 689 if (cfg.mru == 0)
690 cfg.mru = cfg.mtu;
681 cfg.debug = tunnel->debug; 691 cfg.debug = tunnel->debug;
682 692
683 /* Allocate and initialize a new session context. */ 693 /* Allocate and initialize a new session context. */
684 session = l2tp_session_create(sizeof(struct pppol2tp_session), 694 session = l2tp_session_create(sizeof(struct pppol2tp_session),
685 tunnel, sp->pppol2tp.s_session, 695 tunnel, session_id,
686 sp->pppol2tp.d_session, &cfg); 696 peer_session_id, &cfg);
687 if (session == NULL) { 697 if (session == NULL) {
688 error = -ENOMEM; 698 error = -ENOMEM;
689 goto end; 699 goto end;
@@ -756,8 +766,7 @@ end:
756static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr, 766static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
757 int *usockaddr_len, int peer) 767 int *usockaddr_len, int peer)
758{ 768{
759 int len = sizeof(struct sockaddr_pppol2tp); 769 int len = 0;
760 struct sockaddr_pppol2tp sp;
761 int error = 0; 770 int error = 0;
762 struct l2tp_session *session; 771 struct l2tp_session *session;
763 struct l2tp_tunnel *tunnel; 772 struct l2tp_tunnel *tunnel;
@@ -783,21 +792,40 @@ static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
783 goto end_put_sess; 792 goto end_put_sess;
784 } 793 }
785 794
786 memset(&sp, 0, len);
787 sp.sa_family = AF_PPPOX;
788 sp.sa_protocol = PX_PROTO_OL2TP;
789 sp.pppol2tp.fd = tunnel->fd;
790 sp.pppol2tp.pid = pls->owner;
791 sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
792 sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
793 sp.pppol2tp.s_session = session->session_id;
794 sp.pppol2tp.d_session = session->peer_session_id;
795 inet = inet_sk(sk); 795 inet = inet_sk(sk);
796 sp.pppol2tp.addr.sin_family = AF_INET; 796 if (tunnel->version == 2) {
797 sp.pppol2tp.addr.sin_port = inet->inet_dport; 797 struct sockaddr_pppol2tp sp;
798 sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr; 798 len = sizeof(sp);
799 799 memset(&sp, 0, len);
800 memcpy(uaddr, &sp, len); 800 sp.sa_family = AF_PPPOX;
801 sp.sa_protocol = PX_PROTO_OL2TP;
802 sp.pppol2tp.fd = tunnel->fd;
803 sp.pppol2tp.pid = pls->owner;
804 sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
805 sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
806 sp.pppol2tp.s_session = session->session_id;
807 sp.pppol2tp.d_session = session->peer_session_id;
808 sp.pppol2tp.addr.sin_family = AF_INET;
809 sp.pppol2tp.addr.sin_port = inet->inet_dport;
810 sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr;
811 memcpy(uaddr, &sp, len);
812 } else if (tunnel->version == 3) {
813 struct sockaddr_pppol2tpv3 sp;
814 len = sizeof(sp);
815 memset(&sp, 0, len);
816 sp.sa_family = AF_PPPOX;
817 sp.sa_protocol = PX_PROTO_OL2TP;
818 sp.pppol2tp.fd = tunnel->fd;
819 sp.pppol2tp.pid = pls->owner;
820 sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
821 sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
822 sp.pppol2tp.s_session = session->session_id;
823 sp.pppol2tp.d_session = session->peer_session_id;
824 sp.pppol2tp.addr.sin_family = AF_INET;
825 sp.pppol2tp.addr.sin_port = inet->inet_dport;
826 sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr;
827 memcpy(uaddr, &sp, len);
828 }
801 829
802 *usockaddr_len = len; 830 *usockaddr_len = len;
803 831