1/* Copyright (C) 2011-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the hash:net,iface type */
9
10#include <linux/jhash.h>
11#include <linux/module.h>
12#include <linux/ip.h>
13#include <linux/skbuff.h>
14#include <linux/errno.h>
15#include <linux/random.h>
16#include <linux/rbtree.h>
17#include <net/ip.h>
18#include <net/ipv6.h>
19#include <net/netlink.h>
20
21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.h>
24#include <linux/netfilter/ipset/ip_set_hash.h>
25
26#define IPSET_TYPE_REV_MIN	0
27/*				1    nomatch flag support added */
28/*				2    /0 support added */
29/*				3    Counters support added */
30/*				4    Comments support added */
31/*				5    Forceadd support added */
32#define IPSET_TYPE_REV_MAX	6 /* skbinfo support added */
33
34MODULE_LICENSE("GPL");
35MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
36IP_SET_MODULE_DESC("hash:net,iface", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
37MODULE_ALIAS("ip_set_hash:net,iface");
38
39/* Interface name rbtree */
40
41struct iface_node {
42	struct rb_node node;
43	char iface[IFNAMSIZ];
44};
45
46#define iface_data(n)	(rb_entry(n, struct iface_node, node)->iface)
47
48static void
49rbtree_destroy(struct rb_root *root)
50{
51	struct iface_node *node, *next;
52
53	rbtree_postorder_for_each_entry_safe(node, next, root, node)
54		kfree(node);
55
56	*root = RB_ROOT;
57}
58
59static int
60iface_test(struct rb_root *root, const char **iface)
61{
62	struct rb_node *n = root->rb_node;
63
64	while (n) {
65		const char *d = iface_data(n);
66		int res = strcmp(*iface, d);
67
68		if (res < 0)
69			n = n->rb_left;
70		else if (res > 0)
71			n = n->rb_right;
72		else {
73			*iface = d;
74			return 1;
75		}
76	}
77	return 0;
78}
79
80static int
81iface_add(struct rb_root *root, const char **iface)
82{
83	struct rb_node **n = &(root->rb_node), *p = NULL;
84	struct iface_node *d;
85
86	while (*n) {
87		char *ifname = iface_data(*n);
88		int res = strcmp(*iface, ifname);
89
90		p = *n;
91		if (res < 0)
92			n = &((*n)->rb_left);
93		else if (res > 0)
94			n = &((*n)->rb_right);
95		else {
96			*iface = ifname;
97			return 0;
98		}
99	}
100
101	d = kzalloc(sizeof(*d), GFP_ATOMIC);
102	if (!d)
103		return -ENOMEM;
104	strcpy(d->iface, *iface);
105
106	rb_link_node(&d->node, p, n);
107	rb_insert_color(&d->node, root);
108
109	*iface = d->iface;
110	return 0;
111}
112
113/* Type specific function prefix */
114#define HTYPE		hash_netiface
115#define IP_SET_HASH_WITH_NETS
116#define IP_SET_HASH_WITH_RBTREE
117#define IP_SET_HASH_WITH_MULTI
118
119#define STREQ(a, b)	(strcmp(a, b) == 0)
120
121/* IPv4 variant */
122
123struct hash_netiface4_elem_hashed {
124	__be32 ip;
125	u8 physdev;
126	u8 cidr;
127	u8 nomatch;
128	u8 elem;
129};
130
131/* Member elements */
132struct hash_netiface4_elem {
133	__be32 ip;
134	u8 physdev;
135	u8 cidr;
136	u8 nomatch;
137	u8 elem;
138	const char *iface;
139};
140
141/* Common functions */
142
143static inline bool
144hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
145			  const struct hash_netiface4_elem *ip2,
146			  u32 *multi)
147{
148	return ip1->ip == ip2->ip &&
149	       ip1->cidr == ip2->cidr &&
150	       (++*multi) &&
151	       ip1->physdev == ip2->physdev &&
152	       ip1->iface == ip2->iface;
153}
154
155static inline int
156hash_netiface4_do_data_match(const struct hash_netiface4_elem *elem)
157{
158	return elem->nomatch ? -ENOTEMPTY : 1;
159}
160
161static inline void
162hash_netiface4_data_set_flags(struct hash_netiface4_elem *elem, u32 flags)
163{
164	elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
165}
166
167static inline void
168hash_netiface4_data_reset_flags(struct hash_netiface4_elem *elem, u8 *flags)
169{
170	swap(*flags, elem->nomatch);
171}
172
173static inline void
174hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
175{
176	elem->ip &= ip_set_netmask(cidr);
177	elem->cidr = cidr;
178}
179
180static bool
181hash_netiface4_data_list(struct sk_buff *skb,
182			 const struct hash_netiface4_elem *data)
183{
184	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
185
186	if (data->nomatch)
187		flags |= IPSET_FLAG_NOMATCH;
188	if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
189	    nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
190	    nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
191	    (flags &&
192	     nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
193		goto nla_put_failure;
194	return 0;
195
196nla_put_failure:
197	return 1;
198}
199
200static inline void
201hash_netiface4_data_next(struct hash_netiface4_elem *next,
202			 const struct hash_netiface4_elem *d)
203{
204	next->ip = d->ip;
205}
206
207#define MTYPE		hash_netiface4
208#define PF		4
209#define HOST_MASK	32
210#define HKEY_DATALEN	sizeof(struct hash_netiface4_elem_hashed)
211#include "ip_set_hash_gen.h"
212
213static int
214hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
215		    const struct xt_action_param *par,
216		    enum ipset_adt adt, struct ip_set_adt_opt *opt)
217{
218	struct hash_netiface *h = set->data;
219	ipset_adtfn adtfn = set->variant->adt[adt];
220	struct hash_netiface4_elem e = {
221		.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
222		.elem = 1,
223	};
224	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
225	int ret;
226
227	if (e.cidr == 0)
228		return -EINVAL;
229	if (adt == IPSET_TEST)
230		e.cidr = HOST_MASK;
231
232	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
233	e.ip &= ip_set_netmask(e.cidr);
234
235#define IFACE(dir)	(par->dir ? par->dir->name : NULL)
236#define PHYSDEV(dir)	(nf_bridge->dir ? nf_bridge->dir->name : NULL)
237#define SRCDIR		(opt->flags & IPSET_DIM_TWO_SRC)
238
239	if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
240#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
241		const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
242
243		if (!nf_bridge)
244			return -EINVAL;
245		e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
246		e.physdev = 1;
247#else
248		e.iface = NULL;
249#endif
250	} else
251		e.iface = SRCDIR ? IFACE(in) : IFACE(out);
252
253	if (!e.iface)
254		return -EINVAL;
255	ret = iface_test(&h->rbtree, &e.iface);
256	if (adt == IPSET_ADD) {
257		if (!ret) {
258			ret = iface_add(&h->rbtree, &e.iface);
259			if (ret)
260				return ret;
261		}
262	} else if (!ret)
263		return ret;
264
265	return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
266}
267
268static int
269hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
270		    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
271{
272	struct hash_netiface *h = set->data;
273	ipset_adtfn adtfn = set->variant->adt[adt];
274	struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
275	struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
276	u32 ip = 0, ip_to = 0, last;
277	char iface[IFNAMSIZ];
278	int ret;
279
280	if (unlikely(!tb[IPSET_ATTR_IP] ||
281		     !tb[IPSET_ATTR_IFACE] ||
282		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
283		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
284		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
285		     !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
286		     !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
287		     !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
288		     !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
289		return -IPSET_ERR_PROTOCOL;
290
291	if (tb[IPSET_ATTR_LINENO])
292		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
293
294	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
295	      ip_set_get_extensions(set, tb, &ext);
296	if (ret)
297		return ret;
298
299	if (tb[IPSET_ATTR_CIDR]) {
300		e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
301		if (e.cidr > HOST_MASK)
302			return -IPSET_ERR_INVALID_CIDR;
303	}
304
305	strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
306	e.iface = iface;
307	ret = iface_test(&h->rbtree, &e.iface);
308	if (adt == IPSET_ADD) {
309		if (!ret) {
310			ret = iface_add(&h->rbtree, &e.iface);
311			if (ret)
312				return ret;
313		}
314	} else if (!ret)
315		return ret;
316
317	if (tb[IPSET_ATTR_CADT_FLAGS]) {
318		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
319		if (cadt_flags & IPSET_FLAG_PHYSDEV)
320			e.physdev = 1;
321		if (cadt_flags & IPSET_FLAG_NOMATCH)
322			flags |= (IPSET_FLAG_NOMATCH << 16);
323	}
324	if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
325		e.ip = htonl(ip & ip_set_hostmask(e.cidr));
326		ret = adtfn(set, &e, &ext, &ext, flags);
327		return ip_set_enomatch(ret, flags, adt, set) ? -ret :
328		       ip_set_eexist(ret, flags) ? 0 : ret;
329	}
330
331	if (tb[IPSET_ATTR_IP_TO]) {
332		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
333		if (ret)
334			return ret;
335		if (ip_to < ip)
336			swap(ip, ip_to);
337		if (ip + UINT_MAX == ip_to)
338			return -IPSET_ERR_HASH_RANGE;
339	} else
340		ip_set_mask_from_to(ip, ip_to, e.cidr);
341
342	if (retried)
343		ip = ntohl(h->next.ip);
344	while (!after(ip, ip_to)) {
345		e.ip = htonl(ip);
346		last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
347		ret = adtfn(set, &e, &ext, &ext, flags);
348
349		if (ret && !ip_set_eexist(ret, flags))
350			return ret;
351		else
352			ret = 0;
353		ip = last + 1;
354	}
355	return ret;
356}
357
358/* IPv6 variant */
359
360struct hash_netiface6_elem_hashed {
361	union nf_inet_addr ip;
362	u8 physdev;
363	u8 cidr;
364	u8 nomatch;
365	u8 elem;
366};
367
368struct hash_netiface6_elem {
369	union nf_inet_addr ip;
370	u8 physdev;
371	u8 cidr;
372	u8 nomatch;
373	u8 elem;
374	const char *iface;
375};
376
377/* Common functions */
378
379static inline bool
380hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
381			  const struct hash_netiface6_elem *ip2,
382			  u32 *multi)
383{
384	return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
385	       ip1->cidr == ip2->cidr &&
386	       (++*multi) &&
387	       ip1->physdev == ip2->physdev &&
388	       ip1->iface == ip2->iface;
389}
390
391static inline int
392hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem)
393{
394	return elem->nomatch ? -ENOTEMPTY : 1;
395}
396
397static inline void
398hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags)
399{
400	elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
401}
402
403static inline void
404hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags)
405{
406	swap(*flags, elem->nomatch);
407}
408
409static inline void
410hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
411{
412	ip6_netmask(&elem->ip, cidr);
413	elem->cidr = cidr;
414}
415
416static bool
417hash_netiface6_data_list(struct sk_buff *skb,
418			 const struct hash_netiface6_elem *data)
419{
420	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
421
422	if (data->nomatch)
423		flags |= IPSET_FLAG_NOMATCH;
424	if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
425	    nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
426	    nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
427	    (flags &&
428	     nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
429		goto nla_put_failure;
430	return 0;
431
432nla_put_failure:
433	return 1;
434}
435
436static inline void
437hash_netiface6_data_next(struct hash_netiface4_elem *next,
438			 const struct hash_netiface6_elem *d)
439{
440}
441
442#undef MTYPE
443#undef PF
444#undef HOST_MASK
445#undef HKEY_DATALEN
446
447#define MTYPE		hash_netiface6
448#define PF		6
449#define HOST_MASK	128
450#define HKEY_DATALEN	sizeof(struct hash_netiface6_elem_hashed)
451#define IP_SET_EMIT_CREATE
452#include "ip_set_hash_gen.h"
453
454static int
455hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
456		    const struct xt_action_param *par,
457		    enum ipset_adt adt, struct ip_set_adt_opt *opt)
458{
459	struct hash_netiface *h = set->data;
460	ipset_adtfn adtfn = set->variant->adt[adt];
461	struct hash_netiface6_elem e = {
462		.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
463		.elem = 1,
464	};
465	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
466	int ret;
467
468	if (e.cidr == 0)
469		return -EINVAL;
470	if (adt == IPSET_TEST)
471		e.cidr = HOST_MASK;
472
473	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
474	ip6_netmask(&e.ip, e.cidr);
475
476	if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
477#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
478		const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
479
480		if (!nf_bridge)
481			return -EINVAL;
482		e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
483		e.physdev = 1;
484#else
485		e.iface = NULL;
486#endif
487	} else
488		e.iface = SRCDIR ? IFACE(in) : IFACE(out);
489
490	if (!e.iface)
491		return -EINVAL;
492	ret = iface_test(&h->rbtree, &e.iface);
493	if (adt == IPSET_ADD) {
494		if (!ret) {
495			ret = iface_add(&h->rbtree, &e.iface);
496			if (ret)
497				return ret;
498		}
499	} else if (!ret)
500		return ret;
501
502	return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
503}
504
505static int
506hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
507		   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
508{
509	struct hash_netiface *h = set->data;
510	ipset_adtfn adtfn = set->variant->adt[adt];
511	struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 };
512	struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
513	char iface[IFNAMSIZ];
514	int ret;
515
516	if (unlikely(!tb[IPSET_ATTR_IP] ||
517		     !tb[IPSET_ATTR_IFACE] ||
518		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
519		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
520		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
521		     !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
522		     !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
523		     !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
524		     !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
525		return -IPSET_ERR_PROTOCOL;
526	if (unlikely(tb[IPSET_ATTR_IP_TO]))
527		return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
528
529	if (tb[IPSET_ATTR_LINENO])
530		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
531
532	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
533	      ip_set_get_extensions(set, tb, &ext);
534	if (ret)
535		return ret;
536
537	if (tb[IPSET_ATTR_CIDR])
538		e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
539	if (e.cidr > HOST_MASK)
540		return -IPSET_ERR_INVALID_CIDR;
541	ip6_netmask(&e.ip, e.cidr);
542
543	strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
544	e.iface = iface;
545	ret = iface_test(&h->rbtree, &e.iface);
546	if (adt == IPSET_ADD) {
547		if (!ret) {
548			ret = iface_add(&h->rbtree, &e.iface);
549			if (ret)
550				return ret;
551		}
552	} else if (!ret)
553		return ret;
554
555	if (tb[IPSET_ATTR_CADT_FLAGS]) {
556		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
557		if (cadt_flags & IPSET_FLAG_PHYSDEV)
558			e.physdev = 1;
559		if (cadt_flags & IPSET_FLAG_NOMATCH)
560			flags |= (IPSET_FLAG_NOMATCH << 16);
561	}
562
563	ret = adtfn(set, &e, &ext, &ext, flags);
564
565	return ip_set_enomatch(ret, flags, adt, set) ? -ret :
566	       ip_set_eexist(ret, flags) ? 0 : ret;
567}
568
569static struct ip_set_type hash_netiface_type __read_mostly = {
570	.name		= "hash:net,iface",
571	.protocol	= IPSET_PROTOCOL,
572	.features	= IPSET_TYPE_IP | IPSET_TYPE_IFACE |
573			  IPSET_TYPE_NOMATCH,
574	.dimension	= IPSET_DIM_TWO,
575	.family		= NFPROTO_UNSPEC,
576	.revision_min	= IPSET_TYPE_REV_MIN,
577	.revision_max	= IPSET_TYPE_REV_MAX,
578	.create		= hash_netiface_create,
579	.create_policy	= {
580		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
581		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
582		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
583		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
584		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
585		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
586		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
587	},
588	.adt_policy	= {
589		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
590		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
591		[IPSET_ATTR_IFACE]	= { .type = NLA_NUL_STRING,
592					    .len  = IFNAMSIZ - 1 },
593		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
594		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
595		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
596		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
597		[IPSET_ATTR_BYTES]	= { .type = NLA_U64 },
598		[IPSET_ATTR_PACKETS]	= { .type = NLA_U64 },
599		[IPSET_ATTR_COMMENT]	= { .type = NLA_NUL_STRING },
600		[IPSET_ATTR_SKBMARK]	= { .type = NLA_U64 },
601		[IPSET_ATTR_SKBPRIO]	= { .type = NLA_U32 },
602		[IPSET_ATTR_SKBQUEUE]	= { .type = NLA_U16 },
603	},
604	.me		= THIS_MODULE,
605};
606
607static int __init
608hash_netiface_init(void)
609{
610	return ip_set_type_register(&hash_netiface_type);
611}
612
613static void __exit
614hash_netiface_fini(void)
615{
616	ip_set_type_unregister(&hash_netiface_type);
617}
618
619module_init(hash_netiface_init);
620module_exit(hash_netiface_fini);
621