diff options
author | Dmitry Mishin <dim@openvz.org> | 2006-03-21 09:45:21 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-21 09:45:21 +0300 |
commit | 3fdadf7d27e3fbcf72930941884387d1f4936f04 (patch) | |
tree | 167072cf1e60b6b307610563614b435ff0caa52d /net/netfilter | |
parent | c750360938b403e6cc193d293cfbcb099dd6c60e (diff) | |
download | linux-3fdadf7d27e3fbcf72930941884387d1f4936f04.tar.xz |
[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>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nf_sockopt.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c index 0e5c5e204799..da1cd48de216 100644 --- a/net/netfilter/nf_sockopt.c +++ b/net/netfilter/nf_sockopt.c @@ -131,3 +131,72 @@ int nf_getsockopt(struct sock *sk, int pf, int val, char __user *opt, int *len) } EXPORT_SYMBOL(nf_getsockopt); +#ifdef CONFIG_COMPAT +static int compat_nf_sockopt(struct sock *sk, int pf, int val, + char __user *opt, int *len, int get) +{ + struct list_head *i; + struct nf_sockopt_ops *ops; + int ret; + + if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) + return -EINTR; + + list_for_each(i, &nf_sockopts) { + ops = (struct nf_sockopt_ops *)i; + if (ops->pf == pf) { + if (get) { + if (val >= ops->get_optmin + && val < ops->get_optmax) { + ops->use++; + mutex_unlock(&nf_sockopt_mutex); + if (ops->compat_get) + ret = ops->compat_get(sk, + val, opt, len); + else + ret = ops->get(sk, + val, opt, len); + goto out; + } + } else { + if (val >= ops->set_optmin + && val < ops->set_optmax) { + ops->use++; + mutex_unlock(&nf_sockopt_mutex); + if (ops->compat_set) + ret = ops->compat_set(sk, + val, opt, *len); + else + ret = ops->set(sk, + val, opt, *len); + goto out; + } + } + } + } + mutex_unlock(&nf_sockopt_mutex); + return -ENOPROTOOPT; + + out: + mutex_lock(&nf_sockopt_mutex); + ops->use--; + if (ops->cleanup_task) + wake_up_process(ops->cleanup_task); + mutex_unlock(&nf_sockopt_mutex); + return ret; +} + +int compat_nf_setsockopt(struct sock *sk, int pf, + int val, char __user *opt, int len) +{ + return compat_nf_sockopt(sk, pf, val, opt, &len, 0); +} +EXPORT_SYMBOL(compat_nf_setsockopt); + +int compat_nf_getsockopt(struct sock *sk, int pf, + int val, char __user *opt, int *len) +{ + return compat_nf_sockopt(sk, pf, val, opt, len, 1); +} +EXPORT_SYMBOL(compat_nf_getsockopt); +#endif |