aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_sockopt.c106
1 files changed, 44 insertions, 62 deletions
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index 2dfac3253569..87bc1443c520 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -60,46 +60,57 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
60} 60}
61EXPORT_SYMBOL(nf_unregister_sockopt); 61EXPORT_SYMBOL(nf_unregister_sockopt);
62 62
63/* Call get/setsockopt() */ 63static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, int pf,
64static int nf_sockopt(struct sock *sk, int pf, int val, 64 int val, int get)
65 char __user *opt, int *len, int get)
66{ 65{
67 struct nf_sockopt_ops *ops; 66 struct nf_sockopt_ops *ops;
68 int ret;
69 67
70 if (sk->sk_net != &init_net) 68 if (sk->sk_net != &init_net)
71 return -ENOPROTOOPT; 69 return ERR_PTR(-ENOPROTOOPT);
72 70
73 if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) 71 if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
74 return -EINTR; 72 return ERR_PTR(-EINTR);
75 73
76 list_for_each_entry(ops, &nf_sockopts, list) { 74 list_for_each_entry(ops, &nf_sockopts, list) {
77 if (ops->pf == pf) { 75 if (ops->pf == pf) {
78 if (!try_module_get(ops->owner)) 76 if (!try_module_get(ops->owner))
79 goto out_nosup; 77 goto out_nosup;
78
80 if (get) { 79 if (get) {
81 if (val >= ops->get_optmin 80 if (val >= ops->get_optmin &&
82 && val < ops->get_optmax) { 81 val < ops->get_optmax)
83 mutex_unlock(&nf_sockopt_mutex);
84 ret = ops->get(sk, val, opt, len);
85 goto out; 82 goto out;
86 }
87 } else { 83 } else {
88 if (val >= ops->set_optmin 84 if (val >= ops->set_optmin &&
89 && val < ops->set_optmax) { 85 val < ops->set_optmax)
90 mutex_unlock(&nf_sockopt_mutex);
91 ret = ops->set(sk, val, opt, *len);
92 goto out; 86 goto out;
93 }
94 } 87 }
95 module_put(ops->owner); 88 module_put(ops->owner);
96 } 89 }
97 } 90 }
98 out_nosup: 91out_nosup:
92 ops = ERR_PTR(-ENOPROTOOPT);
93out:
99 mutex_unlock(&nf_sockopt_mutex); 94 mutex_unlock(&nf_sockopt_mutex);
100 return -ENOPROTOOPT; 95 return ops;
96}
97
98/* Call get/setsockopt() */
99static int nf_sockopt(struct sock *sk, int pf, int val,
100 char __user *opt, int *len, int get)
101{
102 struct nf_sockopt_ops *ops;
103 int ret;
104
105 ops = nf_sockopt_find(sk, pf, val, get);
106 if (IS_ERR(ops))
107 return PTR_ERR(ops);
108
109 if (get)
110 ret = ops->get(sk, val, opt, len);
111 else
112 ret = ops->set(sk, val, opt, *len);
101 113
102 out:
103 module_put(ops->owner); 114 module_put(ops->owner);
104 return ret; 115 return ret;
105} 116}
@@ -124,51 +135,22 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val,
124 struct nf_sockopt_ops *ops; 135 struct nf_sockopt_ops *ops;
125 int ret; 136 int ret;
126 137
127 if (sk->sk_net != &init_net) 138 ops = nf_sockopt_find(sk, pf, val, get);
128 return -ENOPROTOOPT; 139 if (IS_ERR(ops))
129 140 return PTR_ERR(ops);
130 141
131 if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) 142 if (get) {
132 return -EINTR; 143 if (ops->compat_get)
133 144 ret = ops->compat_get(sk, val, opt, len);
134 list_for_each_entry(ops, &nf_sockopts, list) { 145 else
135 if (ops->pf == pf) { 146 ret = ops->get(sk, val, ops, len);
136 if (!try_module_get(ops->owner)) 147 } else {
137 goto out_nosup; 148 if (ops->compat_set)
138 149 ret = ops->compat_set(sk, val, ops, *len);
139 if (get) { 150 else
140 if (val >= ops->get_optmin 151 ret = ops->set(sk, val, ops, *len);
141 && val < ops->get_optmax) {
142 mutex_unlock(&nf_sockopt_mutex);
143 if (ops->compat_get)
144 ret = ops->compat_get(sk,
145 val, opt, len);
146 else
147 ret = ops->get(sk,
148 val, opt, len);
149 goto out;
150 }
151 } else {
152 if (val >= ops->set_optmin
153 && val < ops->set_optmax) {
154 mutex_unlock(&nf_sockopt_mutex);
155 if (ops->compat_set)
156 ret = ops->compat_set(sk,
157 val, opt, *len);
158 else
159 ret = ops->set(sk,
160 val, opt, *len);
161 goto out;
162 }
163 }
164 module_put(ops->owner);
165 }
166 } 152 }
167 out_nosup:
168 mutex_unlock(&nf_sockopt_mutex);
169 return -ENOPROTOOPT;
170 153
171 out:
172 module_put(ops->owner); 154 module_put(ops->owner);
173 return ret; 155 return ret;
174} 156}