diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
| commit | 1ebbe2b20091d306453a5cf480a87e6cd28ae76f (patch) | |
| tree | f5cd7a0fa69b8b1938cb5a0faed2e7b0628072a5 /net/ipv6/ipv6_sockglue.c | |
| parent | ac58c9059da8886b5e8cde012a80266b18ca146e (diff) | |
| parent | 674a396c6d2ba0341ebdd7c1c9950f32f018e2dd (diff) | |
Merge branch 'linus'
Diffstat (limited to 'net/ipv6/ipv6_sockglue.c')
| -rw-r--r-- | net/ipv6/ipv6_sockglue.c | 163 |
1 files changed, 133 insertions, 30 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index f7142ba519ab..4c20eeb3d568 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -109,19 +109,13 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) | |||
| 109 | return 0; | 109 | return 0; |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | int ipv6_setsockopt(struct sock *sk, int level, int optname, | 112 | static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, |
| 113 | char __user *optval, int optlen) | 113 | char __user *optval, int optlen) |
| 114 | { | 114 | { |
| 115 | struct ipv6_pinfo *np = inet6_sk(sk); | 115 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 116 | int val, valbool; | 116 | int val, valbool; |
| 117 | int retv = -ENOPROTOOPT; | 117 | int retv = -ENOPROTOOPT; |
| 118 | 118 | ||
| 119 | if (level == SOL_IP && sk->sk_type != SOCK_RAW) | ||
| 120 | return udp_prot.setsockopt(sk, level, optname, optval, optlen); | ||
| 121 | |||
| 122 | if(level!=SOL_IPV6) | ||
| 123 | goto out; | ||
| 124 | |||
| 125 | if (optval == NULL) | 119 | if (optval == NULL) |
| 126 | val=0; | 120 | val=0; |
| 127 | else if (get_user(val, (int __user *) optval)) | 121 | else if (get_user(val, (int __user *) optval)) |
| @@ -613,17 +607,9 @@ done: | |||
| 613 | retv = xfrm_user_policy(sk, optname, optval, optlen); | 607 | retv = xfrm_user_policy(sk, optname, optval, optlen); |
| 614 | break; | 608 | break; |
| 615 | 609 | ||
| 616 | #ifdef CONFIG_NETFILTER | ||
| 617 | default: | ||
| 618 | retv = nf_setsockopt(sk, PF_INET6, optname, optval, | ||
| 619 | optlen); | ||
| 620 | break; | ||
| 621 | #endif | ||
| 622 | |||
| 623 | } | 610 | } |
| 624 | release_sock(sk); | 611 | release_sock(sk); |
| 625 | 612 | ||
| 626 | out: | ||
| 627 | return retv; | 613 | return retv; |
| 628 | 614 | ||
| 629 | e_inval: | 615 | e_inval: |
| @@ -631,6 +617,65 @@ e_inval: | |||
| 631 | return -EINVAL; | 617 | return -EINVAL; |
| 632 | } | 618 | } |
| 633 | 619 | ||
| 620 | int ipv6_setsockopt(struct sock *sk, int level, int optname, | ||
| 621 | char __user *optval, int optlen) | ||
| 622 | { | ||
| 623 | int err; | ||
| 624 | |||
| 625 | if (level == SOL_IP && sk->sk_type != SOCK_RAW) | ||
| 626 | return udp_prot.setsockopt(sk, level, optname, optval, optlen); | ||
| 627 | |||
| 628 | if (level != SOL_IPV6) | ||
| 629 | return -ENOPROTOOPT; | ||
| 630 | |||
| 631 | err = do_ipv6_setsockopt(sk, level, optname, optval, optlen); | ||
| 632 | #ifdef CONFIG_NETFILTER | ||
| 633 | /* we need to exclude all possible ENOPROTOOPTs except default case */ | ||
| 634 | if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && | ||
| 635 | optname != IPV6_XFRM_POLICY) { | ||
| 636 | lock_sock(sk); | ||
| 637 | err = nf_setsockopt(sk, PF_INET6, optname, optval, | ||
| 638 | optlen); | ||
| 639 | release_sock(sk); | ||
| 640 | } | ||
| 641 | #endif | ||
| 642 | return err; | ||
| 643 | } | ||
| 644 | |||
| 645 | |||
| 646 | #ifdef CONFIG_COMPAT | ||
| 647 | int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, | ||
| 648 | char __user *optval, int optlen) | ||
| 649 | { | ||
| 650 | int err; | ||
| 651 | |||
| 652 | if (level == SOL_IP && sk->sk_type != SOCK_RAW) { | ||
| 653 | if (udp_prot.compat_setsockopt != NULL) | ||
| 654 | return udp_prot.compat_setsockopt(sk, level, optname, | ||
| 655 | optval, optlen); | ||
| 656 | return udp_prot.setsockopt(sk, level, optname, optval, optlen); | ||
| 657 | } | ||
| 658 | |||
| 659 | if (level != SOL_IPV6) | ||
| 660 | return -ENOPROTOOPT; | ||
| 661 | |||
| 662 | err = do_ipv6_setsockopt(sk, level, optname, optval, optlen); | ||
| 663 | #ifdef CONFIG_NETFILTER | ||
| 664 | /* we need to exclude all possible ENOPROTOOPTs except default case */ | ||
| 665 | if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && | ||
| 666 | optname != IPV6_XFRM_POLICY) { | ||
| 667 | lock_sock(sk); | ||
| 668 | err = compat_nf_setsockopt(sk, PF_INET6, optname, | ||
| 669 | optval, optlen); | ||
| 670 | release_sock(sk); | ||
| 671 | } | ||
| 672 | #endif | ||
| 673 | return err; | ||
| 674 | } | ||
| 675 | |||
| 676 | EXPORT_SYMBOL(compat_ipv6_setsockopt); | ||
| 677 | #endif | ||
| 678 | |||
| 634 | static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, | 679 | static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, |
| 635 | char __user *optval, int len) | 680 | char __user *optval, int len) |
| 636 | { | 681 | { |
| @@ -642,17 +687,13 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, | |||
| 642 | return len; | 687 | return len; |
| 643 | } | 688 | } |
| 644 | 689 | ||
| 645 | int ipv6_getsockopt(struct sock *sk, int level, int optname, | 690 | static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, |
| 646 | char __user *optval, int __user *optlen) | 691 | char __user *optval, int __user *optlen) |
| 647 | { | 692 | { |
| 648 | struct ipv6_pinfo *np = inet6_sk(sk); | 693 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 649 | int len; | 694 | int len; |
| 650 | int val; | 695 | int val; |
| 651 | 696 | ||
| 652 | if (level == SOL_IP && sk->sk_type != SOCK_RAW) | ||
| 653 | return udp_prot.getsockopt(sk, level, optname, optval, optlen); | ||
| 654 | if(level!=SOL_IPV6) | ||
| 655 | return -ENOPROTOOPT; | ||
| 656 | if (get_user(len, optlen)) | 697 | if (get_user(len, optlen)) |
| 657 | return -EFAULT; | 698 | return -EFAULT; |
| 658 | switch (optname) { | 699 | switch (optname) { |
| @@ -842,17 +883,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 842 | break; | 883 | break; |
| 843 | 884 | ||
| 844 | default: | 885 | default: |
| 845 | #ifdef CONFIG_NETFILTER | ||
| 846 | lock_sock(sk); | ||
| 847 | val = nf_getsockopt(sk, PF_INET6, optname, optval, | ||
| 848 | &len); | ||
| 849 | release_sock(sk); | ||
| 850 | if (val >= 0) | ||
| 851 | val = put_user(len, optlen); | ||
| 852 | return val; | ||
| 853 | #else | ||
| 854 | return -EINVAL; | 886 | return -EINVAL; |
| 855 | #endif | ||
| 856 | } | 887 | } |
| 857 | len = min_t(unsigned int, sizeof(int), len); | 888 | len = min_t(unsigned int, sizeof(int), len); |
| 858 | if(put_user(len, optlen)) | 889 | if(put_user(len, optlen)) |
| @@ -862,6 +893,78 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 862 | return 0; | 893 | return 0; |
| 863 | } | 894 | } |
| 864 | 895 | ||
| 896 | int ipv6_getsockopt(struct sock *sk, int level, int optname, | ||
| 897 | char __user *optval, int __user *optlen) | ||
| 898 | { | ||
| 899 | int err; | ||
| 900 | |||
| 901 | if (level == SOL_IP && sk->sk_type != SOCK_RAW) | ||
| 902 | return udp_prot.getsockopt(sk, level, optname, optval, optlen); | ||
| 903 | |||
| 904 | if(level != SOL_IPV6) | ||
| 905 | return -ENOPROTOOPT; | ||
| 906 | |||
| 907 | err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); | ||
| 908 | #ifdef CONFIG_NETFILTER | ||
| 909 | /* we need to exclude all possible EINVALs except default case */ | ||
| 910 | if (err == -EINVAL && optname != IPV6_ADDRFORM && | ||
| 911 | optname != MCAST_MSFILTER) { | ||
| 912 | int len; | ||
| 913 | |||
| 914 | if (get_user(len, optlen)) | ||
| 915 | return -EFAULT; | ||
| 916 | |||
| 917 | lock_sock(sk); | ||
| 918 | err = nf_getsockopt(sk, PF_INET6, optname, optval, | ||
| 919 | &len); | ||
| 920 | release_sock(sk); | ||
| 921 | if (err >= 0) | ||
| 922 | err = put_user(len, optlen); | ||
| 923 | } | ||
| 924 | #endif | ||
| 925 | return err; | ||
| 926 | } | ||
| 927 | |||
| 928 | #ifdef CONFIG_COMPAT | ||
| 929 | int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, | ||
| 930 | char __user *optval, int __user *optlen) | ||
| 931 | { | ||
| 932 | int err; | ||
| 933 | |||
| 934 | if (level == SOL_IP && sk->sk_type != SOCK_RAW) { | ||
| 935 | if (udp_prot.compat_getsockopt != NULL) | ||
| 936 | return udp_prot.compat_getsockopt(sk, level, optname, | ||
| 937 | optval, optlen); | ||
| 938 | return udp_prot.getsockopt(sk, level, optname, optval, optlen); | ||
| 939 | } | ||
| 940 | |||
| 941 | if (level != SOL_IPV6) | ||
| 942 | return -ENOPROTOOPT; | ||
| 943 | |||
| 944 | err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); | ||
| 945 | #ifdef CONFIG_NETFILTER | ||
| 946 | /* we need to exclude all possible EINVALs except default case */ | ||
| 947 | if (err == -EINVAL && optname != IPV6_ADDRFORM && | ||
| 948 | optname != MCAST_MSFILTER) { | ||
| 949 | int len; | ||
| 950 | |||
| 951 | if (get_user(len, optlen)) | ||
| 952 | return -EFAULT; | ||
| 953 | |||
| 954 | lock_sock(sk); | ||
| 955 | err = compat_nf_getsockopt(sk, PF_INET6, | ||
| 956 | optname, optval, &len); | ||
| 957 | release_sock(sk); | ||
| 958 | if (err >= 0) | ||
| 959 | err = put_user(len, optlen); | ||
| 960 | } | ||
| 961 | #endif | ||
| 962 | return err; | ||
| 963 | } | ||
| 964 | |||
| 965 | EXPORT_SYMBOL(compat_ipv6_getsockopt); | ||
| 966 | #endif | ||
| 967 | |||
| 865 | void __init ipv6_packet_init(void) | 968 | void __init ipv6_packet_init(void) |
| 866 | { | 969 | { |
| 867 | dev_add_pack(&ipv6_packet_type); | 970 | dev_add_pack(&ipv6_packet_type); |
