1 // SPDX-License-Identifier: GPL-2.0-only
3 * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
5 * This software has been sponsored by Sophos Astaro <http://www.sophos.com>
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/netlink.h>
12 #include <linux/netfilter.h>
13 #include <linux/netfilter/nfnetlink.h>
14 #include <linux/netfilter/nf_tables.h>
15 #include <linux/netfilter/nf_tables_compat.h>
16 #include <linux/netfilter/x_tables.h>
17 #include <linux/netfilter_ipv4/ip_tables.h>
18 #include <linux/netfilter_ipv6/ip6_tables.h>
19 #include <linux/netfilter_bridge/ebtables.h>
20 #include <linux/netfilter_arp/arp_tables.h>
21 #include <net/netfilter/nf_tables.h>
23 /* Used for matches where *info is larger than X byte */
24 #define NFT_MATCH_LARGE_THRESH 192
26 struct nft_xt_match_priv
{
30 static refcount_t nft_compat_pending_destroy
= REFCOUNT_INIT(1);
32 static int nft_compat_chain_validate_dependency(const struct nft_ctx
*ctx
,
33 const char *tablename
)
35 enum nft_chain_types type
= NFT_CHAIN_T_DEFAULT
;
36 const struct nft_chain
*chain
= ctx
->chain
;
37 const struct nft_base_chain
*basechain
;
40 !nft_is_base_chain(chain
))
43 basechain
= nft_base_chain(chain
);
44 if (strcmp(tablename
, "nat") == 0) {
45 if (ctx
->family
!= NFPROTO_BRIDGE
)
46 type
= NFT_CHAIN_T_NAT
;
47 if (basechain
->type
->type
!= type
)
58 struct arpt_entry arp
;
62 nft_compat_set_par(struct xt_action_param
*par
, void *xt
, const void *xt_info
)
65 par
->targinfo
= xt_info
;
69 static void nft_target_eval_xt(const struct nft_expr
*expr
,
70 struct nft_regs
*regs
,
71 const struct nft_pktinfo
*pkt
)
73 void *info
= nft_expr_priv(expr
);
74 struct xt_target
*target
= expr
->ops
->data
;
75 struct sk_buff
*skb
= pkt
->skb
;
78 nft_compat_set_par((struct xt_action_param
*)&pkt
->xt
, target
, info
);
80 ret
= target
->target(skb
, &pkt
->xt
);
87 regs
->verdict
.code
= NFT_CONTINUE
;
90 regs
->verdict
.code
= ret
;
95 static void nft_target_eval_bridge(const struct nft_expr
*expr
,
96 struct nft_regs
*regs
,
97 const struct nft_pktinfo
*pkt
)
99 void *info
= nft_expr_priv(expr
);
100 struct xt_target
*target
= expr
->ops
->data
;
101 struct sk_buff
*skb
= pkt
->skb
;
104 nft_compat_set_par((struct xt_action_param
*)&pkt
->xt
, target
, info
);
106 ret
= target
->target(skb
, &pkt
->xt
);
113 regs
->verdict
.code
= NF_ACCEPT
;
116 regs
->verdict
.code
= NF_DROP
;
119 regs
->verdict
.code
= NFT_CONTINUE
;
122 regs
->verdict
.code
= NFT_RETURN
;
125 regs
->verdict
.code
= ret
;
130 static const struct nla_policy nft_target_policy
[NFTA_TARGET_MAX
+ 1] = {
131 [NFTA_TARGET_NAME
] = { .type
= NLA_NUL_STRING
},
132 [NFTA_TARGET_REV
] = { .type
= NLA_U32
},
133 [NFTA_TARGET_INFO
] = { .type
= NLA_BINARY
},
137 nft_target_set_tgchk_param(struct xt_tgchk_param
*par
,
138 const struct nft_ctx
*ctx
,
139 struct xt_target
*target
, void *info
,
140 union nft_entry
*entry
, u16 proto
, bool inv
)
143 par
->table
= ctx
->table
->name
;
144 switch (ctx
->family
) {
146 entry
->e4
.ip
.proto
= proto
;
147 entry
->e4
.ip
.invflags
= inv
? IPT_INV_PROTO
: 0;
151 entry
->e6
.ipv6
.flags
|= IP6T_F_PROTO
;
153 entry
->e6
.ipv6
.proto
= proto
;
154 entry
->e6
.ipv6
.invflags
= inv
? IP6T_INV_PROTO
: 0;
157 entry
->ebt
.ethproto
= (__force __be16
)proto
;
158 entry
->ebt
.invflags
= inv
? EBT_IPROTO
: 0;
163 par
->entryinfo
= entry
;
164 par
->target
= target
;
165 par
->targinfo
= info
;
166 if (nft_is_base_chain(ctx
->chain
)) {
167 const struct nft_base_chain
*basechain
=
168 nft_base_chain(ctx
->chain
);
169 const struct nf_hook_ops
*ops
= &basechain
->ops
;
171 par
->hook_mask
= 1 << ops
->hooknum
;
175 par
->family
= ctx
->family
;
176 par
->nft_compat
= true;
179 static void target_compat_from_user(struct xt_target
*t
, void *in
, void *out
)
183 memcpy(out
, in
, t
->targetsize
);
184 pad
= XT_ALIGN(t
->targetsize
) - t
->targetsize
;
186 memset(out
+ t
->targetsize
, 0, pad
);
189 static const struct nla_policy nft_rule_compat_policy
[NFTA_RULE_COMPAT_MAX
+ 1] = {
190 [NFTA_RULE_COMPAT_PROTO
] = { .type
= NLA_U32
},
191 [NFTA_RULE_COMPAT_FLAGS
] = { .type
= NLA_U32
},
194 static int nft_parse_compat(const struct nlattr
*attr
, u16
*proto
, bool *inv
)
196 struct nlattr
*tb
[NFTA_RULE_COMPAT_MAX
+1];
200 err
= nla_parse_nested_deprecated(tb
, NFTA_RULE_COMPAT_MAX
, attr
,
201 nft_rule_compat_policy
, NULL
);
205 if (!tb
[NFTA_RULE_COMPAT_PROTO
] || !tb
[NFTA_RULE_COMPAT_FLAGS
])
208 flags
= ntohl(nla_get_be32(tb
[NFTA_RULE_COMPAT_FLAGS
]));
209 if (flags
& ~NFT_RULE_COMPAT_F_MASK
)
211 if (flags
& NFT_RULE_COMPAT_F_INV
)
214 *proto
= ntohl(nla_get_be32(tb
[NFTA_RULE_COMPAT_PROTO
]));
219 nft_target_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
220 const struct nlattr
* const tb
[])
222 void *info
= nft_expr_priv(expr
);
223 struct xt_target
*target
= expr
->ops
->data
;
224 struct xt_tgchk_param par
;
225 size_t size
= XT_ALIGN(nla_len(tb
[NFTA_TARGET_INFO
]));
228 union nft_entry e
= {};
231 target_compat_from_user(target
, nla_data(tb
[NFTA_TARGET_INFO
]), info
);
233 if (ctx
->nla
[NFTA_RULE_COMPAT
]) {
234 ret
= nft_parse_compat(ctx
->nla
[NFTA_RULE_COMPAT
], &proto
, &inv
);
239 nft_target_set_tgchk_param(&par
, ctx
, target
, info
, &e
, proto
, inv
);
241 /* xtables matches or targets can have side effects, e.g.
242 * creation/destruction of /proc files.
243 * The xt ->destroy functions are run asynchronously from
244 * work queue. If we have pending invocations we thus
245 * need to wait for those to finish.
247 if (refcount_read(&nft_compat_pending_destroy
) > 1)
248 nf_tables_trans_destroy_flush_work();
250 ret
= xt_check_target(&par
, size
, proto
, inv
);
254 /* The standard target cannot be used */
261 static void __nft_mt_tg_destroy(struct module
*me
, const struct nft_expr
*expr
)
263 refcount_dec(&nft_compat_pending_destroy
);
269 nft_target_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
271 struct xt_target
*target
= expr
->ops
->data
;
272 void *info
= nft_expr_priv(expr
);
273 struct module
*me
= target
->me
;
274 struct xt_tgdtor_param par
;
279 par
.family
= ctx
->family
;
280 if (par
.target
->destroy
!= NULL
)
281 par
.target
->destroy(&par
);
283 __nft_mt_tg_destroy(me
, expr
);
286 static int nft_extension_dump_info(struct sk_buff
*skb
, int attr
,
288 unsigned int size
, unsigned int user_size
)
290 unsigned int info_size
, aligned_size
= XT_ALIGN(size
);
293 nla
= nla_reserve(skb
, attr
, aligned_size
);
297 info_size
= user_size
? : size
;
298 memcpy(nla_data(nla
), info
, info_size
);
299 memset(nla_data(nla
) + info_size
, 0, aligned_size
- info_size
);
304 static int nft_target_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
306 const struct xt_target
*target
= expr
->ops
->data
;
307 void *info
= nft_expr_priv(expr
);
309 if (nla_put_string(skb
, NFTA_TARGET_NAME
, target
->name
) ||
310 nla_put_be32(skb
, NFTA_TARGET_REV
, htonl(target
->revision
)) ||
311 nft_extension_dump_info(skb
, NFTA_TARGET_INFO
, info
,
312 target
->targetsize
, target
->usersize
))
313 goto nla_put_failure
;
321 static int nft_target_validate(const struct nft_ctx
*ctx
,
322 const struct nft_expr
*expr
,
323 const struct nft_data
**data
)
325 struct xt_target
*target
= expr
->ops
->data
;
326 unsigned int hook_mask
= 0;
329 if (nft_is_base_chain(ctx
->chain
)) {
330 const struct nft_base_chain
*basechain
=
331 nft_base_chain(ctx
->chain
);
332 const struct nf_hook_ops
*ops
= &basechain
->ops
;
334 hook_mask
= 1 << ops
->hooknum
;
335 if (target
->hooks
&& !(hook_mask
& target
->hooks
))
338 ret
= nft_compat_chain_validate_dependency(ctx
, target
->table
);
345 static void __nft_match_eval(const struct nft_expr
*expr
,
346 struct nft_regs
*regs
,
347 const struct nft_pktinfo
*pkt
,
350 struct xt_match
*match
= expr
->ops
->data
;
351 struct sk_buff
*skb
= pkt
->skb
;
354 nft_compat_set_par((struct xt_action_param
*)&pkt
->xt
, match
, info
);
356 ret
= match
->match(skb
, (struct xt_action_param
*)&pkt
->xt
);
358 if (pkt
->xt
.hotdrop
) {
359 regs
->verdict
.code
= NF_DROP
;
363 switch (ret
? 1 : 0) {
365 regs
->verdict
.code
= NFT_CONTINUE
;
368 regs
->verdict
.code
= NFT_BREAK
;
373 static void nft_match_large_eval(const struct nft_expr
*expr
,
374 struct nft_regs
*regs
,
375 const struct nft_pktinfo
*pkt
)
377 struct nft_xt_match_priv
*priv
= nft_expr_priv(expr
);
379 __nft_match_eval(expr
, regs
, pkt
, priv
->info
);
382 static void nft_match_eval(const struct nft_expr
*expr
,
383 struct nft_regs
*regs
,
384 const struct nft_pktinfo
*pkt
)
386 __nft_match_eval(expr
, regs
, pkt
, nft_expr_priv(expr
));
389 static const struct nla_policy nft_match_policy
[NFTA_MATCH_MAX
+ 1] = {
390 [NFTA_MATCH_NAME
] = { .type
= NLA_NUL_STRING
},
391 [NFTA_MATCH_REV
] = { .type
= NLA_U32
},
392 [NFTA_MATCH_INFO
] = { .type
= NLA_BINARY
},
395 /* struct xt_mtchk_param and xt_tgchk_param look very similar */
397 nft_match_set_mtchk_param(struct xt_mtchk_param
*par
, const struct nft_ctx
*ctx
,
398 struct xt_match
*match
, void *info
,
399 union nft_entry
*entry
, u16 proto
, bool inv
)
402 par
->table
= ctx
->table
->name
;
403 switch (ctx
->family
) {
405 entry
->e4
.ip
.proto
= proto
;
406 entry
->e4
.ip
.invflags
= inv
? IPT_INV_PROTO
: 0;
410 entry
->e6
.ipv6
.flags
|= IP6T_F_PROTO
;
412 entry
->e6
.ipv6
.proto
= proto
;
413 entry
->e6
.ipv6
.invflags
= inv
? IP6T_INV_PROTO
: 0;
416 entry
->ebt
.ethproto
= (__force __be16
)proto
;
417 entry
->ebt
.invflags
= inv
? EBT_IPROTO
: 0;
422 par
->entryinfo
= entry
;
424 par
->matchinfo
= info
;
425 if (nft_is_base_chain(ctx
->chain
)) {
426 const struct nft_base_chain
*basechain
=
427 nft_base_chain(ctx
->chain
);
428 const struct nf_hook_ops
*ops
= &basechain
->ops
;
430 par
->hook_mask
= 1 << ops
->hooknum
;
434 par
->family
= ctx
->family
;
435 par
->nft_compat
= true;
438 static void match_compat_from_user(struct xt_match
*m
, void *in
, void *out
)
442 memcpy(out
, in
, m
->matchsize
);
443 pad
= XT_ALIGN(m
->matchsize
) - m
->matchsize
;
445 memset(out
+ m
->matchsize
, 0, pad
);
449 __nft_match_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
450 const struct nlattr
* const tb
[],
453 struct xt_match
*match
= expr
->ops
->data
;
454 struct xt_mtchk_param par
;
455 size_t size
= XT_ALIGN(nla_len(tb
[NFTA_MATCH_INFO
]));
458 union nft_entry e
= {};
461 match_compat_from_user(match
, nla_data(tb
[NFTA_MATCH_INFO
]), info
);
463 if (ctx
->nla
[NFTA_RULE_COMPAT
]) {
464 ret
= nft_parse_compat(ctx
->nla
[NFTA_RULE_COMPAT
], &proto
, &inv
);
469 nft_match_set_mtchk_param(&par
, ctx
, match
, info
, &e
, proto
, inv
);
471 return xt_check_match(&par
, size
, proto
, inv
);
475 nft_match_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
476 const struct nlattr
* const tb
[])
478 return __nft_match_init(ctx
, expr
, tb
, nft_expr_priv(expr
));
482 nft_match_large_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
483 const struct nlattr
* const tb
[])
485 struct nft_xt_match_priv
*priv
= nft_expr_priv(expr
);
486 struct xt_match
*m
= expr
->ops
->data
;
489 priv
->info
= kmalloc(XT_ALIGN(m
->matchsize
), GFP_KERNEL
);
493 ret
= __nft_match_init(ctx
, expr
, tb
, priv
->info
);
500 __nft_match_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
503 struct xt_match
*match
= expr
->ops
->data
;
504 struct module
*me
= match
->me
;
505 struct xt_mtdtor_param par
;
509 par
.matchinfo
= info
;
510 par
.family
= ctx
->family
;
511 if (par
.match
->destroy
!= NULL
)
512 par
.match
->destroy(&par
);
514 __nft_mt_tg_destroy(me
, expr
);
518 nft_match_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
520 __nft_match_destroy(ctx
, expr
, nft_expr_priv(expr
));
524 nft_match_large_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
526 struct nft_xt_match_priv
*priv
= nft_expr_priv(expr
);
528 __nft_match_destroy(ctx
, expr
, priv
->info
);
532 static int __nft_match_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
,
535 struct xt_match
*match
= expr
->ops
->data
;
537 if (nla_put_string(skb
, NFTA_MATCH_NAME
, match
->name
) ||
538 nla_put_be32(skb
, NFTA_MATCH_REV
, htonl(match
->revision
)) ||
539 nft_extension_dump_info(skb
, NFTA_MATCH_INFO
, info
,
540 match
->matchsize
, match
->usersize
))
541 goto nla_put_failure
;
549 static int nft_match_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
551 return __nft_match_dump(skb
, expr
, nft_expr_priv(expr
));
554 static int nft_match_large_dump(struct sk_buff
*skb
, const struct nft_expr
*e
)
556 struct nft_xt_match_priv
*priv
= nft_expr_priv(e
);
558 return __nft_match_dump(skb
, e
, priv
->info
);
561 static int nft_match_validate(const struct nft_ctx
*ctx
,
562 const struct nft_expr
*expr
,
563 const struct nft_data
**data
)
565 struct xt_match
*match
= expr
->ops
->data
;
566 unsigned int hook_mask
= 0;
569 if (nft_is_base_chain(ctx
->chain
)) {
570 const struct nft_base_chain
*basechain
=
571 nft_base_chain(ctx
->chain
);
572 const struct nf_hook_ops
*ops
= &basechain
->ops
;
574 hook_mask
= 1 << ops
->hooknum
;
575 if (match
->hooks
&& !(hook_mask
& match
->hooks
))
578 ret
= nft_compat_chain_validate_dependency(ctx
, match
->table
);
586 nfnl_compat_fill_info(struct sk_buff
*skb
, u32 portid
, u32 seq
, u32 type
,
587 int event
, u16 family
, const char *name
,
590 struct nlmsghdr
*nlh
;
591 struct nfgenmsg
*nfmsg
;
592 unsigned int flags
= portid
? NLM_F_MULTI
: 0;
594 event
= nfnl_msg_type(NFNL_SUBSYS_NFT_COMPAT
, event
);
595 nlh
= nlmsg_put(skb
, portid
, seq
, event
, sizeof(*nfmsg
), flags
);
599 nfmsg
= nlmsg_data(nlh
);
600 nfmsg
->nfgen_family
= family
;
601 nfmsg
->version
= NFNETLINK_V0
;
604 if (nla_put_string(skb
, NFTA_COMPAT_NAME
, name
) ||
605 nla_put_be32(skb
, NFTA_COMPAT_REV
, htonl(rev
)) ||
606 nla_put_be32(skb
, NFTA_COMPAT_TYPE
, htonl(target
)))
607 goto nla_put_failure
;
614 nlmsg_cancel(skb
, nlh
);
618 static int nfnl_compat_get_rcu(struct net
*net
, struct sock
*nfnl
,
619 struct sk_buff
*skb
, const struct nlmsghdr
*nlh
,
620 const struct nlattr
* const tb
[],
621 struct netlink_ext_ack
*extack
)
624 struct nfgenmsg
*nfmsg
;
628 struct sk_buff
*skb2
;
630 if (tb
[NFTA_COMPAT_NAME
] == NULL
||
631 tb
[NFTA_COMPAT_REV
] == NULL
||
632 tb
[NFTA_COMPAT_TYPE
] == NULL
)
635 name
= nla_data(tb
[NFTA_COMPAT_NAME
]);
636 rev
= ntohl(nla_get_be32(tb
[NFTA_COMPAT_REV
]));
637 target
= ntohl(nla_get_be32(tb
[NFTA_COMPAT_TYPE
]));
639 nfmsg
= nlmsg_data(nlh
);
641 switch(nfmsg
->nfgen_family
) {
655 pr_err("nft_compat: unsupported protocol %d\n",
656 nfmsg
->nfgen_family
);
660 if (!try_module_get(THIS_MODULE
))
664 try_then_request_module(xt_find_revision(nfmsg
->nfgen_family
, name
,
670 skb2
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
676 /* include the best revision for this extension in the message */
677 if (nfnl_compat_fill_info(skb2
, NETLINK_CB(skb
).portid
,
679 NFNL_MSG_TYPE(nlh
->nlmsg_type
),
682 name
, ret
, target
) <= 0) {
687 ret
= netlink_unicast(nfnl
, skb2
, NETLINK_CB(skb
).portid
,
693 module_put(THIS_MODULE
);
694 return ret
== -EAGAIN
? -ENOBUFS
: ret
;
697 static const struct nla_policy nfnl_compat_policy_get
[NFTA_COMPAT_MAX
+1] = {
698 [NFTA_COMPAT_NAME
] = { .type
= NLA_NUL_STRING
,
699 .len
= NFT_COMPAT_NAME_MAX
-1 },
700 [NFTA_COMPAT_REV
] = { .type
= NLA_U32
},
701 [NFTA_COMPAT_TYPE
] = { .type
= NLA_U32
},
704 static const struct nfnl_callback nfnl_nft_compat_cb
[NFNL_MSG_COMPAT_MAX
] = {
705 [NFNL_MSG_COMPAT_GET
] = { .call_rcu
= nfnl_compat_get_rcu
,
706 .attr_count
= NFTA_COMPAT_MAX
,
707 .policy
= nfnl_compat_policy_get
},
710 static const struct nfnetlink_subsystem nfnl_compat_subsys
= {
711 .name
= "nft-compat",
712 .subsys_id
= NFNL_SUBSYS_NFT_COMPAT
,
713 .cb_count
= NFNL_MSG_COMPAT_MAX
,
714 .cb
= nfnl_nft_compat_cb
,
717 static struct nft_expr_type nft_match_type
;
719 static void nft_mt_tg_deactivate(const struct nft_ctx
*ctx
,
720 const struct nft_expr
*expr
,
721 enum nft_trans_phase phase
)
723 if (phase
== NFT_TRANS_COMMIT
)
724 refcount_inc(&nft_compat_pending_destroy
);
727 static const struct nft_expr_ops
*
728 nft_match_select_ops(const struct nft_ctx
*ctx
,
729 const struct nlattr
* const tb
[])
731 struct nft_expr_ops
*ops
;
732 struct xt_match
*match
;
733 unsigned int matchsize
;
738 if (tb
[NFTA_MATCH_NAME
] == NULL
||
739 tb
[NFTA_MATCH_REV
] == NULL
||
740 tb
[NFTA_MATCH_INFO
] == NULL
)
741 return ERR_PTR(-EINVAL
);
743 mt_name
= nla_data(tb
[NFTA_MATCH_NAME
]);
744 rev
= ntohl(nla_get_be32(tb
[NFTA_MATCH_REV
]));
745 family
= ctx
->family
;
747 match
= xt_request_find_match(family
, mt_name
, rev
);
749 return ERR_PTR(-ENOENT
);
751 if (match
->matchsize
> nla_len(tb
[NFTA_MATCH_INFO
])) {
756 ops
= kzalloc(sizeof(struct nft_expr_ops
), GFP_KERNEL
);
762 ops
->type
= &nft_match_type
;
763 ops
->eval
= nft_match_eval
;
764 ops
->init
= nft_match_init
;
765 ops
->deactivate
= nft_mt_tg_deactivate
,
766 ops
->destroy
= nft_match_destroy
;
767 ops
->dump
= nft_match_dump
;
768 ops
->validate
= nft_match_validate
;
771 matchsize
= NFT_EXPR_SIZE(XT_ALIGN(match
->matchsize
));
772 if (matchsize
> NFT_MATCH_LARGE_THRESH
) {
773 matchsize
= NFT_EXPR_SIZE(sizeof(struct nft_xt_match_priv
));
775 ops
->eval
= nft_match_large_eval
;
776 ops
->init
= nft_match_large_init
;
777 ops
->destroy
= nft_match_large_destroy
;
778 ops
->dump
= nft_match_large_dump
;
781 ops
->size
= matchsize
;
785 module_put(match
->me
);
789 static void nft_match_release_ops(const struct nft_expr_ops
*ops
)
791 struct xt_match
*match
= ops
->data
;
793 module_put(match
->me
);
797 static struct nft_expr_type nft_match_type __read_mostly
= {
799 .select_ops
= nft_match_select_ops
,
800 .release_ops
= nft_match_release_ops
,
801 .policy
= nft_match_policy
,
802 .maxattr
= NFTA_MATCH_MAX
,
803 .owner
= THIS_MODULE
,
806 static struct nft_expr_type nft_target_type
;
808 static const struct nft_expr_ops
*
809 nft_target_select_ops(const struct nft_ctx
*ctx
,
810 const struct nlattr
* const tb
[])
812 struct nft_expr_ops
*ops
;
813 struct xt_target
*target
;
818 if (tb
[NFTA_TARGET_NAME
] == NULL
||
819 tb
[NFTA_TARGET_REV
] == NULL
||
820 tb
[NFTA_TARGET_INFO
] == NULL
)
821 return ERR_PTR(-EINVAL
);
823 tg_name
= nla_data(tb
[NFTA_TARGET_NAME
]);
824 rev
= ntohl(nla_get_be32(tb
[NFTA_TARGET_REV
]));
825 family
= ctx
->family
;
827 if (strcmp(tg_name
, XT_ERROR_TARGET
) == 0 ||
828 strcmp(tg_name
, XT_STANDARD_TARGET
) == 0 ||
829 strcmp(tg_name
, "standard") == 0)
830 return ERR_PTR(-EINVAL
);
832 target
= xt_request_find_target(family
, tg_name
, rev
);
834 return ERR_PTR(-ENOENT
);
836 if (!target
->target
) {
841 if (target
->targetsize
> nla_len(tb
[NFTA_TARGET_INFO
])) {
846 ops
= kzalloc(sizeof(struct nft_expr_ops
), GFP_KERNEL
);
852 ops
->type
= &nft_target_type
;
853 ops
->size
= NFT_EXPR_SIZE(XT_ALIGN(target
->targetsize
));
854 ops
->init
= nft_target_init
;
855 ops
->destroy
= nft_target_destroy
;
856 ops
->deactivate
= nft_mt_tg_deactivate
,
857 ops
->dump
= nft_target_dump
;
858 ops
->validate
= nft_target_validate
;
861 if (family
== NFPROTO_BRIDGE
)
862 ops
->eval
= nft_target_eval_bridge
;
864 ops
->eval
= nft_target_eval_xt
;
868 module_put(target
->me
);
872 static void nft_target_release_ops(const struct nft_expr_ops
*ops
)
874 struct xt_target
*target
= ops
->data
;
876 module_put(target
->me
);
880 static struct nft_expr_type nft_target_type __read_mostly
= {
882 .select_ops
= nft_target_select_ops
,
883 .release_ops
= nft_target_release_ops
,
884 .policy
= nft_target_policy
,
885 .maxattr
= NFTA_TARGET_MAX
,
886 .owner
= THIS_MODULE
,
889 static int __init
nft_compat_module_init(void)
893 ret
= nft_register_expr(&nft_match_type
);
897 ret
= nft_register_expr(&nft_target_type
);
901 ret
= nfnetlink_subsys_register(&nfnl_compat_subsys
);
903 pr_err("nft_compat: cannot register with nfnetlink.\n");
909 nft_unregister_expr(&nft_target_type
);
911 nft_unregister_expr(&nft_match_type
);
915 static void __exit
nft_compat_module_exit(void)
917 nfnetlink_subsys_unregister(&nfnl_compat_subsys
);
918 nft_unregister_expr(&nft_target_type
);
919 nft_unregister_expr(&nft_match_type
);
921 WARN_ON_ONCE(refcount_read(&nft_compat_pending_destroy
) != 1);
924 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT
);
926 module_init(nft_compat_module_init
);
927 module_exit(nft_compat_module_exit
);
929 MODULE_LICENSE("GPL");
930 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
931 MODULE_ALIAS_NFT_EXPR("match");
932 MODULE_ALIAS_NFT_EXPR("target");
933 MODULE_DESCRIPTION("x_tables over nftables support");