2 * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
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.
8 * This software has been sponsored by Sophos Astaro <http://www.sophos.com>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/netlink.h>
15 #include <linux/netfilter.h>
16 #include <linux/netfilter/nfnetlink.h>
17 #include <linux/netfilter/nf_tables.h>
18 #include <linux/netfilter/nf_tables_compat.h>
19 #include <linux/netfilter/x_tables.h>
20 #include <linux/netfilter_ipv4/ip_tables.h>
21 #include <linux/netfilter_ipv6/ip6_tables.h>
22 #include <linux/netfilter_bridge/ebtables.h>
23 #include <linux/netfilter_arp/arp_tables.h>
24 #include <net/netfilter/nf_tables.h>
27 struct list_head head
;
28 struct nft_expr_ops ops
;
31 /* Unlike other expressions, ops doesn't have static storage duration.
32 * nft core assumes they do. We use kfree_rcu so that nft core can
33 * can check expr->ops->size even after nft_compat->destroy() frees
34 * the nft_xt struct that holds the ops structure.
36 struct rcu_head rcu_head
;
39 /* Used for matches where *info is larger than X byte */
40 #define NFT_MATCH_LARGE_THRESH 192
42 struct nft_xt_match_priv
{
46 static bool nft_xt_put(struct nft_xt
*xt
)
48 if (--xt
->refcnt
== 0) {
50 kfree_rcu(xt
, rcu_head
);
57 static int nft_compat_chain_validate_dependency(const struct nft_ctx
*ctx
,
58 const char *tablename
)
60 enum nft_chain_types type
= NFT_CHAIN_T_DEFAULT
;
61 const struct nft_chain
*chain
= ctx
->chain
;
62 const struct nft_base_chain
*basechain
;
65 !nft_is_base_chain(chain
))
68 basechain
= nft_base_chain(chain
);
69 if (strcmp(tablename
, "nat") == 0) {
70 if (ctx
->family
!= NFPROTO_BRIDGE
)
71 type
= NFT_CHAIN_T_NAT
;
72 if (basechain
->type
->type
!= type
)
83 struct arpt_entry arp
;
87 nft_compat_set_par(struct xt_action_param
*par
, void *xt
, const void *xt_info
)
90 par
->targinfo
= xt_info
;
94 static void nft_target_eval_xt(const struct nft_expr
*expr
,
95 struct nft_regs
*regs
,
96 const struct nft_pktinfo
*pkt
)
98 void *info
= nft_expr_priv(expr
);
99 struct xt_target
*target
= expr
->ops
->data
;
100 struct sk_buff
*skb
= pkt
->skb
;
103 nft_compat_set_par((struct xt_action_param
*)&pkt
->xt
, target
, info
);
105 ret
= target
->target(skb
, &pkt
->xt
);
112 regs
->verdict
.code
= NFT_CONTINUE
;
115 regs
->verdict
.code
= ret
;
120 static void nft_target_eval_bridge(const struct nft_expr
*expr
,
121 struct nft_regs
*regs
,
122 const struct nft_pktinfo
*pkt
)
124 void *info
= nft_expr_priv(expr
);
125 struct xt_target
*target
= expr
->ops
->data
;
126 struct sk_buff
*skb
= pkt
->skb
;
129 nft_compat_set_par((struct xt_action_param
*)&pkt
->xt
, target
, info
);
131 ret
= target
->target(skb
, &pkt
->xt
);
138 regs
->verdict
.code
= NF_ACCEPT
;
141 regs
->verdict
.code
= NF_DROP
;
144 regs
->verdict
.code
= NFT_CONTINUE
;
147 regs
->verdict
.code
= NFT_RETURN
;
150 regs
->verdict
.code
= ret
;
155 static const struct nla_policy nft_target_policy
[NFTA_TARGET_MAX
+ 1] = {
156 [NFTA_TARGET_NAME
] = { .type
= NLA_NUL_STRING
},
157 [NFTA_TARGET_REV
] = { .type
= NLA_U32
},
158 [NFTA_TARGET_INFO
] = { .type
= NLA_BINARY
},
162 nft_target_set_tgchk_param(struct xt_tgchk_param
*par
,
163 const struct nft_ctx
*ctx
,
164 struct xt_target
*target
, void *info
,
165 union nft_entry
*entry
, u16 proto
, bool inv
)
168 par
->table
= ctx
->table
->name
;
169 switch (ctx
->family
) {
171 entry
->e4
.ip
.proto
= proto
;
172 entry
->e4
.ip
.invflags
= inv
? IPT_INV_PROTO
: 0;
176 entry
->e6
.ipv6
.flags
|= IP6T_F_PROTO
;
178 entry
->e6
.ipv6
.proto
= proto
;
179 entry
->e6
.ipv6
.invflags
= inv
? IP6T_INV_PROTO
: 0;
182 entry
->ebt
.ethproto
= (__force __be16
)proto
;
183 entry
->ebt
.invflags
= inv
? EBT_IPROTO
: 0;
188 par
->entryinfo
= entry
;
189 par
->target
= target
;
190 par
->targinfo
= info
;
191 if (nft_is_base_chain(ctx
->chain
)) {
192 const struct nft_base_chain
*basechain
=
193 nft_base_chain(ctx
->chain
);
194 const struct nf_hook_ops
*ops
= &basechain
->ops
;
196 par
->hook_mask
= 1 << ops
->hooknum
;
200 par
->family
= ctx
->family
;
201 par
->nft_compat
= true;
204 static void target_compat_from_user(struct xt_target
*t
, void *in
, void *out
)
208 memcpy(out
, in
, t
->targetsize
);
209 pad
= XT_ALIGN(t
->targetsize
) - t
->targetsize
;
211 memset(out
+ t
->targetsize
, 0, pad
);
214 static const struct nla_policy nft_rule_compat_policy
[NFTA_RULE_COMPAT_MAX
+ 1] = {
215 [NFTA_RULE_COMPAT_PROTO
] = { .type
= NLA_U32
},
216 [NFTA_RULE_COMPAT_FLAGS
] = { .type
= NLA_U32
},
219 static int nft_parse_compat(const struct nlattr
*attr
, u16
*proto
, bool *inv
)
221 struct nlattr
*tb
[NFTA_RULE_COMPAT_MAX
+1];
225 err
= nla_parse_nested(tb
, NFTA_RULE_COMPAT_MAX
, attr
,
226 nft_rule_compat_policy
, NULL
);
230 if (!tb
[NFTA_RULE_COMPAT_PROTO
] || !tb
[NFTA_RULE_COMPAT_FLAGS
])
233 flags
= ntohl(nla_get_be32(tb
[NFTA_RULE_COMPAT_FLAGS
]));
234 if (flags
& ~NFT_RULE_COMPAT_F_MASK
)
236 if (flags
& NFT_RULE_COMPAT_F_INV
)
239 *proto
= ntohl(nla_get_be32(tb
[NFTA_RULE_COMPAT_PROTO
]));
244 nft_target_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
245 const struct nlattr
* const tb
[])
247 void *info
= nft_expr_priv(expr
);
248 struct xt_target
*target
= expr
->ops
->data
;
249 struct xt_tgchk_param par
;
250 size_t size
= XT_ALIGN(nla_len(tb
[NFTA_TARGET_INFO
]));
251 struct nft_xt
*nft_xt
;
254 union nft_entry e
= {};
257 target_compat_from_user(target
, nla_data(tb
[NFTA_TARGET_INFO
]), info
);
259 if (ctx
->nla
[NFTA_RULE_COMPAT
]) {
260 ret
= nft_parse_compat(ctx
->nla
[NFTA_RULE_COMPAT
], &proto
, &inv
);
265 nft_target_set_tgchk_param(&par
, ctx
, target
, info
, &e
, proto
, inv
);
267 ret
= xt_check_target(&par
, size
, proto
, inv
);
271 /* The standard target cannot be used */
275 nft_xt
= container_of(expr
->ops
, struct nft_xt
, ops
);
281 nft_target_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
283 struct xt_target
*target
= expr
->ops
->data
;
284 void *info
= nft_expr_priv(expr
);
285 struct xt_tgdtor_param par
;
290 par
.family
= ctx
->family
;
291 if (par
.target
->destroy
!= NULL
)
292 par
.target
->destroy(&par
);
294 if (nft_xt_put(container_of(expr
->ops
, struct nft_xt
, ops
)))
295 module_put(target
->me
);
298 static int nft_extension_dump_info(struct sk_buff
*skb
, int attr
,
300 unsigned int size
, unsigned int user_size
)
302 unsigned int info_size
, aligned_size
= XT_ALIGN(size
);
305 nla
= nla_reserve(skb
, attr
, aligned_size
);
309 info_size
= user_size
? : size
;
310 memcpy(nla_data(nla
), info
, info_size
);
311 memset(nla_data(nla
) + info_size
, 0, aligned_size
- info_size
);
316 static int nft_target_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
318 const struct xt_target
*target
= expr
->ops
->data
;
319 void *info
= nft_expr_priv(expr
);
321 if (nla_put_string(skb
, NFTA_TARGET_NAME
, target
->name
) ||
322 nla_put_be32(skb
, NFTA_TARGET_REV
, htonl(target
->revision
)) ||
323 nft_extension_dump_info(skb
, NFTA_TARGET_INFO
, info
,
324 target
->targetsize
, target
->usersize
))
325 goto nla_put_failure
;
333 static int nft_target_validate(const struct nft_ctx
*ctx
,
334 const struct nft_expr
*expr
,
335 const struct nft_data
**data
)
337 struct xt_target
*target
= expr
->ops
->data
;
338 unsigned int hook_mask
= 0;
341 if (nft_is_base_chain(ctx
->chain
)) {
342 const struct nft_base_chain
*basechain
=
343 nft_base_chain(ctx
->chain
);
344 const struct nf_hook_ops
*ops
= &basechain
->ops
;
346 hook_mask
= 1 << ops
->hooknum
;
347 if (target
->hooks
&& !(hook_mask
& target
->hooks
))
350 ret
= nft_compat_chain_validate_dependency(ctx
, target
->table
);
357 static void __nft_match_eval(const struct nft_expr
*expr
,
358 struct nft_regs
*regs
,
359 const struct nft_pktinfo
*pkt
,
362 struct xt_match
*match
= expr
->ops
->data
;
363 struct sk_buff
*skb
= pkt
->skb
;
366 nft_compat_set_par((struct xt_action_param
*)&pkt
->xt
, match
, info
);
368 ret
= match
->match(skb
, (struct xt_action_param
*)&pkt
->xt
);
370 if (pkt
->xt
.hotdrop
) {
371 regs
->verdict
.code
= NF_DROP
;
375 switch (ret
? 1 : 0) {
377 regs
->verdict
.code
= NFT_CONTINUE
;
380 regs
->verdict
.code
= NFT_BREAK
;
385 static void nft_match_large_eval(const struct nft_expr
*expr
,
386 struct nft_regs
*regs
,
387 const struct nft_pktinfo
*pkt
)
389 struct nft_xt_match_priv
*priv
= nft_expr_priv(expr
);
391 __nft_match_eval(expr
, regs
, pkt
, priv
->info
);
394 static void nft_match_eval(const struct nft_expr
*expr
,
395 struct nft_regs
*regs
,
396 const struct nft_pktinfo
*pkt
)
398 __nft_match_eval(expr
, regs
, pkt
, nft_expr_priv(expr
));
401 static const struct nla_policy nft_match_policy
[NFTA_MATCH_MAX
+ 1] = {
402 [NFTA_MATCH_NAME
] = { .type
= NLA_NUL_STRING
},
403 [NFTA_MATCH_REV
] = { .type
= NLA_U32
},
404 [NFTA_MATCH_INFO
] = { .type
= NLA_BINARY
},
407 /* struct xt_mtchk_param and xt_tgchk_param look very similar */
409 nft_match_set_mtchk_param(struct xt_mtchk_param
*par
, const struct nft_ctx
*ctx
,
410 struct xt_match
*match
, void *info
,
411 union nft_entry
*entry
, u16 proto
, bool inv
)
414 par
->table
= ctx
->table
->name
;
415 switch (ctx
->family
) {
417 entry
->e4
.ip
.proto
= proto
;
418 entry
->e4
.ip
.invflags
= inv
? IPT_INV_PROTO
: 0;
422 entry
->e6
.ipv6
.flags
|= IP6T_F_PROTO
;
424 entry
->e6
.ipv6
.proto
= proto
;
425 entry
->e6
.ipv6
.invflags
= inv
? IP6T_INV_PROTO
: 0;
428 entry
->ebt
.ethproto
= (__force __be16
)proto
;
429 entry
->ebt
.invflags
= inv
? EBT_IPROTO
: 0;
434 par
->entryinfo
= entry
;
436 par
->matchinfo
= info
;
437 if (nft_is_base_chain(ctx
->chain
)) {
438 const struct nft_base_chain
*basechain
=
439 nft_base_chain(ctx
->chain
);
440 const struct nf_hook_ops
*ops
= &basechain
->ops
;
442 par
->hook_mask
= 1 << ops
->hooknum
;
446 par
->family
= ctx
->family
;
447 par
->nft_compat
= true;
450 static void match_compat_from_user(struct xt_match
*m
, void *in
, void *out
)
454 memcpy(out
, in
, m
->matchsize
);
455 pad
= XT_ALIGN(m
->matchsize
) - m
->matchsize
;
457 memset(out
+ m
->matchsize
, 0, pad
);
461 __nft_match_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
462 const struct nlattr
* const tb
[],
465 struct xt_match
*match
= expr
->ops
->data
;
466 struct xt_mtchk_param par
;
467 size_t size
= XT_ALIGN(nla_len(tb
[NFTA_MATCH_INFO
]));
468 struct nft_xt
*nft_xt
;
471 union nft_entry e
= {};
474 match_compat_from_user(match
, nla_data(tb
[NFTA_MATCH_INFO
]), info
);
476 if (ctx
->nla
[NFTA_RULE_COMPAT
]) {
477 ret
= nft_parse_compat(ctx
->nla
[NFTA_RULE_COMPAT
], &proto
, &inv
);
482 nft_match_set_mtchk_param(&par
, ctx
, match
, info
, &e
, proto
, inv
);
484 ret
= xt_check_match(&par
, size
, proto
, inv
);
488 nft_xt
= container_of(expr
->ops
, struct nft_xt
, ops
);
494 nft_match_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
495 const struct nlattr
* const tb
[])
497 return __nft_match_init(ctx
, expr
, tb
, nft_expr_priv(expr
));
501 nft_match_large_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
502 const struct nlattr
* const tb
[])
504 struct nft_xt_match_priv
*priv
= nft_expr_priv(expr
);
505 struct xt_match
*m
= expr
->ops
->data
;
508 priv
->info
= kmalloc(XT_ALIGN(m
->matchsize
), GFP_KERNEL
);
512 ret
= __nft_match_init(ctx
, expr
, tb
, priv
->info
);
519 __nft_match_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
522 struct xt_match
*match
= expr
->ops
->data
;
523 struct module
*me
= match
->me
;
524 struct xt_mtdtor_param par
;
528 par
.matchinfo
= info
;
529 par
.family
= ctx
->family
;
530 if (par
.match
->destroy
!= NULL
)
531 par
.match
->destroy(&par
);
533 if (nft_xt_put(container_of(expr
->ops
, struct nft_xt
, ops
)))
538 nft_match_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
540 __nft_match_destroy(ctx
, expr
, nft_expr_priv(expr
));
544 nft_match_large_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
546 struct nft_xt_match_priv
*priv
= nft_expr_priv(expr
);
548 __nft_match_destroy(ctx
, expr
, priv
->info
);
552 static int __nft_match_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
,
555 struct xt_match
*match
= expr
->ops
->data
;
557 if (nla_put_string(skb
, NFTA_MATCH_NAME
, match
->name
) ||
558 nla_put_be32(skb
, NFTA_MATCH_REV
, htonl(match
->revision
)) ||
559 nft_extension_dump_info(skb
, NFTA_MATCH_INFO
, info
,
560 match
->matchsize
, match
->usersize
))
561 goto nla_put_failure
;
569 static int nft_match_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
571 return __nft_match_dump(skb
, expr
, nft_expr_priv(expr
));
574 static int nft_match_large_dump(struct sk_buff
*skb
, const struct nft_expr
*e
)
576 struct nft_xt_match_priv
*priv
= nft_expr_priv(e
);
578 return __nft_match_dump(skb
, e
, priv
->info
);
581 static int nft_match_validate(const struct nft_ctx
*ctx
,
582 const struct nft_expr
*expr
,
583 const struct nft_data
**data
)
585 struct xt_match
*match
= expr
->ops
->data
;
586 unsigned int hook_mask
= 0;
589 if (nft_is_base_chain(ctx
->chain
)) {
590 const struct nft_base_chain
*basechain
=
591 nft_base_chain(ctx
->chain
);
592 const struct nf_hook_ops
*ops
= &basechain
->ops
;
594 hook_mask
= 1 << ops
->hooknum
;
595 if (match
->hooks
&& !(hook_mask
& match
->hooks
))
598 ret
= nft_compat_chain_validate_dependency(ctx
, match
->table
);
606 nfnl_compat_fill_info(struct sk_buff
*skb
, u32 portid
, u32 seq
, u32 type
,
607 int event
, u16 family
, const char *name
,
610 struct nlmsghdr
*nlh
;
611 struct nfgenmsg
*nfmsg
;
612 unsigned int flags
= portid
? NLM_F_MULTI
: 0;
614 event
= nfnl_msg_type(NFNL_SUBSYS_NFT_COMPAT
, event
);
615 nlh
= nlmsg_put(skb
, portid
, seq
, event
, sizeof(*nfmsg
), flags
);
619 nfmsg
= nlmsg_data(nlh
);
620 nfmsg
->nfgen_family
= family
;
621 nfmsg
->version
= NFNETLINK_V0
;
624 if (nla_put_string(skb
, NFTA_COMPAT_NAME
, name
) ||
625 nla_put_be32(skb
, NFTA_COMPAT_REV
, htonl(rev
)) ||
626 nla_put_be32(skb
, NFTA_COMPAT_TYPE
, htonl(target
)))
627 goto nla_put_failure
;
634 nlmsg_cancel(skb
, nlh
);
638 static int nfnl_compat_get_rcu(struct net
*net
, struct sock
*nfnl
,
639 struct sk_buff
*skb
, const struct nlmsghdr
*nlh
,
640 const struct nlattr
* const tb
[],
641 struct netlink_ext_ack
*extack
)
644 struct nfgenmsg
*nfmsg
;
648 struct sk_buff
*skb2
;
650 if (tb
[NFTA_COMPAT_NAME
] == NULL
||
651 tb
[NFTA_COMPAT_REV
] == NULL
||
652 tb
[NFTA_COMPAT_TYPE
] == NULL
)
655 name
= nla_data(tb
[NFTA_COMPAT_NAME
]);
656 rev
= ntohl(nla_get_be32(tb
[NFTA_COMPAT_REV
]));
657 target
= ntohl(nla_get_be32(tb
[NFTA_COMPAT_TYPE
]));
659 nfmsg
= nlmsg_data(nlh
);
661 switch(nfmsg
->nfgen_family
) {
675 pr_err("nft_compat: unsupported protocol %d\n",
676 nfmsg
->nfgen_family
);
680 if (!try_module_get(THIS_MODULE
))
684 try_then_request_module(xt_find_revision(nfmsg
->nfgen_family
, name
,
690 skb2
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
696 /* include the best revision for this extension in the message */
697 if (nfnl_compat_fill_info(skb2
, NETLINK_CB(skb
).portid
,
699 NFNL_MSG_TYPE(nlh
->nlmsg_type
),
702 name
, ret
, target
) <= 0) {
707 ret
= netlink_unicast(nfnl
, skb2
, NETLINK_CB(skb
).portid
,
713 module_put(THIS_MODULE
);
714 return ret
== -EAGAIN
? -ENOBUFS
: ret
;
717 static const struct nla_policy nfnl_compat_policy_get
[NFTA_COMPAT_MAX
+1] = {
718 [NFTA_COMPAT_NAME
] = { .type
= NLA_NUL_STRING
,
719 .len
= NFT_COMPAT_NAME_MAX
-1 },
720 [NFTA_COMPAT_REV
] = { .type
= NLA_U32
},
721 [NFTA_COMPAT_TYPE
] = { .type
= NLA_U32
},
724 static const struct nfnl_callback nfnl_nft_compat_cb
[NFNL_MSG_COMPAT_MAX
] = {
725 [NFNL_MSG_COMPAT_GET
] = { .call_rcu
= nfnl_compat_get_rcu
,
726 .attr_count
= NFTA_COMPAT_MAX
,
727 .policy
= nfnl_compat_policy_get
},
730 static const struct nfnetlink_subsystem nfnl_compat_subsys
= {
731 .name
= "nft-compat",
732 .subsys_id
= NFNL_SUBSYS_NFT_COMPAT
,
733 .cb_count
= NFNL_MSG_COMPAT_MAX
,
734 .cb
= nfnl_nft_compat_cb
,
737 static LIST_HEAD(nft_match_list
);
739 static struct nft_expr_type nft_match_type
;
741 static bool nft_match_cmp(const struct xt_match
*match
,
742 const char *name
, u32 rev
, u32 family
)
744 return strcmp(match
->name
, name
) == 0 && match
->revision
== rev
&&
745 (match
->family
== NFPROTO_UNSPEC
|| match
->family
== family
);
748 static const struct nft_expr_ops
*
749 nft_match_select_ops(const struct nft_ctx
*ctx
,
750 const struct nlattr
* const tb
[])
752 struct nft_xt
*nft_match
;
753 struct xt_match
*match
;
754 unsigned int matchsize
;
759 if (tb
[NFTA_MATCH_NAME
] == NULL
||
760 tb
[NFTA_MATCH_REV
] == NULL
||
761 tb
[NFTA_MATCH_INFO
] == NULL
)
762 return ERR_PTR(-EINVAL
);
764 mt_name
= nla_data(tb
[NFTA_MATCH_NAME
]);
765 rev
= ntohl(nla_get_be32(tb
[NFTA_MATCH_REV
]));
766 family
= ctx
->family
;
768 /* Re-use the existing match if it's already loaded. */
769 list_for_each_entry(nft_match
, &nft_match_list
, head
) {
770 struct xt_match
*match
= nft_match
->ops
.data
;
772 if (nft_match_cmp(match
, mt_name
, rev
, family
))
773 return &nft_match
->ops
;
776 match
= xt_request_find_match(family
, mt_name
, rev
);
778 return ERR_PTR(-ENOENT
);
780 if (match
->matchsize
> nla_len(tb
[NFTA_MATCH_INFO
])) {
785 /* This is the first time we use this match, allocate operations */
786 nft_match
= kzalloc(sizeof(struct nft_xt
), GFP_KERNEL
);
787 if (nft_match
== NULL
) {
792 nft_match
->refcnt
= 0;
793 nft_match
->ops
.type
= &nft_match_type
;
794 nft_match
->ops
.eval
= nft_match_eval
;
795 nft_match
->ops
.init
= nft_match_init
;
796 nft_match
->ops
.destroy
= nft_match_destroy
;
797 nft_match
->ops
.dump
= nft_match_dump
;
798 nft_match
->ops
.validate
= nft_match_validate
;
799 nft_match
->ops
.data
= match
;
801 matchsize
= NFT_EXPR_SIZE(XT_ALIGN(match
->matchsize
));
802 if (matchsize
> NFT_MATCH_LARGE_THRESH
) {
803 matchsize
= NFT_EXPR_SIZE(sizeof(struct nft_xt_match_priv
));
805 nft_match
->ops
.eval
= nft_match_large_eval
;
806 nft_match
->ops
.init
= nft_match_large_init
;
807 nft_match
->ops
.destroy
= nft_match_large_destroy
;
808 nft_match
->ops
.dump
= nft_match_large_dump
;
811 nft_match
->ops
.size
= matchsize
;
813 list_add(&nft_match
->head
, &nft_match_list
);
815 return &nft_match
->ops
;
817 module_put(match
->me
);
821 static struct nft_expr_type nft_match_type __read_mostly
= {
823 .select_ops
= nft_match_select_ops
,
824 .policy
= nft_match_policy
,
825 .maxattr
= NFTA_MATCH_MAX
,
826 .owner
= THIS_MODULE
,
829 static LIST_HEAD(nft_target_list
);
831 static struct nft_expr_type nft_target_type
;
833 static bool nft_target_cmp(const struct xt_target
*tg
,
834 const char *name
, u32 rev
, u32 family
)
836 return strcmp(tg
->name
, name
) == 0 && tg
->revision
== rev
&&
837 (tg
->family
== NFPROTO_UNSPEC
|| tg
->family
== family
);
840 static const struct nft_expr_ops
*
841 nft_target_select_ops(const struct nft_ctx
*ctx
,
842 const struct nlattr
* const tb
[])
844 struct nft_xt
*nft_target
;
845 struct xt_target
*target
;
850 if (tb
[NFTA_TARGET_NAME
] == NULL
||
851 tb
[NFTA_TARGET_REV
] == NULL
||
852 tb
[NFTA_TARGET_INFO
] == NULL
)
853 return ERR_PTR(-EINVAL
);
855 tg_name
= nla_data(tb
[NFTA_TARGET_NAME
]);
856 rev
= ntohl(nla_get_be32(tb
[NFTA_TARGET_REV
]));
857 family
= ctx
->family
;
859 if (strcmp(tg_name
, XT_ERROR_TARGET
) == 0 ||
860 strcmp(tg_name
, XT_STANDARD_TARGET
) == 0 ||
861 strcmp(tg_name
, "standard") == 0)
862 return ERR_PTR(-EINVAL
);
864 /* Re-use the existing target if it's already loaded. */
865 list_for_each_entry(nft_target
, &nft_target_list
, head
) {
866 struct xt_target
*target
= nft_target
->ops
.data
;
871 if (nft_target_cmp(target
, tg_name
, rev
, family
))
872 return &nft_target
->ops
;
875 target
= xt_request_find_target(family
, tg_name
, rev
);
877 return ERR_PTR(-ENOENT
);
879 if (!target
->target
) {
884 if (target
->targetsize
> nla_len(tb
[NFTA_TARGET_INFO
])) {
889 /* This is the first time we use this target, allocate operations */
890 nft_target
= kzalloc(sizeof(struct nft_xt
), GFP_KERNEL
);
891 if (nft_target
== NULL
) {
896 nft_target
->refcnt
= 0;
897 nft_target
->ops
.type
= &nft_target_type
;
898 nft_target
->ops
.size
= NFT_EXPR_SIZE(XT_ALIGN(target
->targetsize
));
899 nft_target
->ops
.init
= nft_target_init
;
900 nft_target
->ops
.destroy
= nft_target_destroy
;
901 nft_target
->ops
.dump
= nft_target_dump
;
902 nft_target
->ops
.validate
= nft_target_validate
;
903 nft_target
->ops
.data
= target
;
905 if (family
== NFPROTO_BRIDGE
)
906 nft_target
->ops
.eval
= nft_target_eval_bridge
;
908 nft_target
->ops
.eval
= nft_target_eval_xt
;
910 list_add(&nft_target
->head
, &nft_target_list
);
912 return &nft_target
->ops
;
914 module_put(target
->me
);
918 static struct nft_expr_type nft_target_type __read_mostly
= {
920 .select_ops
= nft_target_select_ops
,
921 .policy
= nft_target_policy
,
922 .maxattr
= NFTA_TARGET_MAX
,
923 .owner
= THIS_MODULE
,
926 static int __init
nft_compat_module_init(void)
930 ret
= nft_register_expr(&nft_match_type
);
934 ret
= nft_register_expr(&nft_target_type
);
938 ret
= nfnetlink_subsys_register(&nfnl_compat_subsys
);
940 pr_err("nft_compat: cannot register with nfnetlink.\n");
947 nft_unregister_expr(&nft_target_type
);
949 nft_unregister_expr(&nft_match_type
);
953 static void __exit
nft_compat_module_exit(void)
955 struct nft_xt
*xt
, *next
;
957 /* list should be empty here, it can be non-empty only in case there
958 * was an error that caused nft_xt expr to not be initialized fully
959 * and noone else requested the same expression later.
961 * In this case, the lists contain 0-refcount entries that still
962 * hold module reference.
964 list_for_each_entry_safe(xt
, next
, &nft_target_list
, head
) {
965 struct xt_target
*target
= xt
->ops
.data
;
967 if (WARN_ON_ONCE(xt
->refcnt
))
969 module_put(target
->me
);
973 list_for_each_entry_safe(xt
, next
, &nft_match_list
, head
) {
974 struct xt_match
*match
= xt
->ops
.data
;
976 if (WARN_ON_ONCE(xt
->refcnt
))
978 module_put(match
->me
);
981 nfnetlink_subsys_unregister(&nfnl_compat_subsys
);
982 nft_unregister_expr(&nft_target_type
);
983 nft_unregister_expr(&nft_match_type
);
986 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT
);
988 module_init(nft_compat_module_init
);
989 module_exit(nft_compat_module_exit
);
991 MODULE_LICENSE("GPL");
992 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
993 MODULE_ALIAS_NFT_EXPR("match");
994 MODULE_ALIAS_NFT_EXPR("target");