#include <linux/skbuff.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
-#include <asm/bug.h>
#include <net/ip.h>
#include <net/sock.h>
err = rawv6_push_pending_frames(sk, &fl, rp);
}
done:
- ip6_dst_store(sk, dst,
- ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ?
- &np->daddr : NULL);
-
+ dst_release(dst);
release_sock(sk);
out:
fl6_sock_release(flowlabel);
}
-static int rawv6_setsockopt(struct sock *sk, int level, int optname,
+static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen)
{
struct raw6_sock *rp = raw6_sk(sk);
int val;
- switch(level) {
- case SOL_RAW:
- break;
-
- case SOL_ICMPV6:
- if (inet_sk(sk)->num != IPPROTO_ICMPV6)
- return -EOPNOTSUPP;
- return rawv6_seticmpfilter(sk, level, optname, optval,
- optlen);
- case SOL_IPV6:
- if (optname == IPV6_CHECKSUM)
- break;
- default:
- return ipv6_setsockopt(sk, level, optname, optval,
- optlen);
- };
-
if (get_user(val, (int __user *)optval))
return -EFAULT;
}
}
-static int rawv6_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
+static int rawv6_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
{
- struct raw6_sock *rp = raw6_sk(sk);
- int val, len;
-
switch(level) {
case SOL_RAW:
break;
case SOL_ICMPV6:
if (inet_sk(sk)->num != IPPROTO_ICMPV6)
return -EOPNOTSUPP;
- return rawv6_geticmpfilter(sk, level, optname, optval,
+ return rawv6_seticmpfilter(sk, level, optname, optval,
optlen);
case SOL_IPV6:
if (optname == IPV6_CHECKSUM)
break;
default:
- return ipv6_getsockopt(sk, level, optname, optval,
+ return ipv6_setsockopt(sk, level, optname, optval,
optlen);
};
+ return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
+}
+
+#ifdef CONFIG_COMPAT
+static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
+{
+ switch(level) {
+ case SOL_RAW:
+ break;
+
+ case SOL_ICMPV6:
+ if (inet_sk(sk)->num != IPPROTO_ICMPV6)
+ return -EOPNOTSUPP;
+ return rawv6_seticmpfilter(sk, level, optname, optval,
+ optlen);
+ case SOL_IPV6:
+ if (optname == IPV6_CHECKSUM)
+ break;
+ default:
+ return compat_ipv6_setsockopt(sk, level,
+ optname, optval, optlen);
+ };
+ return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
+}
+#endif
+
+static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ struct raw6_sock *rp = raw6_sk(sk);
+ int val, len;
if (get_user(len,optlen))
return -EFAULT;
return 0;
}
+static int rawv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ switch(level) {
+ case SOL_RAW:
+ break;
+
+ case SOL_ICMPV6:
+ if (inet_sk(sk)->num != IPPROTO_ICMPV6)
+ return -EOPNOTSUPP;
+ return rawv6_geticmpfilter(sk, level, optname, optval,
+ optlen);
+ case SOL_IPV6:
+ if (optname == IPV6_CHECKSUM)
+ break;
+ default:
+ return ipv6_getsockopt(sk, level, optname, optval,
+ optlen);
+ };
+ return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
+}
+
+#ifdef CONFIG_COMPAT
+static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ switch(level) {
+ case SOL_RAW:
+ break;
+
+ case SOL_ICMPV6:
+ if (inet_sk(sk)->num != IPPROTO_ICMPV6)
+ return -EOPNOTSUPP;
+ return rawv6_geticmpfilter(sk, level, optname, optval,
+ optlen);
+ case SOL_IPV6:
+ if (optname == IPV6_CHECKSUM)
+ break;
+ default:
+ return compat_ipv6_getsockopt(sk, level,
+ optname, optval, optlen);
+ };
+ return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
+}
+#endif
+
static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
switch(cmd) {
.destroy = inet6_destroy_sock,
.setsockopt = rawv6_setsockopt,
.getsockopt = rawv6_getsockopt,
+#ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_rawv6_setsockopt,
+ .compat_getsockopt = compat_rawv6_getsockopt,
+#endif
.sendmsg = rawv6_sendmsg,
.recvmsg = rawv6_recvmsg,
.bind = rawv6_bind,