diff options
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r-- | net/ipv6/raw.c | 145 |
1 files changed, 101 insertions, 44 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ae20a0ec9bd8..fa1ce0ae123e 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -859,29 +859,12 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, | |||
859 | } | 859 | } |
860 | 860 | ||
861 | 861 | ||
862 | static int rawv6_setsockopt(struct sock *sk, int level, int optname, | 862 | static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, |
863 | char __user *optval, int optlen) | 863 | char __user *optval, int optlen) |
864 | { | 864 | { |
865 | struct raw6_sock *rp = raw6_sk(sk); | 865 | struct raw6_sock *rp = raw6_sk(sk); |
866 | int val; | 866 | int val; |
867 | 867 | ||
868 | switch(level) { | ||
869 | case SOL_RAW: | ||
870 | break; | ||
871 | |||
872 | case SOL_ICMPV6: | ||
873 | if (inet_sk(sk)->num != IPPROTO_ICMPV6) | ||
874 | return -EOPNOTSUPP; | ||
875 | return rawv6_seticmpfilter(sk, level, optname, optval, | ||
876 | optlen); | ||
877 | case SOL_IPV6: | ||
878 | if (optname == IPV6_CHECKSUM) | ||
879 | break; | ||
880 | default: | ||
881 | return ipv6_setsockopt(sk, level, optname, optval, | ||
882 | optlen); | ||
883 | }; | ||
884 | |||
885 | if (get_user(val, (int __user *)optval)) | 868 | if (get_user(val, (int __user *)optval)) |
886 | return -EFAULT; | 869 | return -EFAULT; |
887 | 870 | ||
@@ -906,12 +889,9 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname, | |||
906 | } | 889 | } |
907 | } | 890 | } |
908 | 891 | ||
909 | static int rawv6_getsockopt(struct sock *sk, int level, int optname, | 892 | static int rawv6_setsockopt(struct sock *sk, int level, int optname, |
910 | char __user *optval, int __user *optlen) | 893 | char __user *optval, int optlen) |
911 | { | 894 | { |
912 | struct raw6_sock *rp = raw6_sk(sk); | ||
913 | int val, len; | ||
914 | |||
915 | switch(level) { | 895 | switch(level) { |
916 | case SOL_RAW: | 896 | case SOL_RAW: |
917 | break; | 897 | break; |
@@ -919,15 +899,45 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
919 | case SOL_ICMPV6: | 899 | case SOL_ICMPV6: |
920 | if (inet_sk(sk)->num != IPPROTO_ICMPV6) | 900 | if (inet_sk(sk)->num != IPPROTO_ICMPV6) |
921 | return -EOPNOTSUPP; | 901 | return -EOPNOTSUPP; |
922 | return rawv6_geticmpfilter(sk, level, optname, optval, | 902 | return rawv6_seticmpfilter(sk, level, optname, optval, |
923 | optlen); | 903 | optlen); |
924 | case SOL_IPV6: | 904 | case SOL_IPV6: |
925 | if (optname == IPV6_CHECKSUM) | 905 | if (optname == IPV6_CHECKSUM) |
926 | break; | 906 | break; |
927 | default: | 907 | default: |
928 | return ipv6_getsockopt(sk, level, optname, optval, | 908 | return ipv6_setsockopt(sk, level, optname, optval, |
929 | optlen); | 909 | optlen); |
930 | }; | 910 | }; |
911 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); | ||
912 | } | ||
913 | |||
914 | #ifdef CONFIG_COMPAT | ||
915 | static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname, | ||
916 | char __user *optval, int optlen) | ||
917 | { | ||
918 | switch (level) { | ||
919 | case SOL_RAW: | ||
920 | break; | ||
921 | case SOL_ICMPV6: | ||
922 | if (inet_sk(sk)->num != IPPROTO_ICMPV6) | ||
923 | return -EOPNOTSUPP; | ||
924 | return rawv6_seticmpfilter(sk, level, optname, optval, optlen); | ||
925 | case SOL_IPV6: | ||
926 | if (optname == IPV6_CHECKSUM) | ||
927 | break; | ||
928 | default: | ||
929 | return compat_ipv6_setsockopt(sk, level, optname, | ||
930 | optval, optlen); | ||
931 | }; | ||
932 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); | ||
933 | } | ||
934 | #endif | ||
935 | |||
936 | static int do_rawv6_getsockopt(struct sock *sk, int level, int optname, | ||
937 | char __user *optval, int __user *optlen) | ||
938 | { | ||
939 | struct raw6_sock *rp = raw6_sk(sk); | ||
940 | int val, len; | ||
931 | 941 | ||
932 | if (get_user(len,optlen)) | 942 | if (get_user(len,optlen)) |
933 | return -EFAULT; | 943 | return -EFAULT; |
@@ -953,6 +963,50 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
953 | return 0; | 963 | return 0; |
954 | } | 964 | } |
955 | 965 | ||
966 | static int rawv6_getsockopt(struct sock *sk, int level, int optname, | ||
967 | char __user *optval, int __user *optlen) | ||
968 | { | ||
969 | switch(level) { | ||
970 | case SOL_RAW: | ||
971 | break; | ||
972 | |||
973 | case SOL_ICMPV6: | ||
974 | if (inet_sk(sk)->num != IPPROTO_ICMPV6) | ||
975 | return -EOPNOTSUPP; | ||
976 | return rawv6_geticmpfilter(sk, level, optname, optval, | ||
977 | optlen); | ||
978 | case SOL_IPV6: | ||
979 | if (optname == IPV6_CHECKSUM) | ||
980 | break; | ||
981 | default: | ||
982 | return ipv6_getsockopt(sk, level, optname, optval, | ||
983 | optlen); | ||
984 | }; | ||
985 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); | ||
986 | } | ||
987 | |||
988 | #ifdef CONFIG_COMPAT | ||
989 | static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname, | ||
990 | char __user *optval, int __user *optlen) | ||
991 | { | ||
992 | switch (level) { | ||
993 | case SOL_RAW: | ||
994 | break; | ||
995 | case SOL_ICMPV6: | ||
996 | if (inet_sk(sk)->num != IPPROTO_ICMPV6) | ||
997 | return -EOPNOTSUPP; | ||
998 | return rawv6_geticmpfilter(sk, level, optname, optval, optlen); | ||
999 | case SOL_IPV6: | ||
1000 | if (optname == IPV6_CHECKSUM) | ||
1001 | break; | ||
1002 | default: | ||
1003 | return compat_ipv6_getsockopt(sk, level, optname, | ||
1004 | optval, optlen); | ||
1005 | }; | ||
1006 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); | ||
1007 | } | ||
1008 | #endif | ||
1009 | |||
956 | static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) | 1010 | static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) |
957 | { | 1011 | { |
958 | switch(cmd) { | 1012 | switch(cmd) { |
@@ -998,23 +1052,27 @@ static int rawv6_init_sk(struct sock *sk) | |||
998 | } | 1052 | } |
999 | 1053 | ||
1000 | struct proto rawv6_prot = { | 1054 | struct proto rawv6_prot = { |
1001 | .name = "RAWv6", | 1055 | .name = "RAWv6", |
1002 | .owner = THIS_MODULE, | 1056 | .owner = THIS_MODULE, |
1003 | .close = rawv6_close, | 1057 | .close = rawv6_close, |
1004 | .connect = ip6_datagram_connect, | 1058 | .connect = ip6_datagram_connect, |
1005 | .disconnect = udp_disconnect, | 1059 | .disconnect = udp_disconnect, |
1006 | .ioctl = rawv6_ioctl, | 1060 | .ioctl = rawv6_ioctl, |
1007 | .init = rawv6_init_sk, | 1061 | .init = rawv6_init_sk, |
1008 | .destroy = inet6_destroy_sock, | 1062 | .destroy = inet6_destroy_sock, |
1009 | .setsockopt = rawv6_setsockopt, | 1063 | .setsockopt = rawv6_setsockopt, |
1010 | .getsockopt = rawv6_getsockopt, | 1064 | .getsockopt = rawv6_getsockopt, |
1011 | .sendmsg = rawv6_sendmsg, | 1065 | .sendmsg = rawv6_sendmsg, |
1012 | .recvmsg = rawv6_recvmsg, | 1066 | .recvmsg = rawv6_recvmsg, |
1013 | .bind = rawv6_bind, | 1067 | .bind = rawv6_bind, |
1014 | .backlog_rcv = rawv6_rcv_skb, | 1068 | .backlog_rcv = rawv6_rcv_skb, |
1015 | .hash = raw_v6_hash, | 1069 | .hash = raw_v6_hash, |
1016 | .unhash = raw_v6_unhash, | 1070 | .unhash = raw_v6_unhash, |
1017 | .obj_size = sizeof(struct raw6_sock), | 1071 | .obj_size = sizeof(struct raw6_sock), |
1072 | #ifdef CONFIG_COMPAT | ||
1073 | .compat_setsockopt = compat_rawv6_setsockopt, | ||
1074 | .compat_getsockopt = compat_rawv6_getsockopt, | ||
1075 | #endif | ||
1018 | }; | 1076 | }; |
1019 | 1077 | ||
1020 | #ifdef CONFIG_PROC_FS | 1078 | #ifdef CONFIG_PROC_FS |
@@ -1140,7 +1198,7 @@ static int raw6_seq_open(struct inode *inode, struct file *file) | |||
1140 | { | 1198 | { |
1141 | struct seq_file *seq; | 1199 | struct seq_file *seq; |
1142 | int rc = -ENOMEM; | 1200 | int rc = -ENOMEM; |
1143 | struct raw6_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); | 1201 | struct raw6_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL); |
1144 | if (!s) | 1202 | if (!s) |
1145 | goto out; | 1203 | goto out; |
1146 | rc = seq_open(file, &raw6_seq_ops); | 1204 | rc = seq_open(file, &raw6_seq_ops); |
@@ -1148,7 +1206,6 @@ static int raw6_seq_open(struct inode *inode, struct file *file) | |||
1148 | goto out_kfree; | 1206 | goto out_kfree; |
1149 | seq = file->private_data; | 1207 | seq = file->private_data; |
1150 | seq->private = s; | 1208 | seq->private = s; |
1151 | memset(s, 0, sizeof(*s)); | ||
1152 | out: | 1209 | out: |
1153 | return rc; | 1210 | return rc; |
1154 | out_kfree: | 1211 | out_kfree: |