aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-04-03 16:23:58 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-04 12:17:40 -0400
commitcfdfab314647b1755afedc33ab66f3f247e161ae (patch)
treee844207925d20a832f575793ca9d6e1d4ff546f8 /net/netfilter
parentb81b7be6ae830a507d15cf4fc626be02cc9ab79b (diff)
netfilter: Create and use nf_hook_state.
Instead of passing a large number of arguments down into the nf_hook() entry points, create a structure which carries this state down through the hook processing layers. This makes is so that if we want to change the types or signatures of any of these pieces of state, there are less places that need to be changed. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/core.c32
-rw-r--r--net/netfilter/nf_internals.h11
-rw-r--r--net/netfilter/nf_queue.c38
3 files changed, 36 insertions, 45 deletions
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index fea9ef566427..11d04ebfc5e3 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -120,12 +120,8 @@ EXPORT_SYMBOL(nf_unregister_hooks);
120 120
121unsigned int nf_iterate(struct list_head *head, 121unsigned int nf_iterate(struct list_head *head,
122 struct sk_buff *skb, 122 struct sk_buff *skb,
123 unsigned int hook, 123 struct nf_hook_state *state,
124 const struct net_device *indev, 124 struct nf_hook_ops **elemp)
125 const struct net_device *outdev,
126 struct nf_hook_ops **elemp,
127 int (*okfn)(struct sk_buff *),
128 int hook_thresh)
129{ 125{
130 unsigned int verdict; 126 unsigned int verdict;
131 127
@@ -134,19 +130,20 @@ unsigned int nf_iterate(struct list_head *head,
134 * function because of risk of continuing from deleted element. 130 * function because of risk of continuing from deleted element.
135 */ 131 */
136 list_for_each_entry_continue_rcu((*elemp), head, list) { 132 list_for_each_entry_continue_rcu((*elemp), head, list) {
137 if (hook_thresh > (*elemp)->priority) 133 if (state->thresh > (*elemp)->priority)
138 continue; 134 continue;
139 135
140 /* Optimization: we don't need to hold module 136 /* Optimization: we don't need to hold module
141 reference here, since function can't sleep. --RR */ 137 reference here, since function can't sleep. --RR */
142repeat: 138repeat:
143 verdict = (*elemp)->hook(*elemp, skb, indev, outdev, okfn); 139 verdict = (*elemp)->hook(*elemp, skb, state->in, state->out,
140 state->okfn);
144 if (verdict != NF_ACCEPT) { 141 if (verdict != NF_ACCEPT) {
145#ifdef CONFIG_NETFILTER_DEBUG 142#ifdef CONFIG_NETFILTER_DEBUG
146 if (unlikely((verdict & NF_VERDICT_MASK) 143 if (unlikely((verdict & NF_VERDICT_MASK)
147 > NF_MAX_VERDICT)) { 144 > NF_MAX_VERDICT)) {
148 NFDEBUG("Evil return from %p(%u).\n", 145 NFDEBUG("Evil return from %p(%u).\n",
149 (*elemp)->hook, hook); 146 (*elemp)->hook, state->hook);
150 continue; 147 continue;
151 } 148 }
152#endif 149#endif
@@ -161,11 +158,7 @@ repeat:
161 158
162/* Returns 1 if okfn() needs to be executed by the caller, 159/* Returns 1 if okfn() needs to be executed by the caller,
163 * -EPERM for NF_DROP, 0 otherwise. */ 160 * -EPERM for NF_DROP, 0 otherwise. */
164int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb, 161int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
165 struct net_device *indev,
166 struct net_device *outdev,
167 int (*okfn)(struct sk_buff *),
168 int hook_thresh)
169{ 162{
170 struct nf_hook_ops *elem; 163 struct nf_hook_ops *elem;
171 unsigned int verdict; 164 unsigned int verdict;
@@ -174,10 +167,11 @@ int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
174 /* We may already have this, but read-locks nest anyway */ 167 /* We may already have this, but read-locks nest anyway */
175 rcu_read_lock(); 168 rcu_read_lock();
176 169
177 elem = list_entry_rcu(&nf_hooks[pf][hook], struct nf_hook_ops, list); 170 elem = list_entry_rcu(&nf_hooks[state->pf][state->hook],
171 struct nf_hook_ops, list);
178next_hook: 172next_hook:
179 verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev, 173 verdict = nf_iterate(&nf_hooks[state->pf][state->hook], skb, state,
180 outdev, &elem, okfn, hook_thresh); 174 &elem);
181 if (verdict == NF_ACCEPT || verdict == NF_STOP) { 175 if (verdict == NF_ACCEPT || verdict == NF_STOP) {
182 ret = 1; 176 ret = 1;
183 } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) { 177 } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
@@ -186,8 +180,8 @@ next_hook:
186 if (ret == 0) 180 if (ret == 0)
187 ret = -EPERM; 181 ret = -EPERM;
188 } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { 182 } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
189 int err = nf_queue(skb, elem, pf, hook, indev, outdev, okfn, 183 int err = nf_queue(skb, elem, state,
190 verdict >> NF_VERDICT_QBITS); 184 verdict >> NF_VERDICT_QBITS);
191 if (err < 0) { 185 if (err < 0) {
192 if (err == -ECANCELED) 186 if (err == -ECANCELED)
193 goto next_hook; 187 goto next_hook;
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
index 61a3c927e63c..ea7f36784b3d 100644
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -14,16 +14,11 @@
14 14
15/* core.c */ 15/* core.c */
16unsigned int nf_iterate(struct list_head *head, struct sk_buff *skb, 16unsigned int nf_iterate(struct list_head *head, struct sk_buff *skb,
17 unsigned int hook, const struct net_device *indev, 17 struct nf_hook_state *state, struct nf_hook_ops **elemp);
18 const struct net_device *outdev,
19 struct nf_hook_ops **elemp,
20 int (*okfn)(struct sk_buff *), int hook_thresh);
21 18
22/* nf_queue.c */ 19/* nf_queue.c */
23int nf_queue(struct sk_buff *skb, struct nf_hook_ops *elem, u_int8_t pf, 20int nf_queue(struct sk_buff *skb, struct nf_hook_ops *elem,
24 unsigned int hook, struct net_device *indev, 21 struct nf_hook_state *state, unsigned int queuenum);
25 struct net_device *outdev, int (*okfn)(struct sk_buff *),
26 unsigned int queuenum);
27int __init netfilter_queue_init(void); 22int __init netfilter_queue_init(void);
28 23
29/* nf_log.c */ 24/* nf_log.c */
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 4c8b68e5fa16..6f8e9485cc83 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -100,12 +100,9 @@ EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs);
100 * through nf_reinject(). 100 * through nf_reinject().
101 */ 101 */
102int nf_queue(struct sk_buff *skb, 102int nf_queue(struct sk_buff *skb,
103 struct nf_hook_ops *elem, 103 struct nf_hook_ops *elem,
104 u_int8_t pf, unsigned int hook, 104 struct nf_hook_state *state,
105 struct net_device *indev, 105 unsigned int queuenum)
106 struct net_device *outdev,
107 int (*okfn)(struct sk_buff *),
108 unsigned int queuenum)
109{ 106{
110 int status = -ENOENT; 107 int status = -ENOENT;
111 struct nf_queue_entry *entry = NULL; 108 struct nf_queue_entry *entry = NULL;
@@ -121,7 +118,7 @@ int nf_queue(struct sk_buff *skb,
121 goto err_unlock; 118 goto err_unlock;
122 } 119 }
123 120
124 afinfo = nf_get_afinfo(pf); 121 afinfo = nf_get_afinfo(state->pf);
125 if (!afinfo) 122 if (!afinfo)
126 goto err_unlock; 123 goto err_unlock;
127 124
@@ -134,11 +131,11 @@ int nf_queue(struct sk_buff *skb,
134 *entry = (struct nf_queue_entry) { 131 *entry = (struct nf_queue_entry) {
135 .skb = skb, 132 .skb = skb,
136 .elem = elem, 133 .elem = elem,
137 .pf = pf, 134 .pf = state->pf,
138 .hook = hook, 135 .hook = state->hook,
139 .indev = indev, 136 .indev = state->in,
140 .outdev = outdev, 137 .outdev = state->out,
141 .okfn = okfn, 138 .okfn = state->okfn,
142 .size = sizeof(*entry) + afinfo->route_key_size, 139 .size = sizeof(*entry) + afinfo->route_key_size,
143 }; 140 };
144 141
@@ -171,6 +168,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
171 struct sk_buff *skb = entry->skb; 168 struct sk_buff *skb = entry->skb;
172 struct nf_hook_ops *elem = entry->elem; 169 struct nf_hook_ops *elem = entry->elem;
173 const struct nf_afinfo *afinfo; 170 const struct nf_afinfo *afinfo;
171 struct nf_hook_state state;
174 int err; 172 int err;
175 173
176 rcu_read_lock(); 174 rcu_read_lock();
@@ -189,12 +187,17 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
189 verdict = NF_DROP; 187 verdict = NF_DROP;
190 } 188 }
191 189
190 state.hook = entry->hook;
191 state.thresh = INT_MIN;
192 state.pf = entry->pf;
193 state.in = entry->indev;
194 state.out = entry->outdev;
195 state.okfn = entry->okfn;
196
192 if (verdict == NF_ACCEPT) { 197 if (verdict == NF_ACCEPT) {
193 next_hook: 198 next_hook:
194 verdict = nf_iterate(&nf_hooks[entry->pf][entry->hook], 199 verdict = nf_iterate(&nf_hooks[entry->pf][entry->hook],
195 skb, entry->hook, 200 skb, &state, &elem);
196 entry->indev, entry->outdev, &elem,
197 entry->okfn, INT_MIN);
198 } 201 }
199 202
200 switch (verdict & NF_VERDICT_MASK) { 203 switch (verdict & NF_VERDICT_MASK) {
@@ -205,9 +208,8 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
205 local_bh_enable(); 208 local_bh_enable();
206 break; 209 break;
207 case NF_QUEUE: 210 case NF_QUEUE:
208 err = nf_queue(skb, elem, entry->pf, entry->hook, 211 err = nf_queue(skb, elem, &state,
209 entry->indev, entry->outdev, entry->okfn, 212 verdict >> NF_VERDICT_QBITS);
210 verdict >> NF_VERDICT_QBITS);
211 if (err < 0) { 213 if (err < 0) {
212 if (err == -ECANCELED) 214 if (err == -ECANCELED)
213 goto next_hook; 215 goto next_hook;