ALSA: hda - Don't access stereo amps for mono channel widgets
[linux-drm-fsl-dcu.git] / net / netfilter / nft_compat.c
1 /*
2  * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
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  * This software has been sponsored by Sophos Astaro <http://www.sophos.com>
9  */
10
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 <net/netfilter/nf_tables.h>
24
25 static int nft_compat_chain_validate_dependency(const char *tablename,
26                                                 const struct nft_chain *chain)
27 {
28         const struct nft_base_chain *basechain;
29
30         if (!tablename || !(chain->flags & NFT_BASE_CHAIN))
31                 return 0;
32
33         basechain = nft_base_chain(chain);
34         if (strcmp(tablename, "nat") == 0 &&
35             basechain->type->type != NFT_CHAIN_T_NAT)
36                 return -EINVAL;
37
38         return 0;
39 }
40
41 union nft_entry {
42         struct ipt_entry e4;
43         struct ip6t_entry e6;
44         struct ebt_entry ebt;
45 };
46
47 static inline void
48 nft_compat_set_par(struct xt_action_param *par, void *xt, const void *xt_info)
49 {
50         par->target     = xt;
51         par->targinfo   = xt_info;
52         par->hotdrop    = false;
53 }
54
55 static void nft_target_eval_xt(const struct nft_expr *expr,
56                                struct nft_data data[NFT_REG_MAX + 1],
57                                const struct nft_pktinfo *pkt)
58 {
59         void *info = nft_expr_priv(expr);
60         struct xt_target *target = expr->ops->data;
61         struct sk_buff *skb = pkt->skb;
62         int ret;
63
64         nft_compat_set_par((struct xt_action_param *)&pkt->xt, target, info);
65
66         ret = target->target(skb, &pkt->xt);
67
68         if (pkt->xt.hotdrop)
69                 ret = NF_DROP;
70
71         switch (ret) {
72         case XT_CONTINUE:
73                 data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
74                 break;
75         default:
76                 data[NFT_REG_VERDICT].verdict = ret;
77                 break;
78         }
79 }
80
81 static void nft_target_eval_bridge(const struct nft_expr *expr,
82                                    struct nft_data data[NFT_REG_MAX + 1],
83                                    const struct nft_pktinfo *pkt)
84 {
85         void *info = nft_expr_priv(expr);
86         struct xt_target *target = expr->ops->data;
87         struct sk_buff *skb = pkt->skb;
88         int ret;
89
90         nft_compat_set_par((struct xt_action_param *)&pkt->xt, target, info);
91
92         ret = target->target(skb, &pkt->xt);
93
94         if (pkt->xt.hotdrop)
95                 ret = NF_DROP;
96
97         switch (ret) {
98         case EBT_ACCEPT:
99                 data[NFT_REG_VERDICT].verdict = NF_ACCEPT;
100                 break;
101         case EBT_DROP:
102                 data[NFT_REG_VERDICT].verdict = NF_DROP;
103                 break;
104         case EBT_CONTINUE:
105                 data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
106                 break;
107         case EBT_RETURN:
108                 data[NFT_REG_VERDICT].verdict = NFT_RETURN;
109                 break;
110         default:
111                 data[NFT_REG_VERDICT].verdict = ret;
112                 break;
113         }
114 }
115
116 static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = {
117         [NFTA_TARGET_NAME]      = { .type = NLA_NUL_STRING },
118         [NFTA_TARGET_REV]       = { .type = NLA_U32 },
119         [NFTA_TARGET_INFO]      = { .type = NLA_BINARY },
120 };
121
122 static void
123 nft_target_set_tgchk_param(struct xt_tgchk_param *par,
124                            const struct nft_ctx *ctx,
125                            struct xt_target *target, void *info,
126                            union nft_entry *entry, u8 proto, bool inv)
127 {
128         par->net        = ctx->net;
129         par->table      = ctx->table->name;
130         switch (ctx->afi->family) {
131         case AF_INET:
132                 entry->e4.ip.proto = proto;
133                 entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
134                 break;
135         case AF_INET6:
136                 entry->e6.ipv6.proto = proto;
137                 entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
138                 break;
139         case NFPROTO_BRIDGE:
140                 entry->ebt.ethproto = proto;
141                 entry->ebt.invflags = inv ? EBT_IPROTO : 0;
142                 break;
143         }
144         par->entryinfo  = entry;
145         par->target     = target;
146         par->targinfo   = info;
147         if (ctx->chain->flags & NFT_BASE_CHAIN) {
148                 const struct nft_base_chain *basechain =
149                                                 nft_base_chain(ctx->chain);
150                 const struct nf_hook_ops *ops = &basechain->ops[0];
151
152                 par->hook_mask = 1 << ops->hooknum;
153         } else {
154                 par->hook_mask = 0;
155         }
156         par->family     = ctx->afi->family;
157 }
158
159 static void target_compat_from_user(struct xt_target *t, void *in, void *out)
160 {
161         int pad;
162
163         memcpy(out, in, t->targetsize);
164         pad = XT_ALIGN(t->targetsize) - t->targetsize;
165         if (pad > 0)
166                 memset(out + t->targetsize, 0, pad);
167 }
168
169 static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1] = {
170         [NFTA_RULE_COMPAT_PROTO]        = { .type = NLA_U32 },
171         [NFTA_RULE_COMPAT_FLAGS]        = { .type = NLA_U32 },
172 };
173
174 static int nft_parse_compat(const struct nlattr *attr, u8 *proto, bool *inv)
175 {
176         struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1];
177         u32 flags;
178         int err;
179
180         err = nla_parse_nested(tb, NFTA_RULE_COMPAT_MAX, attr,
181                                nft_rule_compat_policy);
182         if (err < 0)
183                 return err;
184
185         if (!tb[NFTA_RULE_COMPAT_PROTO] || !tb[NFTA_RULE_COMPAT_FLAGS])
186                 return -EINVAL;
187
188         flags = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_FLAGS]));
189         if (flags & ~NFT_RULE_COMPAT_F_MASK)
190                 return -EINVAL;
191         if (flags & NFT_RULE_COMPAT_F_INV)
192                 *inv = true;
193
194         *proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO]));
195         return 0;
196 }
197
198 static int
199 nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
200                 const struct nlattr * const tb[])
201 {
202         void *info = nft_expr_priv(expr);
203         struct xt_target *target = expr->ops->data;
204         struct xt_tgchk_param par;
205         size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO]));
206         u8 proto = 0;
207         bool inv = false;
208         union nft_entry e = {};
209         int ret;
210
211         ret = nft_compat_chain_validate_dependency(target->table, ctx->chain);
212         if (ret < 0)
213                 goto err;
214
215         target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info);
216
217         if (ctx->nla[NFTA_RULE_COMPAT]) {
218                 ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
219                 if (ret < 0)
220                         goto err;
221         }
222
223         nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
224
225         ret = xt_check_target(&par, size, proto, inv);
226         if (ret < 0)
227                 goto err;
228
229         /* The standard target cannot be used */
230         if (target->target == NULL) {
231                 ret = -EINVAL;
232                 goto err;
233         }
234
235         return 0;
236 err:
237         module_put(target->me);
238         return ret;
239 }
240
241 static void
242 nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
243 {
244         struct xt_target *target = expr->ops->data;
245         void *info = nft_expr_priv(expr);
246         struct xt_tgdtor_param par;
247
248         par.net = ctx->net;
249         par.target = target;
250         par.targinfo = info;
251         par.family = ctx->afi->family;
252         if (par.target->destroy != NULL)
253                 par.target->destroy(&par);
254
255         module_put(target->me);
256 }
257
258 static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
259 {
260         const struct xt_target *target = expr->ops->data;
261         void *info = nft_expr_priv(expr);
262
263         if (nla_put_string(skb, NFTA_TARGET_NAME, target->name) ||
264             nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision)) ||
265             nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(target->targetsize), info))
266                 goto nla_put_failure;
267
268         return 0;
269
270 nla_put_failure:
271         return -1;
272 }
273
274 static int nft_target_validate(const struct nft_ctx *ctx,
275                                const struct nft_expr *expr,
276                                const struct nft_data **data)
277 {
278         struct xt_target *target = expr->ops->data;
279         unsigned int hook_mask = 0;
280         int ret;
281
282         if (ctx->chain->flags & NFT_BASE_CHAIN) {
283                 const struct nft_base_chain *basechain =
284                                                 nft_base_chain(ctx->chain);
285                 const struct nf_hook_ops *ops = &basechain->ops[0];
286
287                 hook_mask = 1 << ops->hooknum;
288                 if (!(hook_mask & target->hooks))
289                         return -EINVAL;
290
291                 ret = nft_compat_chain_validate_dependency(target->table,
292                                                            ctx->chain);
293                 if (ret < 0)
294                         return ret;
295         }
296         return 0;
297 }
298
299 static void nft_match_eval(const struct nft_expr *expr,
300                            struct nft_data data[NFT_REG_MAX + 1],
301                            const struct nft_pktinfo *pkt)
302 {
303         void *info = nft_expr_priv(expr);
304         struct xt_match *match = expr->ops->data;
305         struct sk_buff *skb = pkt->skb;
306         bool ret;
307
308         nft_compat_set_par((struct xt_action_param *)&pkt->xt, match, info);
309
310         ret = match->match(skb, (struct xt_action_param *)&pkt->xt);
311
312         if (pkt->xt.hotdrop) {
313                 data[NFT_REG_VERDICT].verdict = NF_DROP;
314                 return;
315         }
316
317         switch(ret) {
318         case true:
319                 data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
320                 break;
321         case false:
322                 data[NFT_REG_VERDICT].verdict = NFT_BREAK;
323                 break;
324         }
325 }
326
327 static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = {
328         [NFTA_MATCH_NAME]       = { .type = NLA_NUL_STRING },
329         [NFTA_MATCH_REV]        = { .type = NLA_U32 },
330         [NFTA_MATCH_INFO]       = { .type = NLA_BINARY },
331 };
332
333 /* struct xt_mtchk_param and xt_tgchk_param look very similar */
334 static void
335 nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
336                           struct xt_match *match, void *info,
337                           union nft_entry *entry, u8 proto, bool inv)
338 {
339         par->net        = ctx->net;
340         par->table      = ctx->table->name;
341         switch (ctx->afi->family) {
342         case AF_INET:
343                 entry->e4.ip.proto = proto;
344                 entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
345                 break;
346         case AF_INET6:
347                 entry->e6.ipv6.proto = proto;
348                 entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
349                 break;
350         case NFPROTO_BRIDGE:
351                 entry->ebt.ethproto = proto;
352                 entry->ebt.invflags = inv ? EBT_IPROTO : 0;
353                 break;
354         }
355         par->entryinfo  = entry;
356         par->match      = match;
357         par->matchinfo  = info;
358         if (ctx->chain->flags & NFT_BASE_CHAIN) {
359                 const struct nft_base_chain *basechain =
360                                                 nft_base_chain(ctx->chain);
361                 const struct nf_hook_ops *ops = &basechain->ops[0];
362
363                 par->hook_mask = 1 << ops->hooknum;
364         } else {
365                 par->hook_mask = 0;
366         }
367         par->family     = ctx->afi->family;
368 }
369
370 static void match_compat_from_user(struct xt_match *m, void *in, void *out)
371 {
372         int pad;
373
374         memcpy(out, in, m->matchsize);
375         pad = XT_ALIGN(m->matchsize) - m->matchsize;
376         if (pad > 0)
377                 memset(out + m->matchsize, 0, pad);
378 }
379
380 static int
381 nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
382                 const struct nlattr * const tb[])
383 {
384         void *info = nft_expr_priv(expr);
385         struct xt_match *match = expr->ops->data;
386         struct xt_mtchk_param par;
387         size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO]));
388         u8 proto = 0;
389         bool inv = false;
390         union nft_entry e = {};
391         int ret;
392
393         ret = nft_compat_chain_validate_dependency(match->table, ctx->chain);
394         if (ret < 0)
395                 goto err;
396
397         match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info);
398
399         if (ctx->nla[NFTA_RULE_COMPAT]) {
400                 ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
401                 if (ret < 0)
402                         goto err;
403         }
404
405         nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv);
406
407         ret = xt_check_match(&par, size, proto, inv);
408         if (ret < 0)
409                 goto err;
410
411         return 0;
412 err:
413         module_put(match->me);
414         return ret;
415 }
416
417 static void
418 nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
419 {
420         struct xt_match *match = expr->ops->data;
421         void *info = nft_expr_priv(expr);
422         struct xt_mtdtor_param par;
423
424         par.net = ctx->net;
425         par.match = match;
426         par.matchinfo = info;
427         par.family = ctx->afi->family;
428         if (par.match->destroy != NULL)
429                 par.match->destroy(&par);
430
431         module_put(match->me);
432 }
433
434 static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
435 {
436         void *info = nft_expr_priv(expr);
437         struct xt_match *match = expr->ops->data;
438
439         if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) ||
440             nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision)) ||
441             nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(match->matchsize), info))
442                 goto nla_put_failure;
443
444         return 0;
445
446 nla_put_failure:
447         return -1;
448 }
449
450 static int nft_match_validate(const struct nft_ctx *ctx,
451                               const struct nft_expr *expr,
452                               const struct nft_data **data)
453 {
454         struct xt_match *match = expr->ops->data;
455         unsigned int hook_mask = 0;
456         int ret;
457
458         if (ctx->chain->flags & NFT_BASE_CHAIN) {
459                 const struct nft_base_chain *basechain =
460                                                 nft_base_chain(ctx->chain);
461                 const struct nf_hook_ops *ops = &basechain->ops[0];
462
463                 hook_mask = 1 << ops->hooknum;
464                 if (!(hook_mask & match->hooks))
465                         return -EINVAL;
466
467                 ret = nft_compat_chain_validate_dependency(match->table,
468                                                            ctx->chain);
469                 if (ret < 0)
470                         return ret;
471         }
472         return 0;
473 }
474
475 static int
476 nfnl_compat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
477                       int event, u16 family, const char *name,
478                       int rev, int target)
479 {
480         struct nlmsghdr *nlh;
481         struct nfgenmsg *nfmsg;
482         unsigned int flags = portid ? NLM_F_MULTI : 0;
483
484         event |= NFNL_SUBSYS_NFT_COMPAT << 8;
485         nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
486         if (nlh == NULL)
487                 goto nlmsg_failure;
488
489         nfmsg = nlmsg_data(nlh);
490         nfmsg->nfgen_family = family;
491         nfmsg->version = NFNETLINK_V0;
492         nfmsg->res_id = 0;
493
494         if (nla_put_string(skb, NFTA_COMPAT_NAME, name) ||
495             nla_put_be32(skb, NFTA_COMPAT_REV, htonl(rev)) ||
496             nla_put_be32(skb, NFTA_COMPAT_TYPE, htonl(target)))
497                 goto nla_put_failure;
498
499         nlmsg_end(skb, nlh);
500         return skb->len;
501
502 nlmsg_failure:
503 nla_put_failure:
504         nlmsg_cancel(skb, nlh);
505         return -1;
506 }
507
508 static int
509 nfnl_compat_get(struct sock *nfnl, struct sk_buff *skb,
510                 const struct nlmsghdr *nlh, const struct nlattr * const tb[])
511 {
512         int ret = 0, target;
513         struct nfgenmsg *nfmsg;
514         const char *fmt;
515         const char *name;
516         u32 rev;
517         struct sk_buff *skb2;
518
519         if (tb[NFTA_COMPAT_NAME] == NULL ||
520             tb[NFTA_COMPAT_REV] == NULL ||
521             tb[NFTA_COMPAT_TYPE] == NULL)
522                 return -EINVAL;
523
524         name = nla_data(tb[NFTA_COMPAT_NAME]);
525         rev = ntohl(nla_get_be32(tb[NFTA_COMPAT_REV]));
526         target = ntohl(nla_get_be32(tb[NFTA_COMPAT_TYPE]));
527
528         nfmsg = nlmsg_data(nlh);
529
530         switch(nfmsg->nfgen_family) {
531         case AF_INET:
532                 fmt = "ipt_%s";
533                 break;
534         case AF_INET6:
535                 fmt = "ip6t_%s";
536                 break;
537         case NFPROTO_BRIDGE:
538                 fmt = "ebt_%s";
539                 break;
540         default:
541                 pr_err("nft_compat: unsupported protocol %d\n",
542                         nfmsg->nfgen_family);
543                 return -EINVAL;
544         }
545
546         try_then_request_module(xt_find_revision(nfmsg->nfgen_family, name,
547                                                  rev, target, &ret),
548                                                  fmt, name);
549
550         if (ret < 0)
551                 return ret;
552
553         skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
554         if (skb2 == NULL)
555                 return -ENOMEM;
556
557         /* include the best revision for this extension in the message */
558         if (nfnl_compat_fill_info(skb2, NETLINK_CB(skb).portid,
559                                   nlh->nlmsg_seq,
560                                   NFNL_MSG_TYPE(nlh->nlmsg_type),
561                                   NFNL_MSG_COMPAT_GET,
562                                   nfmsg->nfgen_family,
563                                   name, ret, target) <= 0) {
564                 kfree_skb(skb2);
565                 return -ENOSPC;
566         }
567
568         ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid,
569                                 MSG_DONTWAIT);
570         if (ret > 0)
571                 ret = 0;
572
573         return ret == -EAGAIN ? -ENOBUFS : ret;
574 }
575
576 static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = {
577         [NFTA_COMPAT_NAME]      = { .type = NLA_NUL_STRING,
578                                     .len = NFT_COMPAT_NAME_MAX-1 },
579         [NFTA_COMPAT_REV]       = { .type = NLA_U32 },
580         [NFTA_COMPAT_TYPE]      = { .type = NLA_U32 },
581 };
582
583 static const struct nfnl_callback nfnl_nft_compat_cb[NFNL_MSG_COMPAT_MAX] = {
584         [NFNL_MSG_COMPAT_GET]           = { .call = nfnl_compat_get,
585                                             .attr_count = NFTA_COMPAT_MAX,
586                                             .policy = nfnl_compat_policy_get },
587 };
588
589 static const struct nfnetlink_subsystem nfnl_compat_subsys = {
590         .name           = "nft-compat",
591         .subsys_id      = NFNL_SUBSYS_NFT_COMPAT,
592         .cb_count       = NFNL_MSG_COMPAT_MAX,
593         .cb             = nfnl_nft_compat_cb,
594 };
595
596 static LIST_HEAD(nft_match_list);
597
598 struct nft_xt {
599         struct list_head        head;
600         struct nft_expr_ops     ops;
601 };
602
603 static struct nft_expr_type nft_match_type;
604
605 static const struct nft_expr_ops *
606 nft_match_select_ops(const struct nft_ctx *ctx,
607                      const struct nlattr * const tb[])
608 {
609         struct nft_xt *nft_match;
610         struct xt_match *match;
611         char *mt_name;
612         __u32 rev, family;
613
614         if (tb[NFTA_MATCH_NAME] == NULL ||
615             tb[NFTA_MATCH_REV] == NULL ||
616             tb[NFTA_MATCH_INFO] == NULL)
617                 return ERR_PTR(-EINVAL);
618
619         mt_name = nla_data(tb[NFTA_MATCH_NAME]);
620         rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV]));
621         family = ctx->afi->family;
622
623         /* Re-use the existing match if it's already loaded. */
624         list_for_each_entry(nft_match, &nft_match_list, head) {
625                 struct xt_match *match = nft_match->ops.data;
626
627                 if (strcmp(match->name, mt_name) == 0 &&
628                     match->revision == rev && match->family == family) {
629                         if (!try_module_get(match->me))
630                                 return ERR_PTR(-ENOENT);
631
632                         return &nft_match->ops;
633                 }
634         }
635
636         match = xt_request_find_match(family, mt_name, rev);
637         if (IS_ERR(match))
638                 return ERR_PTR(-ENOENT);
639
640         /* This is the first time we use this match, allocate operations */
641         nft_match = kzalloc(sizeof(struct nft_xt), GFP_KERNEL);
642         if (nft_match == NULL)
643                 return ERR_PTR(-ENOMEM);
644
645         nft_match->ops.type = &nft_match_type;
646         nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
647         nft_match->ops.eval = nft_match_eval;
648         nft_match->ops.init = nft_match_init;
649         nft_match->ops.destroy = nft_match_destroy;
650         nft_match->ops.dump = nft_match_dump;
651         nft_match->ops.validate = nft_match_validate;
652         nft_match->ops.data = match;
653
654         list_add(&nft_match->head, &nft_match_list);
655
656         return &nft_match->ops;
657 }
658
659 static void nft_match_release(void)
660 {
661         struct nft_xt *nft_match, *tmp;
662
663         list_for_each_entry_safe(nft_match, tmp, &nft_match_list, head)
664                 kfree(nft_match);
665 }
666
667 static struct nft_expr_type nft_match_type __read_mostly = {
668         .name           = "match",
669         .select_ops     = nft_match_select_ops,
670         .policy         = nft_match_policy,
671         .maxattr        = NFTA_MATCH_MAX,
672         .owner          = THIS_MODULE,
673 };
674
675 static LIST_HEAD(nft_target_list);
676
677 static struct nft_expr_type nft_target_type;
678
679 static const struct nft_expr_ops *
680 nft_target_select_ops(const struct nft_ctx *ctx,
681                       const struct nlattr * const tb[])
682 {
683         struct nft_xt *nft_target;
684         struct xt_target *target;
685         char *tg_name;
686         __u32 rev, family;
687
688         if (tb[NFTA_TARGET_NAME] == NULL ||
689             tb[NFTA_TARGET_REV] == NULL ||
690             tb[NFTA_TARGET_INFO] == NULL)
691                 return ERR_PTR(-EINVAL);
692
693         tg_name = nla_data(tb[NFTA_TARGET_NAME]);
694         rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV]));
695         family = ctx->afi->family;
696
697         /* Re-use the existing target if it's already loaded. */
698         list_for_each_entry(nft_target, &nft_target_list, head) {
699                 struct xt_target *target = nft_target->ops.data;
700
701                 if (strcmp(target->name, tg_name) == 0 &&
702                     target->revision == rev && target->family == family) {
703                         if (!try_module_get(target->me))
704                                 return ERR_PTR(-ENOENT);
705
706                         return &nft_target->ops;
707                 }
708         }
709
710         target = xt_request_find_target(family, tg_name, rev);
711         if (IS_ERR(target))
712                 return ERR_PTR(-ENOENT);
713
714         /* This is the first time we use this target, allocate operations */
715         nft_target = kzalloc(sizeof(struct nft_xt), GFP_KERNEL);
716         if (nft_target == NULL)
717                 return ERR_PTR(-ENOMEM);
718
719         nft_target->ops.type = &nft_target_type;
720         nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
721         nft_target->ops.init = nft_target_init;
722         nft_target->ops.destroy = nft_target_destroy;
723         nft_target->ops.dump = nft_target_dump;
724         nft_target->ops.validate = nft_target_validate;
725         nft_target->ops.data = target;
726
727         if (family == NFPROTO_BRIDGE)
728                 nft_target->ops.eval = nft_target_eval_bridge;
729         else
730                 nft_target->ops.eval = nft_target_eval_xt;
731
732         list_add(&nft_target->head, &nft_target_list);
733
734         return &nft_target->ops;
735 }
736
737 static void nft_target_release(void)
738 {
739         struct nft_xt *nft_target, *tmp;
740
741         list_for_each_entry_safe(nft_target, tmp, &nft_target_list, head)
742                 kfree(nft_target);
743 }
744
745 static struct nft_expr_type nft_target_type __read_mostly = {
746         .name           = "target",
747         .select_ops     = nft_target_select_ops,
748         .policy         = nft_target_policy,
749         .maxattr        = NFTA_TARGET_MAX,
750         .owner          = THIS_MODULE,
751 };
752
753 static int __init nft_compat_module_init(void)
754 {
755         int ret;
756
757         ret = nft_register_expr(&nft_match_type);
758         if (ret < 0)
759                 return ret;
760
761         ret = nft_register_expr(&nft_target_type);
762         if (ret < 0)
763                 goto err_match;
764
765         ret = nfnetlink_subsys_register(&nfnl_compat_subsys);
766         if (ret < 0) {
767                 pr_err("nft_compat: cannot register with nfnetlink.\n");
768                 goto err_target;
769         }
770
771         pr_info("nf_tables_compat: (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>\n");
772
773         return ret;
774
775 err_target:
776         nft_unregister_expr(&nft_target_type);
777 err_match:
778         nft_unregister_expr(&nft_match_type);
779         return ret;
780 }
781
782 static void __exit nft_compat_module_exit(void)
783 {
784         nfnetlink_subsys_unregister(&nfnl_compat_subsys);
785         nft_unregister_expr(&nft_target_type);
786         nft_unregister_expr(&nft_match_type);
787         nft_match_release();
788         nft_target_release();
789 }
790
791 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT);
792
793 module_init(nft_compat_module_init);
794 module_exit(nft_compat_module_exit);
795
796 MODULE_LICENSE("GPL");
797 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
798 MODULE_ALIAS_NFT_EXPR("match");
799 MODULE_ALIAS_NFT_EXPR("target");