[NET]: {get|set}sockopt compatibility layer

This patch extends {get|set}sockopt compatibility layer in order to
move protocol specific parts to their place and avoid huge universal
net/compat.c file in the future.

Signed-off-by: Dmitry Mishin <dim@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index ae20a0e..8de5a8e 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -859,29 +859,12 @@
 }
 
 
-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;
 
@@ -906,12 +889,9 @@
 	}
 }
 
-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;
@@ -919,15 +899,47 @@
 		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;
@@ -953,6 +965,52 @@
 	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) {
@@ -1008,6 +1066,10 @@
 	.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,