aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c145
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
862static int rawv6_setsockopt(struct sock *sk, int level, int optname, 862static 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
909static int rawv6_getsockopt(struct sock *sk, int level, int optname, 892static 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
915static 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
936static 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
966static 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
989static 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
956static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) 1010static 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
1000struct proto rawv6_prot = { 1054struct 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));
1152out: 1209out:
1153 return rc; 1210 return rc;
1154out_kfree: 1211out_kfree: