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