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>
26 /* Used for matches where *info is larger than X byte */
27 #define NFT_MATCH_LARGE_THRESH 192
29 struct nft_xt_match_priv
{
33 static int nft_compat_chain_validate_dependency(const struct nft_ctx
*ctx
,
34 const char *tablename
)
36 enum nft_chain_types type
= NFT_CHAIN_T_DEFAULT
;
37 const struct nft_chain
*chain
= ctx
->chain
;
38 const struct nft_base_chain
*basechain
;
41 !nft_is_base_chain(chain
))
44 basechain
= nft_base_chain(chain
);
45 if (strcmp(tablename
, "nat") == 0) {
46 if (ctx
->family
!= NFPROTO_BRIDGE
)
47 type
= NFT_CHAIN_T_NAT
;
48 if (basechain
->type
->type
!= type
)
59 struct arpt_entry arp
;
63 nft_compat_set_par(struct xt_action_param
*par
, void *xt
, const void *xt_info
)
66 par
->targinfo
= xt_info
;
70 static void nft_target_eval_xt(const struct nft_expr
*expr
,
71 struct nft_regs
*regs
,
72 const struct nft_pktinfo
*pkt
)
74 void *info
= nft_expr_priv(expr
);
75 struct xt_target
*target
= expr
->ops
->data
;
76 struct sk_buff
*skb
= pkt
->skb
;
79 nft_compat_set_par((struct xt_action_param
*)&pkt
->xt
, target
, info
);
81 ret
= target
->target(skb
, &pkt
->xt
);
88 regs
->verdict
.code
= NFT_CONTINUE
;
91 regs
->verdict
.code
= ret
;
96 static void nft_target_eval_bridge(const struct nft_expr
*expr
,
97 struct nft_regs
*regs
,
98 const struct nft_pktinfo
*pkt
)
100 void *info
= nft_expr_priv(expr
);
101 struct xt_target
*target
= expr
->ops
->data
;
102 struct sk_buff
*skb
= pkt
->skb
;
105 nft_compat_set_par((struct xt_action_param
*)&pkt
->xt
, target
, info
);
107 ret
= target
->target(skb
, &pkt
->xt
);
114 regs
->verdict
.code
= NF_ACCEPT
;
117 regs
->verdict
.code
= NF_DROP
;
120 regs
->verdict
.code
= NFT_CONTINUE
;
123 regs
->verdict
.code
= NFT_RETURN
;
126 regs
->verdict
.code
= ret
;
131 static const struct nla_policy nft_target_policy
[NFTA_TARGET_MAX
+ 1] = {
132 [NFTA_TARGET_NAME
] = { .type
= NLA_NUL_STRING
},
133 [NFTA_TARGET_REV
] = { .type
= NLA_U32
},
134 [NFTA_TARGET_INFO
] = { .type
= NLA_BINARY
},
138 nft_target_set_tgchk_param(struct xt_tgchk_param
*par
,
139 const struct nft_ctx
*ctx
,
140 struct xt_target
*target
, void *info
,
141 union nft_entry
*entry
, u16 proto
, bool inv
)
144 par
->table
= ctx
->table
->name
;
145 switch (ctx
->family
) {
147 entry
->e4
.ip
.proto
= proto
;
148 entry
->e4
.ip
.invflags
= inv
? IPT_INV_PROTO
: 0;
152 entry
->e6
.ipv6
.flags
|= IP6T_F_PROTO
;
154 entry
->e6
.ipv6
.proto
= proto
;
155 entry
->e6
.ipv6
.invflags
= inv
? IP6T_INV_PROTO
: 0;
158 entry
->ebt
.ethproto
= (__force __be16
)proto
;
159 entry
->ebt
.invflags
= inv
? EBT_IPROTO
: 0;
164 par
->entryinfo
= entry
;
165 par
->target
= target
;
166 par
->targinfo
= info
;
167 if (nft_is_base_chain(ctx
->chain
)) {
168 const struct nft_base_chain
*basechain
=
169 nft_base_chain(ctx
->chain
);
170 const struct nf_hook_ops
*ops
= &basechain
->ops
;
172 par
->hook_mask
= 1 << ops
->hooknum
;
176 par
->family
= ctx
->family
;
177 par
->nft_compat
= true;
180 static void target_compat_from_user(struct xt_target
*t
, void *in
, void *out
)
184 memcpy(out
, in
, t
->targetsize
);
185 pad
= XT_ALIGN(t
->targetsize
) - t
->targetsize
;
187 memset(out
+ t
->targetsize
, 0, pad
);
190 static const struct nla_policy nft_rule_compat_policy
[NFTA_RULE_COMPAT_MAX
+ 1] = {
191 [NFTA_RULE_COMPAT_PROTO
] = { .type
= NLA_U32
},
192 [NFTA_RULE_COMPAT_FLAGS
] = { .type
= NLA_U32
},
195 static int nft_parse_compat(const struct nlattr
*attr
, u16
*proto
, bool *inv
)
197 struct nlattr
*tb
[NFTA_RULE_COMPAT_MAX
+1];
201 err
= nla_parse_nested(tb
, NFTA_RULE_COMPAT_MAX
, attr
,
202 nft_rule_compat_policy
, NULL
);
206 if (!tb
[NFTA_RULE_COMPAT_PROTO
] || !tb
[NFTA_RULE_COMPAT_FLAGS
])
209 flags
= ntohl(nla_get_be32(tb
[NFTA_RULE_COMPAT_FLAGS
]));
210 if (flags
& ~NFT_RULE_COMPAT_F_MASK
)
212 if (flags
& NFT_RULE_COMPAT_F_INV
)
215 *proto
= ntohl(nla_get_be32(tb
[NFTA_RULE_COMPAT_PROTO
]));
220 nft_target_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
221 const struct nlattr
* const tb
[])
223 void *info
= nft_expr_priv(expr
);
224 struct xt_target
*target
= expr
->ops
->data
;
225 struct xt_tgchk_param par
;
226 size_t size
= XT_ALIGN(nla_len(tb
[NFTA_TARGET_INFO
]));
229 union nft_entry e
= {};
232 target_compat_from_user(target
, nla_data(tb
[NFTA_TARGET_INFO
]), info
);
234 if (ctx
->nla
[NFTA_RULE_COMPAT
]) {
235 ret
= nft_parse_compat(ctx
->nla
[NFTA_RULE_COMPAT
], &proto
, &inv
);
240 nft_target_set_tgchk_param(&par
, ctx
, target
, info
, &e
, proto
, inv
);
242 ret
= xt_check_target(&par
, size
, proto
, inv
);
246 /* The standard target cannot be used */
254 nft_target_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
256 struct xt_target
*target
= expr
->ops
->data
;
257 void *info
= nft_expr_priv(expr
);
258 struct module
*me
= target
->me
;
259 struct xt_tgdtor_param par
;
264 par
.family
= ctx
->family
;
265 if (par
.target
->destroy
!= NULL
)
266 par
.target
->destroy(&par
);
272 static int nft_extension_dump_info(struct sk_buff
*skb
, int attr
,
274 unsigned int size
, unsigned int user_size
)
276 unsigned int info_size
, aligned_size
= XT_ALIGN(size
);
279 nla
= nla_reserve(skb
, attr
, aligned_size
);
283 info_size
= user_size
? : size
;
284 memcpy(nla_data(nla
), info
, info_size
);
285 memset(nla_data(nla
) + info_size
, 0, aligned_size
- info_size
);
290 static int nft_target_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
292 const struct xt_target
*target
= expr
->ops
->data
;
293 void *info
= nft_expr_priv(expr
);
295 if (nla_put_string(skb
, NFTA_TARGET_NAME
, target
->name
) ||
296 nla_put_be32(skb
, NFTA_TARGET_REV
, htonl(target
->revision
)) ||
297 nft_extension_dump_info(skb
, NFTA_TARGET_INFO
, info
,
298 target
->targetsize
, target
->usersize
))
299 goto nla_put_failure
;
307 static int nft_target_validate(const struct nft_ctx
*ctx
,
308 const struct nft_expr
*expr
,
309 const struct nft_data
**data
)
311 struct xt_target
*target
= expr
->ops
->data
;
312 unsigned int hook_mask
= 0;
315 if (nft_is_base_chain(ctx
->chain
)) {
316 const struct nft_base_chain
*basechain
=
317 nft_base_chain(ctx
->chain
);
318 const struct nf_hook_ops
*ops
= &basechain
->ops
;
320 hook_mask
= 1 << ops
->hooknum
;
321 if (target
->hooks
&& !(hook_mask
& target
->hooks
))
324 ret
= nft_compat_chain_validate_dependency(ctx
, target
->table
);
331 static void __nft_match_eval(const struct nft_expr
*expr
,
332 struct nft_regs
*regs
,
333 const struct nft_pktinfo
*pkt
,
336 struct xt_match
*match
= expr
->ops
->data
;
337 struct sk_buff
*skb
= pkt
->skb
;
340 nft_compat_set_par((struct xt_action_param
*)&pkt
->xt
, match
, info
);
342 ret
= match
->match(skb
, (struct xt_action_param
*)&pkt
->xt
);
344 if (pkt
->xt
.hotdrop
) {
345 regs
->verdict
.code
= NF_DROP
;
349 switch (ret
? 1 : 0) {
351 regs
->verdict
.code
= NFT_CONTINUE
;
354 regs
->verdict
.code
= NFT_BREAK
;
359 static void nft_match_large_eval(const struct nft_expr
*expr
,
360 struct nft_regs
*regs
,
361 const struct nft_pktinfo
*pkt
)
363 struct nft_xt_match_priv
*priv
= nft_expr_priv(expr
);
365 __nft_match_eval(expr
, regs
, pkt
, priv
->info
);
368 static void nft_match_eval(const struct nft_expr
*expr
,
369 struct nft_regs
*regs
,
370 const struct nft_pktinfo
*pkt
)
372 __nft_match_eval(expr
, regs
, pkt
, nft_expr_priv(expr
));
375 static const struct nla_policy nft_match_policy
[NFTA_MATCH_MAX
+ 1] = {
376 [NFTA_MATCH_NAME
] = { .type
= NLA_NUL_STRING
},
377 [NFTA_MATCH_REV
] = { .type
= NLA_U32
},
378 [NFTA_MATCH_INFO
] = { .type
= NLA_BINARY
},
381 /* struct xt_mtchk_param and xt_tgchk_param look very similar */
383 nft_match_set_mtchk_param(struct xt_mtchk_param
*par
, const struct nft_ctx
*ctx
,
384 struct xt_match
*match
, void *info
,
385 union nft_entry
*entry
, u16 proto
, bool inv
)
388 par
->table
= ctx
->table
->name
;
389 switch (ctx
->family
) {
391 entry
->e4
.ip
.proto
= proto
;
392 entry
->e4
.ip
.invflags
= inv
? IPT_INV_PROTO
: 0;
396 entry
->e6
.ipv6
.flags
|= IP6T_F_PROTO
;
398 entry
->e6
.ipv6
.proto
= proto
;
399 entry
->e6
.ipv6
.invflags
= inv
? IP6T_INV_PROTO
: 0;
402 entry
->ebt
.ethproto
= (__force __be16
)proto
;
403 entry
->ebt
.invflags
= inv
? EBT_IPROTO
: 0;
408 par
->entryinfo
= entry
;
410 par
->matchinfo
= info
;
411 if (nft_is_base_chain(ctx
->chain
)) {
412 const struct nft_base_chain
*basechain
=
413 nft_base_chain(ctx
->chain
);
414 const struct nf_hook_ops
*ops
= &basechain
->ops
;
416 par
->hook_mask
= 1 << ops
->hooknum
;
420 par
->family
= ctx
->family
;
421 par
->nft_compat
= true;
424 static void match_compat_from_user(struct xt_match
*m
, void *in
, void *out
)
428 memcpy(out
, in
, m
->matchsize
);
429 pad
= XT_ALIGN(m
->matchsize
) - m
->matchsize
;
431 memset(out
+ m
->matchsize
, 0, pad
);
435 __nft_match_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
436 const struct nlattr
* const tb
[],
439 struct xt_match
*match
= expr
->ops
->data
;
440 struct xt_mtchk_param par
;
441 size_t size
= XT_ALIGN(nla_len(tb
[NFTA_MATCH_INFO
]));
444 union nft_entry e
= {};
447 match_compat_from_user(match
, nla_data(tb
[NFTA_MATCH_INFO
]), info
);
449 if (ctx
->nla
[NFTA_RULE_COMPAT
]) {
450 ret
= nft_parse_compat(ctx
->nla
[NFTA_RULE_COMPAT
], &proto
, &inv
);
455 nft_match_set_mtchk_param(&par
, ctx
, match
, info
, &e
, proto
, inv
);
457 return xt_check_match(&par
, size
, proto
, inv
);
461 nft_match_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
462 const struct nlattr
* const tb
[])
464 return __nft_match_init(ctx
, expr
, tb
, nft_expr_priv(expr
));
468 nft_match_large_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
469 const struct nlattr
* const tb
[])
471 struct nft_xt_match_priv
*priv
= nft_expr_priv(expr
);
472 struct xt_match
*m
= expr
->ops
->data
;
475 priv
->info
= kmalloc(XT_ALIGN(m
->matchsize
), GFP_KERNEL
);
479 ret
= __nft_match_init(ctx
, expr
, tb
, priv
->info
);
486 __nft_match_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
489 struct xt_match
*match
= expr
->ops
->data
;
490 struct module
*me
= match
->me
;
491 struct xt_mtdtor_param par
;
495 par
.matchinfo
= info
;
496 par
.family
= ctx
->family
;
497 if (par
.match
->destroy
!= NULL
)
498 par
.match
->destroy(&par
);
505 nft_match_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
507 __nft_match_destroy(ctx
, expr
, nft_expr_priv(expr
));
511 nft_match_large_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
513 struct nft_xt_match_priv
*priv
= nft_expr_priv(expr
);
515 __nft_match_destroy(ctx
, expr
, priv
->info
);
519 static int __nft_match_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
,
522 struct xt_match
*match
= expr
->ops
->data
;
524 if (nla_put_string(skb
, NFTA_MATCH_NAME
, match
->name
) ||
525 nla_put_be32(skb
, NFTA_MATCH_REV
, htonl(match
->revision
)) ||
526 nft_extension_dump_info(skb
, NFTA_MATCH_INFO
, info
,
527 match
->matchsize
, match
->usersize
))
528 goto nla_put_failure
;
536 static int nft_match_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
538 return __nft_match_dump(skb
, expr
, nft_expr_priv(expr
));
541 static int nft_match_large_dump(struct sk_buff
*skb
, const struct nft_expr
*e
)
543 struct nft_xt_match_priv
*priv
= nft_expr_priv(e
);
545 return __nft_match_dump(skb
, e
, priv
->info
);
548 static int nft_match_validate(const struct nft_ctx
*ctx
,
549 const struct nft_expr
*expr
,
550 const struct nft_data
**data
)
552 struct xt_match
*match
= expr
->ops
->data
;
553 unsigned int hook_mask
= 0;
556 if (nft_is_base_chain(ctx
->chain
)) {
557 const struct nft_base_chain
*basechain
=
558 nft_base_chain(ctx
->chain
);
559 const struct nf_hook_ops
*ops
= &basechain
->ops
;
561 hook_mask
= 1 << ops
->hooknum
;
562 if (match
->hooks
&& !(hook_mask
& match
->hooks
))
565 ret
= nft_compat_chain_validate_dependency(ctx
, match
->table
);
573 nfnl_compat_fill_info(struct sk_buff
*skb
, u32 portid
, u32 seq
, u32 type
,
574 int event
, u16 family
, const char *name
,
577 struct nlmsghdr
*nlh
;
578 struct nfgenmsg
*nfmsg
;
579 unsigned int flags
= portid
? NLM_F_MULTI
: 0;
581 event
= nfnl_msg_type(NFNL_SUBSYS_NFT_COMPAT
, event
);
582 nlh
= nlmsg_put(skb
, portid
, seq
, event
, sizeof(*nfmsg
), flags
);
586 nfmsg
= nlmsg_data(nlh
);
587 nfmsg
->nfgen_family
= family
;
588 nfmsg
->version
= NFNETLINK_V0
;
591 if (nla_put_string(skb
, NFTA_COMPAT_NAME
, name
) ||
592 nla_put_be32(skb
, NFTA_COMPAT_REV
, htonl(rev
)) ||
593 nla_put_be32(skb
, NFTA_COMPAT_TYPE
, htonl(target
)))
594 goto nla_put_failure
;
601 nlmsg_cancel(skb
, nlh
);
605 static int nfnl_compat_get_rcu(struct net
*net
, struct sock
*nfnl
,
606 struct sk_buff
*skb
, const struct nlmsghdr
*nlh
,
607 const struct nlattr
* const tb
[],
608 struct netlink_ext_ack
*extack
)
611 struct nfgenmsg
*nfmsg
;
615 struct sk_buff
*skb2
;
617 if (tb
[NFTA_COMPAT_NAME
] == NULL
||
618 tb
[NFTA_COMPAT_REV
] == NULL
||
619 tb
[NFTA_COMPAT_TYPE
] == NULL
)
622 name
= nla_data(tb
[NFTA_COMPAT_NAME
]);
623 rev
= ntohl(nla_get_be32(tb
[NFTA_COMPAT_REV
]));
624 target
= ntohl(nla_get_be32(tb
[NFTA_COMPAT_TYPE
]));
626 nfmsg
= nlmsg_data(nlh
);
628 switch(nfmsg
->nfgen_family
) {
642 pr_err("nft_compat: unsupported protocol %d\n",
643 nfmsg
->nfgen_family
);
647 if (!try_module_get(THIS_MODULE
))
651 try_then_request_module(xt_find_revision(nfmsg
->nfgen_family
, name
,
657 skb2
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
663 /* include the best revision for this extension in the message */
664 if (nfnl_compat_fill_info(skb2
, NETLINK_CB(skb
).portid
,
666 NFNL_MSG_TYPE(nlh
->nlmsg_type
),
669 name
, ret
, target
) <= 0) {
674 ret
= netlink_unicast(nfnl
, skb2
, NETLINK_CB(skb
).portid
,
680 module_put(THIS_MODULE
);
681 return ret
== -EAGAIN
? -ENOBUFS
: ret
;
684 static const struct nla_policy nfnl_compat_policy_get
[NFTA_COMPAT_MAX
+1] = {
685 [NFTA_COMPAT_NAME
] = { .type
= NLA_NUL_STRING
,
686 .len
= NFT_COMPAT_NAME_MAX
-1 },
687 [NFTA_COMPAT_REV
] = { .type
= NLA_U32
},
688 [NFTA_COMPAT_TYPE
] = { .type
= NLA_U32
},
691 static const struct nfnl_callback nfnl_nft_compat_cb
[NFNL_MSG_COMPAT_MAX
] = {
692 [NFNL_MSG_COMPAT_GET
] = { .call_rcu
= nfnl_compat_get_rcu
,
693 .attr_count
= NFTA_COMPAT_MAX
,
694 .policy
= nfnl_compat_policy_get
},
697 static const struct nfnetlink_subsystem nfnl_compat_subsys
= {
698 .name
= "nft-compat",
699 .subsys_id
= NFNL_SUBSYS_NFT_COMPAT
,
700 .cb_count
= NFNL_MSG_COMPAT_MAX
,
701 .cb
= nfnl_nft_compat_cb
,
704 static struct nft_expr_type nft_match_type
;
706 static const struct nft_expr_ops
*
707 nft_match_select_ops(const struct nft_ctx
*ctx
,
708 const struct nlattr
* const tb
[])
710 struct nft_expr_ops
*ops
;
711 struct xt_match
*match
;
712 unsigned int matchsize
;
717 if (tb
[NFTA_MATCH_NAME
] == NULL
||
718 tb
[NFTA_MATCH_REV
] == NULL
||
719 tb
[NFTA_MATCH_INFO
] == NULL
)
720 return ERR_PTR(-EINVAL
);
722 mt_name
= nla_data(tb
[NFTA_MATCH_NAME
]);
723 rev
= ntohl(nla_get_be32(tb
[NFTA_MATCH_REV
]));
724 family
= ctx
->family
;
726 match
= xt_request_find_match(family
, mt_name
, rev
);
728 return ERR_PTR(-ENOENT
);
730 if (match
->matchsize
> nla_len(tb
[NFTA_MATCH_INFO
])) {
735 ops
= kzalloc(sizeof(struct nft_expr_ops
), GFP_KERNEL
);
741 ops
->type
= &nft_match_type
;
742 ops
->eval
= nft_match_eval
;
743 ops
->init
= nft_match_init
;
744 ops
->destroy
= nft_match_destroy
;
745 ops
->dump
= nft_match_dump
;
746 ops
->validate
= nft_match_validate
;
749 matchsize
= NFT_EXPR_SIZE(XT_ALIGN(match
->matchsize
));
750 if (matchsize
> NFT_MATCH_LARGE_THRESH
) {
751 matchsize
= NFT_EXPR_SIZE(sizeof(struct nft_xt_match_priv
));
753 ops
->eval
= nft_match_large_eval
;
754 ops
->init
= nft_match_large_init
;
755 ops
->destroy
= nft_match_large_destroy
;
756 ops
->dump
= nft_match_large_dump
;
759 ops
->size
= matchsize
;
763 module_put(match
->me
);
767 static void nft_match_release_ops(const struct nft_expr_ops
*ops
)
769 struct xt_match
*match
= ops
->data
;
771 module_put(match
->me
);
775 static struct nft_expr_type nft_match_type __read_mostly
= {
777 .select_ops
= nft_match_select_ops
,
778 .release_ops
= nft_match_release_ops
,
779 .policy
= nft_match_policy
,
780 .maxattr
= NFTA_MATCH_MAX
,
781 .owner
= THIS_MODULE
,
784 static struct nft_expr_type nft_target_type
;
786 static const struct nft_expr_ops
*
787 nft_target_select_ops(const struct nft_ctx
*ctx
,
788 const struct nlattr
* const tb
[])
790 struct nft_expr_ops
*ops
;
791 struct xt_target
*target
;
796 if (tb
[NFTA_TARGET_NAME
] == NULL
||
797 tb
[NFTA_TARGET_REV
] == NULL
||
798 tb
[NFTA_TARGET_INFO
] == NULL
)
799 return ERR_PTR(-EINVAL
);
801 tg_name
= nla_data(tb
[NFTA_TARGET_NAME
]);
802 rev
= ntohl(nla_get_be32(tb
[NFTA_TARGET_REV
]));
803 family
= ctx
->family
;
805 if (strcmp(tg_name
, XT_ERROR_TARGET
) == 0 ||
806 strcmp(tg_name
, XT_STANDARD_TARGET
) == 0 ||
807 strcmp(tg_name
, "standard") == 0)
808 return ERR_PTR(-EINVAL
);
810 target
= xt_request_find_target(family
, tg_name
, rev
);
812 return ERR_PTR(-ENOENT
);
814 if (!target
->target
) {
819 if (target
->targetsize
> nla_len(tb
[NFTA_TARGET_INFO
])) {
824 ops
= kzalloc(sizeof(struct nft_expr_ops
), GFP_KERNEL
);
830 ops
->type
= &nft_target_type
;
831 ops
->size
= NFT_EXPR_SIZE(XT_ALIGN(target
->targetsize
));
832 ops
->init
= nft_target_init
;
833 ops
->destroy
= nft_target_destroy
;
834 ops
->dump
= nft_target_dump
;
835 ops
->validate
= nft_target_validate
;
838 if (family
== NFPROTO_BRIDGE
)
839 ops
->eval
= nft_target_eval_bridge
;
841 ops
->eval
= nft_target_eval_xt
;
845 module_put(target
->me
);
849 static void nft_target_release_ops(const struct nft_expr_ops
*ops
)
851 struct xt_target
*target
= ops
->data
;
853 module_put(target
->me
);
857 static struct nft_expr_type nft_target_type __read_mostly
= {
859 .select_ops
= nft_target_select_ops
,
860 .release_ops
= nft_target_release_ops
,
861 .policy
= nft_target_policy
,
862 .maxattr
= NFTA_TARGET_MAX
,
863 .owner
= THIS_MODULE
,
866 static int __init
nft_compat_module_init(void)
870 ret
= nft_register_expr(&nft_match_type
);
874 ret
= nft_register_expr(&nft_target_type
);
878 ret
= nfnetlink_subsys_register(&nfnl_compat_subsys
);
880 pr_err("nft_compat: cannot register with nfnetlink.\n");
886 nft_unregister_expr(&nft_target_type
);
888 nft_unregister_expr(&nft_match_type
);
892 static void __exit
nft_compat_module_exit(void)
894 nfnetlink_subsys_unregister(&nfnl_compat_subsys
);
895 nft_unregister_expr(&nft_target_type
);
896 nft_unregister_expr(&nft_match_type
);
899 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT
);
901 module_init(nft_compat_module_init
);
902 module_exit(nft_compat_module_exit
);
904 MODULE_LICENSE("GPL");
905 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
906 MODULE_ALIAS_NFT_EXPR("match");
907 MODULE_ALIAS_NFT_EXPR("target");