diff options
Diffstat (limited to 'net/sched/act_ipt.c')
-rw-r--r-- | net/sched/act_ipt.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index b8c50600697a..378c1c976058 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -31,8 +31,10 @@ | |||
31 | #define IPT_TAB_MASK 15 | 31 | #define IPT_TAB_MASK 15 |
32 | 32 | ||
33 | static int ipt_net_id; | 33 | static int ipt_net_id; |
34 | static struct tc_action_ops act_ipt_ops; | ||
34 | 35 | ||
35 | static int xt_net_id; | 36 | static int xt_net_id; |
37 | static struct tc_action_ops act_xt_ops; | ||
36 | 38 | ||
37 | static int ipt_init_target(struct xt_entry_target *t, char *table, | 39 | static int ipt_init_target(struct xt_entry_target *t, char *table, |
38 | unsigned int hook) | 40 | unsigned int hook) |
@@ -90,8 +92,8 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { | |||
90 | }; | 92 | }; |
91 | 93 | ||
92 | static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | 94 | static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, |
93 | struct nlattr *est, struct tc_action *a, int ovr, | 95 | struct nlattr *est, struct tc_action **a, |
94 | int bind) | 96 | const struct tc_action_ops *ops, int ovr, int bind) |
95 | { | 97 | { |
96 | struct nlattr *tb[TCA_IPT_MAX + 1]; | 98 | struct nlattr *tb[TCA_IPT_MAX + 1]; |
97 | struct tcf_ipt *ipt; | 99 | struct tcf_ipt *ipt; |
@@ -118,19 +120,19 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | |||
118 | 120 | ||
119 | if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) { | 121 | if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) { |
120 | if (exists) | 122 | if (exists) |
121 | tcf_hash_release(a, bind); | 123 | tcf_hash_release(*a, bind); |
122 | return -EINVAL; | 124 | return -EINVAL; |
123 | } | 125 | } |
124 | 126 | ||
125 | td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); | 127 | td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); |
126 | if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) { | 128 | if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) { |
127 | if (exists) | 129 | if (exists) |
128 | tcf_hash_release(a, bind); | 130 | tcf_hash_release(*a, bind); |
129 | return -EINVAL; | 131 | return -EINVAL; |
130 | } | 132 | } |
131 | 133 | ||
132 | if (!exists) { | 134 | if (!exists) { |
133 | ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind, | 135 | ret = tcf_hash_create(tn, index, est, a, ops, bind, |
134 | false); | 136 | false); |
135 | if (ret) | 137 | if (ret) |
136 | return ret; | 138 | return ret; |
@@ -138,13 +140,11 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | |||
138 | } else { | 140 | } else { |
139 | if (bind)/* dont override defaults */ | 141 | if (bind)/* dont override defaults */ |
140 | return 0; | 142 | return 0; |
141 | tcf_hash_release(a, bind); | 143 | tcf_hash_release(*a, bind); |
142 | 144 | ||
143 | if (!ovr) | 145 | if (!ovr) |
144 | return -EEXIST; | 146 | return -EEXIST; |
145 | } | 147 | } |
146 | ipt = to_ipt(a); | ||
147 | |||
148 | hook = nla_get_u32(tb[TCA_IPT_HOOK]); | 148 | hook = nla_get_u32(tb[TCA_IPT_HOOK]); |
149 | 149 | ||
150 | err = -ENOMEM; | 150 | err = -ENOMEM; |
@@ -163,6 +163,8 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | |||
163 | if (err < 0) | 163 | if (err < 0) |
164 | goto err3; | 164 | goto err3; |
165 | 165 | ||
166 | ipt = to_ipt(*a); | ||
167 | |||
166 | spin_lock_bh(&ipt->tcf_lock); | 168 | spin_lock_bh(&ipt->tcf_lock); |
167 | if (ret != ACT_P_CREATED) { | 169 | if (ret != ACT_P_CREATED) { |
168 | ipt_destroy_target(ipt->tcfi_t); | 170 | ipt_destroy_target(ipt->tcfi_t); |
@@ -174,7 +176,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | |||
174 | ipt->tcfi_hook = hook; | 176 | ipt->tcfi_hook = hook; |
175 | spin_unlock_bh(&ipt->tcf_lock); | 177 | spin_unlock_bh(&ipt->tcf_lock); |
176 | if (ret == ACT_P_CREATED) | 178 | if (ret == ACT_P_CREATED) |
177 | tcf_hash_insert(tn, a); | 179 | tcf_hash_insert(tn, *a); |
178 | return ret; | 180 | return ret; |
179 | 181 | ||
180 | err3: | 182 | err3: |
@@ -183,33 +185,33 @@ err2: | |||
183 | kfree(tname); | 185 | kfree(tname); |
184 | err1: | 186 | err1: |
185 | if (ret == ACT_P_CREATED) | 187 | if (ret == ACT_P_CREATED) |
186 | tcf_hash_cleanup(a, est); | 188 | tcf_hash_cleanup(*a, est); |
187 | return err; | 189 | return err; |
188 | } | 190 | } |
189 | 191 | ||
190 | static int tcf_ipt_init(struct net *net, struct nlattr *nla, | 192 | static int tcf_ipt_init(struct net *net, struct nlattr *nla, |
191 | struct nlattr *est, struct tc_action *a, int ovr, | 193 | struct nlattr *est, struct tc_action **a, int ovr, |
192 | int bind) | 194 | int bind) |
193 | { | 195 | { |
194 | struct tc_action_net *tn = net_generic(net, ipt_net_id); | 196 | struct tc_action_net *tn = net_generic(net, ipt_net_id); |
195 | 197 | ||
196 | return __tcf_ipt_init(tn, nla, est, a, ovr, bind); | 198 | return __tcf_ipt_init(tn, nla, est, a, &act_ipt_ops, ovr, bind); |
197 | } | 199 | } |
198 | 200 | ||
199 | static int tcf_xt_init(struct net *net, struct nlattr *nla, | 201 | static int tcf_xt_init(struct net *net, struct nlattr *nla, |
200 | struct nlattr *est, struct tc_action *a, int ovr, | 202 | struct nlattr *est, struct tc_action **a, int ovr, |
201 | int bind) | 203 | int bind) |
202 | { | 204 | { |
203 | struct tc_action_net *tn = net_generic(net, xt_net_id); | 205 | struct tc_action_net *tn = net_generic(net, xt_net_id); |
204 | 206 | ||
205 | return __tcf_ipt_init(tn, nla, est, a, ovr, bind); | 207 | return __tcf_ipt_init(tn, nla, est, a, &act_xt_ops, ovr, bind); |
206 | } | 208 | } |
207 | 209 | ||
208 | static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, | 210 | static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, |
209 | struct tcf_result *res) | 211 | struct tcf_result *res) |
210 | { | 212 | { |
211 | int ret = 0, result = 0; | 213 | int ret = 0, result = 0; |
212 | struct tcf_ipt *ipt = a->priv; | 214 | struct tcf_ipt *ipt = to_ipt(a); |
213 | struct xt_action_param par; | 215 | struct xt_action_param par; |
214 | 216 | ||
215 | if (skb_unclone(skb, GFP_ATOMIC)) | 217 | if (skb_unclone(skb, GFP_ATOMIC)) |
@@ -259,7 +261,7 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, | |||
259 | int ref) | 261 | int ref) |
260 | { | 262 | { |
261 | unsigned char *b = skb_tail_pointer(skb); | 263 | unsigned char *b = skb_tail_pointer(skb); |
262 | struct tcf_ipt *ipt = a->priv; | 264 | struct tcf_ipt *ipt = to_ipt(a); |
263 | struct xt_entry_target *t; | 265 | struct xt_entry_target *t; |
264 | struct tcf_t tm; | 266 | struct tcf_t tm; |
265 | struct tc_cnt c; | 267 | struct tc_cnt c; |
@@ -299,14 +301,14 @@ nla_put_failure: | |||
299 | 301 | ||
300 | static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, | 302 | static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, |
301 | struct netlink_callback *cb, int type, | 303 | struct netlink_callback *cb, int type, |
302 | struct tc_action *a) | 304 | const struct tc_action_ops *ops) |
303 | { | 305 | { |
304 | struct tc_action_net *tn = net_generic(net, ipt_net_id); | 306 | struct tc_action_net *tn = net_generic(net, ipt_net_id); |
305 | 307 | ||
306 | return tcf_generic_walker(tn, skb, cb, type, a); | 308 | return tcf_generic_walker(tn, skb, cb, type, ops); |
307 | } | 309 | } |
308 | 310 | ||
309 | static int tcf_ipt_search(struct net *net, struct tc_action *a, u32 index) | 311 | static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index) |
310 | { | 312 | { |
311 | struct tc_action_net *tn = net_generic(net, ipt_net_id); | 313 | struct tc_action_net *tn = net_generic(net, ipt_net_id); |
312 | 314 | ||
@@ -323,6 +325,7 @@ static struct tc_action_ops act_ipt_ops = { | |||
323 | .init = tcf_ipt_init, | 325 | .init = tcf_ipt_init, |
324 | .walk = tcf_ipt_walker, | 326 | .walk = tcf_ipt_walker, |
325 | .lookup = tcf_ipt_search, | 327 | .lookup = tcf_ipt_search, |
328 | .size = sizeof(struct tcf_ipt), | ||
326 | }; | 329 | }; |
327 | 330 | ||
328 | static __net_init int ipt_init_net(struct net *net) | 331 | static __net_init int ipt_init_net(struct net *net) |
@@ -348,14 +351,14 @@ static struct pernet_operations ipt_net_ops = { | |||
348 | 351 | ||
349 | static int tcf_xt_walker(struct net *net, struct sk_buff *skb, | 352 | static int tcf_xt_walker(struct net *net, struct sk_buff *skb, |
350 | struct netlink_callback *cb, int type, | 353 | struct netlink_callback *cb, int type, |
351 | struct tc_action *a) | 354 | const struct tc_action_ops *ops) |
352 | { | 355 | { |
353 | struct tc_action_net *tn = net_generic(net, xt_net_id); | 356 | struct tc_action_net *tn = net_generic(net, xt_net_id); |
354 | 357 | ||
355 | return tcf_generic_walker(tn, skb, cb, type, a); | 358 | return tcf_generic_walker(tn, skb, cb, type, ops); |
356 | } | 359 | } |
357 | 360 | ||
358 | static int tcf_xt_search(struct net *net, struct tc_action *a, u32 index) | 361 | static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index) |
359 | { | 362 | { |
360 | struct tc_action_net *tn = net_generic(net, xt_net_id); | 363 | struct tc_action_net *tn = net_generic(net, xt_net_id); |
361 | 364 | ||
@@ -372,6 +375,7 @@ static struct tc_action_ops act_xt_ops = { | |||
372 | .init = tcf_xt_init, | 375 | .init = tcf_xt_init, |
373 | .walk = tcf_xt_walker, | 376 | .walk = tcf_xt_walker, |
374 | .lookup = tcf_xt_search, | 377 | .lookup = tcf_xt_search, |
378 | .size = sizeof(struct tcf_ipt), | ||
375 | }; | 379 | }; |
376 | 380 | ||
377 | static __net_init int xt_init_net(struct net *net) | 381 | static __net_init int xt_init_net(struct net *net) |