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