[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>
This commit is contained in:
committed by
David S. Miller
parent
c750360938
commit
3fdadf7d27
@@ -109,19 +109,13 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int optlen)
|
||||
{
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
int val, valbool;
|
||||
int retv = -ENOPROTOOPT;
|
||||
|
||||
if (level == SOL_IP && sk->sk_type != SOCK_RAW)
|
||||
return udp_prot.setsockopt(sk, level, optname, optval, optlen);
|
||||
|
||||
if(level!=SOL_IPV6)
|
||||
goto out;
|
||||
|
||||
if (optval == NULL)
|
||||
val=0;
|
||||
else if (get_user(val, (int __user *) optval))
|
||||
@@ -613,17 +607,9 @@ done:
|
||||
retv = xfrm_user_policy(sk, optname, optval, optlen);
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_NETFILTER
|
||||
default:
|
||||
retv = nf_setsockopt(sk, PF_INET6, optname, optval,
|
||||
optlen);
|
||||
break;
|
||||
#endif
|
||||
|
||||
}
|
||||
release_sock(sk);
|
||||
|
||||
out:
|
||||
return retv;
|
||||
|
||||
e_inval:
|
||||
@@ -631,6 +617,65 @@ e_inval:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int optlen)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (level == SOL_IP && sk->sk_type != SOCK_RAW)
|
||||
return udp_prot.setsockopt(sk, level, optname, optval, optlen);
|
||||
|
||||
if (level != SOL_IPV6)
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
|
||||
#ifdef CONFIG_NETFILTER
|
||||
/* we need to exclude all possible ENOPROTOOPTs except default case */
|
||||
if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
|
||||
optname != IPV6_XFRM_POLICY) {
|
||||
lock_sock(sk);
|
||||
err = nf_setsockopt(sk, PF_INET6, optname, optval,
|
||||
optlen);
|
||||
release_sock(sk);
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int optlen)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
|
||||
if (udp_prot.compat_setsockopt)
|
||||
return udp_prot.compat_setsockopt(sk, level,
|
||||
optname, optval, optlen);
|
||||
else
|
||||
return udp_prot.setsockopt(sk, level,
|
||||
optname, optval, optlen);
|
||||
}
|
||||
|
||||
if (level != SOL_IPV6)
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
|
||||
#ifdef CONFIG_NETFILTER
|
||||
/* we need to exclude all possible ENOPROTOOPTs except default case */
|
||||
if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
|
||||
optname != IPV6_XFRM_POLICY) {
|
||||
lock_sock(sk);
|
||||
err = compat_nf_setsockopt(sk, PF_INET6, optname, optval,
|
||||
optlen);
|
||||
release_sock(sk);
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
|
||||
char __user *optval, int len)
|
||||
{
|
||||
@@ -642,17 +687,13 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
|
||||
return len;
|
||||
}
|
||||
|
||||
int ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
int len;
|
||||
int val;
|
||||
|
||||
if (level == SOL_IP && sk->sk_type != SOCK_RAW)
|
||||
return udp_prot.getsockopt(sk, level, optname, optval, optlen);
|
||||
if(level!=SOL_IPV6)
|
||||
return -ENOPROTOOPT;
|
||||
if (get_user(len, optlen))
|
||||
return -EFAULT;
|
||||
switch (optname) {
|
||||
@@ -842,17 +883,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef CONFIG_NETFILTER
|
||||
lock_sock(sk);
|
||||
val = nf_getsockopt(sk, PF_INET6, optname, optval,
|
||||
&len);
|
||||
release_sock(sk);
|
||||
if (val >= 0)
|
||||
val = put_user(len, optlen);
|
||||
return val;
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
}
|
||||
len = min_t(unsigned int, sizeof(int), len);
|
||||
if(put_user(len, optlen))
|
||||
@@ -862,6 +893,78 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (level == SOL_IP && sk->sk_type != SOCK_RAW)
|
||||
return udp_prot.getsockopt(sk, level, optname, optval, optlen);
|
||||
|
||||
if(level != SOL_IPV6)
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
|
||||
#ifdef CONFIG_NETFILTER
|
||||
/* we need to exclude all possible EINVALs except default case */
|
||||
if (err == -ENOPROTOOPT && optname != IPV6_ADDRFORM &&
|
||||
optname != MCAST_MSFILTER) {
|
||||
int len;
|
||||
|
||||
if (get_user(len, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
lock_sock(sk);
|
||||
err = nf_getsockopt(sk, PF_INET6, optname, optval,
|
||||
&len);
|
||||
release_sock(sk);
|
||||
if (err >= 0)
|
||||
err = put_user(len, optlen);
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
|
||||
if (udp_prot.compat_getsockopt)
|
||||
return udp_prot.compat_getsockopt(sk, level,
|
||||
optname, optval, optlen);
|
||||
else
|
||||
return udp_prot.getsockopt(sk, level,
|
||||
optname, optval, optlen);
|
||||
}
|
||||
|
||||
if(level != SOL_IPV6)
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
|
||||
#ifdef CONFIG_NETFILTER
|
||||
/* we need to exclude all possible EINVALs except default case */
|
||||
if (err == -ENOPROTOOPT && optname != IPV6_ADDRFORM &&
|
||||
optname != MCAST_MSFILTER) {
|
||||
int len;
|
||||
|
||||
if (get_user(len, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
lock_sock(sk);
|
||||
err = compat_nf_getsockopt(sk, PF_INET6, optname, optval,
|
||||
&len);
|
||||
release_sock(sk);
|
||||
if (err >= 0)
|
||||
err = put_user(len, optlen);
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init ipv6_packet_init(void)
|
||||
{
|
||||
dev_add_pack(&ipv6_packet_type);
|
||||
|
Reference in New Issue
Block a user