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