diff options
36 files changed, 739 insertions, 579 deletions
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 34e7a2b7f867..f1bd3962e6b6 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h | |||
@@ -12,9 +12,10 @@ | |||
12 | #ifndef __LINUX_BRIDGE_EFF_H | 12 | #ifndef __LINUX_BRIDGE_EFF_H |
13 | #define __LINUX_BRIDGE_EFF_H | 13 | #define __LINUX_BRIDGE_EFF_H |
14 | 14 | ||
15 | #include <linux/if.h> | ||
16 | #include <linux/if_ether.h> | ||
15 | #include <uapi/linux/netfilter_bridge/ebtables.h> | 17 | #include <uapi/linux/netfilter_bridge/ebtables.h> |
16 | 18 | ||
17 | |||
18 | /* return values for match() functions */ | 19 | /* return values for match() functions */ |
19 | #define EBT_MATCH 0 | 20 | #define EBT_MATCH 0 |
20 | #define EBT_NOMATCH 1 | 21 | #define EBT_NOMATCH 1 |
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index d6a2f0ed5130..e6bcf55dcf20 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _NET_NF_TABLES_H | 1 | #ifndef _NET_NF_TABLES_H |
2 | #define _NET_NF_TABLES_H | 2 | #define _NET_NF_TABLES_H |
3 | 3 | ||
4 | #include <linux/module.h> | ||
4 | #include <linux/list.h> | 5 | #include <linux/list.h> |
5 | #include <linux/netfilter.h> | 6 | #include <linux/netfilter.h> |
6 | #include <linux/netfilter/nfnetlink.h> | 7 | #include <linux/netfilter/nfnetlink.h> |
@@ -36,29 +37,43 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, | |||
36 | pkt->xt.family = ops->pf; | 37 | pkt->xt.family = ops->pf; |
37 | } | 38 | } |
38 | 39 | ||
40 | /** | ||
41 | * struct nft_verdict - nf_tables verdict | ||
42 | * | ||
43 | * @code: nf_tables/netfilter verdict code | ||
44 | * @chain: destination chain for NFT_JUMP/NFT_GOTO | ||
45 | */ | ||
46 | struct nft_verdict { | ||
47 | u32 code; | ||
48 | struct nft_chain *chain; | ||
49 | }; | ||
50 | |||
39 | struct nft_data { | 51 | struct nft_data { |
40 | union { | 52 | union { |
41 | u32 data[4]; | 53 | u32 data[4]; |
42 | struct { | 54 | struct nft_verdict verdict; |
43 | u32 verdict; | ||
44 | struct nft_chain *chain; | ||
45 | }; | ||
46 | }; | 55 | }; |
47 | } __attribute__((aligned(__alignof__(u64)))); | 56 | } __attribute__((aligned(__alignof__(u64)))); |
48 | 57 | ||
49 | static inline int nft_data_cmp(const struct nft_data *d1, | 58 | /** |
50 | const struct nft_data *d2, | 59 | * struct nft_regs - nf_tables register set |
51 | unsigned int len) | 60 | * |
52 | { | 61 | * @data: data registers |
53 | return memcmp(d1->data, d2->data, len); | 62 | * @verdict: verdict register |
54 | } | 63 | * |
64 | * The first four data registers alias to the verdict register. | ||
65 | */ | ||
66 | struct nft_regs { | ||
67 | union { | ||
68 | u32 data[20]; | ||
69 | struct nft_verdict verdict; | ||
70 | }; | ||
71 | }; | ||
55 | 72 | ||
56 | static inline void nft_data_copy(struct nft_data *dst, | 73 | static inline void nft_data_copy(u32 *dst, const struct nft_data *src, |
57 | const struct nft_data *src) | 74 | unsigned int len) |
58 | { | 75 | { |
59 | BUILD_BUG_ON(__alignof__(*dst) != __alignof__(u64)); | 76 | memcpy(dst, src, len); |
60 | *(u64 *)&dst->data[0] = *(u64 *)&src->data[0]; | ||
61 | *(u64 *)&dst->data[2] = *(u64 *)&src->data[2]; | ||
62 | } | 77 | } |
63 | 78 | ||
64 | static inline void nft_data_debug(const struct nft_data *data) | 79 | static inline void nft_data_debug(const struct nft_data *data) |
@@ -96,7 +111,8 @@ struct nft_data_desc { | |||
96 | unsigned int len; | 111 | unsigned int len; |
97 | }; | 112 | }; |
98 | 113 | ||
99 | int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data, | 114 | int nft_data_init(const struct nft_ctx *ctx, |
115 | struct nft_data *data, unsigned int size, | ||
100 | struct nft_data_desc *desc, const struct nlattr *nla); | 116 | struct nft_data_desc *desc, const struct nlattr *nla); |
101 | void nft_data_uninit(const struct nft_data *data, enum nft_data_types type); | 117 | void nft_data_uninit(const struct nft_data *data, enum nft_data_types type); |
102 | int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, | 118 | int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, |
@@ -112,12 +128,14 @@ static inline enum nft_registers nft_type_to_reg(enum nft_data_types type) | |||
112 | return type == NFT_DATA_VERDICT ? NFT_REG_VERDICT : NFT_REG_1; | 128 | return type == NFT_DATA_VERDICT ? NFT_REG_VERDICT : NFT_REG_1; |
113 | } | 129 | } |
114 | 130 | ||
115 | int nft_validate_input_register(enum nft_registers reg); | 131 | unsigned int nft_parse_register(const struct nlattr *attr); |
116 | int nft_validate_output_register(enum nft_registers reg); | 132 | int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg); |
117 | int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg, | ||
118 | const struct nft_data *data, | ||
119 | enum nft_data_types type); | ||
120 | 133 | ||
134 | int nft_validate_register_load(enum nft_registers reg, unsigned int len); | ||
135 | int nft_validate_register_store(const struct nft_ctx *ctx, | ||
136 | enum nft_registers reg, | ||
137 | const struct nft_data *data, | ||
138 | enum nft_data_types type, unsigned int len); | ||
121 | 139 | ||
122 | /** | 140 | /** |
123 | * struct nft_userdata - user defined data associated with an object | 141 | * struct nft_userdata - user defined data associated with an object |
@@ -141,7 +159,10 @@ struct nft_userdata { | |||
141 | * @priv: element private data and extensions | 159 | * @priv: element private data and extensions |
142 | */ | 160 | */ |
143 | struct nft_set_elem { | 161 | struct nft_set_elem { |
144 | struct nft_data key; | 162 | union { |
163 | u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)]; | ||
164 | struct nft_data val; | ||
165 | } key; | ||
145 | void *priv; | 166 | void *priv; |
146 | }; | 167 | }; |
147 | 168 | ||
@@ -216,15 +237,15 @@ struct nft_expr; | |||
216 | */ | 237 | */ |
217 | struct nft_set_ops { | 238 | struct nft_set_ops { |
218 | bool (*lookup)(const struct nft_set *set, | 239 | bool (*lookup)(const struct nft_set *set, |
219 | const struct nft_data *key, | 240 | const u32 *key, |
220 | const struct nft_set_ext **ext); | 241 | const struct nft_set_ext **ext); |
221 | bool (*update)(struct nft_set *set, | 242 | bool (*update)(struct nft_set *set, |
222 | const struct nft_data *key, | 243 | const u32 *key, |
223 | void *(*new)(struct nft_set *, | 244 | void *(*new)(struct nft_set *, |
224 | const struct nft_expr *, | 245 | const struct nft_expr *, |
225 | struct nft_data []), | 246 | struct nft_regs *), |
226 | const struct nft_expr *expr, | 247 | const struct nft_expr *expr, |
227 | struct nft_data data[], | 248 | struct nft_regs *regs, |
228 | const struct nft_set_ext **ext); | 249 | const struct nft_set_ext **ext); |
229 | 250 | ||
230 | int (*insert)(const struct nft_set *set, | 251 | int (*insert)(const struct nft_set *set, |
@@ -350,6 +371,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
350 | * @NFT_SET_EXT_TIMEOUT: element timeout | 371 | * @NFT_SET_EXT_TIMEOUT: element timeout |
351 | * @NFT_SET_EXT_EXPIRATION: element expiration time | 372 | * @NFT_SET_EXT_EXPIRATION: element expiration time |
352 | * @NFT_SET_EXT_USERDATA: user data associated with the element | 373 | * @NFT_SET_EXT_USERDATA: user data associated with the element |
374 | * @NFT_SET_EXT_EXPR: expression assiociated with the element | ||
353 | * @NFT_SET_EXT_NUM: number of extension types | 375 | * @NFT_SET_EXT_NUM: number of extension types |
354 | */ | 376 | */ |
355 | enum nft_set_extensions { | 377 | enum nft_set_extensions { |
@@ -359,6 +381,7 @@ enum nft_set_extensions { | |||
359 | NFT_SET_EXT_TIMEOUT, | 381 | NFT_SET_EXT_TIMEOUT, |
360 | NFT_SET_EXT_EXPIRATION, | 382 | NFT_SET_EXT_EXPIRATION, |
361 | NFT_SET_EXT_USERDATA, | 383 | NFT_SET_EXT_USERDATA, |
384 | NFT_SET_EXT_EXPR, | ||
362 | NFT_SET_EXT_NUM | 385 | NFT_SET_EXT_NUM |
363 | }; | 386 | }; |
364 | 387 | ||
@@ -470,6 +493,11 @@ static inline struct nft_userdata *nft_set_ext_userdata(const struct nft_set_ext | |||
470 | return nft_set_ext(ext, NFT_SET_EXT_USERDATA); | 493 | return nft_set_ext(ext, NFT_SET_EXT_USERDATA); |
471 | } | 494 | } |
472 | 495 | ||
496 | static inline struct nft_expr *nft_set_ext_expr(const struct nft_set_ext *ext) | ||
497 | { | ||
498 | return nft_set_ext(ext, NFT_SET_EXT_EXPR); | ||
499 | } | ||
500 | |||
473 | static inline bool nft_set_elem_expired(const struct nft_set_ext *ext) | 501 | static inline bool nft_set_elem_expired(const struct nft_set_ext *ext) |
474 | { | 502 | { |
475 | return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) && | 503 | return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) && |
@@ -484,8 +512,7 @@ static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set, | |||
484 | 512 | ||
485 | void *nft_set_elem_init(const struct nft_set *set, | 513 | void *nft_set_elem_init(const struct nft_set *set, |
486 | const struct nft_set_ext_tmpl *tmpl, | 514 | const struct nft_set_ext_tmpl *tmpl, |
487 | const struct nft_data *key, | 515 | const u32 *key, const u32 *data, |
488 | const struct nft_data *data, | ||
489 | u64 timeout, gfp_t gfp); | 516 | u64 timeout, gfp_t gfp); |
490 | void nft_set_elem_destroy(const struct nft_set *set, void *elem); | 517 | void nft_set_elem_destroy(const struct nft_set *set, void *elem); |
491 | 518 | ||
@@ -556,6 +583,7 @@ static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb, | |||
556 | * @policy: netlink attribute policy | 583 | * @policy: netlink attribute policy |
557 | * @maxattr: highest netlink attribute number | 584 | * @maxattr: highest netlink attribute number |
558 | * @family: address family for AF-specific types | 585 | * @family: address family for AF-specific types |
586 | * @flags: expression type flags | ||
559 | */ | 587 | */ |
560 | struct nft_expr_type { | 588 | struct nft_expr_type { |
561 | const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *, | 589 | const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *, |
@@ -567,8 +595,11 @@ struct nft_expr_type { | |||
567 | const struct nla_policy *policy; | 595 | const struct nla_policy *policy; |
568 | unsigned int maxattr; | 596 | unsigned int maxattr; |
569 | u8 family; | 597 | u8 family; |
598 | u8 flags; | ||
570 | }; | 599 | }; |
571 | 600 | ||
601 | #define NFT_EXPR_STATEFUL 0x1 | ||
602 | |||
572 | /** | 603 | /** |
573 | * struct nft_expr_ops - nf_tables expression operations | 604 | * struct nft_expr_ops - nf_tables expression operations |
574 | * | 605 | * |
@@ -584,7 +615,7 @@ struct nft_expr_type { | |||
584 | struct nft_expr; | 615 | struct nft_expr; |
585 | struct nft_expr_ops { | 616 | struct nft_expr_ops { |
586 | void (*eval)(const struct nft_expr *expr, | 617 | void (*eval)(const struct nft_expr *expr, |
587 | struct nft_data data[NFT_REG_MAX + 1], | 618 | struct nft_regs *regs, |
588 | const struct nft_pktinfo *pkt); | 619 | const struct nft_pktinfo *pkt); |
589 | unsigned int size; | 620 | unsigned int size; |
590 | 621 | ||
@@ -622,6 +653,18 @@ static inline void *nft_expr_priv(const struct nft_expr *expr) | |||
622 | return (void *)expr->data; | 653 | return (void *)expr->data; |
623 | } | 654 | } |
624 | 655 | ||
656 | struct nft_expr *nft_expr_init(const struct nft_ctx *ctx, | ||
657 | const struct nlattr *nla); | ||
658 | void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr); | ||
659 | int nft_expr_dump(struct sk_buff *skb, unsigned int attr, | ||
660 | const struct nft_expr *expr); | ||
661 | |||
662 | static inline void nft_expr_clone(struct nft_expr *dst, struct nft_expr *src) | ||
663 | { | ||
664 | __module_get(src->ops->type->owner); | ||
665 | memcpy(dst, src, src->ops->size); | ||
666 | } | ||
667 | |||
625 | /** | 668 | /** |
626 | * struct nft_rule - nf_tables rule | 669 | * struct nft_rule - nf_tables rule |
627 | * | 670 | * |
diff --git a/include/net/netfilter/nft_meta.h b/include/net/netfilter/nft_meta.h index 0ee47c3e2e31..711887a09e91 100644 --- a/include/net/netfilter/nft_meta.h +++ b/include/net/netfilter/nft_meta.h | |||
@@ -26,11 +26,11 @@ int nft_meta_set_dump(struct sk_buff *skb, | |||
26 | const struct nft_expr *expr); | 26 | const struct nft_expr *expr); |
27 | 27 | ||
28 | void nft_meta_get_eval(const struct nft_expr *expr, | 28 | void nft_meta_get_eval(const struct nft_expr *expr, |
29 | struct nft_data data[NFT_REG_MAX + 1], | 29 | struct nft_regs *regs, |
30 | const struct nft_pktinfo *pkt); | 30 | const struct nft_pktinfo *pkt); |
31 | 31 | ||
32 | void nft_meta_set_eval(const struct nft_expr *expr, | 32 | void nft_meta_set_eval(const struct nft_expr *expr, |
33 | struct nft_data data[NFT_REG_MAX + 1], | 33 | struct nft_regs *regs, |
34 | const struct nft_pktinfo *pkt); | 34 | const struct nft_pktinfo *pkt); |
35 | 35 | ||
36 | #endif | 36 | #endif |
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 05ee1e0804a3..5fa1cd04762e 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h | |||
@@ -5,16 +5,45 @@ | |||
5 | #define NFT_CHAIN_MAXNAMELEN 32 | 5 | #define NFT_CHAIN_MAXNAMELEN 32 |
6 | #define NFT_USERDATA_MAXLEN 256 | 6 | #define NFT_USERDATA_MAXLEN 256 |
7 | 7 | ||
8 | /** | ||
9 | * enum nft_registers - nf_tables registers | ||
10 | * | ||
11 | * nf_tables used to have five registers: a verdict register and four data | ||
12 | * registers of size 16. The data registers have been changed to 16 registers | ||
13 | * of size 4. For compatibility reasons, the NFT_REG_[1-4] registers still | ||
14 | * map to areas of size 16, the 4 byte registers are addressed using | ||
15 | * NFT_REG32_00 - NFT_REG32_15. | ||
16 | */ | ||
8 | enum nft_registers { | 17 | enum nft_registers { |
9 | NFT_REG_VERDICT, | 18 | NFT_REG_VERDICT, |
10 | NFT_REG_1, | 19 | NFT_REG_1, |
11 | NFT_REG_2, | 20 | NFT_REG_2, |
12 | NFT_REG_3, | 21 | NFT_REG_3, |
13 | NFT_REG_4, | 22 | NFT_REG_4, |
14 | __NFT_REG_MAX | 23 | __NFT_REG_MAX, |
24 | |||
25 | NFT_REG32_00 = 8, | ||
26 | MFT_REG32_01, | ||
27 | NFT_REG32_02, | ||
28 | NFT_REG32_03, | ||
29 | NFT_REG32_04, | ||
30 | NFT_REG32_05, | ||
31 | NFT_REG32_06, | ||
32 | NFT_REG32_07, | ||
33 | NFT_REG32_08, | ||
34 | NFT_REG32_09, | ||
35 | NFT_REG32_10, | ||
36 | NFT_REG32_11, | ||
37 | NFT_REG32_12, | ||
38 | NFT_REG32_13, | ||
39 | NFT_REG32_14, | ||
40 | NFT_REG32_15, | ||
15 | }; | 41 | }; |
16 | #define NFT_REG_MAX (__NFT_REG_MAX - 1) | 42 | #define NFT_REG_MAX (__NFT_REG_MAX - 1) |
17 | 43 | ||
44 | #define NFT_REG_SIZE 16 | ||
45 | #define NFT_REG32_SIZE 4 | ||
46 | |||
18 | /** | 47 | /** |
19 | * enum nft_verdicts - nf_tables internal verdicts | 48 | * enum nft_verdicts - nf_tables internal verdicts |
20 | * | 49 | * |
@@ -209,6 +238,7 @@ enum nft_rule_compat_attributes { | |||
209 | * @NFT_SET_INTERVAL: set contains intervals | 238 | * @NFT_SET_INTERVAL: set contains intervals |
210 | * @NFT_SET_MAP: set is used as a dictionary | 239 | * @NFT_SET_MAP: set is used as a dictionary |
211 | * @NFT_SET_TIMEOUT: set uses timeouts | 240 | * @NFT_SET_TIMEOUT: set uses timeouts |
241 | * @NFT_SET_EVAL: set contains expressions for evaluation | ||
212 | */ | 242 | */ |
213 | enum nft_set_flags { | 243 | enum nft_set_flags { |
214 | NFT_SET_ANONYMOUS = 0x1, | 244 | NFT_SET_ANONYMOUS = 0x1, |
@@ -216,6 +246,7 @@ enum nft_set_flags { | |||
216 | NFT_SET_INTERVAL = 0x4, | 246 | NFT_SET_INTERVAL = 0x4, |
217 | NFT_SET_MAP = 0x8, | 247 | NFT_SET_MAP = 0x8, |
218 | NFT_SET_TIMEOUT = 0x10, | 248 | NFT_SET_TIMEOUT = 0x10, |
249 | NFT_SET_EVAL = 0x20, | ||
219 | }; | 250 | }; |
220 | 251 | ||
221 | /** | 252 | /** |
@@ -293,6 +324,7 @@ enum nft_set_elem_flags { | |||
293 | * @NFTA_SET_ELEM_TIMEOUT: timeout value (NLA_U64) | 324 | * @NFTA_SET_ELEM_TIMEOUT: timeout value (NLA_U64) |
294 | * @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64) | 325 | * @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64) |
295 | * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY) | 326 | * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY) |
327 | * @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes) | ||
296 | */ | 328 | */ |
297 | enum nft_set_elem_attributes { | 329 | enum nft_set_elem_attributes { |
298 | NFTA_SET_ELEM_UNSPEC, | 330 | NFTA_SET_ELEM_UNSPEC, |
@@ -302,6 +334,7 @@ enum nft_set_elem_attributes { | |||
302 | NFTA_SET_ELEM_TIMEOUT, | 334 | NFTA_SET_ELEM_TIMEOUT, |
303 | NFTA_SET_ELEM_EXPIRATION, | 335 | NFTA_SET_ELEM_EXPIRATION, |
304 | NFTA_SET_ELEM_USERDATA, | 336 | NFTA_SET_ELEM_USERDATA, |
337 | NFTA_SET_ELEM_EXPR, | ||
305 | __NFTA_SET_ELEM_MAX | 338 | __NFTA_SET_ELEM_MAX |
306 | }; | 339 | }; |
307 | #define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1) | 340 | #define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1) |
@@ -359,6 +392,9 @@ enum nft_data_attributes { | |||
359 | }; | 392 | }; |
360 | #define NFTA_DATA_MAX (__NFTA_DATA_MAX - 1) | 393 | #define NFTA_DATA_MAX (__NFTA_DATA_MAX - 1) |
361 | 394 | ||
395 | /* Maximum length of a value */ | ||
396 | #define NFT_DATA_VALUE_MAXLEN 64 | ||
397 | |||
362 | /** | 398 | /** |
363 | * enum nft_verdict_attributes - nf_tables verdict netlink attributes | 399 | * enum nft_verdict_attributes - nf_tables verdict netlink attributes |
364 | * | 400 | * |
@@ -531,6 +567,7 @@ enum nft_dynset_ops { | |||
531 | * @NFTA_DYNSET_SREG_KEY: source register of the key (NLA_U32) | 567 | * @NFTA_DYNSET_SREG_KEY: source register of the key (NLA_U32) |
532 | * @NFTA_DYNSET_SREG_DATA: source register of the data (NLA_U32) | 568 | * @NFTA_DYNSET_SREG_DATA: source register of the data (NLA_U32) |
533 | * @NFTA_DYNSET_TIMEOUT: timeout value for the new element (NLA_U64) | 569 | * @NFTA_DYNSET_TIMEOUT: timeout value for the new element (NLA_U64) |
570 | * @NFTA_DYNSET_EXPR: expression (NLA_NESTED: nft_expr_attributes) | ||
534 | */ | 571 | */ |
535 | enum nft_dynset_attributes { | 572 | enum nft_dynset_attributes { |
536 | NFTA_DYNSET_UNSPEC, | 573 | NFTA_DYNSET_UNSPEC, |
@@ -540,6 +577,7 @@ enum nft_dynset_attributes { | |||
540 | NFTA_DYNSET_SREG_KEY, | 577 | NFTA_DYNSET_SREG_KEY, |
541 | NFTA_DYNSET_SREG_DATA, | 578 | NFTA_DYNSET_SREG_DATA, |
542 | NFTA_DYNSET_TIMEOUT, | 579 | NFTA_DYNSET_TIMEOUT, |
580 | NFTA_DYNSET_EXPR, | ||
543 | __NFTA_DYNSET_MAX, | 581 | __NFTA_DYNSET_MAX, |
544 | }; | 582 | }; |
545 | #define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1) | 583 | #define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1) |
diff --git a/include/uapi/linux/netfilter_bridge/ebtables.h b/include/uapi/linux/netfilter_bridge/ebtables.h index ba993360dbe9..773dfe8924c7 100644 --- a/include/uapi/linux/netfilter_bridge/ebtables.h +++ b/include/uapi/linux/netfilter_bridge/ebtables.h | |||
@@ -12,9 +12,7 @@ | |||
12 | 12 | ||
13 | #ifndef _UAPI__LINUX_BRIDGE_EFF_H | 13 | #ifndef _UAPI__LINUX_BRIDGE_EFF_H |
14 | #define _UAPI__LINUX_BRIDGE_EFF_H | 14 | #define _UAPI__LINUX_BRIDGE_EFF_H |
15 | #include <linux/if.h> | ||
16 | #include <linux/netfilter_bridge.h> | 15 | #include <linux/netfilter_bridge.h> |
17 | #include <linux/if_ether.h> | ||
18 | 16 | ||
19 | #define EBT_TABLE_MAXNAMELEN 32 | 17 | #define EBT_TABLE_MAXNAMELEN 32 |
20 | #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN | 18 | #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN |
diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c index 4f02109d708f..a21269b83f16 100644 --- a/net/bridge/netfilter/nft_meta_bridge.c +++ b/net/bridge/netfilter/nft_meta_bridge.c | |||
@@ -19,12 +19,12 @@ | |||
19 | #include "../br_private.h" | 19 | #include "../br_private.h" |
20 | 20 | ||
21 | static void nft_meta_bridge_get_eval(const struct nft_expr *expr, | 21 | static void nft_meta_bridge_get_eval(const struct nft_expr *expr, |
22 | struct nft_data data[NFT_REG_MAX + 1], | 22 | struct nft_regs *regs, |
23 | const struct nft_pktinfo *pkt) | 23 | const struct nft_pktinfo *pkt) |
24 | { | 24 | { |
25 | const struct nft_meta *priv = nft_expr_priv(expr); | 25 | const struct nft_meta *priv = nft_expr_priv(expr); |
26 | const struct net_device *in = pkt->in, *out = pkt->out; | 26 | const struct net_device *in = pkt->in, *out = pkt->out; |
27 | struct nft_data *dest = &data[priv->dreg]; | 27 | u32 *dest = ®s->data[priv->dreg]; |
28 | const struct net_bridge_port *p; | 28 | const struct net_bridge_port *p; |
29 | 29 | ||
30 | switch (priv->key) { | 30 | switch (priv->key) { |
@@ -40,12 +40,12 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr, | |||
40 | goto out; | 40 | goto out; |
41 | } | 41 | } |
42 | 42 | ||
43 | strncpy((char *)dest->data, p->br->dev->name, sizeof(dest->data)); | 43 | strncpy((char *)dest, p->br->dev->name, IFNAMSIZ); |
44 | return; | 44 | return; |
45 | out: | 45 | out: |
46 | return nft_meta_get_eval(expr, data, pkt); | 46 | return nft_meta_get_eval(expr, regs, pkt); |
47 | err: | 47 | err: |
48 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 48 | regs->verdict.code = NFT_BREAK; |
49 | } | 49 | } |
50 | 50 | ||
51 | static int nft_meta_bridge_get_init(const struct nft_ctx *ctx, | 51 | static int nft_meta_bridge_get_init(const struct nft_ctx *ctx, |
@@ -53,27 +53,21 @@ static int nft_meta_bridge_get_init(const struct nft_ctx *ctx, | |||
53 | const struct nlattr * const tb[]) | 53 | const struct nlattr * const tb[]) |
54 | { | 54 | { |
55 | struct nft_meta *priv = nft_expr_priv(expr); | 55 | struct nft_meta *priv = nft_expr_priv(expr); |
56 | int err; | 56 | unsigned int len; |
57 | 57 | ||
58 | priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); | 58 | priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); |
59 | switch (priv->key) { | 59 | switch (priv->key) { |
60 | case NFT_META_BRI_IIFNAME: | 60 | case NFT_META_BRI_IIFNAME: |
61 | case NFT_META_BRI_OIFNAME: | 61 | case NFT_META_BRI_OIFNAME: |
62 | len = IFNAMSIZ; | ||
62 | break; | 63 | break; |
63 | default: | 64 | default: |
64 | return nft_meta_get_init(ctx, expr, tb); | 65 | return nft_meta_get_init(ctx, expr, tb); |
65 | } | 66 | } |
66 | 67 | ||
67 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG])); | 68 | priv->dreg = nft_parse_register(tb[NFTA_META_DREG]); |
68 | err = nft_validate_output_register(priv->dreg); | 69 | return nft_validate_register_store(ctx, priv->dreg, NULL, |
69 | if (err < 0) | 70 | NFT_DATA_VALUE, len); |
70 | return err; | ||
71 | |||
72 | err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); | ||
73 | if (err < 0) | ||
74 | return err; | ||
75 | |||
76 | return 0; | ||
77 | } | 71 | } |
78 | 72 | ||
79 | static struct nft_expr_type nft_meta_bridge_type; | 73 | static struct nft_expr_type nft_meta_bridge_type; |
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index ae8141f409d9..858d848564ee 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
@@ -257,8 +257,8 @@ static void nft_reject_br_send_v6_unreach(struct net *net, | |||
257 | } | 257 | } |
258 | 258 | ||
259 | static void nft_reject_bridge_eval(const struct nft_expr *expr, | 259 | static void nft_reject_bridge_eval(const struct nft_expr *expr, |
260 | struct nft_data data[NFT_REG_MAX + 1], | 260 | struct nft_regs *regs, |
261 | const struct nft_pktinfo *pkt) | 261 | const struct nft_pktinfo *pkt) |
262 | { | 262 | { |
263 | struct nft_reject *priv = nft_expr_priv(expr); | 263 | struct nft_reject *priv = nft_expr_priv(expr); |
264 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | 264 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); |
@@ -310,7 +310,7 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, | |||
310 | break; | 310 | break; |
311 | } | 311 | } |
312 | out: | 312 | out: |
313 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 313 | regs->verdict.code = NF_DROP; |
314 | } | 314 | } |
315 | 315 | ||
316 | static int nft_reject_bridge_validate(const struct nft_ctx *ctx, | 316 | static int nft_reject_bridge_validate(const struct nft_ctx *ctx, |
diff --git a/net/ipv4/netfilter/nft_masq_ipv4.c b/net/ipv4/netfilter/nft_masq_ipv4.c index 665de06561cd..40e414c4ca56 100644 --- a/net/ipv4/netfilter/nft_masq_ipv4.c +++ b/net/ipv4/netfilter/nft_masq_ipv4.c | |||
@@ -17,20 +17,17 @@ | |||
17 | #include <net/netfilter/ipv4/nf_nat_masquerade.h> | 17 | #include <net/netfilter/ipv4/nf_nat_masquerade.h> |
18 | 18 | ||
19 | static void nft_masq_ipv4_eval(const struct nft_expr *expr, | 19 | static void nft_masq_ipv4_eval(const struct nft_expr *expr, |
20 | struct nft_data data[NFT_REG_MAX + 1], | 20 | struct nft_regs *regs, |
21 | const struct nft_pktinfo *pkt) | 21 | const struct nft_pktinfo *pkt) |
22 | { | 22 | { |
23 | struct nft_masq *priv = nft_expr_priv(expr); | 23 | struct nft_masq *priv = nft_expr_priv(expr); |
24 | struct nf_nat_range range; | 24 | struct nf_nat_range range; |
25 | unsigned int verdict; | ||
26 | 25 | ||
27 | memset(&range, 0, sizeof(range)); | 26 | memset(&range, 0, sizeof(range)); |
28 | range.flags = priv->flags; | 27 | range.flags = priv->flags; |
29 | 28 | ||
30 | verdict = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum, | 29 | regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum, |
31 | &range, pkt->out); | 30 | &range, pkt->out); |
32 | |||
33 | data[NFT_REG_VERDICT].verdict = verdict; | ||
34 | } | 31 | } |
35 | 32 | ||
36 | static struct nft_expr_type nft_masq_ipv4_type; | 33 | static struct nft_expr_type nft_masq_ipv4_type; |
diff --git a/net/ipv4/netfilter/nft_redir_ipv4.c b/net/ipv4/netfilter/nft_redir_ipv4.c index 6ecfce63201a..d8d795df9c13 100644 --- a/net/ipv4/netfilter/nft_redir_ipv4.c +++ b/net/ipv4/netfilter/nft_redir_ipv4.c | |||
@@ -18,26 +18,25 @@ | |||
18 | #include <net/netfilter/nft_redir.h> | 18 | #include <net/netfilter/nft_redir.h> |
19 | 19 | ||
20 | static void nft_redir_ipv4_eval(const struct nft_expr *expr, | 20 | static void nft_redir_ipv4_eval(const struct nft_expr *expr, |
21 | struct nft_data data[NFT_REG_MAX + 1], | 21 | struct nft_regs *regs, |
22 | const struct nft_pktinfo *pkt) | 22 | const struct nft_pktinfo *pkt) |
23 | { | 23 | { |
24 | struct nft_redir *priv = nft_expr_priv(expr); | 24 | struct nft_redir *priv = nft_expr_priv(expr); |
25 | struct nf_nat_ipv4_multi_range_compat mr; | 25 | struct nf_nat_ipv4_multi_range_compat mr; |
26 | unsigned int verdict; | ||
27 | 26 | ||
28 | memset(&mr, 0, sizeof(mr)); | 27 | memset(&mr, 0, sizeof(mr)); |
29 | if (priv->sreg_proto_min) { | 28 | if (priv->sreg_proto_min) { |
30 | mr.range[0].min.all = | 29 | mr.range[0].min.all = |
31 | *(__be16 *)&data[priv->sreg_proto_min].data[0]; | 30 | *(__be16 *)®s->data[priv->sreg_proto_min]; |
32 | mr.range[0].max.all = | 31 | mr.range[0].max.all = |
33 | *(__be16 *)&data[priv->sreg_proto_max].data[0]; | 32 | *(__be16 *)®s->data[priv->sreg_proto_max]; |
34 | mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 33 | mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
35 | } | 34 | } |
36 | 35 | ||
37 | mr.range[0].flags |= priv->flags; | 36 | mr.range[0].flags |= priv->flags; |
38 | 37 | ||
39 | verdict = nf_nat_redirect_ipv4(pkt->skb, &mr, pkt->ops->hooknum); | 38 | regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, |
40 | data[NFT_REG_VERDICT].verdict = verdict; | 39 | pkt->ops->hooknum); |
41 | } | 40 | } |
42 | 41 | ||
43 | static struct nft_expr_type nft_redir_ipv4_type; | 42 | static struct nft_expr_type nft_redir_ipv4_type; |
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c index a7621faa9678..b07e58b51158 100644 --- a/net/ipv4/netfilter/nft_reject_ipv4.c +++ b/net/ipv4/netfilter/nft_reject_ipv4.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <net/netfilter/nft_reject.h> | 20 | #include <net/netfilter/nft_reject.h> |
21 | 21 | ||
22 | static void nft_reject_ipv4_eval(const struct nft_expr *expr, | 22 | static void nft_reject_ipv4_eval(const struct nft_expr *expr, |
23 | struct nft_data data[NFT_REG_MAX + 1], | 23 | struct nft_regs *regs, |
24 | const struct nft_pktinfo *pkt) | 24 | const struct nft_pktinfo *pkt) |
25 | { | 25 | { |
26 | struct nft_reject *priv = nft_expr_priv(expr); | 26 | struct nft_reject *priv = nft_expr_priv(expr); |
@@ -37,7 +37,7 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr, | |||
37 | break; | 37 | break; |
38 | } | 38 | } |
39 | 39 | ||
40 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 40 | regs->verdict.code = NF_DROP; |
41 | } | 41 | } |
42 | 42 | ||
43 | static struct nft_expr_type nft_reject_ipv4_type; | 43 | static struct nft_expr_type nft_reject_ipv4_type; |
diff --git a/net/ipv6/netfilter/nft_masq_ipv6.c b/net/ipv6/netfilter/nft_masq_ipv6.c index 529c119cbb14..cd1ac1637a05 100644 --- a/net/ipv6/netfilter/nft_masq_ipv6.c +++ b/net/ipv6/netfilter/nft_masq_ipv6.c | |||
@@ -18,19 +18,16 @@ | |||
18 | #include <net/netfilter/ipv6/nf_nat_masquerade.h> | 18 | #include <net/netfilter/ipv6/nf_nat_masquerade.h> |
19 | 19 | ||
20 | static void nft_masq_ipv6_eval(const struct nft_expr *expr, | 20 | static void nft_masq_ipv6_eval(const struct nft_expr *expr, |
21 | struct nft_data data[NFT_REG_MAX + 1], | 21 | struct nft_regs *regs, |
22 | const struct nft_pktinfo *pkt) | 22 | const struct nft_pktinfo *pkt) |
23 | { | 23 | { |
24 | struct nft_masq *priv = nft_expr_priv(expr); | 24 | struct nft_masq *priv = nft_expr_priv(expr); |
25 | struct nf_nat_range range; | 25 | struct nf_nat_range range; |
26 | unsigned int verdict; | ||
27 | 26 | ||
28 | memset(&range, 0, sizeof(range)); | 27 | memset(&range, 0, sizeof(range)); |
29 | range.flags = priv->flags; | 28 | range.flags = priv->flags; |
30 | 29 | ||
31 | verdict = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); | 30 | regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); |
32 | |||
33 | data[NFT_REG_VERDICT].verdict = verdict; | ||
34 | } | 31 | } |
35 | 32 | ||
36 | static struct nft_expr_type nft_masq_ipv6_type; | 33 | static struct nft_expr_type nft_masq_ipv6_type; |
diff --git a/net/ipv6/netfilter/nft_redir_ipv6.c b/net/ipv6/netfilter/nft_redir_ipv6.c index 11820b6b3613..effd393bd517 100644 --- a/net/ipv6/netfilter/nft_redir_ipv6.c +++ b/net/ipv6/netfilter/nft_redir_ipv6.c | |||
@@ -18,26 +18,25 @@ | |||
18 | #include <net/netfilter/nf_nat_redirect.h> | 18 | #include <net/netfilter/nf_nat_redirect.h> |
19 | 19 | ||
20 | static void nft_redir_ipv6_eval(const struct nft_expr *expr, | 20 | static void nft_redir_ipv6_eval(const struct nft_expr *expr, |
21 | struct nft_data data[NFT_REG_MAX + 1], | 21 | struct nft_regs *regs, |
22 | const struct nft_pktinfo *pkt) | 22 | const struct nft_pktinfo *pkt) |
23 | { | 23 | { |
24 | struct nft_redir *priv = nft_expr_priv(expr); | 24 | struct nft_redir *priv = nft_expr_priv(expr); |
25 | struct nf_nat_range range; | 25 | struct nf_nat_range range; |
26 | unsigned int verdict; | ||
27 | 26 | ||
28 | memset(&range, 0, sizeof(range)); | 27 | memset(&range, 0, sizeof(range)); |
29 | if (priv->sreg_proto_min) { | 28 | if (priv->sreg_proto_min) { |
30 | range.min_proto.all = | 29 | range.min_proto.all = |
31 | *(__be16 *)&data[priv->sreg_proto_min].data[0]; | 30 | *(__be16 *)®s->data[priv->sreg_proto_min], |
32 | range.max_proto.all = | 31 | range.max_proto.all = |
33 | *(__be16 *)&data[priv->sreg_proto_max].data[0]; | 32 | *(__be16 *)®s->data[priv->sreg_proto_max], |
34 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 33 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
35 | } | 34 | } |
36 | 35 | ||
37 | range.flags |= priv->flags; | 36 | range.flags |= priv->flags; |
38 | 37 | ||
39 | verdict = nf_nat_redirect_ipv6(pkt->skb, &range, pkt->ops->hooknum); | 38 | regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range, |
40 | data[NFT_REG_VERDICT].verdict = verdict; | 39 | pkt->ops->hooknum); |
41 | } | 40 | } |
42 | 41 | ||
43 | static struct nft_expr_type nft_redir_ipv6_type; | 42 | static struct nft_expr_type nft_redir_ipv6_type; |
diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c index 71c7be5ee43a..d0d1540ecf87 100644 --- a/net/ipv6/netfilter/nft_reject_ipv6.c +++ b/net/ipv6/netfilter/nft_reject_ipv6.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <net/netfilter/ipv6/nf_reject.h> | 20 | #include <net/netfilter/ipv6/nf_reject.h> |
21 | 21 | ||
22 | static void nft_reject_ipv6_eval(const struct nft_expr *expr, | 22 | static void nft_reject_ipv6_eval(const struct nft_expr *expr, |
23 | struct nft_data data[NFT_REG_MAX + 1], | 23 | struct nft_regs *regs, |
24 | const struct nft_pktinfo *pkt) | 24 | const struct nft_pktinfo *pkt) |
25 | { | 25 | { |
26 | struct nft_reject *priv = nft_expr_priv(expr); | 26 | struct nft_reject *priv = nft_expr_priv(expr); |
@@ -38,7 +38,7 @@ static void nft_reject_ipv6_eval(const struct nft_expr *expr, | |||
38 | break; | 38 | break; |
39 | } | 39 | } |
40 | 40 | ||
41 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 41 | regs->verdict.code = NF_DROP; |
42 | } | 42 | } |
43 | 43 | ||
44 | static struct nft_expr_type nft_reject_ipv6_type; | 44 | static struct nft_expr_type nft_reject_ipv6_type; |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 0b96fa0d64b2..78af83bc9c8e 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -1545,6 +1545,23 @@ nla_put_failure: | |||
1545 | return -1; | 1545 | return -1; |
1546 | }; | 1546 | }; |
1547 | 1547 | ||
1548 | int nft_expr_dump(struct sk_buff *skb, unsigned int attr, | ||
1549 | const struct nft_expr *expr) | ||
1550 | { | ||
1551 | struct nlattr *nest; | ||
1552 | |||
1553 | nest = nla_nest_start(skb, attr); | ||
1554 | if (!nest) | ||
1555 | goto nla_put_failure; | ||
1556 | if (nf_tables_fill_expr_info(skb, expr) < 0) | ||
1557 | goto nla_put_failure; | ||
1558 | nla_nest_end(skb, nest); | ||
1559 | return 0; | ||
1560 | |||
1561 | nla_put_failure: | ||
1562 | return -1; | ||
1563 | } | ||
1564 | |||
1548 | struct nft_expr_info { | 1565 | struct nft_expr_info { |
1549 | const struct nft_expr_ops *ops; | 1566 | const struct nft_expr_ops *ops; |
1550 | struct nlattr *tb[NFT_EXPR_MAXATTR + 1]; | 1567 | struct nlattr *tb[NFT_EXPR_MAXATTR + 1]; |
@@ -1622,6 +1639,39 @@ static void nf_tables_expr_destroy(const struct nft_ctx *ctx, | |||
1622 | module_put(expr->ops->type->owner); | 1639 | module_put(expr->ops->type->owner); |
1623 | } | 1640 | } |
1624 | 1641 | ||
1642 | struct nft_expr *nft_expr_init(const struct nft_ctx *ctx, | ||
1643 | const struct nlattr *nla) | ||
1644 | { | ||
1645 | struct nft_expr_info info; | ||
1646 | struct nft_expr *expr; | ||
1647 | int err; | ||
1648 | |||
1649 | err = nf_tables_expr_parse(ctx, nla, &info); | ||
1650 | if (err < 0) | ||
1651 | goto err1; | ||
1652 | |||
1653 | err = -ENOMEM; | ||
1654 | expr = kzalloc(info.ops->size, GFP_KERNEL); | ||
1655 | if (expr == NULL) | ||
1656 | goto err2; | ||
1657 | |||
1658 | err = nf_tables_newexpr(ctx, &info, expr); | ||
1659 | if (err < 0) | ||
1660 | goto err2; | ||
1661 | |||
1662 | return expr; | ||
1663 | err2: | ||
1664 | module_put(info.ops->type->owner); | ||
1665 | err1: | ||
1666 | return ERR_PTR(err); | ||
1667 | } | ||
1668 | |||
1669 | void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr) | ||
1670 | { | ||
1671 | nf_tables_expr_destroy(ctx, expr); | ||
1672 | kfree(expr); | ||
1673 | } | ||
1674 | |||
1625 | /* | 1675 | /* |
1626 | * Rules | 1676 | * Rules |
1627 | */ | 1677 | */ |
@@ -1703,12 +1753,8 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net, | |||
1703 | if (list == NULL) | 1753 | if (list == NULL) |
1704 | goto nla_put_failure; | 1754 | goto nla_put_failure; |
1705 | nft_rule_for_each_expr(expr, next, rule) { | 1755 | nft_rule_for_each_expr(expr, next, rule) { |
1706 | struct nlattr *elem = nla_nest_start(skb, NFTA_LIST_ELEM); | 1756 | if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0) |
1707 | if (elem == NULL) | ||
1708 | goto nla_put_failure; | 1757 | goto nla_put_failure; |
1709 | if (nf_tables_fill_expr_info(skb, expr) < 0) | ||
1710 | goto nla_put_failure; | ||
1711 | nla_nest_end(skb, elem); | ||
1712 | } | 1758 | } |
1713 | nla_nest_end(skb, list); | 1759 | nla_nest_end(skb, list); |
1714 | 1760 | ||
@@ -2608,16 +2654,20 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, | |||
2608 | } | 2654 | } |
2609 | 2655 | ||
2610 | desc.klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN])); | 2656 | desc.klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN])); |
2611 | if (desc.klen == 0 || desc.klen > FIELD_SIZEOF(struct nft_data, data)) | 2657 | if (desc.klen == 0 || desc.klen > NFT_DATA_VALUE_MAXLEN) |
2612 | return -EINVAL; | 2658 | return -EINVAL; |
2613 | 2659 | ||
2614 | flags = 0; | 2660 | flags = 0; |
2615 | if (nla[NFTA_SET_FLAGS] != NULL) { | 2661 | if (nla[NFTA_SET_FLAGS] != NULL) { |
2616 | flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS])); | 2662 | flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS])); |
2617 | if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT | | 2663 | if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT | |
2618 | NFT_SET_INTERVAL | NFT_SET_MAP | | 2664 | NFT_SET_INTERVAL | NFT_SET_TIMEOUT | |
2619 | NFT_SET_TIMEOUT)) | 2665 | NFT_SET_MAP | NFT_SET_EVAL)) |
2620 | return -EINVAL; | 2666 | return -EINVAL; |
2667 | /* Only one of both operations is supported */ | ||
2668 | if ((flags & (NFT_SET_MAP | NFT_SET_EVAL)) == | ||
2669 | (NFT_SET_MAP | NFT_SET_EVAL)) | ||
2670 | return -EOPNOTSUPP; | ||
2621 | } | 2671 | } |
2622 | 2672 | ||
2623 | dtype = 0; | 2673 | dtype = 0; |
@@ -2634,11 +2684,10 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, | |||
2634 | if (nla[NFTA_SET_DATA_LEN] == NULL) | 2684 | if (nla[NFTA_SET_DATA_LEN] == NULL) |
2635 | return -EINVAL; | 2685 | return -EINVAL; |
2636 | desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN])); | 2686 | desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN])); |
2637 | if (desc.dlen == 0 || | 2687 | if (desc.dlen == 0 || desc.dlen > NFT_DATA_VALUE_MAXLEN) |
2638 | desc.dlen > FIELD_SIZEOF(struct nft_data, data)) | ||
2639 | return -EINVAL; | 2688 | return -EINVAL; |
2640 | } else | 2689 | } else |
2641 | desc.dlen = sizeof(struct nft_data); | 2690 | desc.dlen = sizeof(struct nft_verdict); |
2642 | } else if (flags & NFT_SET_MAP) | 2691 | } else if (flags & NFT_SET_MAP) |
2643 | return -EINVAL; | 2692 | return -EINVAL; |
2644 | 2693 | ||
@@ -2797,9 +2846,10 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx, | |||
2797 | enum nft_registers dreg; | 2846 | enum nft_registers dreg; |
2798 | 2847 | ||
2799 | dreg = nft_type_to_reg(set->dtype); | 2848 | dreg = nft_type_to_reg(set->dtype); |
2800 | return nft_validate_data_load(ctx, dreg, nft_set_ext_data(ext), | 2849 | return nft_validate_register_store(ctx, dreg, nft_set_ext_data(ext), |
2801 | set->dtype == NFT_DATA_VERDICT ? | 2850 | set->dtype == NFT_DATA_VERDICT ? |
2802 | NFT_DATA_VERDICT : NFT_DATA_VALUE); | 2851 | NFT_DATA_VERDICT : NFT_DATA_VALUE, |
2852 | set->dlen); | ||
2803 | } | 2853 | } |
2804 | 2854 | ||
2805 | int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, | 2855 | int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, |
@@ -2853,12 +2903,13 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
2853 | 2903 | ||
2854 | const struct nft_set_ext_type nft_set_ext_types[] = { | 2904 | const struct nft_set_ext_type nft_set_ext_types[] = { |
2855 | [NFT_SET_EXT_KEY] = { | 2905 | [NFT_SET_EXT_KEY] = { |
2856 | .len = sizeof(struct nft_data), | 2906 | .align = __alignof__(u32), |
2857 | .align = __alignof__(struct nft_data), | ||
2858 | }, | 2907 | }, |
2859 | [NFT_SET_EXT_DATA] = { | 2908 | [NFT_SET_EXT_DATA] = { |
2860 | .len = sizeof(struct nft_data), | 2909 | .align = __alignof__(u32), |
2861 | .align = __alignof__(struct nft_data), | 2910 | }, |
2911 | [NFT_SET_EXT_EXPR] = { | ||
2912 | .align = __alignof__(struct nft_expr), | ||
2862 | }, | 2913 | }, |
2863 | [NFT_SET_EXT_FLAGS] = { | 2914 | [NFT_SET_EXT_FLAGS] = { |
2864 | .len = sizeof(u8), | 2915 | .len = sizeof(u8), |
@@ -2946,6 +2997,10 @@ static int nf_tables_fill_setelem(struct sk_buff *skb, | |||
2946 | set->dlen) < 0) | 2997 | set->dlen) < 0) |
2947 | goto nla_put_failure; | 2998 | goto nla_put_failure; |
2948 | 2999 | ||
3000 | if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR) && | ||
3001 | nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, nft_set_ext_expr(ext)) < 0) | ||
3002 | goto nla_put_failure; | ||
3003 | |||
2949 | if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && | 3004 | if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && |
2950 | nla_put_be32(skb, NFTA_SET_ELEM_FLAGS, | 3005 | nla_put_be32(skb, NFTA_SET_ELEM_FLAGS, |
2951 | htonl(*nft_set_ext_flags(ext)))) | 3006 | htonl(*nft_set_ext_flags(ext)))) |
@@ -3200,8 +3255,7 @@ static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx, | |||
3200 | 3255 | ||
3201 | void *nft_set_elem_init(const struct nft_set *set, | 3256 | void *nft_set_elem_init(const struct nft_set *set, |
3202 | const struct nft_set_ext_tmpl *tmpl, | 3257 | const struct nft_set_ext_tmpl *tmpl, |
3203 | const struct nft_data *key, | 3258 | const u32 *key, const u32 *data, |
3204 | const struct nft_data *data, | ||
3205 | u64 timeout, gfp_t gfp) | 3259 | u64 timeout, gfp_t gfp) |
3206 | { | 3260 | { |
3207 | struct nft_set_ext *ext; | 3261 | struct nft_set_ext *ext; |
@@ -3233,6 +3287,8 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem) | |||
3233 | nft_data_uninit(nft_set_ext_key(ext), NFT_DATA_VALUE); | 3287 | nft_data_uninit(nft_set_ext_key(ext), NFT_DATA_VALUE); |
3234 | if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA)) | 3288 | if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA)) |
3235 | nft_data_uninit(nft_set_ext_data(ext), set->dtype); | 3289 | nft_data_uninit(nft_set_ext_data(ext), set->dtype); |
3290 | if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) | ||
3291 | nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext)); | ||
3236 | 3292 | ||
3237 | kfree(elem); | 3293 | kfree(elem); |
3238 | } | 3294 | } |
@@ -3299,14 +3355,15 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | |||
3299 | timeout = set->timeout; | 3355 | timeout = set->timeout; |
3300 | } | 3356 | } |
3301 | 3357 | ||
3302 | err = nft_data_init(ctx, &elem.key, &d1, nla[NFTA_SET_ELEM_KEY]); | 3358 | err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &d1, |
3359 | nla[NFTA_SET_ELEM_KEY]); | ||
3303 | if (err < 0) | 3360 | if (err < 0) |
3304 | goto err1; | 3361 | goto err1; |
3305 | err = -EINVAL; | 3362 | err = -EINVAL; |
3306 | if (d1.type != NFT_DATA_VALUE || d1.len != set->klen) | 3363 | if (d1.type != NFT_DATA_VALUE || d1.len != set->klen) |
3307 | goto err2; | 3364 | goto err2; |
3308 | 3365 | ||
3309 | nft_set_ext_add(&tmpl, NFT_SET_EXT_KEY); | 3366 | nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, d1.len); |
3310 | if (timeout > 0) { | 3367 | if (timeout > 0) { |
3311 | nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION); | 3368 | nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION); |
3312 | if (timeout != set->timeout) | 3369 | if (timeout != set->timeout) |
@@ -3314,7 +3371,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | |||
3314 | } | 3371 | } |
3315 | 3372 | ||
3316 | if (nla[NFTA_SET_ELEM_DATA] != NULL) { | 3373 | if (nla[NFTA_SET_ELEM_DATA] != NULL) { |
3317 | err = nft_data_init(ctx, &data, &d2, nla[NFTA_SET_ELEM_DATA]); | 3374 | err = nft_data_init(ctx, &data, sizeof(data), &d2, |
3375 | nla[NFTA_SET_ELEM_DATA]); | ||
3318 | if (err < 0) | 3376 | if (err < 0) |
3319 | goto err2; | 3377 | goto err2; |
3320 | 3378 | ||
@@ -3333,13 +3391,14 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | |||
3333 | if (!(binding->flags & NFT_SET_MAP)) | 3391 | if (!(binding->flags & NFT_SET_MAP)) |
3334 | continue; | 3392 | continue; |
3335 | 3393 | ||
3336 | err = nft_validate_data_load(&bind_ctx, dreg, | 3394 | err = nft_validate_register_store(&bind_ctx, dreg, |
3337 | &data, d2.type); | 3395 | &data, |
3396 | d2.type, d2.len); | ||
3338 | if (err < 0) | 3397 | if (err < 0) |
3339 | goto err3; | 3398 | goto err3; |
3340 | } | 3399 | } |
3341 | 3400 | ||
3342 | nft_set_ext_add(&tmpl, NFT_SET_EXT_DATA); | 3401 | nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, d2.len); |
3343 | } | 3402 | } |
3344 | 3403 | ||
3345 | /* The full maximum length of userdata can exceed the maximum | 3404 | /* The full maximum length of userdata can exceed the maximum |
@@ -3355,7 +3414,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | |||
3355 | } | 3414 | } |
3356 | 3415 | ||
3357 | err = -ENOMEM; | 3416 | err = -ENOMEM; |
3358 | elem.priv = nft_set_elem_init(set, &tmpl, &elem.key, &data, | 3417 | elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, data.data, |
3359 | timeout, GFP_KERNEL); | 3418 | timeout, GFP_KERNEL); |
3360 | if (elem.priv == NULL) | 3419 | if (elem.priv == NULL) |
3361 | goto err3; | 3420 | goto err3; |
@@ -3390,7 +3449,7 @@ err3: | |||
3390 | if (nla[NFTA_SET_ELEM_DATA] != NULL) | 3449 | if (nla[NFTA_SET_ELEM_DATA] != NULL) |
3391 | nft_data_uninit(&data, d2.type); | 3450 | nft_data_uninit(&data, d2.type); |
3392 | err2: | 3451 | err2: |
3393 | nft_data_uninit(&elem.key, d1.type); | 3452 | nft_data_uninit(&elem.key.val, d1.type); |
3394 | err1: | 3453 | err1: |
3395 | return err; | 3454 | return err; |
3396 | } | 3455 | } |
@@ -3457,7 +3516,8 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, | |||
3457 | if (nla[NFTA_SET_ELEM_KEY] == NULL) | 3516 | if (nla[NFTA_SET_ELEM_KEY] == NULL) |
3458 | goto err1; | 3517 | goto err1; |
3459 | 3518 | ||
3460 | err = nft_data_init(ctx, &elem.key, &desc, nla[NFTA_SET_ELEM_KEY]); | 3519 | err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc, |
3520 | nla[NFTA_SET_ELEM_KEY]); | ||
3461 | if (err < 0) | 3521 | if (err < 0) |
3462 | goto err1; | 3522 | goto err1; |
3463 | 3523 | ||
@@ -3484,7 +3544,7 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, | |||
3484 | err3: | 3544 | err3: |
3485 | kfree(trans); | 3545 | kfree(trans); |
3486 | err2: | 3546 | err2: |
3487 | nft_data_uninit(&elem.key, desc.type); | 3547 | nft_data_uninit(&elem.key.val, desc.type); |
3488 | err1: | 3548 | err1: |
3489 | return err; | 3549 | return err; |
3490 | } | 3550 | } |
@@ -4047,10 +4107,10 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx, | |||
4047 | return 0; | 4107 | return 0; |
4048 | 4108 | ||
4049 | data = nft_set_ext_data(ext); | 4109 | data = nft_set_ext_data(ext); |
4050 | switch (data->verdict) { | 4110 | switch (data->verdict.code) { |
4051 | case NFT_JUMP: | 4111 | case NFT_JUMP: |
4052 | case NFT_GOTO: | 4112 | case NFT_GOTO: |
4053 | return nf_tables_check_loops(ctx, data->chain); | 4113 | return nf_tables_check_loops(ctx, data->verdict.chain); |
4054 | default: | 4114 | default: |
4055 | return 0; | 4115 | return 0; |
4056 | } | 4116 | } |
@@ -4083,10 +4143,11 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx, | |||
4083 | if (data == NULL) | 4143 | if (data == NULL) |
4084 | continue; | 4144 | continue; |
4085 | 4145 | ||
4086 | switch (data->verdict) { | 4146 | switch (data->verdict.code) { |
4087 | case NFT_JUMP: | 4147 | case NFT_JUMP: |
4088 | case NFT_GOTO: | 4148 | case NFT_GOTO: |
4089 | err = nf_tables_check_loops(ctx, data->chain); | 4149 | err = nf_tables_check_loops(ctx, |
4150 | data->verdict.chain); | ||
4090 | if (err < 0) | 4151 | if (err < 0) |
4091 | return err; | 4152 | return err; |
4092 | default: | 4153 | default: |
@@ -4120,85 +4181,129 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx, | |||
4120 | } | 4181 | } |
4121 | 4182 | ||
4122 | /** | 4183 | /** |
4123 | * nft_validate_input_register - validate an expressions' input register | 4184 | * nft_parse_register - parse a register value from a netlink attribute |
4124 | * | 4185 | * |
4125 | * @reg: the register number | 4186 | * @attr: netlink attribute |
4126 | * | 4187 | * |
4127 | * Validate that the input register is one of the general purpose | 4188 | * Parse and translate a register value from a netlink attribute. |
4128 | * registers. | 4189 | * Registers used to be 128 bit wide, these register numbers will be |
4190 | * mapped to the corresponding 32 bit register numbers. | ||
4129 | */ | 4191 | */ |
4130 | int nft_validate_input_register(enum nft_registers reg) | 4192 | unsigned int nft_parse_register(const struct nlattr *attr) |
4131 | { | 4193 | { |
4132 | if (reg <= NFT_REG_VERDICT) | 4194 | unsigned int reg; |
4133 | return -EINVAL; | 4195 | |
4134 | if (reg > NFT_REG_MAX) | 4196 | reg = ntohl(nla_get_be32(attr)); |
4135 | return -ERANGE; | 4197 | switch (reg) { |
4136 | return 0; | 4198 | case NFT_REG_VERDICT...NFT_REG_4: |
4199 | return reg * NFT_REG_SIZE / NFT_REG32_SIZE; | ||
4200 | default: | ||
4201 | return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00; | ||
4202 | } | ||
4137 | } | 4203 | } |
4138 | EXPORT_SYMBOL_GPL(nft_validate_input_register); | 4204 | EXPORT_SYMBOL_GPL(nft_parse_register); |
4139 | 4205 | ||
4140 | /** | 4206 | /** |
4141 | * nft_validate_output_register - validate an expressions' output register | 4207 | * nft_dump_register - dump a register value to a netlink attribute |
4208 | * | ||
4209 | * @skb: socket buffer | ||
4210 | * @attr: attribute number | ||
4211 | * @reg: register number | ||
4212 | * | ||
4213 | * Construct a netlink attribute containing the register number. For | ||
4214 | * compatibility reasons, register numbers being a multiple of 4 are | ||
4215 | * translated to the corresponding 128 bit register numbers. | ||
4216 | */ | ||
4217 | int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg) | ||
4218 | { | ||
4219 | if (reg % (NFT_REG_SIZE / NFT_REG32_SIZE) == 0) | ||
4220 | reg = reg / (NFT_REG_SIZE / NFT_REG32_SIZE); | ||
4221 | else | ||
4222 | reg = reg - NFT_REG_SIZE / NFT_REG32_SIZE + NFT_REG32_00; | ||
4223 | |||
4224 | return nla_put_be32(skb, attr, htonl(reg)); | ||
4225 | } | ||
4226 | EXPORT_SYMBOL_GPL(nft_dump_register); | ||
4227 | |||
4228 | /** | ||
4229 | * nft_validate_register_load - validate a load from a register | ||
4142 | * | 4230 | * |
4143 | * @reg: the register number | 4231 | * @reg: the register number |
4232 | * @len: the length of the data | ||
4144 | * | 4233 | * |
4145 | * Validate that the output register is one of the general purpose | 4234 | * Validate that the input register is one of the general purpose |
4146 | * registers or the verdict register. | 4235 | * registers and that the length of the load is within the bounds. |
4147 | */ | 4236 | */ |
4148 | int nft_validate_output_register(enum nft_registers reg) | 4237 | int nft_validate_register_load(enum nft_registers reg, unsigned int len) |
4149 | { | 4238 | { |
4150 | if (reg < NFT_REG_VERDICT) | 4239 | if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE) |
4240 | return -EINVAL; | ||
4241 | if (len == 0) | ||
4151 | return -EINVAL; | 4242 | return -EINVAL; |
4152 | if (reg > NFT_REG_MAX) | 4243 | if (reg * NFT_REG32_SIZE + len > FIELD_SIZEOF(struct nft_regs, data)) |
4153 | return -ERANGE; | 4244 | return -ERANGE; |
4245 | |||
4154 | return 0; | 4246 | return 0; |
4155 | } | 4247 | } |
4156 | EXPORT_SYMBOL_GPL(nft_validate_output_register); | 4248 | EXPORT_SYMBOL_GPL(nft_validate_register_load); |
4157 | 4249 | ||
4158 | /** | 4250 | /** |
4159 | * nft_validate_data_load - validate an expressions' data load | 4251 | * nft_validate_register_store - validate an expressions' register store |
4160 | * | 4252 | * |
4161 | * @ctx: context of the expression performing the load | 4253 | * @ctx: context of the expression performing the load |
4162 | * @reg: the destination register number | 4254 | * @reg: the destination register number |
4163 | * @data: the data to load | 4255 | * @data: the data to load |
4164 | * @type: the data type | 4256 | * @type: the data type |
4257 | * @len: the length of the data | ||
4165 | * | 4258 | * |
4166 | * Validate that a data load uses the appropriate data type for | 4259 | * Validate that a data load uses the appropriate data type for |
4167 | * the destination register. A value of NULL for the data means | 4260 | * the destination register and the length is within the bounds. |
4168 | * that its runtime gathered data, which is always of type | 4261 | * A value of NULL for the data means that its runtime gathered |
4169 | * NFT_DATA_VALUE. | 4262 | * data. |
4170 | */ | 4263 | */ |
4171 | int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg, | 4264 | int nft_validate_register_store(const struct nft_ctx *ctx, |
4172 | const struct nft_data *data, | 4265 | enum nft_registers reg, |
4173 | enum nft_data_types type) | 4266 | const struct nft_data *data, |
4267 | enum nft_data_types type, unsigned int len) | ||
4174 | { | 4268 | { |
4175 | int err; | 4269 | int err; |
4176 | 4270 | ||
4177 | switch (reg) { | 4271 | switch (reg) { |
4178 | case NFT_REG_VERDICT: | 4272 | case NFT_REG_VERDICT: |
4179 | if (data == NULL || type != NFT_DATA_VERDICT) | 4273 | if (type != NFT_DATA_VERDICT) |
4180 | return -EINVAL; | 4274 | return -EINVAL; |
4181 | 4275 | ||
4182 | if (data->verdict == NFT_GOTO || data->verdict == NFT_JUMP) { | 4276 | if (data != NULL && |
4183 | err = nf_tables_check_loops(ctx, data->chain); | 4277 | (data->verdict.code == NFT_GOTO || |
4278 | data->verdict.code == NFT_JUMP)) { | ||
4279 | err = nf_tables_check_loops(ctx, data->verdict.chain); | ||
4184 | if (err < 0) | 4280 | if (err < 0) |
4185 | return err; | 4281 | return err; |
4186 | 4282 | ||
4187 | if (ctx->chain->level + 1 > data->chain->level) { | 4283 | if (ctx->chain->level + 1 > |
4284 | data->verdict.chain->level) { | ||
4188 | if (ctx->chain->level + 1 == NFT_JUMP_STACK_SIZE) | 4285 | if (ctx->chain->level + 1 == NFT_JUMP_STACK_SIZE) |
4189 | return -EMLINK; | 4286 | return -EMLINK; |
4190 | data->chain->level = ctx->chain->level + 1; | 4287 | data->verdict.chain->level = ctx->chain->level + 1; |
4191 | } | 4288 | } |
4192 | } | 4289 | } |
4193 | 4290 | ||
4194 | return 0; | 4291 | return 0; |
4195 | default: | 4292 | default: |
4293 | if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE) | ||
4294 | return -EINVAL; | ||
4295 | if (len == 0) | ||
4296 | return -EINVAL; | ||
4297 | if (reg * NFT_REG32_SIZE + len > | ||
4298 | FIELD_SIZEOF(struct nft_regs, data)) | ||
4299 | return -ERANGE; | ||
4300 | |||
4196 | if (data != NULL && type != NFT_DATA_VALUE) | 4301 | if (data != NULL && type != NFT_DATA_VALUE) |
4197 | return -EINVAL; | 4302 | return -EINVAL; |
4198 | return 0; | 4303 | return 0; |
4199 | } | 4304 | } |
4200 | } | 4305 | } |
4201 | EXPORT_SYMBOL_GPL(nft_validate_data_load); | 4306 | EXPORT_SYMBOL_GPL(nft_validate_register_store); |
4202 | 4307 | ||
4203 | static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = { | 4308 | static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = { |
4204 | [NFTA_VERDICT_CODE] = { .type = NLA_U32 }, | 4309 | [NFTA_VERDICT_CODE] = { .type = NLA_U32 }, |
@@ -4219,11 +4324,11 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
4219 | 4324 | ||
4220 | if (!tb[NFTA_VERDICT_CODE]) | 4325 | if (!tb[NFTA_VERDICT_CODE]) |
4221 | return -EINVAL; | 4326 | return -EINVAL; |
4222 | data->verdict = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE])); | 4327 | data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE])); |
4223 | 4328 | ||
4224 | switch (data->verdict) { | 4329 | switch (data->verdict.code) { |
4225 | default: | 4330 | default: |
4226 | switch (data->verdict & NF_VERDICT_MASK) { | 4331 | switch (data->verdict.code & NF_VERDICT_MASK) { |
4227 | case NF_ACCEPT: | 4332 | case NF_ACCEPT: |
4228 | case NF_DROP: | 4333 | case NF_DROP: |
4229 | case NF_QUEUE: | 4334 | case NF_QUEUE: |
@@ -4249,7 +4354,7 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
4249 | return -EOPNOTSUPP; | 4354 | return -EOPNOTSUPP; |
4250 | 4355 | ||
4251 | chain->use++; | 4356 | chain->use++; |
4252 | data->chain = chain; | 4357 | data->verdict.chain = chain; |
4253 | desc->len = sizeof(data); | 4358 | desc->len = sizeof(data); |
4254 | break; | 4359 | break; |
4255 | } | 4360 | } |
@@ -4260,10 +4365,10 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
4260 | 4365 | ||
4261 | static void nft_verdict_uninit(const struct nft_data *data) | 4366 | static void nft_verdict_uninit(const struct nft_data *data) |
4262 | { | 4367 | { |
4263 | switch (data->verdict) { | 4368 | switch (data->verdict.code) { |
4264 | case NFT_JUMP: | 4369 | case NFT_JUMP: |
4265 | case NFT_GOTO: | 4370 | case NFT_GOTO: |
4266 | data->chain->use--; | 4371 | data->verdict.chain->use--; |
4267 | break; | 4372 | break; |
4268 | } | 4373 | } |
4269 | } | 4374 | } |
@@ -4276,13 +4381,14 @@ static int nft_verdict_dump(struct sk_buff *skb, const struct nft_data *data) | |||
4276 | if (!nest) | 4381 | if (!nest) |
4277 | goto nla_put_failure; | 4382 | goto nla_put_failure; |
4278 | 4383 | ||
4279 | if (nla_put_be32(skb, NFTA_VERDICT_CODE, htonl(data->verdict))) | 4384 | if (nla_put_be32(skb, NFTA_VERDICT_CODE, htonl(data->verdict.code))) |
4280 | goto nla_put_failure; | 4385 | goto nla_put_failure; |
4281 | 4386 | ||
4282 | switch (data->verdict) { | 4387 | switch (data->verdict.code) { |
4283 | case NFT_JUMP: | 4388 | case NFT_JUMP: |
4284 | case NFT_GOTO: | 4389 | case NFT_GOTO: |
4285 | if (nla_put_string(skb, NFTA_VERDICT_CHAIN, data->chain->name)) | 4390 | if (nla_put_string(skb, NFTA_VERDICT_CHAIN, |
4391 | data->verdict.chain->name)) | ||
4286 | goto nla_put_failure; | 4392 | goto nla_put_failure; |
4287 | } | 4393 | } |
4288 | nla_nest_end(skb, nest); | 4394 | nla_nest_end(skb, nest); |
@@ -4292,7 +4398,8 @@ nla_put_failure: | |||
4292 | return -1; | 4398 | return -1; |
4293 | } | 4399 | } |
4294 | 4400 | ||
4295 | static int nft_value_init(const struct nft_ctx *ctx, struct nft_data *data, | 4401 | static int nft_value_init(const struct nft_ctx *ctx, |
4402 | struct nft_data *data, unsigned int size, | ||
4296 | struct nft_data_desc *desc, const struct nlattr *nla) | 4403 | struct nft_data_desc *desc, const struct nlattr *nla) |
4297 | { | 4404 | { |
4298 | unsigned int len; | 4405 | unsigned int len; |
@@ -4300,10 +4407,10 @@ static int nft_value_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
4300 | len = nla_len(nla); | 4407 | len = nla_len(nla); |
4301 | if (len == 0) | 4408 | if (len == 0) |
4302 | return -EINVAL; | 4409 | return -EINVAL; |
4303 | if (len > sizeof(data->data)) | 4410 | if (len > size) |
4304 | return -EOVERFLOW; | 4411 | return -EOVERFLOW; |
4305 | 4412 | ||
4306 | nla_memcpy(data->data, nla, sizeof(data->data)); | 4413 | nla_memcpy(data->data, nla, len); |
4307 | desc->type = NFT_DATA_VALUE; | 4414 | desc->type = NFT_DATA_VALUE; |
4308 | desc->len = len; | 4415 | desc->len = len; |
4309 | return 0; | 4416 | return 0; |
@@ -4316,8 +4423,7 @@ static int nft_value_dump(struct sk_buff *skb, const struct nft_data *data, | |||
4316 | } | 4423 | } |
4317 | 4424 | ||
4318 | static const struct nla_policy nft_data_policy[NFTA_DATA_MAX + 1] = { | 4425 | static const struct nla_policy nft_data_policy[NFTA_DATA_MAX + 1] = { |
4319 | [NFTA_DATA_VALUE] = { .type = NLA_BINARY, | 4426 | [NFTA_DATA_VALUE] = { .type = NLA_BINARY }, |
4320 | .len = FIELD_SIZEOF(struct nft_data, data) }, | ||
4321 | [NFTA_DATA_VERDICT] = { .type = NLA_NESTED }, | 4427 | [NFTA_DATA_VERDICT] = { .type = NLA_NESTED }, |
4322 | }; | 4428 | }; |
4323 | 4429 | ||
@@ -4326,6 +4432,7 @@ static const struct nla_policy nft_data_policy[NFTA_DATA_MAX + 1] = { | |||
4326 | * | 4432 | * |
4327 | * @ctx: context of the expression using the data | 4433 | * @ctx: context of the expression using the data |
4328 | * @data: destination struct nft_data | 4434 | * @data: destination struct nft_data |
4435 | * @size: maximum data length | ||
4329 | * @desc: data description | 4436 | * @desc: data description |
4330 | * @nla: netlink attribute containing data | 4437 | * @nla: netlink attribute containing data |
4331 | * | 4438 | * |
@@ -4335,7 +4442,8 @@ static const struct nla_policy nft_data_policy[NFTA_DATA_MAX + 1] = { | |||
4335 | * The caller can indicate that it only wants to accept data of type | 4442 | * The caller can indicate that it only wants to accept data of type |
4336 | * NFT_DATA_VALUE by passing NULL for the ctx argument. | 4443 | * NFT_DATA_VALUE by passing NULL for the ctx argument. |
4337 | */ | 4444 | */ |
4338 | int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data, | 4445 | int nft_data_init(const struct nft_ctx *ctx, |
4446 | struct nft_data *data, unsigned int size, | ||
4339 | struct nft_data_desc *desc, const struct nlattr *nla) | 4447 | struct nft_data_desc *desc, const struct nlattr *nla) |
4340 | { | 4448 | { |
4341 | struct nlattr *tb[NFTA_DATA_MAX + 1]; | 4449 | struct nlattr *tb[NFTA_DATA_MAX + 1]; |
@@ -4346,7 +4454,8 @@ int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
4346 | return err; | 4454 | return err; |
4347 | 4455 | ||
4348 | if (tb[NFTA_DATA_VALUE]) | 4456 | if (tb[NFTA_DATA_VALUE]) |
4349 | return nft_value_init(ctx, data, desc, tb[NFTA_DATA_VALUE]); | 4457 | return nft_value_init(ctx, data, size, desc, |
4458 | tb[NFTA_DATA_VALUE]); | ||
4350 | if (tb[NFTA_DATA_VERDICT] && ctx != NULL) | 4459 | if (tb[NFTA_DATA_VERDICT] && ctx != NULL) |
4351 | return nft_verdict_init(ctx, data, desc, tb[NFTA_DATA_VERDICT]); | 4460 | return nft_verdict_init(ctx, data, desc, tb[NFTA_DATA_VERDICT]); |
4352 | return -EINVAL; | 4461 | return -EINVAL; |
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 7caf08a9225d..f153b07073af 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
@@ -65,23 +65,23 @@ static inline void nft_trace_packet(const struct nft_pktinfo *pkt, | |||
65 | } | 65 | } |
66 | 66 | ||
67 | static void nft_cmp_fast_eval(const struct nft_expr *expr, | 67 | static void nft_cmp_fast_eval(const struct nft_expr *expr, |
68 | struct nft_data data[NFT_REG_MAX + 1]) | 68 | struct nft_regs *regs) |
69 | { | 69 | { |
70 | const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); | 70 | const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); |
71 | u32 mask = nft_cmp_fast_mask(priv->len); | 71 | u32 mask = nft_cmp_fast_mask(priv->len); |
72 | 72 | ||
73 | if ((data[priv->sreg].data[0] & mask) == priv->data) | 73 | if ((regs->data[priv->sreg] & mask) == priv->data) |
74 | return; | 74 | return; |
75 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 75 | regs->verdict.code = NFT_BREAK; |
76 | } | 76 | } |
77 | 77 | ||
78 | static bool nft_payload_fast_eval(const struct nft_expr *expr, | 78 | static bool nft_payload_fast_eval(const struct nft_expr *expr, |
79 | struct nft_data data[NFT_REG_MAX + 1], | 79 | struct nft_regs *regs, |
80 | const struct nft_pktinfo *pkt) | 80 | const struct nft_pktinfo *pkt) |
81 | { | 81 | { |
82 | const struct nft_payload *priv = nft_expr_priv(expr); | 82 | const struct nft_payload *priv = nft_expr_priv(expr); |
83 | const struct sk_buff *skb = pkt->skb; | 83 | const struct sk_buff *skb = pkt->skb; |
84 | struct nft_data *dest = &data[priv->dreg]; | 84 | u32 *dest = ®s->data[priv->dreg]; |
85 | unsigned char *ptr; | 85 | unsigned char *ptr; |
86 | 86 | ||
87 | if (priv->base == NFT_PAYLOAD_NETWORK_HEADER) | 87 | if (priv->base == NFT_PAYLOAD_NETWORK_HEADER) |
@@ -94,12 +94,13 @@ static bool nft_payload_fast_eval(const struct nft_expr *expr, | |||
94 | if (unlikely(ptr + priv->len >= skb_tail_pointer(skb))) | 94 | if (unlikely(ptr + priv->len >= skb_tail_pointer(skb))) |
95 | return false; | 95 | return false; |
96 | 96 | ||
97 | *dest = 0; | ||
97 | if (priv->len == 2) | 98 | if (priv->len == 2) |
98 | *(u16 *)dest->data = *(u16 *)ptr; | 99 | *(u16 *)dest = *(u16 *)ptr; |
99 | else if (priv->len == 4) | 100 | else if (priv->len == 4) |
100 | *(u32 *)dest->data = *(u32 *)ptr; | 101 | *(u32 *)dest = *(u32 *)ptr; |
101 | else | 102 | else |
102 | *(u8 *)dest->data = *(u8 *)ptr; | 103 | *(u8 *)dest = *(u8 *)ptr; |
103 | return true; | 104 | return true; |
104 | } | 105 | } |
105 | 106 | ||
@@ -116,7 +117,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) | |||
116 | const struct net *net = read_pnet(&nft_base_chain(basechain)->pnet); | 117 | const struct net *net = read_pnet(&nft_base_chain(basechain)->pnet); |
117 | const struct nft_rule *rule; | 118 | const struct nft_rule *rule; |
118 | const struct nft_expr *expr, *last; | 119 | const struct nft_expr *expr, *last; |
119 | struct nft_data data[NFT_REG_MAX + 1]; | 120 | struct nft_regs regs; |
120 | unsigned int stackptr = 0; | 121 | unsigned int stackptr = 0; |
121 | struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; | 122 | struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; |
122 | struct nft_stats *stats; | 123 | struct nft_stats *stats; |
@@ -127,7 +128,7 @@ do_chain: | |||
127 | rulenum = 0; | 128 | rulenum = 0; |
128 | rule = list_entry(&chain->rules, struct nft_rule, list); | 129 | rule = list_entry(&chain->rules, struct nft_rule, list); |
129 | next_rule: | 130 | next_rule: |
130 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 131 | regs.verdict.code = NFT_CONTINUE; |
131 | list_for_each_entry_continue_rcu(rule, &chain->rules, list) { | 132 | list_for_each_entry_continue_rcu(rule, &chain->rules, list) { |
132 | 133 | ||
133 | /* This rule is not active, skip. */ | 134 | /* This rule is not active, skip. */ |
@@ -138,18 +139,18 @@ next_rule: | |||
138 | 139 | ||
139 | nft_rule_for_each_expr(expr, last, rule) { | 140 | nft_rule_for_each_expr(expr, last, rule) { |
140 | if (expr->ops == &nft_cmp_fast_ops) | 141 | if (expr->ops == &nft_cmp_fast_ops) |
141 | nft_cmp_fast_eval(expr, data); | 142 | nft_cmp_fast_eval(expr, ®s); |
142 | else if (expr->ops != &nft_payload_fast_ops || | 143 | else if (expr->ops != &nft_payload_fast_ops || |
143 | !nft_payload_fast_eval(expr, data, pkt)) | 144 | !nft_payload_fast_eval(expr, ®s, pkt)) |
144 | expr->ops->eval(expr, data, pkt); | 145 | expr->ops->eval(expr, ®s, pkt); |
145 | 146 | ||
146 | if (data[NFT_REG_VERDICT].verdict != NFT_CONTINUE) | 147 | if (regs.verdict.code != NFT_CONTINUE) |
147 | break; | 148 | break; |
148 | } | 149 | } |
149 | 150 | ||
150 | switch (data[NFT_REG_VERDICT].verdict) { | 151 | switch (regs.verdict.code) { |
151 | case NFT_BREAK: | 152 | case NFT_BREAK: |
152 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 153 | regs.verdict.code = NFT_CONTINUE; |
153 | continue; | 154 | continue; |
154 | case NFT_CONTINUE: | 155 | case NFT_CONTINUE: |
155 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | 156 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); |
@@ -158,15 +159,15 @@ next_rule: | |||
158 | break; | 159 | break; |
159 | } | 160 | } |
160 | 161 | ||
161 | switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) { | 162 | switch (regs.verdict.code & NF_VERDICT_MASK) { |
162 | case NF_ACCEPT: | 163 | case NF_ACCEPT: |
163 | case NF_DROP: | 164 | case NF_DROP: |
164 | case NF_QUEUE: | 165 | case NF_QUEUE: |
165 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | 166 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); |
166 | return data[NFT_REG_VERDICT].verdict; | 167 | return regs.verdict.code; |
167 | } | 168 | } |
168 | 169 | ||
169 | switch (data[NFT_REG_VERDICT].verdict) { | 170 | switch (regs.verdict.code) { |
170 | case NFT_JUMP: | 171 | case NFT_JUMP: |
171 | BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE); | 172 | BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE); |
172 | jumpstack[stackptr].chain = chain; | 173 | jumpstack[stackptr].chain = chain; |
@@ -177,7 +178,7 @@ next_rule: | |||
177 | case NFT_GOTO: | 178 | case NFT_GOTO: |
178 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | 179 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); |
179 | 180 | ||
180 | chain = data[NFT_REG_VERDICT].chain; | 181 | chain = regs.verdict.chain; |
181 | goto do_chain; | 182 | goto do_chain; |
182 | case NFT_CONTINUE: | 183 | case NFT_CONTINUE: |
183 | rulenum++; | 184 | rulenum++; |
diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index 4fb6ee2c1106..d71cc18fa35d 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c | |||
@@ -26,18 +26,16 @@ struct nft_bitwise { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | static void nft_bitwise_eval(const struct nft_expr *expr, | 28 | static void nft_bitwise_eval(const struct nft_expr *expr, |
29 | struct nft_data data[NFT_REG_MAX + 1], | 29 | struct nft_regs *regs, |
30 | const struct nft_pktinfo *pkt) | 30 | const struct nft_pktinfo *pkt) |
31 | { | 31 | { |
32 | const struct nft_bitwise *priv = nft_expr_priv(expr); | 32 | const struct nft_bitwise *priv = nft_expr_priv(expr); |
33 | const struct nft_data *src = &data[priv->sreg]; | 33 | const u32 *src = ®s->data[priv->sreg]; |
34 | struct nft_data *dst = &data[priv->dreg]; | 34 | u32 *dst = ®s->data[priv->dreg]; |
35 | unsigned int i; | 35 | unsigned int i; |
36 | 36 | ||
37 | for (i = 0; i < DIV_ROUND_UP(priv->len, 4); i++) { | 37 | for (i = 0; i < DIV_ROUND_UP(priv->len, 4); i++) |
38 | dst->data[i] = (src->data[i] & priv->mask.data[i]) ^ | 38 | dst[i] = (src[i] & priv->mask.data[i]) ^ priv->xor.data[i]; |
39 | priv->xor.data[i]; | ||
40 | } | ||
41 | } | 39 | } |
42 | 40 | ||
43 | static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = { | 41 | static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = { |
@@ -63,28 +61,27 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, | |||
63 | tb[NFTA_BITWISE_XOR] == NULL) | 61 | tb[NFTA_BITWISE_XOR] == NULL) |
64 | return -EINVAL; | 62 | return -EINVAL; |
65 | 63 | ||
66 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_SREG])); | 64 | priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN])); |
67 | err = nft_validate_input_register(priv->sreg); | 65 | priv->sreg = nft_parse_register(tb[NFTA_BITWISE_SREG]); |
66 | err = nft_validate_register_load(priv->sreg, priv->len); | ||
68 | if (err < 0) | 67 | if (err < 0) |
69 | return err; | 68 | return err; |
70 | 69 | ||
71 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_DREG])); | 70 | priv->dreg = nft_parse_register(tb[NFTA_BITWISE_DREG]); |
72 | err = nft_validate_output_register(priv->dreg); | 71 | err = nft_validate_register_store(ctx, priv->dreg, NULL, |
72 | NFT_DATA_VALUE, priv->len); | ||
73 | if (err < 0) | 73 | if (err < 0) |
74 | return err; | 74 | return err; |
75 | err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); | ||
76 | if (err < 0) | ||
77 | return err; | ||
78 | |||
79 | priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN])); | ||
80 | 75 | ||
81 | err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]); | 76 | err = nft_data_init(NULL, &priv->mask, sizeof(priv->mask), &d1, |
77 | tb[NFTA_BITWISE_MASK]); | ||
82 | if (err < 0) | 78 | if (err < 0) |
83 | return err; | 79 | return err; |
84 | if (d1.len != priv->len) | 80 | if (d1.len != priv->len) |
85 | return -EINVAL; | 81 | return -EINVAL; |
86 | 82 | ||
87 | err = nft_data_init(NULL, &priv->xor, &d2, tb[NFTA_BITWISE_XOR]); | 83 | err = nft_data_init(NULL, &priv->xor, sizeof(priv->xor), &d2, |
84 | tb[NFTA_BITWISE_XOR]); | ||
88 | if (err < 0) | 85 | if (err < 0) |
89 | return err; | 86 | return err; |
90 | if (d2.len != priv->len) | 87 | if (d2.len != priv->len) |
@@ -97,9 +94,9 @@ static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
97 | { | 94 | { |
98 | const struct nft_bitwise *priv = nft_expr_priv(expr); | 95 | const struct nft_bitwise *priv = nft_expr_priv(expr); |
99 | 96 | ||
100 | if (nla_put_be32(skb, NFTA_BITWISE_SREG, htonl(priv->sreg))) | 97 | if (nft_dump_register(skb, NFTA_BITWISE_SREG, priv->sreg)) |
101 | goto nla_put_failure; | 98 | goto nla_put_failure; |
102 | if (nla_put_be32(skb, NFTA_BITWISE_DREG, htonl(priv->dreg))) | 99 | if (nft_dump_register(skb, NFTA_BITWISE_DREG, priv->dreg)) |
103 | goto nla_put_failure; | 100 | goto nla_put_failure; |
104 | if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(priv->len))) | 101 | if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(priv->len))) |
105 | goto nla_put_failure; | 102 | goto nla_put_failure; |
diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c index c39ed8d29df1..fde5145f2e36 100644 --- a/net/netfilter/nft_byteorder.c +++ b/net/netfilter/nft_byteorder.c | |||
@@ -26,16 +26,17 @@ struct nft_byteorder { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | static void nft_byteorder_eval(const struct nft_expr *expr, | 28 | static void nft_byteorder_eval(const struct nft_expr *expr, |
29 | struct nft_data data[NFT_REG_MAX + 1], | 29 | struct nft_regs *regs, |
30 | const struct nft_pktinfo *pkt) | 30 | const struct nft_pktinfo *pkt) |
31 | { | 31 | { |
32 | const struct nft_byteorder *priv = nft_expr_priv(expr); | 32 | const struct nft_byteorder *priv = nft_expr_priv(expr); |
33 | struct nft_data *src = &data[priv->sreg], *dst = &data[priv->dreg]; | 33 | u32 *src = ®s->data[priv->sreg]; |
34 | u32 *dst = ®s->data[priv->dreg]; | ||
34 | union { u32 u32; u16 u16; } *s, *d; | 35 | union { u32 u32; u16 u16; } *s, *d; |
35 | unsigned int i; | 36 | unsigned int i; |
36 | 37 | ||
37 | s = (void *)src->data; | 38 | s = (void *)src; |
38 | d = (void *)dst->data; | 39 | d = (void *)dst; |
39 | 40 | ||
40 | switch (priv->size) { | 41 | switch (priv->size) { |
41 | case 4: | 42 | case 4: |
@@ -87,19 +88,6 @@ static int nft_byteorder_init(const struct nft_ctx *ctx, | |||
87 | tb[NFTA_BYTEORDER_OP] == NULL) | 88 | tb[NFTA_BYTEORDER_OP] == NULL) |
88 | return -EINVAL; | 89 | return -EINVAL; |
89 | 90 | ||
90 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SREG])); | ||
91 | err = nft_validate_input_register(priv->sreg); | ||
92 | if (err < 0) | ||
93 | return err; | ||
94 | |||
95 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_DREG])); | ||
96 | err = nft_validate_output_register(priv->dreg); | ||
97 | if (err < 0) | ||
98 | return err; | ||
99 | err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); | ||
100 | if (err < 0) | ||
101 | return err; | ||
102 | |||
103 | priv->op = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_OP])); | 91 | priv->op = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_OP])); |
104 | switch (priv->op) { | 92 | switch (priv->op) { |
105 | case NFT_BYTEORDER_NTOH: | 93 | case NFT_BYTEORDER_NTOH: |
@@ -109,10 +97,6 @@ static int nft_byteorder_init(const struct nft_ctx *ctx, | |||
109 | return -EINVAL; | 97 | return -EINVAL; |
110 | } | 98 | } |
111 | 99 | ||
112 | priv->len = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_LEN])); | ||
113 | if (priv->len == 0 || priv->len > FIELD_SIZEOF(struct nft_data, data)) | ||
114 | return -EINVAL; | ||
115 | |||
116 | priv->size = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SIZE])); | 100 | priv->size = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SIZE])); |
117 | switch (priv->size) { | 101 | switch (priv->size) { |
118 | case 2: | 102 | case 2: |
@@ -122,16 +106,24 @@ static int nft_byteorder_init(const struct nft_ctx *ctx, | |||
122 | return -EINVAL; | 106 | return -EINVAL; |
123 | } | 107 | } |
124 | 108 | ||
125 | return 0; | 109 | priv->sreg = nft_parse_register(tb[NFTA_BYTEORDER_SREG]); |
110 | priv->len = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_LEN])); | ||
111 | err = nft_validate_register_load(priv->sreg, priv->len); | ||
112 | if (err < 0) | ||
113 | return err; | ||
114 | |||
115 | priv->dreg = nft_parse_register(tb[NFTA_BYTEORDER_DREG]); | ||
116 | return nft_validate_register_store(ctx, priv->dreg, NULL, | ||
117 | NFT_DATA_VALUE, priv->len); | ||
126 | } | 118 | } |
127 | 119 | ||
128 | static int nft_byteorder_dump(struct sk_buff *skb, const struct nft_expr *expr) | 120 | static int nft_byteorder_dump(struct sk_buff *skb, const struct nft_expr *expr) |
129 | { | 121 | { |
130 | const struct nft_byteorder *priv = nft_expr_priv(expr); | 122 | const struct nft_byteorder *priv = nft_expr_priv(expr); |
131 | 123 | ||
132 | if (nla_put_be32(skb, NFTA_BYTEORDER_SREG, htonl(priv->sreg))) | 124 | if (nft_dump_register(skb, NFTA_BYTEORDER_SREG, priv->sreg)) |
133 | goto nla_put_failure; | 125 | goto nla_put_failure; |
134 | if (nla_put_be32(skb, NFTA_BYTEORDER_DREG, htonl(priv->dreg))) | 126 | if (nft_dump_register(skb, NFTA_BYTEORDER_DREG, priv->dreg)) |
135 | goto nla_put_failure; | 127 | goto nla_put_failure; |
136 | if (nla_put_be32(skb, NFTA_BYTEORDER_OP, htonl(priv->op))) | 128 | if (nla_put_be32(skb, NFTA_BYTEORDER_OP, htonl(priv->op))) |
137 | goto nla_put_failure; | 129 | goto nla_put_failure; |
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c index e2b3f51c81f1..e25b35d70e4d 100644 --- a/net/netfilter/nft_cmp.c +++ b/net/netfilter/nft_cmp.c | |||
@@ -25,13 +25,13 @@ struct nft_cmp_expr { | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | static void nft_cmp_eval(const struct nft_expr *expr, | 27 | static void nft_cmp_eval(const struct nft_expr *expr, |
28 | struct nft_data data[NFT_REG_MAX + 1], | 28 | struct nft_regs *regs, |
29 | const struct nft_pktinfo *pkt) | 29 | const struct nft_pktinfo *pkt) |
30 | { | 30 | { |
31 | const struct nft_cmp_expr *priv = nft_expr_priv(expr); | 31 | const struct nft_cmp_expr *priv = nft_expr_priv(expr); |
32 | int d; | 32 | int d; |
33 | 33 | ||
34 | d = nft_data_cmp(&data[priv->sreg], &priv->data, priv->len); | 34 | d = memcmp(®s->data[priv->sreg], &priv->data, priv->len); |
35 | switch (priv->op) { | 35 | switch (priv->op) { |
36 | case NFT_CMP_EQ: | 36 | case NFT_CMP_EQ: |
37 | if (d != 0) | 37 | if (d != 0) |
@@ -59,7 +59,7 @@ static void nft_cmp_eval(const struct nft_expr *expr, | |||
59 | return; | 59 | return; |
60 | 60 | ||
61 | mismatch: | 61 | mismatch: |
62 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 62 | regs->verdict.code = NFT_BREAK; |
63 | } | 63 | } |
64 | 64 | ||
65 | static const struct nla_policy nft_cmp_policy[NFTA_CMP_MAX + 1] = { | 65 | static const struct nla_policy nft_cmp_policy[NFTA_CMP_MAX + 1] = { |
@@ -75,12 +75,16 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
75 | struct nft_data_desc desc; | 75 | struct nft_data_desc desc; |
76 | int err; | 76 | int err; |
77 | 77 | ||
78 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG])); | 78 | err = nft_data_init(NULL, &priv->data, sizeof(priv->data), &desc, |
79 | priv->op = ntohl(nla_get_be32(tb[NFTA_CMP_OP])); | 79 | tb[NFTA_CMP_DATA]); |
80 | |||
81 | err = nft_data_init(NULL, &priv->data, &desc, tb[NFTA_CMP_DATA]); | ||
82 | BUG_ON(err < 0); | 80 | BUG_ON(err < 0); |
83 | 81 | ||
82 | priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); | ||
83 | err = nft_validate_register_load(priv->sreg, desc.len); | ||
84 | if (err < 0) | ||
85 | return err; | ||
86 | |||
87 | priv->op = ntohl(nla_get_be32(tb[NFTA_CMP_OP])); | ||
84 | priv->len = desc.len; | 88 | priv->len = desc.len; |
85 | return 0; | 89 | return 0; |
86 | } | 90 | } |
@@ -89,7 +93,7 @@ static int nft_cmp_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
89 | { | 93 | { |
90 | const struct nft_cmp_expr *priv = nft_expr_priv(expr); | 94 | const struct nft_cmp_expr *priv = nft_expr_priv(expr); |
91 | 95 | ||
92 | if (nla_put_be32(skb, NFTA_CMP_SREG, htonl(priv->sreg))) | 96 | if (nft_dump_register(skb, NFTA_CMP_SREG, priv->sreg)) |
93 | goto nla_put_failure; | 97 | goto nla_put_failure; |
94 | if (nla_put_be32(skb, NFTA_CMP_OP, htonl(priv->op))) | 98 | if (nla_put_be32(skb, NFTA_CMP_OP, htonl(priv->op))) |
95 | goto nla_put_failure; | 99 | goto nla_put_failure; |
@@ -122,13 +126,18 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx, | |||
122 | u32 mask; | 126 | u32 mask; |
123 | int err; | 127 | int err; |
124 | 128 | ||
125 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG])); | 129 | err = nft_data_init(NULL, &data, sizeof(data), &desc, |
126 | 130 | tb[NFTA_CMP_DATA]); | |
127 | err = nft_data_init(NULL, &data, &desc, tb[NFTA_CMP_DATA]); | ||
128 | BUG_ON(err < 0); | 131 | BUG_ON(err < 0); |
129 | desc.len *= BITS_PER_BYTE; | ||
130 | 132 | ||
133 | priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); | ||
134 | err = nft_validate_register_load(priv->sreg, desc.len); | ||
135 | if (err < 0) | ||
136 | return err; | ||
137 | |||
138 | desc.len *= BITS_PER_BYTE; | ||
131 | mask = nft_cmp_fast_mask(desc.len); | 139 | mask = nft_cmp_fast_mask(desc.len); |
140 | |||
132 | priv->data = data.data[0] & mask; | 141 | priv->data = data.data[0] & mask; |
133 | priv->len = desc.len; | 142 | priv->len = desc.len; |
134 | return 0; | 143 | return 0; |
@@ -139,7 +148,7 @@ static int nft_cmp_fast_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
139 | const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); | 148 | const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); |
140 | struct nft_data data; | 149 | struct nft_data data; |
141 | 150 | ||
142 | if (nla_put_be32(skb, NFTA_CMP_SREG, htonl(priv->sreg))) | 151 | if (nft_dump_register(skb, NFTA_CMP_SREG, priv->sreg)) |
143 | goto nla_put_failure; | 152 | goto nla_put_failure; |
144 | if (nla_put_be32(skb, NFTA_CMP_OP, htonl(NFT_CMP_EQ))) | 153 | if (nla_put_be32(skb, NFTA_CMP_OP, htonl(NFT_CMP_EQ))) |
145 | goto nla_put_failure; | 154 | goto nla_put_failure; |
@@ -167,7 +176,6 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) | |||
167 | { | 176 | { |
168 | struct nft_data_desc desc; | 177 | struct nft_data_desc desc; |
169 | struct nft_data data; | 178 | struct nft_data data; |
170 | enum nft_registers sreg; | ||
171 | enum nft_cmp_ops op; | 179 | enum nft_cmp_ops op; |
172 | int err; | 180 | int err; |
173 | 181 | ||
@@ -176,11 +184,6 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) | |||
176 | tb[NFTA_CMP_DATA] == NULL) | 184 | tb[NFTA_CMP_DATA] == NULL) |
177 | return ERR_PTR(-EINVAL); | 185 | return ERR_PTR(-EINVAL); |
178 | 186 | ||
179 | sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG])); | ||
180 | err = nft_validate_input_register(sreg); | ||
181 | if (err < 0) | ||
182 | return ERR_PTR(err); | ||
183 | |||
184 | op = ntohl(nla_get_be32(tb[NFTA_CMP_OP])); | 187 | op = ntohl(nla_get_be32(tb[NFTA_CMP_OP])); |
185 | switch (op) { | 188 | switch (op) { |
186 | case NFT_CMP_EQ: | 189 | case NFT_CMP_EQ: |
@@ -194,7 +197,8 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) | |||
194 | return ERR_PTR(-EINVAL); | 197 | return ERR_PTR(-EINVAL); |
195 | } | 198 | } |
196 | 199 | ||
197 | err = nft_data_init(NULL, &data, &desc, tb[NFTA_CMP_DATA]); | 200 | err = nft_data_init(NULL, &data, sizeof(data), &desc, |
201 | tb[NFTA_CMP_DATA]); | ||
198 | if (err < 0) | 202 | if (err < 0) |
199 | return ERR_PTR(err); | 203 | return ERR_PTR(err); |
200 | 204 | ||
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 0d137c1ac889..7f29cfc76349 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
@@ -55,7 +55,7 @@ nft_compat_set_par(struct xt_action_param *par, void *xt, const void *xt_info) | |||
55 | } | 55 | } |
56 | 56 | ||
57 | static void nft_target_eval_xt(const struct nft_expr *expr, | 57 | static void nft_target_eval_xt(const struct nft_expr *expr, |
58 | struct nft_data data[NFT_REG_MAX + 1], | 58 | struct nft_regs *regs, |
59 | const struct nft_pktinfo *pkt) | 59 | const struct nft_pktinfo *pkt) |
60 | { | 60 | { |
61 | void *info = nft_expr_priv(expr); | 61 | void *info = nft_expr_priv(expr); |
@@ -72,16 +72,16 @@ static void nft_target_eval_xt(const struct nft_expr *expr, | |||
72 | 72 | ||
73 | switch (ret) { | 73 | switch (ret) { |
74 | case XT_CONTINUE: | 74 | case XT_CONTINUE: |
75 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 75 | regs->verdict.code = NFT_CONTINUE; |
76 | break; | 76 | break; |
77 | default: | 77 | default: |
78 | data[NFT_REG_VERDICT].verdict = ret; | 78 | regs->verdict.code = ret; |
79 | break; | 79 | break; |
80 | } | 80 | } |
81 | } | 81 | } |
82 | 82 | ||
83 | static void nft_target_eval_bridge(const struct nft_expr *expr, | 83 | static void nft_target_eval_bridge(const struct nft_expr *expr, |
84 | struct nft_data data[NFT_REG_MAX + 1], | 84 | struct nft_regs *regs, |
85 | const struct nft_pktinfo *pkt) | 85 | const struct nft_pktinfo *pkt) |
86 | { | 86 | { |
87 | void *info = nft_expr_priv(expr); | 87 | void *info = nft_expr_priv(expr); |
@@ -98,19 +98,19 @@ static void nft_target_eval_bridge(const struct nft_expr *expr, | |||
98 | 98 | ||
99 | switch (ret) { | 99 | switch (ret) { |
100 | case EBT_ACCEPT: | 100 | case EBT_ACCEPT: |
101 | data[NFT_REG_VERDICT].verdict = NF_ACCEPT; | 101 | regs->verdict.code = NF_ACCEPT; |
102 | break; | 102 | break; |
103 | case EBT_DROP: | 103 | case EBT_DROP: |
104 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 104 | regs->verdict.code = NF_DROP; |
105 | break; | 105 | break; |
106 | case EBT_CONTINUE: | 106 | case EBT_CONTINUE: |
107 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 107 | regs->verdict.code = NFT_CONTINUE; |
108 | break; | 108 | break; |
109 | case EBT_RETURN: | 109 | case EBT_RETURN: |
110 | data[NFT_REG_VERDICT].verdict = NFT_RETURN; | 110 | regs->verdict.code = NFT_RETURN; |
111 | break; | 111 | break; |
112 | default: | 112 | default: |
113 | data[NFT_REG_VERDICT].verdict = ret; | 113 | regs->verdict.code = ret; |
114 | break; | 114 | break; |
115 | } | 115 | } |
116 | } | 116 | } |
@@ -304,7 +304,7 @@ static int nft_target_validate(const struct nft_ctx *ctx, | |||
304 | } | 304 | } |
305 | 305 | ||
306 | static void nft_match_eval(const struct nft_expr *expr, | 306 | static void nft_match_eval(const struct nft_expr *expr, |
307 | struct nft_data data[NFT_REG_MAX + 1], | 307 | struct nft_regs *regs, |
308 | const struct nft_pktinfo *pkt) | 308 | const struct nft_pktinfo *pkt) |
309 | { | 309 | { |
310 | void *info = nft_expr_priv(expr); | 310 | void *info = nft_expr_priv(expr); |
@@ -317,16 +317,16 @@ static void nft_match_eval(const struct nft_expr *expr, | |||
317 | ret = match->match(skb, (struct xt_action_param *)&pkt->xt); | 317 | ret = match->match(skb, (struct xt_action_param *)&pkt->xt); |
318 | 318 | ||
319 | if (pkt->xt.hotdrop) { | 319 | if (pkt->xt.hotdrop) { |
320 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 320 | regs->verdict.code = NF_DROP; |
321 | return; | 321 | return; |
322 | } | 322 | } |
323 | 323 | ||
324 | switch (ret ? 1 : 0) { | 324 | switch (ret ? 1 : 0) { |
325 | case 1: | 325 | case 1: |
326 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 326 | regs->verdict.code = NFT_CONTINUE; |
327 | break; | 327 | break; |
328 | case 0: | 328 | case 0: |
329 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 329 | regs->verdict.code = NFT_BREAK; |
330 | break; | 330 | break; |
331 | } | 331 | } |
332 | } | 332 | } |
diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c index c89ee486ce54..17591239229f 100644 --- a/net/netfilter/nft_counter.c +++ b/net/netfilter/nft_counter.c | |||
@@ -24,7 +24,7 @@ struct nft_counter { | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | static void nft_counter_eval(const struct nft_expr *expr, | 26 | static void nft_counter_eval(const struct nft_expr *expr, |
27 | struct nft_data data[NFT_REG_MAX + 1], | 27 | struct nft_regs *regs, |
28 | const struct nft_pktinfo *pkt) | 28 | const struct nft_pktinfo *pkt) |
29 | { | 29 | { |
30 | struct nft_counter *priv = nft_expr_priv(expr); | 30 | struct nft_counter *priv = nft_expr_priv(expr); |
@@ -92,6 +92,7 @@ static struct nft_expr_type nft_counter_type __read_mostly = { | |||
92 | .ops = &nft_counter_ops, | 92 | .ops = &nft_counter_ops, |
93 | .policy = nft_counter_policy, | 93 | .policy = nft_counter_policy, |
94 | .maxattr = NFTA_COUNTER_MAX, | 94 | .maxattr = NFTA_COUNTER_MAX, |
95 | .flags = NFT_EXPR_STATEFUL, | ||
95 | .owner = THIS_MODULE, | 96 | .owner = THIS_MODULE, |
96 | }; | 97 | }; |
97 | 98 | ||
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 18d520e0ca0a..8cbca3432f90 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c | |||
@@ -31,11 +31,11 @@ struct nft_ct { | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | static void nft_ct_get_eval(const struct nft_expr *expr, | 33 | static void nft_ct_get_eval(const struct nft_expr *expr, |
34 | struct nft_data data[NFT_REG_MAX + 1], | 34 | struct nft_regs *regs, |
35 | const struct nft_pktinfo *pkt) | 35 | const struct nft_pktinfo *pkt) |
36 | { | 36 | { |
37 | const struct nft_ct *priv = nft_expr_priv(expr); | 37 | const struct nft_ct *priv = nft_expr_priv(expr); |
38 | struct nft_data *dest = &data[priv->dreg]; | 38 | u32 *dest = ®s->data[priv->dreg]; |
39 | enum ip_conntrack_info ctinfo; | 39 | enum ip_conntrack_info ctinfo; |
40 | const struct nf_conn *ct; | 40 | const struct nf_conn *ct; |
41 | const struct nf_conn_help *help; | 41 | const struct nf_conn_help *help; |
@@ -54,7 +54,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
54 | state = NF_CT_STATE_UNTRACKED_BIT; | 54 | state = NF_CT_STATE_UNTRACKED_BIT; |
55 | else | 55 | else |
56 | state = NF_CT_STATE_BIT(ctinfo); | 56 | state = NF_CT_STATE_BIT(ctinfo); |
57 | dest->data[0] = state; | 57 | *dest = state; |
58 | return; | 58 | return; |
59 | default: | 59 | default: |
60 | break; | 60 | break; |
@@ -65,26 +65,26 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
65 | 65 | ||
66 | switch (priv->key) { | 66 | switch (priv->key) { |
67 | case NFT_CT_DIRECTION: | 67 | case NFT_CT_DIRECTION: |
68 | dest->data[0] = CTINFO2DIR(ctinfo); | 68 | *dest = CTINFO2DIR(ctinfo); |
69 | return; | 69 | return; |
70 | case NFT_CT_STATUS: | 70 | case NFT_CT_STATUS: |
71 | dest->data[0] = ct->status; | 71 | *dest = ct->status; |
72 | return; | 72 | return; |
73 | #ifdef CONFIG_NF_CONNTRACK_MARK | 73 | #ifdef CONFIG_NF_CONNTRACK_MARK |
74 | case NFT_CT_MARK: | 74 | case NFT_CT_MARK: |
75 | dest->data[0] = ct->mark; | 75 | *dest = ct->mark; |
76 | return; | 76 | return; |
77 | #endif | 77 | #endif |
78 | #ifdef CONFIG_NF_CONNTRACK_SECMARK | 78 | #ifdef CONFIG_NF_CONNTRACK_SECMARK |
79 | case NFT_CT_SECMARK: | 79 | case NFT_CT_SECMARK: |
80 | dest->data[0] = ct->secmark; | 80 | *dest = ct->secmark; |
81 | return; | 81 | return; |
82 | #endif | 82 | #endif |
83 | case NFT_CT_EXPIRATION: | 83 | case NFT_CT_EXPIRATION: |
84 | diff = (long)jiffies - (long)ct->timeout.expires; | 84 | diff = (long)jiffies - (long)ct->timeout.expires; |
85 | if (diff < 0) | 85 | if (diff < 0) |
86 | diff = 0; | 86 | diff = 0; |
87 | dest->data[0] = jiffies_to_msecs(diff); | 87 | *dest = jiffies_to_msecs(diff); |
88 | return; | 88 | return; |
89 | case NFT_CT_HELPER: | 89 | case NFT_CT_HELPER: |
90 | if (ct->master == NULL) | 90 | if (ct->master == NULL) |
@@ -95,9 +95,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
95 | helper = rcu_dereference(help->helper); | 95 | helper = rcu_dereference(help->helper); |
96 | if (helper == NULL) | 96 | if (helper == NULL) |
97 | goto err; | 97 | goto err; |
98 | if (strlen(helper->name) >= sizeof(dest->data)) | 98 | strncpy((char *)dest, helper->name, NF_CT_HELPER_NAME_LEN); |
99 | goto err; | ||
100 | strncpy((char *)dest->data, helper->name, sizeof(dest->data)); | ||
101 | return; | 99 | return; |
102 | #ifdef CONFIG_NF_CONNTRACK_LABELS | 100 | #ifdef CONFIG_NF_CONNTRACK_LABELS |
103 | case NFT_CT_LABELS: { | 101 | case NFT_CT_LABELS: { |
@@ -105,17 +103,15 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
105 | unsigned int size; | 103 | unsigned int size; |
106 | 104 | ||
107 | if (!labels) { | 105 | if (!labels) { |
108 | memset(dest->data, 0, sizeof(dest->data)); | 106 | memset(dest, 0, NF_CT_LABELS_MAX_SIZE); |
109 | return; | 107 | return; |
110 | } | 108 | } |
111 | 109 | ||
112 | BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > sizeof(dest->data)); | ||
113 | size = labels->words * sizeof(long); | 110 | size = labels->words * sizeof(long); |
114 | 111 | memcpy(dest, labels->bits, size); | |
115 | memcpy(dest->data, labels->bits, size); | 112 | if (size < NF_CT_LABELS_MAX_SIZE) |
116 | if (size < sizeof(dest->data)) | 113 | memset(((char *) dest) + size, 0, |
117 | memset(((char *) dest->data) + size, 0, | 114 | NF_CT_LABELS_MAX_SIZE - size); |
118 | sizeof(dest->data) - size); | ||
119 | return; | 115 | return; |
120 | } | 116 | } |
121 | #endif | 117 | #endif |
@@ -126,41 +122,41 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
126 | tuple = &ct->tuplehash[priv->dir].tuple; | 122 | tuple = &ct->tuplehash[priv->dir].tuple; |
127 | switch (priv->key) { | 123 | switch (priv->key) { |
128 | case NFT_CT_L3PROTOCOL: | 124 | case NFT_CT_L3PROTOCOL: |
129 | dest->data[0] = nf_ct_l3num(ct); | 125 | *dest = nf_ct_l3num(ct); |
130 | return; | 126 | return; |
131 | case NFT_CT_SRC: | 127 | case NFT_CT_SRC: |
132 | memcpy(dest->data, tuple->src.u3.all, | 128 | memcpy(dest, tuple->src.u3.all, |
133 | nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16); | 129 | nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16); |
134 | return; | 130 | return; |
135 | case NFT_CT_DST: | 131 | case NFT_CT_DST: |
136 | memcpy(dest->data, tuple->dst.u3.all, | 132 | memcpy(dest, tuple->dst.u3.all, |
137 | nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16); | 133 | nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16); |
138 | return; | 134 | return; |
139 | case NFT_CT_PROTOCOL: | 135 | case NFT_CT_PROTOCOL: |
140 | dest->data[0] = nf_ct_protonum(ct); | 136 | *dest = nf_ct_protonum(ct); |
141 | return; | 137 | return; |
142 | case NFT_CT_PROTO_SRC: | 138 | case NFT_CT_PROTO_SRC: |
143 | dest->data[0] = (__force __u16)tuple->src.u.all; | 139 | *dest = (__force __u16)tuple->src.u.all; |
144 | return; | 140 | return; |
145 | case NFT_CT_PROTO_DST: | 141 | case NFT_CT_PROTO_DST: |
146 | dest->data[0] = (__force __u16)tuple->dst.u.all; | 142 | *dest = (__force __u16)tuple->dst.u.all; |
147 | return; | 143 | return; |
148 | default: | 144 | default: |
149 | break; | 145 | break; |
150 | } | 146 | } |
151 | return; | 147 | return; |
152 | err: | 148 | err: |
153 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 149 | regs->verdict.code = NFT_BREAK; |
154 | } | 150 | } |
155 | 151 | ||
156 | static void nft_ct_set_eval(const struct nft_expr *expr, | 152 | static void nft_ct_set_eval(const struct nft_expr *expr, |
157 | struct nft_data data[NFT_REG_MAX + 1], | 153 | struct nft_regs *regs, |
158 | const struct nft_pktinfo *pkt) | 154 | const struct nft_pktinfo *pkt) |
159 | { | 155 | { |
160 | const struct nft_ct *priv = nft_expr_priv(expr); | 156 | const struct nft_ct *priv = nft_expr_priv(expr); |
161 | struct sk_buff *skb = pkt->skb; | 157 | struct sk_buff *skb = pkt->skb; |
162 | #ifdef CONFIG_NF_CONNTRACK_MARK | 158 | #ifdef CONFIG_NF_CONNTRACK_MARK |
163 | u32 value = data[priv->sreg].data[0]; | 159 | u32 value = regs->data[priv->sreg]; |
164 | #endif | 160 | #endif |
165 | enum ip_conntrack_info ctinfo; | 161 | enum ip_conntrack_info ctinfo; |
166 | struct nf_conn *ct; | 162 | struct nf_conn *ct; |
@@ -228,12 +224,17 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, | |||
228 | const struct nlattr * const tb[]) | 224 | const struct nlattr * const tb[]) |
229 | { | 225 | { |
230 | struct nft_ct *priv = nft_expr_priv(expr); | 226 | struct nft_ct *priv = nft_expr_priv(expr); |
227 | unsigned int len; | ||
231 | int err; | 228 | int err; |
232 | 229 | ||
233 | priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY])); | 230 | priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY])); |
234 | switch (priv->key) { | 231 | switch (priv->key) { |
235 | case NFT_CT_STATE: | ||
236 | case NFT_CT_DIRECTION: | 232 | case NFT_CT_DIRECTION: |
233 | if (tb[NFTA_CT_DIRECTION] != NULL) | ||
234 | return -EINVAL; | ||
235 | len = sizeof(u8); | ||
236 | break; | ||
237 | case NFT_CT_STATE: | ||
237 | case NFT_CT_STATUS: | 238 | case NFT_CT_STATUS: |
238 | #ifdef CONFIG_NF_CONNTRACK_MARK | 239 | #ifdef CONFIG_NF_CONNTRACK_MARK |
239 | case NFT_CT_MARK: | 240 | case NFT_CT_MARK: |
@@ -241,22 +242,54 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, | |||
241 | #ifdef CONFIG_NF_CONNTRACK_SECMARK | 242 | #ifdef CONFIG_NF_CONNTRACK_SECMARK |
242 | case NFT_CT_SECMARK: | 243 | case NFT_CT_SECMARK: |
243 | #endif | 244 | #endif |
245 | case NFT_CT_EXPIRATION: | ||
246 | if (tb[NFTA_CT_DIRECTION] != NULL) | ||
247 | return -EINVAL; | ||
248 | len = sizeof(u32); | ||
249 | break; | ||
244 | #ifdef CONFIG_NF_CONNTRACK_LABELS | 250 | #ifdef CONFIG_NF_CONNTRACK_LABELS |
245 | case NFT_CT_LABELS: | 251 | case NFT_CT_LABELS: |
252 | if (tb[NFTA_CT_DIRECTION] != NULL) | ||
253 | return -EINVAL; | ||
254 | len = NF_CT_LABELS_MAX_SIZE; | ||
255 | break; | ||
246 | #endif | 256 | #endif |
247 | case NFT_CT_EXPIRATION: | ||
248 | case NFT_CT_HELPER: | 257 | case NFT_CT_HELPER: |
249 | if (tb[NFTA_CT_DIRECTION] != NULL) | 258 | if (tb[NFTA_CT_DIRECTION] != NULL) |
250 | return -EINVAL; | 259 | return -EINVAL; |
260 | len = NF_CT_HELPER_NAME_LEN; | ||
251 | break; | 261 | break; |
262 | |||
252 | case NFT_CT_L3PROTOCOL: | 263 | case NFT_CT_L3PROTOCOL: |
253 | case NFT_CT_PROTOCOL: | 264 | case NFT_CT_PROTOCOL: |
265 | if (tb[NFTA_CT_DIRECTION] == NULL) | ||
266 | return -EINVAL; | ||
267 | len = sizeof(u8); | ||
268 | break; | ||
254 | case NFT_CT_SRC: | 269 | case NFT_CT_SRC: |
255 | case NFT_CT_DST: | 270 | case NFT_CT_DST: |
271 | if (tb[NFTA_CT_DIRECTION] == NULL) | ||
272 | return -EINVAL; | ||
273 | |||
274 | switch (ctx->afi->family) { | ||
275 | case NFPROTO_IPV4: | ||
276 | len = FIELD_SIZEOF(struct nf_conntrack_tuple, | ||
277 | src.u3.ip); | ||
278 | break; | ||
279 | case NFPROTO_IPV6: | ||
280 | case NFPROTO_INET: | ||
281 | len = FIELD_SIZEOF(struct nf_conntrack_tuple, | ||
282 | src.u3.ip6); | ||
283 | break; | ||
284 | default: | ||
285 | return -EAFNOSUPPORT; | ||
286 | } | ||
287 | break; | ||
256 | case NFT_CT_PROTO_SRC: | 288 | case NFT_CT_PROTO_SRC: |
257 | case NFT_CT_PROTO_DST: | 289 | case NFT_CT_PROTO_DST: |
258 | if (tb[NFTA_CT_DIRECTION] == NULL) | 290 | if (tb[NFTA_CT_DIRECTION] == NULL) |
259 | return -EINVAL; | 291 | return -EINVAL; |
292 | len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all); | ||
260 | break; | 293 | break; |
261 | default: | 294 | default: |
262 | return -EOPNOTSUPP; | 295 | return -EOPNOTSUPP; |
@@ -273,12 +306,9 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, | |||
273 | } | 306 | } |
274 | } | 307 | } |
275 | 308 | ||
276 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_CT_DREG])); | 309 | priv->dreg = nft_parse_register(tb[NFTA_CT_DREG]); |
277 | err = nft_validate_output_register(priv->dreg); | 310 | err = nft_validate_register_store(ctx, priv->dreg, NULL, |
278 | if (err < 0) | 311 | NFT_DATA_VALUE, len); |
279 | return err; | ||
280 | |||
281 | err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); | ||
282 | if (err < 0) | 312 | if (err < 0) |
283 | return err; | 313 | return err; |
284 | 314 | ||
@@ -294,20 +324,22 @@ static int nft_ct_set_init(const struct nft_ctx *ctx, | |||
294 | const struct nlattr * const tb[]) | 324 | const struct nlattr * const tb[]) |
295 | { | 325 | { |
296 | struct nft_ct *priv = nft_expr_priv(expr); | 326 | struct nft_ct *priv = nft_expr_priv(expr); |
327 | unsigned int len; | ||
297 | int err; | 328 | int err; |
298 | 329 | ||
299 | priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY])); | 330 | priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY])); |
300 | switch (priv->key) { | 331 | switch (priv->key) { |
301 | #ifdef CONFIG_NF_CONNTRACK_MARK | 332 | #ifdef CONFIG_NF_CONNTRACK_MARK |
302 | case NFT_CT_MARK: | 333 | case NFT_CT_MARK: |
334 | len = FIELD_SIZEOF(struct nf_conn, mark); | ||
303 | break; | 335 | break; |
304 | #endif | 336 | #endif |
305 | default: | 337 | default: |
306 | return -EOPNOTSUPP; | 338 | return -EOPNOTSUPP; |
307 | } | 339 | } |
308 | 340 | ||
309 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_CT_SREG])); | 341 | priv->sreg = nft_parse_register(tb[NFTA_CT_SREG]); |
310 | err = nft_validate_input_register(priv->sreg); | 342 | err = nft_validate_register_load(priv->sreg, len); |
311 | if (err < 0) | 343 | if (err < 0) |
312 | return err; | 344 | return err; |
313 | 345 | ||
@@ -328,7 +360,7 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
328 | { | 360 | { |
329 | const struct nft_ct *priv = nft_expr_priv(expr); | 361 | const struct nft_ct *priv = nft_expr_priv(expr); |
330 | 362 | ||
331 | if (nla_put_be32(skb, NFTA_CT_DREG, htonl(priv->dreg))) | 363 | if (nft_dump_register(skb, NFTA_CT_DREG, priv->dreg)) |
332 | goto nla_put_failure; | 364 | goto nla_put_failure; |
333 | if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) | 365 | if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) |
334 | goto nla_put_failure; | 366 | goto nla_put_failure; |
@@ -355,7 +387,7 @@ static int nft_ct_set_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
355 | { | 387 | { |
356 | const struct nft_ct *priv = nft_expr_priv(expr); | 388 | const struct nft_ct *priv = nft_expr_priv(expr); |
357 | 389 | ||
358 | if (nla_put_be32(skb, NFTA_CT_SREG, htonl(priv->sreg))) | 390 | if (nft_dump_register(skb, NFTA_CT_SREG, priv->sreg)) |
359 | goto nla_put_failure; | 391 | goto nla_put_failure; |
360 | if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) | 392 | if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) |
361 | goto nla_put_failure; | 393 | goto nla_put_failure; |
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index eeb72dee78ef..513a8ef60a59 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c | |||
@@ -23,13 +23,15 @@ struct nft_dynset { | |||
23 | enum nft_registers sreg_key:8; | 23 | enum nft_registers sreg_key:8; |
24 | enum nft_registers sreg_data:8; | 24 | enum nft_registers sreg_data:8; |
25 | u64 timeout; | 25 | u64 timeout; |
26 | struct nft_expr *expr; | ||
26 | struct nft_set_binding binding; | 27 | struct nft_set_binding binding; |
27 | }; | 28 | }; |
28 | 29 | ||
29 | static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr, | 30 | static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr, |
30 | struct nft_data data[NFT_REG_MAX + 1]) | 31 | struct nft_regs *regs) |
31 | { | 32 | { |
32 | const struct nft_dynset *priv = nft_expr_priv(expr); | 33 | const struct nft_dynset *priv = nft_expr_priv(expr); |
34 | struct nft_set_ext *ext; | ||
33 | u64 timeout; | 35 | u64 timeout; |
34 | void *elem; | 36 | void *elem; |
35 | 37 | ||
@@ -38,35 +40,51 @@ static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr, | |||
38 | 40 | ||
39 | timeout = priv->timeout ? : set->timeout; | 41 | timeout = priv->timeout ? : set->timeout; |
40 | elem = nft_set_elem_init(set, &priv->tmpl, | 42 | elem = nft_set_elem_init(set, &priv->tmpl, |
41 | &data[priv->sreg_key], &data[priv->sreg_data], | 43 | ®s->data[priv->sreg_key], |
44 | ®s->data[priv->sreg_data], | ||
42 | timeout, GFP_ATOMIC); | 45 | timeout, GFP_ATOMIC); |
43 | if (elem == NULL) { | 46 | if (elem == NULL) { |
44 | if (set->size) | 47 | if (set->size) |
45 | atomic_dec(&set->nelems); | 48 | atomic_dec(&set->nelems); |
49 | return NULL; | ||
46 | } | 50 | } |
51 | |||
52 | ext = nft_set_elem_ext(set, elem); | ||
53 | if (priv->expr != NULL) | ||
54 | nft_expr_clone(nft_set_ext_expr(ext), priv->expr); | ||
55 | |||
47 | return elem; | 56 | return elem; |
48 | } | 57 | } |
49 | 58 | ||
50 | static void nft_dynset_eval(const struct nft_expr *expr, | 59 | static void nft_dynset_eval(const struct nft_expr *expr, |
51 | struct nft_data data[NFT_REG_MAX + 1], | 60 | struct nft_regs *regs, |
52 | const struct nft_pktinfo *pkt) | 61 | const struct nft_pktinfo *pkt) |
53 | { | 62 | { |
54 | const struct nft_dynset *priv = nft_expr_priv(expr); | 63 | const struct nft_dynset *priv = nft_expr_priv(expr); |
55 | struct nft_set *set = priv->set; | 64 | struct nft_set *set = priv->set; |
56 | const struct nft_set_ext *ext; | 65 | const struct nft_set_ext *ext; |
66 | const struct nft_expr *sexpr; | ||
57 | u64 timeout; | 67 | u64 timeout; |
58 | 68 | ||
59 | if (set->ops->update(set, &data[priv->sreg_key], nft_dynset_new, | 69 | if (set->ops->update(set, ®s->data[priv->sreg_key], nft_dynset_new, |
60 | expr, data, &ext)) { | 70 | expr, regs, &ext)) { |
71 | sexpr = NULL; | ||
72 | if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) | ||
73 | sexpr = nft_set_ext_expr(ext); | ||
74 | |||
61 | if (priv->op == NFT_DYNSET_OP_UPDATE && | 75 | if (priv->op == NFT_DYNSET_OP_UPDATE && |
62 | nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) { | 76 | nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) { |
63 | timeout = priv->timeout ? : set->timeout; | 77 | timeout = priv->timeout ? : set->timeout; |
64 | *nft_set_ext_expiration(ext) = jiffies + timeout; | 78 | *nft_set_ext_expiration(ext) = jiffies + timeout; |
65 | return; | 79 | } else if (sexpr == NULL) |
66 | } | 80 | goto out; |
67 | } | ||
68 | 81 | ||
69 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 82 | if (sexpr != NULL) |
83 | sexpr->ops->eval(sexpr, regs, pkt); | ||
84 | return; | ||
85 | } | ||
86 | out: | ||
87 | regs->verdict.code = NFT_BREAK; | ||
70 | } | 88 | } |
71 | 89 | ||
72 | static const struct nla_policy nft_dynset_policy[NFTA_DYNSET_MAX + 1] = { | 90 | static const struct nla_policy nft_dynset_policy[NFTA_DYNSET_MAX + 1] = { |
@@ -76,6 +94,7 @@ static const struct nla_policy nft_dynset_policy[NFTA_DYNSET_MAX + 1] = { | |||
76 | [NFTA_DYNSET_SREG_KEY] = { .type = NLA_U32 }, | 94 | [NFTA_DYNSET_SREG_KEY] = { .type = NLA_U32 }, |
77 | [NFTA_DYNSET_SREG_DATA] = { .type = NLA_U32 }, | 95 | [NFTA_DYNSET_SREG_DATA] = { .type = NLA_U32 }, |
78 | [NFTA_DYNSET_TIMEOUT] = { .type = NLA_U64 }, | 96 | [NFTA_DYNSET_TIMEOUT] = { .type = NLA_U64 }, |
97 | [NFTA_DYNSET_EXPR] = { .type = NLA_NESTED }, | ||
79 | }; | 98 | }; |
80 | 99 | ||
81 | static int nft_dynset_init(const struct nft_ctx *ctx, | 100 | static int nft_dynset_init(const struct nft_ctx *ctx, |
@@ -123,8 +142,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx, | |||
123 | timeout = be64_to_cpu(nla_get_be64(tb[NFTA_DYNSET_TIMEOUT])); | 142 | timeout = be64_to_cpu(nla_get_be64(tb[NFTA_DYNSET_TIMEOUT])); |
124 | } | 143 | } |
125 | 144 | ||
126 | priv->sreg_key = ntohl(nla_get_be32(tb[NFTA_DYNSET_SREG_KEY])); | 145 | priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]); |
127 | err = nft_validate_input_register(priv->sreg_key); | 146 | err = nft_validate_register_load(priv->sreg_key, set->klen);; |
128 | if (err < 0) | 147 | if (err < 0) |
129 | return err; | 148 | return err; |
130 | 149 | ||
@@ -134,17 +153,36 @@ static int nft_dynset_init(const struct nft_ctx *ctx, | |||
134 | if (set->dtype == NFT_DATA_VERDICT) | 153 | if (set->dtype == NFT_DATA_VERDICT) |
135 | return -EOPNOTSUPP; | 154 | return -EOPNOTSUPP; |
136 | 155 | ||
137 | priv->sreg_data = ntohl(nla_get_be32(tb[NFTA_DYNSET_SREG_DATA])); | 156 | priv->sreg_data = nft_parse_register(tb[NFTA_DYNSET_SREG_DATA]); |
138 | err = nft_validate_input_register(priv->sreg_data); | 157 | err = nft_validate_register_load(priv->sreg_data, set->dlen); |
139 | if (err < 0) | 158 | if (err < 0) |
140 | return err; | 159 | return err; |
141 | } else if (set->flags & NFT_SET_MAP) | 160 | } else if (set->flags & NFT_SET_MAP) |
142 | return -EINVAL; | 161 | return -EINVAL; |
143 | 162 | ||
163 | if (tb[NFTA_DYNSET_EXPR] != NULL) { | ||
164 | if (!(set->flags & NFT_SET_EVAL)) | ||
165 | return -EINVAL; | ||
166 | if (!(set->flags & NFT_SET_ANONYMOUS)) | ||
167 | return -EOPNOTSUPP; | ||
168 | |||
169 | priv->expr = nft_expr_init(ctx, tb[NFTA_DYNSET_EXPR]); | ||
170 | if (IS_ERR(priv->expr)) | ||
171 | return PTR_ERR(priv->expr); | ||
172 | |||
173 | err = -EOPNOTSUPP; | ||
174 | if (!(priv->expr->ops->type->flags & NFT_EXPR_STATEFUL)) | ||
175 | goto err1; | ||
176 | } else if (set->flags & NFT_SET_EVAL) | ||
177 | return -EINVAL; | ||
178 | |||
144 | nft_set_ext_prepare(&priv->tmpl); | 179 | nft_set_ext_prepare(&priv->tmpl); |
145 | nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_KEY, set->klen); | 180 | nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_KEY, set->klen); |
146 | if (set->flags & NFT_SET_MAP) | 181 | if (set->flags & NFT_SET_MAP) |
147 | nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_DATA, set->dlen); | 182 | nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_DATA, set->dlen); |
183 | if (priv->expr != NULL) | ||
184 | nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_EXPR, | ||
185 | priv->expr->ops->size); | ||
148 | if (set->flags & NFT_SET_TIMEOUT) { | 186 | if (set->flags & NFT_SET_TIMEOUT) { |
149 | if (timeout || set->timeout) | 187 | if (timeout || set->timeout) |
150 | nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_EXPIRATION); | 188 | nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_EXPIRATION); |
@@ -154,10 +192,15 @@ static int nft_dynset_init(const struct nft_ctx *ctx, | |||
154 | 192 | ||
155 | err = nf_tables_bind_set(ctx, set, &priv->binding); | 193 | err = nf_tables_bind_set(ctx, set, &priv->binding); |
156 | if (err < 0) | 194 | if (err < 0) |
157 | return err; | 195 | goto err1; |
158 | 196 | ||
159 | priv->set = set; | 197 | priv->set = set; |
160 | return 0; | 198 | return 0; |
199 | |||
200 | err1: | ||
201 | if (priv->expr != NULL) | ||
202 | nft_expr_destroy(ctx, priv->expr); | ||
203 | return err; | ||
161 | } | 204 | } |
162 | 205 | ||
163 | static void nft_dynset_destroy(const struct nft_ctx *ctx, | 206 | static void nft_dynset_destroy(const struct nft_ctx *ctx, |
@@ -166,16 +209,18 @@ static void nft_dynset_destroy(const struct nft_ctx *ctx, | |||
166 | struct nft_dynset *priv = nft_expr_priv(expr); | 209 | struct nft_dynset *priv = nft_expr_priv(expr); |
167 | 210 | ||
168 | nf_tables_unbind_set(ctx, priv->set, &priv->binding); | 211 | nf_tables_unbind_set(ctx, priv->set, &priv->binding); |
212 | if (priv->expr != NULL) | ||
213 | nft_expr_destroy(ctx, priv->expr); | ||
169 | } | 214 | } |
170 | 215 | ||
171 | static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr) | 216 | static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr) |
172 | { | 217 | { |
173 | const struct nft_dynset *priv = nft_expr_priv(expr); | 218 | const struct nft_dynset *priv = nft_expr_priv(expr); |
174 | 219 | ||
175 | if (nla_put_be32(skb, NFTA_DYNSET_SREG_KEY, htonl(priv->sreg_key))) | 220 | if (nft_dump_register(skb, NFTA_DYNSET_SREG_KEY, priv->sreg_key)) |
176 | goto nla_put_failure; | 221 | goto nla_put_failure; |
177 | if (priv->set->flags & NFT_SET_MAP && | 222 | if (priv->set->flags & NFT_SET_MAP && |
178 | nla_put_be32(skb, NFTA_DYNSET_SREG_DATA, htonl(priv->sreg_data))) | 223 | nft_dump_register(skb, NFTA_DYNSET_SREG_DATA, priv->sreg_data)) |
179 | goto nla_put_failure; | 224 | goto nla_put_failure; |
180 | if (nla_put_be32(skb, NFTA_DYNSET_OP, htonl(priv->op))) | 225 | if (nla_put_be32(skb, NFTA_DYNSET_OP, htonl(priv->op))) |
181 | goto nla_put_failure; | 226 | goto nla_put_failure; |
@@ -183,6 +228,8 @@ static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
183 | goto nla_put_failure; | 228 | goto nla_put_failure; |
184 | if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, cpu_to_be64(priv->timeout))) | 229 | if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, cpu_to_be64(priv->timeout))) |
185 | goto nla_put_failure; | 230 | goto nla_put_failure; |
231 | if (priv->expr && nft_expr_dump(skb, NFTA_DYNSET_EXPR, priv->expr)) | ||
232 | goto nla_put_failure; | ||
186 | return 0; | 233 | return 0; |
187 | 234 | ||
188 | nla_put_failure: | 235 | nla_put_failure: |
diff --git a/net/netfilter/nft_expr_template.c b/net/netfilter/nft_expr_template.c deleted file mode 100644 index b6eed4d5a096..000000000000 --- a/net/netfilter/nft_expr_template.c +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/netlink.h> | ||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter/nf_tables.h> | ||
16 | #include <net/netfilter/nf_tables.h> | ||
17 | |||
18 | struct nft_template { | ||
19 | |||
20 | }; | ||
21 | |||
22 | static void nft_template_eval(const struct nft_expr *expr, | ||
23 | struct nft_data data[NFT_REG_MAX + 1], | ||
24 | const struct nft_pktinfo *pkt) | ||
25 | { | ||
26 | struct nft_template *priv = nft_expr_priv(expr); | ||
27 | |||
28 | } | ||
29 | |||
30 | static const struct nla_policy nft_template_policy[NFTA_TEMPLATE_MAX + 1] = { | ||
31 | [NFTA_TEMPLATE_ATTR] = { .type = NLA_U32 }, | ||
32 | }; | ||
33 | |||
34 | static int nft_template_init(const struct nft_ctx *ctx, | ||
35 | const struct nft_expr *expr, | ||
36 | const struct nlattr * const tb[]) | ||
37 | { | ||
38 | struct nft_template *priv = nft_expr_priv(expr); | ||
39 | |||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static void nft_template_destroy(const struct nft_ctx *ctx, | ||
44 | const struct nft_expr *expr) | ||
45 | { | ||
46 | struct nft_template *priv = nft_expr_priv(expr); | ||
47 | |||
48 | } | ||
49 | |||
50 | static int nft_template_dump(struct sk_buff *skb, const struct nft_expr *expr) | ||
51 | { | ||
52 | const struct nft_template *priv = nft_expr_priv(expr); | ||
53 | |||
54 | NLA_PUT_BE32(skb, NFTA_TEMPLATE_ATTR, priv->field); | ||
55 | return 0; | ||
56 | |||
57 | nla_put_failure: | ||
58 | return -1; | ||
59 | } | ||
60 | |||
61 | static struct nft_expr_type nft_template_type; | ||
62 | static const struct nft_expr_ops nft_template_ops = { | ||
63 | .type = &nft_template_type, | ||
64 | .size = NFT_EXPR_SIZE(sizeof(struct nft_template)), | ||
65 | .eval = nft_template_eval, | ||
66 | .init = nft_template_init, | ||
67 | .destroy = nft_template_destroy, | ||
68 | .dump = nft_template_dump, | ||
69 | }; | ||
70 | |||
71 | static struct nft_expr_type nft_template_type __read_mostly = { | ||
72 | .name = "template", | ||
73 | .ops = &nft_template_ops, | ||
74 | .policy = nft_template_policy, | ||
75 | .maxattr = NFTA_TEMPLATE_MAX, | ||
76 | .owner = THIS_MODULE, | ||
77 | }; | ||
78 | |||
79 | static int __init nft_template_module_init(void) | ||
80 | { | ||
81 | return nft_register_expr(&nft_template_type); | ||
82 | } | ||
83 | |||
84 | static void __exit nft_template_module_exit(void) | ||
85 | { | ||
86 | nft_unregister_expr(&nft_template_type); | ||
87 | } | ||
88 | |||
89 | module_init(nft_template_module_init); | ||
90 | module_exit(nft_template_module_exit); | ||
91 | |||
92 | MODULE_LICENSE("GPL"); | ||
93 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
94 | MODULE_ALIAS_NFT_EXPR("template"); | ||
diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c index 55c939f5371f..ba7aed13e174 100644 --- a/net/netfilter/nft_exthdr.c +++ b/net/netfilter/nft_exthdr.c | |||
@@ -26,11 +26,11 @@ struct nft_exthdr { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | static void nft_exthdr_eval(const struct nft_expr *expr, | 28 | static void nft_exthdr_eval(const struct nft_expr *expr, |
29 | struct nft_data data[NFT_REG_MAX + 1], | 29 | struct nft_regs *regs, |
30 | const struct nft_pktinfo *pkt) | 30 | const struct nft_pktinfo *pkt) |
31 | { | 31 | { |
32 | struct nft_exthdr *priv = nft_expr_priv(expr); | 32 | struct nft_exthdr *priv = nft_expr_priv(expr); |
33 | struct nft_data *dest = &data[priv->dreg]; | 33 | u32 *dest = ®s->data[priv->dreg]; |
34 | unsigned int offset = 0; | 34 | unsigned int offset = 0; |
35 | int err; | 35 | int err; |
36 | 36 | ||
@@ -39,11 +39,12 @@ static void nft_exthdr_eval(const struct nft_expr *expr, | |||
39 | goto err; | 39 | goto err; |
40 | offset += priv->offset; | 40 | offset += priv->offset; |
41 | 41 | ||
42 | if (skb_copy_bits(pkt->skb, offset, dest->data, priv->len) < 0) | 42 | dest[priv->len / NFT_REG32_SIZE] = 0; |
43 | if (skb_copy_bits(pkt->skb, offset, dest, priv->len) < 0) | ||
43 | goto err; | 44 | goto err; |
44 | return; | 45 | return; |
45 | err: | 46 | err: |
46 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 47 | regs->verdict.code = NFT_BREAK; |
47 | } | 48 | } |
48 | 49 | ||
49 | static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = { | 50 | static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = { |
@@ -58,7 +59,6 @@ static int nft_exthdr_init(const struct nft_ctx *ctx, | |||
58 | const struct nlattr * const tb[]) | 59 | const struct nlattr * const tb[]) |
59 | { | 60 | { |
60 | struct nft_exthdr *priv = nft_expr_priv(expr); | 61 | struct nft_exthdr *priv = nft_expr_priv(expr); |
61 | int err; | ||
62 | 62 | ||
63 | if (tb[NFTA_EXTHDR_DREG] == NULL || | 63 | if (tb[NFTA_EXTHDR_DREG] == NULL || |
64 | tb[NFTA_EXTHDR_TYPE] == NULL || | 64 | tb[NFTA_EXTHDR_TYPE] == NULL || |
@@ -69,22 +69,17 @@ static int nft_exthdr_init(const struct nft_ctx *ctx, | |||
69 | priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]); | 69 | priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]); |
70 | priv->offset = ntohl(nla_get_be32(tb[NFTA_EXTHDR_OFFSET])); | 70 | priv->offset = ntohl(nla_get_be32(tb[NFTA_EXTHDR_OFFSET])); |
71 | priv->len = ntohl(nla_get_be32(tb[NFTA_EXTHDR_LEN])); | 71 | priv->len = ntohl(nla_get_be32(tb[NFTA_EXTHDR_LEN])); |
72 | if (priv->len == 0 || | 72 | priv->dreg = nft_parse_register(tb[NFTA_EXTHDR_DREG]); |
73 | priv->len > FIELD_SIZEOF(struct nft_data, data)) | ||
74 | return -EINVAL; | ||
75 | 73 | ||
76 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_EXTHDR_DREG])); | 74 | return nft_validate_register_store(ctx, priv->dreg, NULL, |
77 | err = nft_validate_output_register(priv->dreg); | 75 | NFT_DATA_VALUE, priv->len); |
78 | if (err < 0) | ||
79 | return err; | ||
80 | return nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); | ||
81 | } | 76 | } |
82 | 77 | ||
83 | static int nft_exthdr_dump(struct sk_buff *skb, const struct nft_expr *expr) | 78 | static int nft_exthdr_dump(struct sk_buff *skb, const struct nft_expr *expr) |
84 | { | 79 | { |
85 | const struct nft_exthdr *priv = nft_expr_priv(expr); | 80 | const struct nft_exthdr *priv = nft_expr_priv(expr); |
86 | 81 | ||
87 | if (nla_put_be32(skb, NFTA_EXTHDR_DREG, htonl(priv->dreg))) | 82 | if (nft_dump_register(skb, NFTA_EXTHDR_DREG, priv->dreg)) |
88 | goto nla_put_failure; | 83 | goto nla_put_failure; |
89 | if (nla_put_u8(skb, NFTA_EXTHDR_TYPE, priv->type)) | 84 | if (nla_put_u8(skb, NFTA_EXTHDR_TYPE, priv->type)) |
90 | goto nla_put_failure; | 85 | goto nla_put_failure; |
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index bc23806b7fbe..3f9d45d3d9b7 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c | |||
@@ -36,7 +36,7 @@ struct nft_hash_elem { | |||
36 | 36 | ||
37 | struct nft_hash_cmp_arg { | 37 | struct nft_hash_cmp_arg { |
38 | const struct nft_set *set; | 38 | const struct nft_set *set; |
39 | const struct nft_data *key; | 39 | const u32 *key; |
40 | u8 genmask; | 40 | u8 genmask; |
41 | }; | 41 | }; |
42 | 42 | ||
@@ -62,7 +62,7 @@ static inline int nft_hash_cmp(struct rhashtable_compare_arg *arg, | |||
62 | const struct nft_hash_cmp_arg *x = arg->key; | 62 | const struct nft_hash_cmp_arg *x = arg->key; |
63 | const struct nft_hash_elem *he = ptr; | 63 | const struct nft_hash_elem *he = ptr; |
64 | 64 | ||
65 | if (nft_data_cmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) | 65 | if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) |
66 | return 1; | 66 | return 1; |
67 | if (nft_set_elem_expired(&he->ext)) | 67 | if (nft_set_elem_expired(&he->ext)) |
68 | return 1; | 68 | return 1; |
@@ -71,8 +71,7 @@ static inline int nft_hash_cmp(struct rhashtable_compare_arg *arg, | |||
71 | return 0; | 71 | return 0; |
72 | } | 72 | } |
73 | 73 | ||
74 | static bool nft_hash_lookup(const struct nft_set *set, | 74 | static bool nft_hash_lookup(const struct nft_set *set, const u32 *key, |
75 | const struct nft_data *key, | ||
76 | const struct nft_set_ext **ext) | 75 | const struct nft_set_ext **ext) |
77 | { | 76 | { |
78 | struct nft_hash *priv = nft_set_priv(set); | 77 | struct nft_hash *priv = nft_set_priv(set); |
@@ -90,12 +89,12 @@ static bool nft_hash_lookup(const struct nft_set *set, | |||
90 | return !!he; | 89 | return !!he; |
91 | } | 90 | } |
92 | 91 | ||
93 | static bool nft_hash_update(struct nft_set *set, const struct nft_data *key, | 92 | static bool nft_hash_update(struct nft_set *set, const u32 *key, |
94 | void *(*new)(struct nft_set *, | 93 | void *(*new)(struct nft_set *, |
95 | const struct nft_expr *, | 94 | const struct nft_expr *, |
96 | struct nft_data []), | 95 | struct nft_regs *regs), |
97 | const struct nft_expr *expr, | 96 | const struct nft_expr *expr, |
98 | struct nft_data data[], | 97 | struct nft_regs *regs, |
99 | const struct nft_set_ext **ext) | 98 | const struct nft_set_ext **ext) |
100 | { | 99 | { |
101 | struct nft_hash *priv = nft_set_priv(set); | 100 | struct nft_hash *priv = nft_set_priv(set); |
@@ -110,7 +109,7 @@ static bool nft_hash_update(struct nft_set *set, const struct nft_data *key, | |||
110 | if (he != NULL) | 109 | if (he != NULL) |
111 | goto out; | 110 | goto out; |
112 | 111 | ||
113 | he = new(set, expr, data); | 112 | he = new(set, expr, regs); |
114 | if (he == NULL) | 113 | if (he == NULL) |
115 | goto err1; | 114 | goto err1; |
116 | if (rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, | 115 | if (rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, |
@@ -134,7 +133,7 @@ static int nft_hash_insert(const struct nft_set *set, | |||
134 | struct nft_hash_cmp_arg arg = { | 133 | struct nft_hash_cmp_arg arg = { |
135 | .genmask = nft_genmask_next(read_pnet(&set->pnet)), | 134 | .genmask = nft_genmask_next(read_pnet(&set->pnet)), |
136 | .set = set, | 135 | .set = set, |
137 | .key = &elem->key, | 136 | .key = elem->key.val.data, |
138 | }; | 137 | }; |
139 | 138 | ||
140 | return rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, | 139 | return rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, |
@@ -158,7 +157,7 @@ static void *nft_hash_deactivate(const struct nft_set *set, | |||
158 | struct nft_hash_cmp_arg arg = { | 157 | struct nft_hash_cmp_arg arg = { |
159 | .genmask = nft_genmask_next(read_pnet(&set->pnet)), | 158 | .genmask = nft_genmask_next(read_pnet(&set->pnet)), |
160 | .set = set, | 159 | .set = set, |
161 | .key = &elem->key, | 160 | .key = elem->key.val.data, |
162 | }; | 161 | }; |
163 | 162 | ||
164 | rcu_read_lock(); | 163 | rcu_read_lock(); |
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c index 810385eb7249..db3b746858e3 100644 --- a/net/netfilter/nft_immediate.c +++ b/net/netfilter/nft_immediate.c | |||
@@ -24,12 +24,12 @@ struct nft_immediate_expr { | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | static void nft_immediate_eval(const struct nft_expr *expr, | 26 | static void nft_immediate_eval(const struct nft_expr *expr, |
27 | struct nft_data data[NFT_REG_MAX + 1], | 27 | struct nft_regs *regs, |
28 | const struct nft_pktinfo *pkt) | 28 | const struct nft_pktinfo *pkt) |
29 | { | 29 | { |
30 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); | 30 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); |
31 | 31 | ||
32 | nft_data_copy(&data[priv->dreg], &priv->data); | 32 | nft_data_copy(®s->data[priv->dreg], &priv->data, priv->dlen); |
33 | } | 33 | } |
34 | 34 | ||
35 | static const struct nla_policy nft_immediate_policy[NFTA_IMMEDIATE_MAX + 1] = { | 35 | static const struct nla_policy nft_immediate_policy[NFTA_IMMEDIATE_MAX + 1] = { |
@@ -49,17 +49,15 @@ static int nft_immediate_init(const struct nft_ctx *ctx, | |||
49 | tb[NFTA_IMMEDIATE_DATA] == NULL) | 49 | tb[NFTA_IMMEDIATE_DATA] == NULL) |
50 | return -EINVAL; | 50 | return -EINVAL; |
51 | 51 | ||
52 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_IMMEDIATE_DREG])); | 52 | err = nft_data_init(ctx, &priv->data, sizeof(priv->data), &desc, |
53 | err = nft_validate_output_register(priv->dreg); | 53 | tb[NFTA_IMMEDIATE_DATA]); |
54 | if (err < 0) | ||
55 | return err; | ||
56 | |||
57 | err = nft_data_init(ctx, &priv->data, &desc, tb[NFTA_IMMEDIATE_DATA]); | ||
58 | if (err < 0) | 54 | if (err < 0) |
59 | return err; | 55 | return err; |
60 | priv->dlen = desc.len; | 56 | priv->dlen = desc.len; |
61 | 57 | ||
62 | err = nft_validate_data_load(ctx, priv->dreg, &priv->data, desc.type); | 58 | priv->dreg = nft_parse_register(tb[NFTA_IMMEDIATE_DREG]); |
59 | err = nft_validate_register_store(ctx, priv->dreg, &priv->data, | ||
60 | desc.type, desc.len); | ||
63 | if (err < 0) | 61 | if (err < 0) |
64 | goto err1; | 62 | goto err1; |
65 | 63 | ||
@@ -81,7 +79,7 @@ static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
81 | { | 79 | { |
82 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); | 80 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); |
83 | 81 | ||
84 | if (nla_put_be32(skb, NFTA_IMMEDIATE_DREG, htonl(priv->dreg))) | 82 | if (nft_dump_register(skb, NFTA_IMMEDIATE_DREG, priv->dreg)) |
85 | goto nla_put_failure; | 83 | goto nla_put_failure; |
86 | 84 | ||
87 | return nft_data_dump(skb, NFTA_IMMEDIATE_DATA, &priv->data, | 85 | return nft_data_dump(skb, NFTA_IMMEDIATE_DATA, &priv->data, |
diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c index 85da5bd02f64..435c1ccd6c0e 100644 --- a/net/netfilter/nft_limit.c +++ b/net/netfilter/nft_limit.c | |||
@@ -27,7 +27,7 @@ struct nft_limit { | |||
27 | }; | 27 | }; |
28 | 28 | ||
29 | static void nft_limit_eval(const struct nft_expr *expr, | 29 | static void nft_limit_eval(const struct nft_expr *expr, |
30 | struct nft_data data[NFT_REG_MAX + 1], | 30 | struct nft_regs *regs, |
31 | const struct nft_pktinfo *pkt) | 31 | const struct nft_pktinfo *pkt) |
32 | { | 32 | { |
33 | struct nft_limit *priv = nft_expr_priv(expr); | 33 | struct nft_limit *priv = nft_expr_priv(expr); |
@@ -45,7 +45,7 @@ static void nft_limit_eval(const struct nft_expr *expr, | |||
45 | } | 45 | } |
46 | spin_unlock_bh(&limit_lock); | 46 | spin_unlock_bh(&limit_lock); |
47 | 47 | ||
48 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 48 | regs->verdict.code = NFT_BREAK; |
49 | } | 49 | } |
50 | 50 | ||
51 | static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = { | 51 | static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = { |
@@ -98,6 +98,7 @@ static struct nft_expr_type nft_limit_type __read_mostly = { | |||
98 | .ops = &nft_limit_ops, | 98 | .ops = &nft_limit_ops, |
99 | .policy = nft_limit_policy, | 99 | .policy = nft_limit_policy, |
100 | .maxattr = NFTA_LIMIT_MAX, | 100 | .maxattr = NFTA_LIMIT_MAX, |
101 | .flags = NFT_EXPR_STATEFUL, | ||
101 | .owner = THIS_MODULE, | 102 | .owner = THIS_MODULE, |
102 | }; | 103 | }; |
103 | 104 | ||
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index e18af9db2f04..a13d6a386d63 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c | |||
@@ -27,7 +27,7 @@ struct nft_log { | |||
27 | }; | 27 | }; |
28 | 28 | ||
29 | static void nft_log_eval(const struct nft_expr *expr, | 29 | static void nft_log_eval(const struct nft_expr *expr, |
30 | struct nft_data data[NFT_REG_MAX + 1], | 30 | struct nft_regs *regs, |
31 | const struct nft_pktinfo *pkt) | 31 | const struct nft_pktinfo *pkt) |
32 | { | 32 | { |
33 | const struct nft_log *priv = nft_expr_priv(expr); | 33 | const struct nft_log *priv = nft_expr_priv(expr); |
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index d8cf86fb30fc..b3c31ef8015d 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c | |||
@@ -26,19 +26,20 @@ struct nft_lookup { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | static void nft_lookup_eval(const struct nft_expr *expr, | 28 | static void nft_lookup_eval(const struct nft_expr *expr, |
29 | struct nft_data data[NFT_REG_MAX + 1], | 29 | struct nft_regs *regs, |
30 | const struct nft_pktinfo *pkt) | 30 | const struct nft_pktinfo *pkt) |
31 | { | 31 | { |
32 | const struct nft_lookup *priv = nft_expr_priv(expr); | 32 | const struct nft_lookup *priv = nft_expr_priv(expr); |
33 | const struct nft_set *set = priv->set; | 33 | const struct nft_set *set = priv->set; |
34 | const struct nft_set_ext *ext; | 34 | const struct nft_set_ext *ext; |
35 | 35 | ||
36 | if (set->ops->lookup(set, &data[priv->sreg], &ext)) { | 36 | if (set->ops->lookup(set, ®s->data[priv->sreg], &ext)) { |
37 | if (set->flags & NFT_SET_MAP) | 37 | if (set->flags & NFT_SET_MAP) |
38 | nft_data_copy(&data[priv->dreg], nft_set_ext_data(ext)); | 38 | nft_data_copy(®s->data[priv->dreg], |
39 | nft_set_ext_data(ext), set->dlen); | ||
39 | return; | 40 | return; |
40 | } | 41 | } |
41 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 42 | regs->verdict.code = NFT_BREAK; |
42 | } | 43 | } |
43 | 44 | ||
44 | static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { | 45 | static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { |
@@ -70,8 +71,11 @@ static int nft_lookup_init(const struct nft_ctx *ctx, | |||
70 | return PTR_ERR(set); | 71 | return PTR_ERR(set); |
71 | } | 72 | } |
72 | 73 | ||
73 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_LOOKUP_SREG])); | 74 | if (set->flags & NFT_SET_EVAL) |
74 | err = nft_validate_input_register(priv->sreg); | 75 | return -EOPNOTSUPP; |
76 | |||
77 | priv->sreg = nft_parse_register(tb[NFTA_LOOKUP_SREG]); | ||
78 | err = nft_validate_register_load(priv->sreg, set->klen); | ||
75 | if (err < 0) | 79 | if (err < 0) |
76 | return err; | 80 | return err; |
77 | 81 | ||
@@ -79,16 +83,11 @@ static int nft_lookup_init(const struct nft_ctx *ctx, | |||
79 | if (!(set->flags & NFT_SET_MAP)) | 83 | if (!(set->flags & NFT_SET_MAP)) |
80 | return -EINVAL; | 84 | return -EINVAL; |
81 | 85 | ||
82 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_LOOKUP_DREG])); | 86 | priv->dreg = nft_parse_register(tb[NFTA_LOOKUP_DREG]); |
83 | err = nft_validate_output_register(priv->dreg); | 87 | err = nft_validate_register_store(ctx, priv->dreg, NULL, |
88 | set->dtype, set->dlen); | ||
84 | if (err < 0) | 89 | if (err < 0) |
85 | return err; | 90 | return err; |
86 | |||
87 | if (priv->dreg == NFT_REG_VERDICT) { | ||
88 | if (set->dtype != NFT_DATA_VERDICT) | ||
89 | return -EINVAL; | ||
90 | } else if (set->dtype == NFT_DATA_VERDICT) | ||
91 | return -EINVAL; | ||
92 | } else if (set->flags & NFT_SET_MAP) | 91 | } else if (set->flags & NFT_SET_MAP) |
93 | return -EINVAL; | 92 | return -EINVAL; |
94 | 93 | ||
@@ -116,10 +115,10 @@ static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
116 | 115 | ||
117 | if (nla_put_string(skb, NFTA_LOOKUP_SET, priv->set->name)) | 116 | if (nla_put_string(skb, NFTA_LOOKUP_SET, priv->set->name)) |
118 | goto nla_put_failure; | 117 | goto nla_put_failure; |
119 | if (nla_put_be32(skb, NFTA_LOOKUP_SREG, htonl(priv->sreg))) | 118 | if (nft_dump_register(skb, NFTA_LOOKUP_SREG, priv->sreg)) |
120 | goto nla_put_failure; | 119 | goto nla_put_failure; |
121 | if (priv->set->flags & NFT_SET_MAP) | 120 | if (priv->set->flags & NFT_SET_MAP) |
122 | if (nla_put_be32(skb, NFTA_LOOKUP_DREG, htonl(priv->dreg))) | 121 | if (nft_dump_register(skb, NFTA_LOOKUP_DREG, priv->dreg)) |
123 | goto nla_put_failure; | 122 | goto nla_put_failure; |
124 | return 0; | 123 | return 0; |
125 | 124 | ||
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index d79ce88be77f..52561e1c31e2 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c | |||
@@ -25,62 +25,65 @@ | |||
25 | #include <net/netfilter/nft_meta.h> | 25 | #include <net/netfilter/nft_meta.h> |
26 | 26 | ||
27 | void nft_meta_get_eval(const struct nft_expr *expr, | 27 | void nft_meta_get_eval(const struct nft_expr *expr, |
28 | struct nft_data data[NFT_REG_MAX + 1], | 28 | struct nft_regs *regs, |
29 | const struct nft_pktinfo *pkt) | 29 | const struct nft_pktinfo *pkt) |
30 | { | 30 | { |
31 | const struct nft_meta *priv = nft_expr_priv(expr); | 31 | const struct nft_meta *priv = nft_expr_priv(expr); |
32 | const struct sk_buff *skb = pkt->skb; | 32 | const struct sk_buff *skb = pkt->skb; |
33 | const struct net_device *in = pkt->in, *out = pkt->out; | 33 | const struct net_device *in = pkt->in, *out = pkt->out; |
34 | struct nft_data *dest = &data[priv->dreg]; | 34 | u32 *dest = ®s->data[priv->dreg]; |
35 | 35 | ||
36 | switch (priv->key) { | 36 | switch (priv->key) { |
37 | case NFT_META_LEN: | 37 | case NFT_META_LEN: |
38 | dest->data[0] = skb->len; | 38 | *dest = skb->len; |
39 | break; | 39 | break; |
40 | case NFT_META_PROTOCOL: | 40 | case NFT_META_PROTOCOL: |
41 | *(__be16 *)dest->data = skb->protocol; | 41 | *dest = 0; |
42 | *(__be16 *)dest = skb->protocol; | ||
42 | break; | 43 | break; |
43 | case NFT_META_NFPROTO: | 44 | case NFT_META_NFPROTO: |
44 | dest->data[0] = pkt->ops->pf; | 45 | *dest = pkt->ops->pf; |
45 | break; | 46 | break; |
46 | case NFT_META_L4PROTO: | 47 | case NFT_META_L4PROTO: |
47 | dest->data[0] = pkt->tprot; | 48 | *dest = pkt->tprot; |
48 | break; | 49 | break; |
49 | case NFT_META_PRIORITY: | 50 | case NFT_META_PRIORITY: |
50 | dest->data[0] = skb->priority; | 51 | *dest = skb->priority; |
51 | break; | 52 | break; |
52 | case NFT_META_MARK: | 53 | case NFT_META_MARK: |
53 | dest->data[0] = skb->mark; | 54 | *dest = skb->mark; |
54 | break; | 55 | break; |
55 | case NFT_META_IIF: | 56 | case NFT_META_IIF: |
56 | if (in == NULL) | 57 | if (in == NULL) |
57 | goto err; | 58 | goto err; |
58 | dest->data[0] = in->ifindex; | 59 | *dest = in->ifindex; |
59 | break; | 60 | break; |
60 | case NFT_META_OIF: | 61 | case NFT_META_OIF: |
61 | if (out == NULL) | 62 | if (out == NULL) |
62 | goto err; | 63 | goto err; |
63 | dest->data[0] = out->ifindex; | 64 | *dest = out->ifindex; |
64 | break; | 65 | break; |
65 | case NFT_META_IIFNAME: | 66 | case NFT_META_IIFNAME: |
66 | if (in == NULL) | 67 | if (in == NULL) |
67 | goto err; | 68 | goto err; |
68 | strncpy((char *)dest->data, in->name, sizeof(dest->data)); | 69 | strncpy((char *)dest, in->name, IFNAMSIZ); |
69 | break; | 70 | break; |
70 | case NFT_META_OIFNAME: | 71 | case NFT_META_OIFNAME: |
71 | if (out == NULL) | 72 | if (out == NULL) |
72 | goto err; | 73 | goto err; |
73 | strncpy((char *)dest->data, out->name, sizeof(dest->data)); | 74 | strncpy((char *)dest, out->name, IFNAMSIZ); |
74 | break; | 75 | break; |
75 | case NFT_META_IIFTYPE: | 76 | case NFT_META_IIFTYPE: |
76 | if (in == NULL) | 77 | if (in == NULL) |
77 | goto err; | 78 | goto err; |
78 | *(u16 *)dest->data = in->type; | 79 | *dest = 0; |
80 | *(u16 *)dest = in->type; | ||
79 | break; | 81 | break; |
80 | case NFT_META_OIFTYPE: | 82 | case NFT_META_OIFTYPE: |
81 | if (out == NULL) | 83 | if (out == NULL) |
82 | goto err; | 84 | goto err; |
83 | *(u16 *)dest->data = out->type; | 85 | *dest = 0; |
86 | *(u16 *)dest = out->type; | ||
84 | break; | 87 | break; |
85 | case NFT_META_SKUID: | 88 | case NFT_META_SKUID: |
86 | if (skb->sk == NULL || !sk_fullsock(skb->sk)) | 89 | if (skb->sk == NULL || !sk_fullsock(skb->sk)) |
@@ -93,8 +96,7 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
93 | goto err; | 96 | goto err; |
94 | } | 97 | } |
95 | 98 | ||
96 | dest->data[0] = | 99 | *dest = from_kuid_munged(&init_user_ns, |
97 | from_kuid_munged(&init_user_ns, | ||
98 | skb->sk->sk_socket->file->f_cred->fsuid); | 100 | skb->sk->sk_socket->file->f_cred->fsuid); |
99 | read_unlock_bh(&skb->sk->sk_callback_lock); | 101 | read_unlock_bh(&skb->sk->sk_callback_lock); |
100 | break; | 102 | break; |
@@ -108,8 +110,7 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
108 | read_unlock_bh(&skb->sk->sk_callback_lock); | 110 | read_unlock_bh(&skb->sk->sk_callback_lock); |
109 | goto err; | 111 | goto err; |
110 | } | 112 | } |
111 | dest->data[0] = | 113 | *dest = from_kgid_munged(&init_user_ns, |
112 | from_kgid_munged(&init_user_ns, | ||
113 | skb->sk->sk_socket->file->f_cred->fsgid); | 114 | skb->sk->sk_socket->file->f_cred->fsgid); |
114 | read_unlock_bh(&skb->sk->sk_callback_lock); | 115 | read_unlock_bh(&skb->sk->sk_callback_lock); |
115 | break; | 116 | break; |
@@ -119,33 +120,33 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
119 | 120 | ||
120 | if (dst == NULL) | 121 | if (dst == NULL) |
121 | goto err; | 122 | goto err; |
122 | dest->data[0] = dst->tclassid; | 123 | *dest = dst->tclassid; |
123 | break; | 124 | break; |
124 | } | 125 | } |
125 | #endif | 126 | #endif |
126 | #ifdef CONFIG_NETWORK_SECMARK | 127 | #ifdef CONFIG_NETWORK_SECMARK |
127 | case NFT_META_SECMARK: | 128 | case NFT_META_SECMARK: |
128 | dest->data[0] = skb->secmark; | 129 | *dest = skb->secmark; |
129 | break; | 130 | break; |
130 | #endif | 131 | #endif |
131 | case NFT_META_PKTTYPE: | 132 | case NFT_META_PKTTYPE: |
132 | if (skb->pkt_type != PACKET_LOOPBACK) { | 133 | if (skb->pkt_type != PACKET_LOOPBACK) { |
133 | dest->data[0] = skb->pkt_type; | 134 | *dest = skb->pkt_type; |
134 | break; | 135 | break; |
135 | } | 136 | } |
136 | 137 | ||
137 | switch (pkt->ops->pf) { | 138 | switch (pkt->ops->pf) { |
138 | case NFPROTO_IPV4: | 139 | case NFPROTO_IPV4: |
139 | if (ipv4_is_multicast(ip_hdr(skb)->daddr)) | 140 | if (ipv4_is_multicast(ip_hdr(skb)->daddr)) |
140 | dest->data[0] = PACKET_MULTICAST; | 141 | *dest = PACKET_MULTICAST; |
141 | else | 142 | else |
142 | dest->data[0] = PACKET_BROADCAST; | 143 | *dest = PACKET_BROADCAST; |
143 | break; | 144 | break; |
144 | case NFPROTO_IPV6: | 145 | case NFPROTO_IPV6: |
145 | if (ipv6_hdr(skb)->daddr.s6_addr[0] == 0xFF) | 146 | if (ipv6_hdr(skb)->daddr.s6_addr[0] == 0xFF) |
146 | dest->data[0] = PACKET_MULTICAST; | 147 | *dest = PACKET_MULTICAST; |
147 | else | 148 | else |
148 | dest->data[0] = PACKET_BROADCAST; | 149 | *dest = PACKET_BROADCAST; |
149 | break; | 150 | break; |
150 | default: | 151 | default: |
151 | WARN_ON(1); | 152 | WARN_ON(1); |
@@ -153,22 +154,22 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
153 | } | 154 | } |
154 | break; | 155 | break; |
155 | case NFT_META_CPU: | 156 | case NFT_META_CPU: |
156 | dest->data[0] = raw_smp_processor_id(); | 157 | *dest = raw_smp_processor_id(); |
157 | break; | 158 | break; |
158 | case NFT_META_IIFGROUP: | 159 | case NFT_META_IIFGROUP: |
159 | if (in == NULL) | 160 | if (in == NULL) |
160 | goto err; | 161 | goto err; |
161 | dest->data[0] = in->group; | 162 | *dest = in->group; |
162 | break; | 163 | break; |
163 | case NFT_META_OIFGROUP: | 164 | case NFT_META_OIFGROUP: |
164 | if (out == NULL) | 165 | if (out == NULL) |
165 | goto err; | 166 | goto err; |
166 | dest->data[0] = out->group; | 167 | *dest = out->group; |
167 | break; | 168 | break; |
168 | case NFT_META_CGROUP: | 169 | case NFT_META_CGROUP: |
169 | if (skb->sk == NULL || !sk_fullsock(skb->sk)) | 170 | if (skb->sk == NULL || !sk_fullsock(skb->sk)) |
170 | goto err; | 171 | goto err; |
171 | dest->data[0] = skb->sk->sk_classid; | 172 | *dest = skb->sk->sk_classid; |
172 | break; | 173 | break; |
173 | default: | 174 | default: |
174 | WARN_ON(1); | 175 | WARN_ON(1); |
@@ -177,17 +178,17 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
177 | return; | 178 | return; |
178 | 179 | ||
179 | err: | 180 | err: |
180 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 181 | regs->verdict.code = NFT_BREAK; |
181 | } | 182 | } |
182 | EXPORT_SYMBOL_GPL(nft_meta_get_eval); | 183 | EXPORT_SYMBOL_GPL(nft_meta_get_eval); |
183 | 184 | ||
184 | void nft_meta_set_eval(const struct nft_expr *expr, | 185 | void nft_meta_set_eval(const struct nft_expr *expr, |
185 | struct nft_data data[NFT_REG_MAX + 1], | 186 | struct nft_regs *regs, |
186 | const struct nft_pktinfo *pkt) | 187 | const struct nft_pktinfo *pkt) |
187 | { | 188 | { |
188 | const struct nft_meta *meta = nft_expr_priv(expr); | 189 | const struct nft_meta *meta = nft_expr_priv(expr); |
189 | struct sk_buff *skb = pkt->skb; | 190 | struct sk_buff *skb = pkt->skb; |
190 | u32 value = data[meta->sreg].data[0]; | 191 | u32 value = regs->data[meta->sreg]; |
191 | 192 | ||
192 | switch (meta->key) { | 193 | switch (meta->key) { |
193 | case NFT_META_MARK: | 194 | case NFT_META_MARK: |
@@ -217,22 +218,22 @@ int nft_meta_get_init(const struct nft_ctx *ctx, | |||
217 | const struct nlattr * const tb[]) | 218 | const struct nlattr * const tb[]) |
218 | { | 219 | { |
219 | struct nft_meta *priv = nft_expr_priv(expr); | 220 | struct nft_meta *priv = nft_expr_priv(expr); |
220 | int err; | 221 | unsigned int len; |
221 | 222 | ||
222 | priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); | 223 | priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); |
223 | switch (priv->key) { | 224 | switch (priv->key) { |
224 | case NFT_META_LEN: | ||
225 | case NFT_META_PROTOCOL: | 225 | case NFT_META_PROTOCOL: |
226 | case NFT_META_IIFTYPE: | ||
227 | case NFT_META_OIFTYPE: | ||
228 | len = sizeof(u16); | ||
229 | break; | ||
226 | case NFT_META_NFPROTO: | 230 | case NFT_META_NFPROTO: |
227 | case NFT_META_L4PROTO: | 231 | case NFT_META_L4PROTO: |
232 | case NFT_META_LEN: | ||
228 | case NFT_META_PRIORITY: | 233 | case NFT_META_PRIORITY: |
229 | case NFT_META_MARK: | 234 | case NFT_META_MARK: |
230 | case NFT_META_IIF: | 235 | case NFT_META_IIF: |
231 | case NFT_META_OIF: | 236 | case NFT_META_OIF: |
232 | case NFT_META_IIFNAME: | ||
233 | case NFT_META_OIFNAME: | ||
234 | case NFT_META_IIFTYPE: | ||
235 | case NFT_META_OIFTYPE: | ||
236 | case NFT_META_SKUID: | 237 | case NFT_META_SKUID: |
237 | case NFT_META_SKGID: | 238 | case NFT_META_SKGID: |
238 | #ifdef CONFIG_IP_ROUTE_CLASSID | 239 | #ifdef CONFIG_IP_ROUTE_CLASSID |
@@ -246,21 +247,19 @@ int nft_meta_get_init(const struct nft_ctx *ctx, | |||
246 | case NFT_META_IIFGROUP: | 247 | case NFT_META_IIFGROUP: |
247 | case NFT_META_OIFGROUP: | 248 | case NFT_META_OIFGROUP: |
248 | case NFT_META_CGROUP: | 249 | case NFT_META_CGROUP: |
250 | len = sizeof(u32); | ||
251 | break; | ||
252 | case NFT_META_IIFNAME: | ||
253 | case NFT_META_OIFNAME: | ||
254 | len = IFNAMSIZ; | ||
249 | break; | 255 | break; |
250 | default: | 256 | default: |
251 | return -EOPNOTSUPP; | 257 | return -EOPNOTSUPP; |
252 | } | 258 | } |
253 | 259 | ||
254 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG])); | 260 | priv->dreg = nft_parse_register(tb[NFTA_META_DREG]); |
255 | err = nft_validate_output_register(priv->dreg); | 261 | return nft_validate_register_store(ctx, priv->dreg, NULL, |
256 | if (err < 0) | 262 | NFT_DATA_VALUE, len); |
257 | return err; | ||
258 | |||
259 | err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); | ||
260 | if (err < 0) | ||
261 | return err; | ||
262 | |||
263 | return 0; | ||
264 | } | 263 | } |
265 | EXPORT_SYMBOL_GPL(nft_meta_get_init); | 264 | EXPORT_SYMBOL_GPL(nft_meta_get_init); |
266 | 265 | ||
@@ -269,20 +268,24 @@ int nft_meta_set_init(const struct nft_ctx *ctx, | |||
269 | const struct nlattr * const tb[]) | 268 | const struct nlattr * const tb[]) |
270 | { | 269 | { |
271 | struct nft_meta *priv = nft_expr_priv(expr); | 270 | struct nft_meta *priv = nft_expr_priv(expr); |
271 | unsigned int len; | ||
272 | int err; | 272 | int err; |
273 | 273 | ||
274 | priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); | 274 | priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); |
275 | switch (priv->key) { | 275 | switch (priv->key) { |
276 | case NFT_META_MARK: | 276 | case NFT_META_MARK: |
277 | case NFT_META_PRIORITY: | 277 | case NFT_META_PRIORITY: |
278 | len = sizeof(u32); | ||
279 | break; | ||
278 | case NFT_META_NFTRACE: | 280 | case NFT_META_NFTRACE: |
281 | len = sizeof(u8); | ||
279 | break; | 282 | break; |
280 | default: | 283 | default: |
281 | return -EOPNOTSUPP; | 284 | return -EOPNOTSUPP; |
282 | } | 285 | } |
283 | 286 | ||
284 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_META_SREG])); | 287 | priv->sreg = nft_parse_register(tb[NFTA_META_SREG]); |
285 | err = nft_validate_input_register(priv->sreg); | 288 | err = nft_validate_register_load(priv->sreg, len); |
286 | if (err < 0) | 289 | if (err < 0) |
287 | return err; | 290 | return err; |
288 | 291 | ||
@@ -297,7 +300,7 @@ int nft_meta_get_dump(struct sk_buff *skb, | |||
297 | 300 | ||
298 | if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key))) | 301 | if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key))) |
299 | goto nla_put_failure; | 302 | goto nla_put_failure; |
300 | if (nla_put_be32(skb, NFTA_META_DREG, htonl(priv->dreg))) | 303 | if (nft_dump_register(skb, NFTA_META_DREG, priv->dreg)) |
301 | goto nla_put_failure; | 304 | goto nla_put_failure; |
302 | return 0; | 305 | return 0; |
303 | 306 | ||
@@ -313,7 +316,7 @@ int nft_meta_set_dump(struct sk_buff *skb, | |||
313 | 316 | ||
314 | if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key))) | 317 | if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key))) |
315 | goto nla_put_failure; | 318 | goto nla_put_failure; |
316 | if (nla_put_be32(skb, NFTA_META_SREG, htonl(priv->sreg))) | 319 | if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg)) |
317 | goto nla_put_failure; | 320 | goto nla_put_failure; |
318 | 321 | ||
319 | return 0; | 322 | return 0; |
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c index a0837c6c9283..ee2d71753746 100644 --- a/net/netfilter/nft_nat.c +++ b/net/netfilter/nft_nat.c | |||
@@ -37,7 +37,7 @@ struct nft_nat { | |||
37 | }; | 37 | }; |
38 | 38 | ||
39 | static void nft_nat_eval(const struct nft_expr *expr, | 39 | static void nft_nat_eval(const struct nft_expr *expr, |
40 | struct nft_data data[NFT_REG_MAX + 1], | 40 | struct nft_regs *regs, |
41 | const struct nft_pktinfo *pkt) | 41 | const struct nft_pktinfo *pkt) |
42 | { | 42 | { |
43 | const struct nft_nat *priv = nft_expr_priv(expr); | 43 | const struct nft_nat *priv = nft_expr_priv(expr); |
@@ -49,33 +49,32 @@ static void nft_nat_eval(const struct nft_expr *expr, | |||
49 | if (priv->sreg_addr_min) { | 49 | if (priv->sreg_addr_min) { |
50 | if (priv->family == AF_INET) { | 50 | if (priv->family == AF_INET) { |
51 | range.min_addr.ip = (__force __be32) | 51 | range.min_addr.ip = (__force __be32) |
52 | data[priv->sreg_addr_min].data[0]; | 52 | regs->data[priv->sreg_addr_min]; |
53 | range.max_addr.ip = (__force __be32) | 53 | range.max_addr.ip = (__force __be32) |
54 | data[priv->sreg_addr_max].data[0]; | 54 | regs->data[priv->sreg_addr_max]; |
55 | 55 | ||
56 | } else { | 56 | } else { |
57 | memcpy(range.min_addr.ip6, | 57 | memcpy(range.min_addr.ip6, |
58 | data[priv->sreg_addr_min].data, | 58 | ®s->data[priv->sreg_addr_min], |
59 | sizeof(struct nft_data)); | 59 | sizeof(range.min_addr.ip6)); |
60 | memcpy(range.max_addr.ip6, | 60 | memcpy(range.max_addr.ip6, |
61 | data[priv->sreg_addr_max].data, | 61 | ®s->data[priv->sreg_addr_max], |
62 | sizeof(struct nft_data)); | 62 | sizeof(range.max_addr.ip6)); |
63 | } | 63 | } |
64 | range.flags |= NF_NAT_RANGE_MAP_IPS; | 64 | range.flags |= NF_NAT_RANGE_MAP_IPS; |
65 | } | 65 | } |
66 | 66 | ||
67 | if (priv->sreg_proto_min) { | 67 | if (priv->sreg_proto_min) { |
68 | range.min_proto.all = | 68 | range.min_proto.all = |
69 | *(__be16 *)&data[priv->sreg_proto_min].data[0]; | 69 | *(__be16 *)®s->data[priv->sreg_proto_min]; |
70 | range.max_proto.all = | 70 | range.max_proto.all = |
71 | *(__be16 *)&data[priv->sreg_proto_max].data[0]; | 71 | *(__be16 *)®s->data[priv->sreg_proto_max]; |
72 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 72 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
73 | } | 73 | } |
74 | 74 | ||
75 | range.flags |= priv->flags; | 75 | range.flags |= priv->flags; |
76 | 76 | ||
77 | data[NFT_REG_VERDICT].verdict = | 77 | regs->verdict.code = nf_nat_setup_info(ct, &range, priv->type); |
78 | nf_nat_setup_info(ct, &range, priv->type); | ||
79 | } | 78 | } |
80 | 79 | ||
81 | static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = { | 80 | static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = { |
@@ -119,6 +118,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
119 | const struct nlattr * const tb[]) | 118 | const struct nlattr * const tb[]) |
120 | { | 119 | { |
121 | struct nft_nat *priv = nft_expr_priv(expr); | 120 | struct nft_nat *priv = nft_expr_priv(expr); |
121 | unsigned int alen, plen; | ||
122 | u32 family; | 122 | u32 family; |
123 | int err; | 123 | int err; |
124 | 124 | ||
@@ -146,25 +146,34 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
146 | return -EINVAL; | 146 | return -EINVAL; |
147 | 147 | ||
148 | family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); | 148 | family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); |
149 | if (family != AF_INET && family != AF_INET6) | ||
150 | return -EAFNOSUPPORT; | ||
151 | if (family != ctx->afi->family) | 149 | if (family != ctx->afi->family) |
152 | return -EOPNOTSUPP; | 150 | return -EOPNOTSUPP; |
151 | |||
152 | switch (family) { | ||
153 | case NFPROTO_IPV4: | ||
154 | alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip); | ||
155 | break; | ||
156 | case NFPROTO_IPV6: | ||
157 | alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip6); | ||
158 | break; | ||
159 | default: | ||
160 | return -EAFNOSUPPORT; | ||
161 | } | ||
153 | priv->family = family; | 162 | priv->family = family; |
154 | 163 | ||
155 | if (tb[NFTA_NAT_REG_ADDR_MIN]) { | 164 | if (tb[NFTA_NAT_REG_ADDR_MIN]) { |
156 | priv->sreg_addr_min = | 165 | priv->sreg_addr_min = |
157 | ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN])); | 166 | nft_parse_register(tb[NFTA_NAT_REG_ADDR_MIN]); |
158 | 167 | err = nft_validate_register_load(priv->sreg_addr_min, alen); | |
159 | err = nft_validate_input_register(priv->sreg_addr_min); | ||
160 | if (err < 0) | 168 | if (err < 0) |
161 | return err; | 169 | return err; |
162 | 170 | ||
163 | if (tb[NFTA_NAT_REG_ADDR_MAX]) { | 171 | if (tb[NFTA_NAT_REG_ADDR_MAX]) { |
164 | priv->sreg_addr_max = | 172 | priv->sreg_addr_max = |
165 | ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX])); | 173 | nft_parse_register(tb[NFTA_NAT_REG_ADDR_MAX]); |
166 | 174 | ||
167 | err = nft_validate_input_register(priv->sreg_addr_max); | 175 | err = nft_validate_register_load(priv->sreg_addr_max, |
176 | alen); | ||
168 | if (err < 0) | 177 | if (err < 0) |
169 | return err; | 178 | return err; |
170 | } else { | 179 | } else { |
@@ -172,19 +181,21 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
172 | } | 181 | } |
173 | } | 182 | } |
174 | 183 | ||
184 | plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all); | ||
175 | if (tb[NFTA_NAT_REG_PROTO_MIN]) { | 185 | if (tb[NFTA_NAT_REG_PROTO_MIN]) { |
176 | priv->sreg_proto_min = | 186 | priv->sreg_proto_min = |
177 | ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN])); | 187 | nft_parse_register(tb[NFTA_NAT_REG_PROTO_MIN]); |
178 | 188 | ||
179 | err = nft_validate_input_register(priv->sreg_proto_min); | 189 | err = nft_validate_register_load(priv->sreg_proto_min, plen); |
180 | if (err < 0) | 190 | if (err < 0) |
181 | return err; | 191 | return err; |
182 | 192 | ||
183 | if (tb[NFTA_NAT_REG_PROTO_MAX]) { | 193 | if (tb[NFTA_NAT_REG_PROTO_MAX]) { |
184 | priv->sreg_proto_max = | 194 | priv->sreg_proto_max = |
185 | ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX])); | 195 | nft_parse_register(tb[NFTA_NAT_REG_PROTO_MAX]); |
186 | 196 | ||
187 | err = nft_validate_input_register(priv->sreg_proto_max); | 197 | err = nft_validate_register_load(priv->sreg_proto_max, |
198 | plen); | ||
188 | if (err < 0) | 199 | if (err < 0) |
189 | return err; | 200 | return err; |
190 | } else { | 201 | } else { |
@@ -220,18 +231,18 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
220 | goto nla_put_failure; | 231 | goto nla_put_failure; |
221 | 232 | ||
222 | if (priv->sreg_addr_min) { | 233 | if (priv->sreg_addr_min) { |
223 | if (nla_put_be32(skb, NFTA_NAT_REG_ADDR_MIN, | 234 | if (nft_dump_register(skb, NFTA_NAT_REG_ADDR_MIN, |
224 | htonl(priv->sreg_addr_min)) || | 235 | priv->sreg_addr_min) || |
225 | nla_put_be32(skb, NFTA_NAT_REG_ADDR_MAX, | 236 | nft_dump_register(skb, NFTA_NAT_REG_ADDR_MAX, |
226 | htonl(priv->sreg_addr_max))) | 237 | priv->sreg_addr_max)) |
227 | goto nla_put_failure; | 238 | goto nla_put_failure; |
228 | } | 239 | } |
229 | 240 | ||
230 | if (priv->sreg_proto_min) { | 241 | if (priv->sreg_proto_min) { |
231 | if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN, | 242 | if (nft_dump_register(skb, NFTA_NAT_REG_PROTO_MIN, |
232 | htonl(priv->sreg_proto_min)) || | 243 | priv->sreg_proto_min) || |
233 | nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX, | 244 | nft_dump_register(skb, NFTA_NAT_REG_PROTO_MAX, |
234 | htonl(priv->sreg_proto_max))) | 245 | priv->sreg_proto_max)) |
235 | goto nla_put_failure; | 246 | goto nla_put_failure; |
236 | } | 247 | } |
237 | 248 | ||
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 85daa84bfdfe..94fb3b27a2c5 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c | |||
@@ -18,12 +18,12 @@ | |||
18 | #include <net/netfilter/nf_tables.h> | 18 | #include <net/netfilter/nf_tables.h> |
19 | 19 | ||
20 | static void nft_payload_eval(const struct nft_expr *expr, | 20 | static void nft_payload_eval(const struct nft_expr *expr, |
21 | struct nft_data data[NFT_REG_MAX + 1], | 21 | struct nft_regs *regs, |
22 | const struct nft_pktinfo *pkt) | 22 | const struct nft_pktinfo *pkt) |
23 | { | 23 | { |
24 | const struct nft_payload *priv = nft_expr_priv(expr); | 24 | const struct nft_payload *priv = nft_expr_priv(expr); |
25 | const struct sk_buff *skb = pkt->skb; | 25 | const struct sk_buff *skb = pkt->skb; |
26 | struct nft_data *dest = &data[priv->dreg]; | 26 | u32 *dest = ®s->data[priv->dreg]; |
27 | int offset; | 27 | int offset; |
28 | 28 | ||
29 | switch (priv->base) { | 29 | switch (priv->base) { |
@@ -43,11 +43,12 @@ static void nft_payload_eval(const struct nft_expr *expr, | |||
43 | } | 43 | } |
44 | offset += priv->offset; | 44 | offset += priv->offset; |
45 | 45 | ||
46 | if (skb_copy_bits(skb, offset, dest->data, priv->len) < 0) | 46 | dest[priv->len / NFT_REG32_SIZE] = 0; |
47 | if (skb_copy_bits(skb, offset, dest, priv->len) < 0) | ||
47 | goto err; | 48 | goto err; |
48 | return; | 49 | return; |
49 | err: | 50 | err: |
50 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 51 | regs->verdict.code = NFT_BREAK; |
51 | } | 52 | } |
52 | 53 | ||
53 | static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { | 54 | static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { |
@@ -62,24 +63,21 @@ static int nft_payload_init(const struct nft_ctx *ctx, | |||
62 | const struct nlattr * const tb[]) | 63 | const struct nlattr * const tb[]) |
63 | { | 64 | { |
64 | struct nft_payload *priv = nft_expr_priv(expr); | 65 | struct nft_payload *priv = nft_expr_priv(expr); |
65 | int err; | ||
66 | 66 | ||
67 | priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); | 67 | priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); |
68 | priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); | 68 | priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); |
69 | priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); | 69 | priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); |
70 | priv->dreg = nft_parse_register(tb[NFTA_PAYLOAD_DREG]); | ||
70 | 71 | ||
71 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_DREG])); | 72 | return nft_validate_register_store(ctx, priv->dreg, NULL, |
72 | err = nft_validate_output_register(priv->dreg); | 73 | NFT_DATA_VALUE, priv->len); |
73 | if (err < 0) | ||
74 | return err; | ||
75 | return nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); | ||
76 | } | 74 | } |
77 | 75 | ||
78 | static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr) | 76 | static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr) |
79 | { | 77 | { |
80 | const struct nft_payload *priv = nft_expr_priv(expr); | 78 | const struct nft_payload *priv = nft_expr_priv(expr); |
81 | 79 | ||
82 | if (nla_put_be32(skb, NFTA_PAYLOAD_DREG, htonl(priv->dreg)) || | 80 | if (nft_dump_register(skb, NFTA_PAYLOAD_DREG, priv->dreg) || |
83 | nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) || | 81 | nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) || |
84 | nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) || | 82 | nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) || |
85 | nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len))) | 83 | nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len))) |
@@ -131,9 +129,7 @@ nft_payload_select_ops(const struct nft_ctx *ctx, | |||
131 | } | 129 | } |
132 | 130 | ||
133 | offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); | 131 | offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); |
134 | len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); | 132 | len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); |
135 | if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data)) | ||
136 | return ERR_PTR(-EINVAL); | ||
137 | 133 | ||
138 | if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) && | 134 | if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) && |
139 | base != NFT_PAYLOAD_LL_HEADER) | 135 | base != NFT_PAYLOAD_LL_HEADER) |
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c index e8ae2f6bf232..96805d21d618 100644 --- a/net/netfilter/nft_queue.c +++ b/net/netfilter/nft_queue.c | |||
@@ -28,7 +28,7 @@ struct nft_queue { | |||
28 | }; | 28 | }; |
29 | 29 | ||
30 | static void nft_queue_eval(const struct nft_expr *expr, | 30 | static void nft_queue_eval(const struct nft_expr *expr, |
31 | struct nft_data data[NFT_REG_MAX + 1], | 31 | struct nft_regs *regs, |
32 | const struct nft_pktinfo *pkt) | 32 | const struct nft_pktinfo *pkt) |
33 | { | 33 | { |
34 | struct nft_queue *priv = nft_expr_priv(expr); | 34 | struct nft_queue *priv = nft_expr_priv(expr); |
@@ -51,7 +51,7 @@ static void nft_queue_eval(const struct nft_expr *expr, | |||
51 | if (priv->flags & NFT_QUEUE_FLAG_BYPASS) | 51 | if (priv->flags & NFT_QUEUE_FLAG_BYPASS) |
52 | ret |= NF_VERDICT_FLAG_QUEUE_BYPASS; | 52 | ret |= NF_VERDICT_FLAG_QUEUE_BYPASS; |
53 | 53 | ||
54 | data[NFT_REG_VERDICT].verdict = ret; | 54 | regs->verdict.code = ret; |
55 | } | 55 | } |
56 | 56 | ||
57 | static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = { | 57 | static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = { |
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c index 42d0ca45fb9e..1c30f41cff5b 100644 --- a/net/netfilter/nft_rbtree.c +++ b/net/netfilter/nft_rbtree.c | |||
@@ -30,8 +30,7 @@ struct nft_rbtree_elem { | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | 32 | ||
33 | static bool nft_rbtree_lookup(const struct nft_set *set, | 33 | static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key, |
34 | const struct nft_data *key, | ||
35 | const struct nft_set_ext **ext) | 34 | const struct nft_set_ext **ext) |
36 | { | 35 | { |
37 | const struct nft_rbtree *priv = nft_set_priv(set); | 36 | const struct nft_rbtree *priv = nft_set_priv(set); |
@@ -45,7 +44,7 @@ static bool nft_rbtree_lookup(const struct nft_set *set, | |||
45 | while (parent != NULL) { | 44 | while (parent != NULL) { |
46 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); | 45 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); |
47 | 46 | ||
48 | d = nft_data_cmp(nft_set_ext_key(&rbe->ext), key, set->klen); | 47 | d = memcmp(nft_set_ext_key(&rbe->ext), key, set->klen); |
49 | if (d < 0) { | 48 | if (d < 0) { |
50 | parent = parent->rb_left; | 49 | parent = parent->rb_left; |
51 | interval = rbe; | 50 | interval = rbe; |
@@ -91,9 +90,9 @@ static int __nft_rbtree_insert(const struct nft_set *set, | |||
91 | while (*p != NULL) { | 90 | while (*p != NULL) { |
92 | parent = *p; | 91 | parent = *p; |
93 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); | 92 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); |
94 | d = nft_data_cmp(nft_set_ext_key(&rbe->ext), | 93 | d = memcmp(nft_set_ext_key(&rbe->ext), |
95 | nft_set_ext_key(&new->ext), | 94 | nft_set_ext_key(&new->ext), |
96 | set->klen); | 95 | set->klen); |
97 | if (d < 0) | 96 | if (d < 0) |
98 | p = &parent->rb_left; | 97 | p = &parent->rb_left; |
99 | else if (d > 0) | 98 | else if (d > 0) |
@@ -153,8 +152,8 @@ static void *nft_rbtree_deactivate(const struct nft_set *set, | |||
153 | while (parent != NULL) { | 152 | while (parent != NULL) { |
154 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); | 153 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); |
155 | 154 | ||
156 | d = nft_data_cmp(nft_set_ext_key(&rbe->ext), &elem->key, | 155 | d = memcmp(nft_set_ext_key(&rbe->ext), &elem->key.val, |
157 | set->klen); | 156 | set->klen); |
158 | if (d < 0) | 157 | if (d < 0) |
159 | parent = parent->rb_left; | 158 | parent = parent->rb_left; |
160 | else if (d > 0) | 159 | else if (d > 0) |
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c index d7e9e93a4e90..03f7bf40ae75 100644 --- a/net/netfilter/nft_redir.c +++ b/net/netfilter/nft_redir.c | |||
@@ -44,25 +44,28 @@ int nft_redir_init(const struct nft_ctx *ctx, | |||
44 | const struct nlattr * const tb[]) | 44 | const struct nlattr * const tb[]) |
45 | { | 45 | { |
46 | struct nft_redir *priv = nft_expr_priv(expr); | 46 | struct nft_redir *priv = nft_expr_priv(expr); |
47 | unsigned int plen; | ||
47 | int err; | 48 | int err; |
48 | 49 | ||
49 | err = nft_redir_validate(ctx, expr, NULL); | 50 | err = nft_redir_validate(ctx, expr, NULL); |
50 | if (err < 0) | 51 | if (err < 0) |
51 | return err; | 52 | return err; |
52 | 53 | ||
54 | plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all); | ||
53 | if (tb[NFTA_REDIR_REG_PROTO_MIN]) { | 55 | if (tb[NFTA_REDIR_REG_PROTO_MIN]) { |
54 | priv->sreg_proto_min = | 56 | priv->sreg_proto_min = |
55 | ntohl(nla_get_be32(tb[NFTA_REDIR_REG_PROTO_MIN])); | 57 | nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MIN]); |
56 | 58 | ||
57 | err = nft_validate_input_register(priv->sreg_proto_min); | 59 | err = nft_validate_register_load(priv->sreg_proto_min, plen); |
58 | if (err < 0) | 60 | if (err < 0) |
59 | return err; | 61 | return err; |
60 | 62 | ||
61 | if (tb[NFTA_REDIR_REG_PROTO_MAX]) { | 63 | if (tb[NFTA_REDIR_REG_PROTO_MAX]) { |
62 | priv->sreg_proto_max = | 64 | priv->sreg_proto_max = |
63 | ntohl(nla_get_be32(tb[NFTA_REDIR_REG_PROTO_MAX])); | 65 | nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MAX]); |
64 | 66 | ||
65 | err = nft_validate_input_register(priv->sreg_proto_max); | 67 | err = nft_validate_register_load(priv->sreg_proto_max, |
68 | plen); | ||
66 | if (err < 0) | 69 | if (err < 0) |
67 | return err; | 70 | return err; |
68 | } else { | 71 | } else { |
@@ -85,11 +88,11 @@ int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
85 | const struct nft_redir *priv = nft_expr_priv(expr); | 88 | const struct nft_redir *priv = nft_expr_priv(expr); |
86 | 89 | ||
87 | if (priv->sreg_proto_min) { | 90 | if (priv->sreg_proto_min) { |
88 | if (nla_put_be32(skb, NFTA_REDIR_REG_PROTO_MIN, | 91 | if (nft_dump_register(skb, NFTA_REDIR_REG_PROTO_MIN, |
89 | htonl(priv->sreg_proto_min))) | 92 | priv->sreg_proto_min)) |
90 | goto nla_put_failure; | 93 | goto nla_put_failure; |
91 | if (nla_put_be32(skb, NFTA_REDIR_REG_PROTO_MAX, | 94 | if (nft_dump_register(skb, NFTA_REDIR_REG_PROTO_MAX, |
92 | htonl(priv->sreg_proto_max))) | 95 | priv->sreg_proto_max)) |
93 | goto nla_put_failure; | 96 | goto nla_put_failure; |
94 | } | 97 | } |
95 | 98 | ||
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c index 92877114aff4..62cabee42fbe 100644 --- a/net/netfilter/nft_reject_inet.c +++ b/net/netfilter/nft_reject_inet.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <net/netfilter/ipv6/nf_reject.h> | 18 | #include <net/netfilter/ipv6/nf_reject.h> |
19 | 19 | ||
20 | static void nft_reject_inet_eval(const struct nft_expr *expr, | 20 | static void nft_reject_inet_eval(const struct nft_expr *expr, |
21 | struct nft_data data[NFT_REG_MAX + 1], | 21 | struct nft_regs *regs, |
22 | const struct nft_pktinfo *pkt) | 22 | const struct nft_pktinfo *pkt) |
23 | { | 23 | { |
24 | struct nft_reject *priv = nft_expr_priv(expr); | 24 | struct nft_reject *priv = nft_expr_priv(expr); |
@@ -58,7 +58,8 @@ static void nft_reject_inet_eval(const struct nft_expr *expr, | |||
58 | } | 58 | } |
59 | break; | 59 | break; |
60 | } | 60 | } |
61 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 61 | |
62 | regs->verdict.code = NF_DROP; | ||
62 | } | 63 | } |
63 | 64 | ||
64 | static int nft_reject_inet_init(const struct nft_ctx *ctx, | 65 | static int nft_reject_inet_init(const struct nft_ctx *ctx, |