OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From: Harsha Sharma <harshasharmaiitr@gmail.com> |
2 | Date: Wed, 27 Dec 2017 00:59:00 +0530 |
||
3 | Subject: [PATCH] netfilter: nf_tables: allocate handle and delete objects via |
||
4 | handle |
||
5 | |||
6 | This patch allows deletion of objects via unique handle which can be |
||
7 | listed via '-a' option. |
||
8 | |||
9 | Signed-off-by: Harsha Sharma <harshasharmaiitr@gmail.com> |
||
10 | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> |
||
11 | --- |
||
12 | |||
13 | --- a/include/net/netfilter/nf_tables.h |
||
14 | +++ b/include/net/netfilter/nf_tables.h |
||
15 | @@ -370,6 +370,7 @@ void nft_unregister_set(struct nft_set_t |
||
16 | * @list: table set list node |
||
17 | * @bindings: list of set bindings |
||
18 | * @name: name of the set |
||
19 | + * @handle: unique handle of the set |
||
20 | * @ktype: key type (numeric type defined by userspace, not used in the kernel) |
||
21 | * @dtype: data type (verdict or numeric type defined by userspace) |
||
22 | * @objtype: object type (see NFT_OBJECT_* definitions) |
||
23 | @@ -392,6 +393,7 @@ struct nft_set { |
||
24 | struct list_head list; |
||
25 | struct list_head bindings; |
||
26 | char *name; |
||
27 | + u64 handle; |
||
28 | u32 ktype; |
||
29 | u32 dtype; |
||
30 | u32 objtype; |
||
31 | @@ -941,6 +943,7 @@ unsigned int nft_do_chain(struct nft_pkt |
||
32 | * @objects: stateful objects in the table |
||
33 | * @flowtables: flow tables in the table |
||
34 | * @hgenerator: handle generator state |
||
35 | + * @handle: table handle |
||
36 | * @use: number of chain references to this table |
||
37 | * @flags: table flag (see enum nft_table_flags) |
||
38 | * @genmask: generation mask |
||
39 | @@ -954,6 +957,7 @@ struct nft_table { |
||
40 | struct list_head objects; |
||
41 | struct list_head flowtables; |
||
42 | u64 hgenerator; |
||
43 | + u64 handle; |
||
44 | u32 use; |
||
45 | u16 family:6, |
||
46 | flags:8, |
||
47 | @@ -978,9 +982,9 @@ int nft_verdict_dump(struct sk_buff *skb |
||
48 | * @name: name of this stateful object |
||
49 | * @genmask: generation mask |
||
50 | * @use: number of references to this stateful object |
||
51 | - * @data: object data, layout depends on type |
||
52 | + * @handle: unique object handle |
||
53 | * @ops: object operations |
||
54 | - * @data: pointer to object data |
||
55 | + * @data: object data, layout depends on type |
||
56 | */ |
||
57 | struct nft_object { |
||
58 | struct list_head list; |
||
59 | @@ -988,6 +992,7 @@ struct nft_object { |
||
60 | struct nft_table *table; |
||
61 | u32 genmask:2, |
||
62 | use:30; |
||
63 | + u64 handle; |
||
64 | /* runtime data below here */ |
||
65 | const struct nft_object_ops *ops ____cacheline_aligned; |
||
66 | unsigned char data[] |
||
67 | @@ -1069,6 +1074,7 @@ void nft_unregister_obj(struct nft_objec |
||
68 | * @ops_len: number of hooks in array |
||
69 | * @genmask: generation mask |
||
70 | * @use: number of references to this flow table |
||
71 | + * @handle: unique object handle |
||
72 | * @data: rhashtable and garbage collector |
||
73 | * @ops: array of hooks |
||
74 | */ |
||
75 | @@ -1081,6 +1087,7 @@ struct nft_flowtable { |
||
76 | int ops_len; |
||
77 | u32 genmask:2, |
||
78 | use:30; |
||
79 | + u64 handle; |
||
80 | /* runtime data below here */ |
||
81 | struct nf_hook_ops *ops ____cacheline_aligned; |
||
82 | struct nf_flowtable data; |
||
83 | --- a/include/uapi/linux/netfilter/nf_tables.h |
||
84 | +++ b/include/uapi/linux/netfilter/nf_tables.h |
||
85 | @@ -174,6 +174,8 @@ enum nft_table_attributes { |
||
86 | NFTA_TABLE_NAME, |
||
87 | NFTA_TABLE_FLAGS, |
||
88 | NFTA_TABLE_USE, |
||
89 | + NFTA_TABLE_HANDLE, |
||
90 | + NFTA_TABLE_PAD, |
||
91 | __NFTA_TABLE_MAX |
||
92 | }; |
||
93 | #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1) |
||
94 | @@ -317,6 +319,7 @@ enum nft_set_desc_attributes { |
||
95 | * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32) |
||
96 | * @NFTA_SET_USERDATA: user data (NLA_BINARY) |
||
97 | * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*) |
||
98 | + * @NFTA_SET_HANDLE: set handle (NLA_U64) |
||
99 | */ |
||
100 | enum nft_set_attributes { |
||
101 | NFTA_SET_UNSPEC, |
||
102 | @@ -335,6 +338,7 @@ enum nft_set_attributes { |
||
103 | NFTA_SET_USERDATA, |
||
104 | NFTA_SET_PAD, |
||
105 | NFTA_SET_OBJ_TYPE, |
||
106 | + NFTA_SET_HANDLE, |
||
107 | __NFTA_SET_MAX |
||
108 | }; |
||
109 | #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) |
||
110 | @@ -1314,6 +1318,7 @@ enum nft_ct_helper_attributes { |
||
111 | * @NFTA_OBJ_TYPE: stateful object type (NLA_U32) |
||
112 | * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED) |
||
113 | * @NFTA_OBJ_USE: number of references to this expression (NLA_U32) |
||
114 | + * @NFTA_OBJ_HANDLE: object handle (NLA_U64) |
||
115 | */ |
||
116 | enum nft_object_attributes { |
||
117 | NFTA_OBJ_UNSPEC, |
||
118 | @@ -1322,6 +1327,8 @@ enum nft_object_attributes { |
||
119 | NFTA_OBJ_TYPE, |
||
120 | NFTA_OBJ_DATA, |
||
121 | NFTA_OBJ_USE, |
||
122 | + NFTA_OBJ_HANDLE, |
||
123 | + NFTA_OBJ_PAD, |
||
124 | __NFTA_OBJ_MAX |
||
125 | }; |
||
126 | #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) |
||
127 | @@ -1333,6 +1340,7 @@ enum nft_object_attributes { |
||
128 | * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING) |
||
129 | * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) |
||
130 | * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) |
||
131 | + * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) |
||
132 | */ |
||
133 | enum nft_flowtable_attributes { |
||
134 | NFTA_FLOWTABLE_UNSPEC, |
||
135 | @@ -1340,6 +1348,8 @@ enum nft_flowtable_attributes { |
||
136 | NFTA_FLOWTABLE_NAME, |
||
137 | NFTA_FLOWTABLE_HOOK, |
||
138 | NFTA_FLOWTABLE_USE, |
||
139 | + NFTA_FLOWTABLE_HANDLE, |
||
140 | + NFTA_FLOWTABLE_PAD, |
||
141 | __NFTA_FLOWTABLE_MAX |
||
142 | }; |
||
143 | #define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) |
||
144 | --- a/net/netfilter/nf_tables_api.c |
||
145 | +++ b/net/netfilter/nf_tables_api.c |
||
146 | @@ -26,6 +26,7 @@ |
||
147 | static LIST_HEAD(nf_tables_expressions); |
||
148 | static LIST_HEAD(nf_tables_objects); |
||
149 | static LIST_HEAD(nf_tables_flowtables); |
||
150 | +static u64 table_handle; |
||
151 | |||
152 | static void nft_ctx_init(struct nft_ctx *ctx, |
||
153 | struct net *net, |
||
154 | @@ -361,6 +362,20 @@ static struct nft_table *nft_table_looku |
||
155 | return NULL; |
||
156 | } |
||
157 | |||
158 | +static struct nft_table *nft_table_lookup_byhandle(const struct net *net, |
||
159 | + const struct nlattr *nla, |
||
160 | + u8 genmask) |
||
161 | +{ |
||
162 | + struct nft_table *table; |
||
163 | + |
||
164 | + list_for_each_entry(table, &net->nft.tables, list) { |
||
165 | + if (be64_to_cpu(nla_get_be64(nla)) == table->handle && |
||
166 | + nft_active_genmask(table, genmask)) |
||
167 | + return table; |
||
168 | + } |
||
169 | + return NULL; |
||
170 | +} |
||
171 | + |
||
172 | static struct nft_table *nf_tables_table_lookup(const struct net *net, |
||
173 | const struct nlattr *nla, |
||
174 | u8 family, u8 genmask) |
||
175 | @@ -377,6 +392,22 @@ static struct nft_table *nf_tables_table |
||
176 | return ERR_PTR(-ENOENT); |
||
177 | } |
||
178 | |||
179 | +static struct nft_table *nf_tables_table_lookup_byhandle(const struct net *net, |
||
180 | + const struct nlattr *nla, |
||
181 | + u8 genmask) |
||
182 | +{ |
||
183 | + struct nft_table *table; |
||
184 | + |
||
185 | + if (nla == NULL) |
||
186 | + return ERR_PTR(-EINVAL); |
||
187 | + |
||
188 | + table = nft_table_lookup_byhandle(net, nla, genmask); |
||
189 | + if (table != NULL) |
||
190 | + return table; |
||
191 | + |
||
192 | + return ERR_PTR(-ENOENT); |
||
193 | +} |
||
194 | + |
||
195 | static inline u64 nf_tables_alloc_handle(struct nft_table *table) |
||
196 | { |
||
197 | return ++table->hgenerator; |
||
198 | @@ -423,6 +454,7 @@ static const struct nla_policy nft_table |
||
199 | [NFTA_TABLE_NAME] = { .type = NLA_STRING, |
||
200 | .len = NFT_TABLE_MAXNAMELEN - 1 }, |
||
201 | [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, |
||
202 | + [NFTA_TABLE_HANDLE] = { .type = NLA_U64 }, |
||
203 | }; |
||
204 | |||
205 | static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, |
||
206 | @@ -444,7 +476,9 @@ static int nf_tables_fill_table_info(str |
||
207 | |||
208 | if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || |
||
209 | nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) || |
||
210 | - nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use))) |
||
211 | + nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) || |
||
212 | + nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle), |
||
213 | + NFTA_TABLE_PAD)) |
||
214 | goto nla_put_failure; |
||
215 | |||
216 | nlmsg_end(skb, nlh); |
||
217 | @@ -703,6 +737,7 @@ static int nf_tables_newtable(struct net |
||
218 | INIT_LIST_HEAD(&table->flowtables); |
||
219 | table->family = family; |
||
220 | table->flags = flags; |
||
221 | + table->handle = ++table_handle; |
||
222 | |||
223 | nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); |
||
224 | err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); |
||
225 | @@ -820,11 +855,18 @@ static int nf_tables_deltable(struct net |
||
226 | struct nft_ctx ctx; |
||
227 | |||
228 | nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla); |
||
229 | - if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) |
||
230 | + if (family == AF_UNSPEC || |
||
231 | + (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE])) |
||
232 | return nft_flush(&ctx, family); |
||
233 | |||
234 | - table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, |
||
235 | - genmask); |
||
236 | + if (nla[NFTA_TABLE_HANDLE]) |
||
237 | + table = nf_tables_table_lookup_byhandle(net, |
||
238 | + nla[NFTA_TABLE_HANDLE], |
||
239 | + genmask); |
||
240 | + else |
||
241 | + table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], |
||
242 | + family, genmask); |
||
243 | + |
||
244 | if (IS_ERR(table)) |
||
245 | return PTR_ERR(table); |
||
246 | |||
3 | office | 247 | @@ -1565,6 +1607,7 @@ static int nf_tables_delchain(struct net |
1 | office | 248 | struct nft_rule *rule; |
249 | int family = nfmsg->nfgen_family; |
||
250 | struct nft_ctx ctx; |
||
251 | + u64 handle; |
||
252 | u32 use; |
||
253 | int err; |
||
254 | |||
3 | office | 255 | @@ -1573,7 +1616,12 @@ static int nf_tables_delchain(struct net |
1 | office | 256 | if (IS_ERR(table)) |
257 | return PTR_ERR(table); |
||
258 | |||
259 | - chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); |
||
260 | + if (nla[NFTA_CHAIN_HANDLE]) { |
||
261 | + handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); |
||
262 | + chain = nf_tables_chain_lookup_byhandle(table, handle, genmask); |
||
263 | + } else { |
||
264 | + chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); |
||
265 | + } |
||
266 | if (IS_ERR(chain)) |
||
267 | return PTR_ERR(chain); |
||
268 | |||
3 | office | 269 | @@ -2547,6 +2595,7 @@ static const struct nla_policy nft_set_p |
1 | office | 270 | [NFTA_SET_USERDATA] = { .type = NLA_BINARY, |
271 | .len = NFT_USERDATA_MAXLEN }, |
||
272 | [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 }, |
||
273 | + [NFTA_SET_HANDLE] = { .type = NLA_U64 }, |
||
274 | }; |
||
275 | |||
276 | static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { |
||
3 | office | 277 | @@ -2590,6 +2639,22 @@ static struct nft_set *nf_tables_set_loo |
1 | office | 278 | return ERR_PTR(-ENOENT); |
279 | } |
||
280 | |||
281 | +static struct nft_set *nf_tables_set_lookup_byhandle(const struct nft_table *table, |
||
282 | + const struct nlattr *nla, u8 genmask) |
||
283 | +{ |
||
284 | + struct nft_set *set; |
||
285 | + |
||
286 | + if (nla == NULL) |
||
287 | + return ERR_PTR(-EINVAL); |
||
288 | + |
||
289 | + list_for_each_entry(set, &table->sets, list) { |
||
290 | + if (be64_to_cpu(nla_get_be64(nla)) == set->handle && |
||
291 | + nft_active_genmask(set, genmask)) |
||
292 | + return set; |
||
293 | + } |
||
294 | + return ERR_PTR(-ENOENT); |
||
295 | +} |
||
296 | + |
||
297 | static struct nft_set *nf_tables_set_lookup_byid(const struct net *net, |
||
298 | const struct nlattr *nla, |
||
299 | u8 genmask) |
||
3 | office | 300 | @@ -2706,6 +2771,9 @@ static int nf_tables_fill_set(struct sk_ |
1 | office | 301 | goto nla_put_failure; |
302 | if (nla_put_string(skb, NFTA_SET_NAME, set->name)) |
||
303 | goto nla_put_failure; |
||
304 | + if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle), |
||
305 | + NFTA_SET_PAD)) |
||
306 | + goto nla_put_failure; |
||
307 | if (set->flags != 0) |
||
308 | if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags))) |
||
309 | goto nla_put_failure; |
||
3 | office | 310 | @@ -3114,6 +3182,7 @@ static int nf_tables_newset(struct net * |
1 | office | 311 | set->udata = udata; |
312 | set->timeout = timeout; |
||
313 | set->gc_int = gc_int; |
||
314 | + set->handle = nf_tables_alloc_handle(table); |
||
315 | |||
316 | err = ops->init(set, &desc, nla); |
||
317 | if (err < 0) |
||
3 | office | 318 | @@ -3173,7 +3242,10 @@ static int nf_tables_delset(struct net * |
1 | office | 319 | if (err < 0) |
320 | return err; |
||
321 | |||
322 | - set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); |
||
323 | + if (nla[NFTA_SET_HANDLE]) |
||
324 | + set = nf_tables_set_lookup_byhandle(ctx.table, nla[NFTA_SET_HANDLE], genmask); |
||
325 | + else |
||
326 | + set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); |
||
327 | if (IS_ERR(set)) |
||
328 | return PTR_ERR(set); |
||
329 | |||
3 | office | 330 | @@ -4233,6 +4305,21 @@ struct nft_object *nf_tables_obj_lookup( |
1 | office | 331 | } |
332 | EXPORT_SYMBOL_GPL(nf_tables_obj_lookup); |
||
333 | |||
334 | +struct nft_object *nf_tables_obj_lookup_byhandle(const struct nft_table *table, |
||
335 | + const struct nlattr *nla, |
||
336 | + u32 objtype, u8 genmask) |
||
337 | +{ |
||
338 | + struct nft_object *obj; |
||
339 | + |
||
340 | + list_for_each_entry(obj, &table->objects, list) { |
||
341 | + if (be64_to_cpu(nla_get_be64(nla)) == obj->handle && |
||
342 | + objtype == obj->ops->type->type && |
||
343 | + nft_active_genmask(obj, genmask)) |
||
344 | + return obj; |
||
345 | + } |
||
346 | + return ERR_PTR(-ENOENT); |
||
347 | +} |
||
348 | + |
||
349 | static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { |
||
350 | [NFTA_OBJ_TABLE] = { .type = NLA_STRING, |
||
351 | .len = NFT_TABLE_MAXNAMELEN - 1 }, |
||
3 | office | 352 | @@ -4240,6 +4327,7 @@ static const struct nla_policy nft_obj_p |
1 | office | 353 | .len = NFT_OBJ_MAXNAMELEN - 1 }, |
354 | [NFTA_OBJ_TYPE] = { .type = NLA_U32 }, |
||
355 | [NFTA_OBJ_DATA] = { .type = NLA_NESTED }, |
||
356 | + [NFTA_OBJ_HANDLE] = { .type = NLA_U64}, |
||
357 | }; |
||
358 | |||
359 | static struct nft_object *nft_obj_init(const struct nft_ctx *ctx, |
||
3 | office | 360 | @@ -4387,6 +4475,8 @@ static int nf_tables_newobj(struct net * |
1 | office | 361 | goto err1; |
362 | } |
||
363 | obj->table = table; |
||
364 | + obj->handle = nf_tables_alloc_handle(table); |
||
365 | + |
||
366 | obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL); |
||
367 | if (!obj->name) { |
||
368 | err = -ENOMEM; |
||
3 | office | 369 | @@ -4433,7 +4523,9 @@ static int nf_tables_fill_obj_info(struc |
1 | office | 370 | nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || |
371 | nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || |
||
372 | nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || |
||
373 | - nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset)) |
||
374 | + nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) || |
||
375 | + nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle), |
||
376 | + NFTA_OBJ_PAD)) |
||
377 | goto nla_put_failure; |
||
378 | |||
379 | nlmsg_end(skb, nlh); |
||
3 | office | 380 | @@ -4631,7 +4723,7 @@ static int nf_tables_delobj(struct net * |
1 | office | 381 | u32 objtype; |
382 | |||
383 | if (!nla[NFTA_OBJ_TYPE] || |
||
384 | - !nla[NFTA_OBJ_NAME]) |
||
385 | + (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE])) |
||
386 | return -EINVAL; |
||
387 | |||
388 | table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, |
||
3 | office | 389 | @@ -4640,7 +4732,12 @@ static int nf_tables_delobj(struct net * |
1 | office | 390 | return PTR_ERR(table); |
391 | |||
392 | objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); |
||
393 | - obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); |
||
394 | + if (nla[NFTA_OBJ_HANDLE]) |
||
395 | + obj = nf_tables_obj_lookup_byhandle(table, nla[NFTA_OBJ_HANDLE], |
||
396 | + objtype, genmask); |
||
397 | + else |
||
398 | + obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], |
||
399 | + objtype, genmask); |
||
400 | if (IS_ERR(obj)) |
||
401 | return PTR_ERR(obj); |
||
402 | if (obj->use > 0) |
||
3 | office | 403 | @@ -4712,6 +4809,7 @@ static const struct nla_policy nft_flowt |
1 | office | 404 | [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING, |
405 | .len = NFT_NAME_MAXLEN - 1 }, |
||
406 | [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, |
||
407 | + [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 }, |
||
408 | }; |
||
409 | |||
410 | struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, |
||
3 | office | 411 | @@ -4729,6 +4827,20 @@ struct nft_flowtable *nf_tables_flowtabl |
1 | office | 412 | } |
413 | EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup); |
||
414 | |||
415 | +struct nft_flowtable * |
||
416 | +nf_tables_flowtable_lookup_byhandle(const struct nft_table *table, |
||
417 | + const struct nlattr *nla, u8 genmask) |
||
418 | +{ |
||
419 | + struct nft_flowtable *flowtable; |
||
420 | + |
||
421 | + list_for_each_entry(flowtable, &table->flowtables, list) { |
||
422 | + if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle && |
||
423 | + nft_active_genmask(flowtable, genmask)) |
||
424 | + return flowtable; |
||
425 | + } |
||
426 | + return ERR_PTR(-ENOENT); |
||
427 | +} |
||
428 | + |
||
429 | #define NFT_FLOWTABLE_DEVICE_MAX 8 |
||
430 | |||
431 | static int nf_tables_parse_devices(const struct nft_ctx *ctx, |
||
3 | office | 432 | @@ -4937,6 +5049,8 @@ static int nf_tables_newflowtable(struct |
1 | office | 433 | return -ENOMEM; |
434 | |||
435 | flowtable->table = table; |
||
436 | + flowtable->handle = nf_tables_alloc_handle(table); |
||
437 | + |
||
438 | flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); |
||
439 | if (!flowtable->name) { |
||
440 | err = -ENOMEM; |
||
3 | office | 441 | @@ -5011,8 +5125,14 @@ static int nf_tables_delflowtable(struct |
1 | office | 442 | if (IS_ERR(table)) |
443 | return PTR_ERR(table); |
||
444 | |||
445 | - flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], |
||
446 | - genmask); |
||
447 | + if (nla[NFTA_FLOWTABLE_HANDLE]) |
||
448 | + flowtable = nf_tables_flowtable_lookup_byhandle(table, |
||
449 | + nla[NFTA_FLOWTABLE_HANDLE], |
||
450 | + genmask); |
||
451 | + else |
||
452 | + flowtable = nf_tables_flowtable_lookup(table, |
||
453 | + nla[NFTA_FLOWTABLE_NAME], |
||
454 | + genmask); |
||
455 | if (IS_ERR(flowtable)) |
||
456 | return PTR_ERR(flowtable); |
||
457 | if (flowtable->use > 0) |
||
3 | office | 458 | @@ -5045,7 +5165,9 @@ static int nf_tables_fill_flowtable_info |
1 | office | 459 | |
460 | if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || |
||
461 | nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || |
||
462 | - nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use))) |
||
463 | + nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || |
||
464 | + nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), |
||
465 | + NFTA_FLOWTABLE_PAD)) |
||
466 | goto nla_put_failure; |
||
467 | |||
468 | nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); |