| .. | .. |
|---|
| 651 | 651 | return mtu - PPPOL2TP_HEADER_OVERHEAD; |
|---|
| 652 | 652 | } |
|---|
| 653 | 653 | |
|---|
| 654 | +static struct l2tp_tunnel *pppol2tp_tunnel_get(struct net *net, |
|---|
| 655 | + const struct l2tp_connect_info *info, |
|---|
| 656 | + bool *new_tunnel) |
|---|
| 657 | +{ |
|---|
| 658 | + struct l2tp_tunnel *tunnel; |
|---|
| 659 | + int error; |
|---|
| 660 | + |
|---|
| 661 | + *new_tunnel = false; |
|---|
| 662 | + |
|---|
| 663 | + tunnel = l2tp_tunnel_get(net, info->tunnel_id); |
|---|
| 664 | + |
|---|
| 665 | + /* Special case: create tunnel context if session_id and |
|---|
| 666 | + * peer_session_id is 0. Otherwise look up tunnel using supplied |
|---|
| 667 | + * tunnel id. |
|---|
| 668 | + */ |
|---|
| 669 | + if (!info->session_id && !info->peer_session_id) { |
|---|
| 670 | + if (!tunnel) { |
|---|
| 671 | + struct l2tp_tunnel_cfg tcfg = { |
|---|
| 672 | + .encap = L2TP_ENCAPTYPE_UDP, |
|---|
| 673 | + }; |
|---|
| 674 | + |
|---|
| 675 | + /* Prevent l2tp_tunnel_register() from trying to set up |
|---|
| 676 | + * a kernel socket. |
|---|
| 677 | + */ |
|---|
| 678 | + if (info->fd < 0) |
|---|
| 679 | + return ERR_PTR(-EBADF); |
|---|
| 680 | + |
|---|
| 681 | + error = l2tp_tunnel_create(info->fd, |
|---|
| 682 | + info->version, |
|---|
| 683 | + info->tunnel_id, |
|---|
| 684 | + info->peer_tunnel_id, &tcfg, |
|---|
| 685 | + &tunnel); |
|---|
| 686 | + if (error < 0) |
|---|
| 687 | + return ERR_PTR(error); |
|---|
| 688 | + |
|---|
| 689 | + l2tp_tunnel_inc_refcount(tunnel); |
|---|
| 690 | + error = l2tp_tunnel_register(tunnel, net, &tcfg); |
|---|
| 691 | + if (error < 0) { |
|---|
| 692 | + kfree(tunnel); |
|---|
| 693 | + return ERR_PTR(error); |
|---|
| 694 | + } |
|---|
| 695 | + |
|---|
| 696 | + *new_tunnel = true; |
|---|
| 697 | + } |
|---|
| 698 | + } else { |
|---|
| 699 | + /* Error if we can't find the tunnel */ |
|---|
| 700 | + if (!tunnel) |
|---|
| 701 | + return ERR_PTR(-ENOENT); |
|---|
| 702 | + |
|---|
| 703 | + /* Error if socket is not prepped */ |
|---|
| 704 | + if (!tunnel->sock) { |
|---|
| 705 | + l2tp_tunnel_dec_refcount(tunnel); |
|---|
| 706 | + return ERR_PTR(-ENOENT); |
|---|
| 707 | + } |
|---|
| 708 | + } |
|---|
| 709 | + |
|---|
| 710 | + return tunnel; |
|---|
| 711 | +} |
|---|
| 712 | + |
|---|
| 654 | 713 | /* connect() handler. Attach a PPPoX socket to a tunnel UDP socket |
|---|
| 655 | 714 | */ |
|---|
| 656 | 715 | static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, |
|---|
| .. | .. |
|---|
| 664 | 723 | struct pppol2tp_session *ps; |
|---|
| 665 | 724 | struct l2tp_session_cfg cfg = { 0, }; |
|---|
| 666 | 725 | bool drop_refcnt = false; |
|---|
| 667 | | - bool drop_tunnel = false; |
|---|
| 668 | 726 | bool new_session = false; |
|---|
| 669 | 727 | bool new_tunnel = false; |
|---|
| 670 | 728 | int error; |
|---|
| .. | .. |
|---|
| 672 | 730 | error = pppol2tp_sockaddr_get_info(uservaddr, sockaddr_len, &info); |
|---|
| 673 | 731 | if (error < 0) |
|---|
| 674 | 732 | return error; |
|---|
| 733 | + |
|---|
| 734 | + /* Don't bind if tunnel_id is 0 */ |
|---|
| 735 | + if (!info.tunnel_id) |
|---|
| 736 | + return -EINVAL; |
|---|
| 737 | + |
|---|
| 738 | + tunnel = pppol2tp_tunnel_get(sock_net(sk), &info, &new_tunnel); |
|---|
| 739 | + if (IS_ERR(tunnel)) |
|---|
| 740 | + return PTR_ERR(tunnel); |
|---|
| 675 | 741 | |
|---|
| 676 | 742 | lock_sock(sk); |
|---|
| 677 | 743 | |
|---|
| .. | .. |
|---|
| 684 | 750 | error = -EALREADY; |
|---|
| 685 | 751 | if (sk->sk_user_data) |
|---|
| 686 | 752 | goto end; /* socket is already attached */ |
|---|
| 687 | | - |
|---|
| 688 | | - /* Don't bind if tunnel_id is 0 */ |
|---|
| 689 | | - error = -EINVAL; |
|---|
| 690 | | - if (!info.tunnel_id) |
|---|
| 691 | | - goto end; |
|---|
| 692 | | - |
|---|
| 693 | | - tunnel = l2tp_tunnel_get(sock_net(sk), info.tunnel_id); |
|---|
| 694 | | - if (tunnel) |
|---|
| 695 | | - drop_tunnel = true; |
|---|
| 696 | | - |
|---|
| 697 | | - /* Special case: create tunnel context if session_id and |
|---|
| 698 | | - * peer_session_id is 0. Otherwise look up tunnel using supplied |
|---|
| 699 | | - * tunnel id. |
|---|
| 700 | | - */ |
|---|
| 701 | | - if (!info.session_id && !info.peer_session_id) { |
|---|
| 702 | | - if (!tunnel) { |
|---|
| 703 | | - struct l2tp_tunnel_cfg tcfg = { |
|---|
| 704 | | - .encap = L2TP_ENCAPTYPE_UDP, |
|---|
| 705 | | - }; |
|---|
| 706 | | - |
|---|
| 707 | | - /* Prevent l2tp_tunnel_register() from trying to set up |
|---|
| 708 | | - * a kernel socket. |
|---|
| 709 | | - */ |
|---|
| 710 | | - if (info.fd < 0) { |
|---|
| 711 | | - error = -EBADF; |
|---|
| 712 | | - goto end; |
|---|
| 713 | | - } |
|---|
| 714 | | - |
|---|
| 715 | | - error = l2tp_tunnel_create(info.fd, |
|---|
| 716 | | - info.version, |
|---|
| 717 | | - info.tunnel_id, |
|---|
| 718 | | - info.peer_tunnel_id, &tcfg, |
|---|
| 719 | | - &tunnel); |
|---|
| 720 | | - if (error < 0) |
|---|
| 721 | | - goto end; |
|---|
| 722 | | - |
|---|
| 723 | | - l2tp_tunnel_inc_refcount(tunnel); |
|---|
| 724 | | - error = l2tp_tunnel_register(tunnel, sock_net(sk), |
|---|
| 725 | | - &tcfg); |
|---|
| 726 | | - if (error < 0) { |
|---|
| 727 | | - kfree(tunnel); |
|---|
| 728 | | - goto end; |
|---|
| 729 | | - } |
|---|
| 730 | | - drop_tunnel = true; |
|---|
| 731 | | - new_tunnel = true; |
|---|
| 732 | | - } |
|---|
| 733 | | - } else { |
|---|
| 734 | | - /* Error if we can't find the tunnel */ |
|---|
| 735 | | - error = -ENOENT; |
|---|
| 736 | | - if (!tunnel) |
|---|
| 737 | | - goto end; |
|---|
| 738 | | - |
|---|
| 739 | | - /* Error if socket is not prepped */ |
|---|
| 740 | | - if (!tunnel->sock) |
|---|
| 741 | | - goto end; |
|---|
| 742 | | - } |
|---|
| 743 | 753 | |
|---|
| 744 | 754 | if (tunnel->peer_tunnel_id == 0) |
|---|
| 745 | 755 | tunnel->peer_tunnel_id = info.peer_tunnel_id; |
|---|
| .. | .. |
|---|
| 841 | 851 | } |
|---|
| 842 | 852 | if (drop_refcnt) |
|---|
| 843 | 853 | l2tp_session_dec_refcount(session); |
|---|
| 844 | | - if (drop_tunnel) |
|---|
| 845 | | - l2tp_tunnel_dec_refcount(tunnel); |
|---|
| 854 | + l2tp_tunnel_dec_refcount(tunnel); |
|---|
| 846 | 855 | release_sock(sk); |
|---|
| 847 | 856 | |
|---|
| 848 | 857 | return error; |
|---|