1 /* Copyright (C) 2011 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_timeout.h>
25 #include <linux/netfilter/ipset/ip_set_hash.h>
26 
27 MODULE_LICENSE("GPL");
28 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
29 MODULE_DESCRIPTION("hash:net,iface type of IP sets");
30 MODULE_ALIAS("ip_set_hash:net,iface");
31 
32 /* Interface name rbtree */
33 
34 struct iface_node {
35 	struct rb_node node;
36 	char iface[IFNAMSIZ];
37 };
38 
39 #define iface_data(n)	(rb_entry(n, struct iface_node, node)->iface)
40 
41 static inline long
ifname_compare(const char * _a,const char * _b)42 ifname_compare(const char *_a, const char *_b)
43 {
44 	const long *a = (const long *)_a;
45 	const long *b = (const long *)_b;
46 
47 	BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
48 	if (a[0] != b[0])
49 		return a[0] - b[0];
50 	if (IFNAMSIZ > sizeof(long)) {
51 		if (a[1] != b[1])
52 			return a[1] - b[1];
53 	}
54 	if (IFNAMSIZ > 2 * sizeof(long)) {
55 		if (a[2] != b[2])
56 			return a[2] - b[2];
57 	}
58 	if (IFNAMSIZ > 3 * sizeof(long)) {
59 		if (a[3] != b[3])
60 			return a[3] - b[3];
61 	}
62 	return 0;
63 }
64 
65 static void
rbtree_destroy(struct rb_root * root)66 rbtree_destroy(struct rb_root *root)
67 {
68 	struct rb_node *p, *n = root->rb_node;
69 	struct iface_node *node;
70 
71 	/* Non-recursive destroy, like in ext3 */
72 	while (n) {
73 		if (n->rb_left) {
74 			n = n->rb_left;
75 			continue;
76 		}
77 		if (n->rb_right) {
78 			n = n->rb_right;
79 			continue;
80 		}
81 		p = rb_parent(n);
82 		node = rb_entry(n, struct iface_node, node);
83 		if (!p)
84 			*root = RB_ROOT;
85 		else if (p->rb_left == n)
86 			p->rb_left = NULL;
87 		else if (p->rb_right == n)
88 			p->rb_right = NULL;
89 
90 		kfree(node);
91 		n = p;
92 	}
93 }
94 
95 static int
iface_test(struct rb_root * root,const char ** iface)96 iface_test(struct rb_root *root, const char **iface)
97 {
98 	struct rb_node *n = root->rb_node;
99 
100 	while (n) {
101 		const char *d = iface_data(n);
102 		long res = ifname_compare(*iface, d);
103 
104 		if (res < 0)
105 			n = n->rb_left;
106 		else if (res > 0)
107 			n = n->rb_right;
108 		else {
109 			*iface = d;
110 			return 1;
111 		}
112 	}
113 	return 0;
114 }
115 
116 static int
iface_add(struct rb_root * root,const char ** iface)117 iface_add(struct rb_root *root, const char **iface)
118 {
119 	struct rb_node **n = &(root->rb_node), *p = NULL;
120 	struct iface_node *d;
121 
122 	while (*n) {
123 		char *ifname = iface_data(*n);
124 		long res = ifname_compare(*iface, ifname);
125 
126 		p = *n;
127 		if (res < 0)
128 			n = &((*n)->rb_left);
129 		else if (res > 0)
130 			n = &((*n)->rb_right);
131 		else {
132 			*iface = ifname;
133 			return 0;
134 		}
135 	}
136 
137 	d = kzalloc(sizeof(*d), GFP_ATOMIC);
138 	if (!d)
139 		return -ENOMEM;
140 	strcpy(d->iface, *iface);
141 
142 	rb_link_node(&d->node, p, n);
143 	rb_insert_color(&d->node, root);
144 
145 	*iface = d->iface;
146 	return 0;
147 }
148 
149 /* Type specific function prefix */
150 #define TYPE		hash_netiface
151 
152 static bool
153 hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
154 
155 #define hash_netiface4_same_set	hash_netiface_same_set
156 #define hash_netiface6_same_set	hash_netiface_same_set
157 
158 #define STREQ(a, b)	(strcmp(a, b) == 0)
159 
160 /* The type variant functions: IPv4 */
161 
162 struct hash_netiface4_elem_hashed {
163 	__be32 ip;
164 	u8 physdev;
165 	u8 cidr;
166 	u16 padding;
167 };
168 
169 #define HKEY_DATALEN	sizeof(struct hash_netiface4_elem_hashed)
170 
171 /* Member elements without timeout */
172 struct hash_netiface4_elem {
173 	__be32 ip;
174 	u8 physdev;
175 	u8 cidr;
176 	u16 padding;
177 	const char *iface;
178 };
179 
180 /* Member elements with timeout support */
181 struct hash_netiface4_telem {
182 	__be32 ip;
183 	u8 physdev;
184 	u8 cidr;
185 	u16 padding;
186 	const char *iface;
187 	unsigned long timeout;
188 };
189 
190 static inline bool
hash_netiface4_data_equal(const struct hash_netiface4_elem * ip1,const struct hash_netiface4_elem * ip2,u32 * multi)191 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
192 			  const struct hash_netiface4_elem *ip2,
193 			  u32 *multi)
194 {
195 	return ip1->ip == ip2->ip &&
196 	       ip1->cidr == ip2->cidr &&
197 	       (++*multi) &&
198 	       ip1->physdev == ip2->physdev &&
199 	       ip1->iface == ip2->iface;
200 }
201 
202 static inline bool
hash_netiface4_data_isnull(const struct hash_netiface4_elem * elem)203 hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
204 {
205 	return elem->cidr == 0;
206 }
207 
208 static inline void
hash_netiface4_data_copy(struct hash_netiface4_elem * dst,const struct hash_netiface4_elem * src)209 hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
210 			 const struct hash_netiface4_elem *src) {
211 	dst->ip = src->ip;
212 	dst->cidr = src->cidr;
213 	dst->physdev = src->physdev;
214 	dst->iface = src->iface;
215 }
216 
217 static inline void
hash_netiface4_data_netmask(struct hash_netiface4_elem * elem,u8 cidr)218 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
219 {
220 	elem->ip &= ip_set_netmask(cidr);
221 	elem->cidr = cidr;
222 }
223 
224 static inline void
hash_netiface4_data_zero_out(struct hash_netiface4_elem * elem)225 hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
226 {
227 	elem->cidr = 0;
228 }
229 
230 static bool
hash_netiface4_data_list(struct sk_buff * skb,const struct hash_netiface4_elem * data)231 hash_netiface4_data_list(struct sk_buff *skb,
232 			 const struct hash_netiface4_elem *data)
233 {
234 	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
235 
236 	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
237 	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
238 	NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
239 	if (flags)
240 		NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
241 	return 0;
242 
243 nla_put_failure:
244 	return 1;
245 }
246 
247 static bool
hash_netiface4_data_tlist(struct sk_buff * skb,const struct hash_netiface4_elem * data)248 hash_netiface4_data_tlist(struct sk_buff *skb,
249 			  const struct hash_netiface4_elem *data)
250 {
251 	const struct hash_netiface4_telem *tdata =
252 		(const struct hash_netiface4_telem *)data;
253 	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
254 
255 	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
256 	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
257 	NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
258 	if (flags)
259 		NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
260 	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
261 		      htonl(ip_set_timeout_get(tdata->timeout)));
262 
263 	return 0;
264 
265 nla_put_failure:
266 	return 1;
267 }
268 
269 #define IP_SET_HASH_WITH_NETS
270 #define IP_SET_HASH_WITH_RBTREE
271 #define IP_SET_HASH_WITH_MULTI
272 
273 #define PF		4
274 #define HOST_MASK	32
275 #include <linux/netfilter/ipset/ip_set_ahash.h>
276 
277 static inline void
hash_netiface4_data_next(struct ip_set_hash * h,const struct hash_netiface4_elem * d)278 hash_netiface4_data_next(struct ip_set_hash *h,
279 			 const struct hash_netiface4_elem *d)
280 {
281 	h->next.ip = ntohl(d->ip);
282 }
283 
284 static int
hash_netiface4_kadt(struct ip_set * set,const struct sk_buff * skb,const struct xt_action_param * par,enum ipset_adt adt,const struct ip_set_adt_opt * opt)285 hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
286 		    const struct xt_action_param *par,
287 		    enum ipset_adt adt, const struct ip_set_adt_opt *opt)
288 {
289 	struct ip_set_hash *h = set->data;
290 	ipset_adtfn adtfn = set->variant->adt[adt];
291 	struct hash_netiface4_elem data = {
292 		.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
293 	};
294 	int ret;
295 
296 	if (data.cidr == 0)
297 		return -EINVAL;
298 	if (adt == IPSET_TEST)
299 		data.cidr = HOST_MASK;
300 
301 	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
302 	data.ip &= ip_set_netmask(data.cidr);
303 
304 #define IFACE(dir)	(par->dir ? par->dir->name : NULL)
305 #define PHYSDEV(dir)	(nf_bridge->dir ? nf_bridge->dir->name : NULL)
306 #define SRCDIR		(opt->flags & IPSET_DIM_TWO_SRC)
307 
308 	if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
309 #ifdef CONFIG_BRIDGE_NETFILTER
310 		const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
311 
312 		if (!nf_bridge)
313 			return -EINVAL;
314 		data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
315 		data.physdev = 1;
316 #else
317 		data.iface = NULL;
318 #endif
319 	} else
320 		data.iface = SRCDIR ? IFACE(in) : IFACE(out);
321 
322 	if (!data.iface)
323 		return -EINVAL;
324 	ret = iface_test(&h->rbtree, &data.iface);
325 	if (adt == IPSET_ADD) {
326 		if (!ret) {
327 			ret = iface_add(&h->rbtree, &data.iface);
328 			if (ret)
329 				return ret;
330 		}
331 	} else if (!ret)
332 		return ret;
333 
334 	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
335 }
336 
337 static int
hash_netiface4_uadt(struct ip_set * set,struct nlattr * tb[],enum ipset_adt adt,u32 * lineno,u32 flags,bool retried)338 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
339 		    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
340 {
341 	struct ip_set_hash *h = set->data;
342 	ipset_adtfn adtfn = set->variant->adt[adt];
343 	struct hash_netiface4_elem data = { .cidr = HOST_MASK };
344 	u32 ip = 0, ip_to, last;
345 	u32 timeout = h->timeout;
346 	char iface[IFNAMSIZ] = {};
347 	int ret;
348 
349 	if (unlikely(!tb[IPSET_ATTR_IP] ||
350 		     !tb[IPSET_ATTR_IFACE] ||
351 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
352 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
353 		return -IPSET_ERR_PROTOCOL;
354 
355 	if (tb[IPSET_ATTR_LINENO])
356 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
357 
358 	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
359 	if (ret)
360 		return ret;
361 
362 	if (tb[IPSET_ATTR_CIDR]) {
363 		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
364 		if (!data.cidr)
365 			return -IPSET_ERR_INVALID_CIDR;
366 	}
367 
368 	if (tb[IPSET_ATTR_TIMEOUT]) {
369 		if (!with_timeout(h->timeout))
370 			return -IPSET_ERR_TIMEOUT;
371 		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
372 	}
373 
374 	strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
375 	data.iface = iface;
376 	ret = iface_test(&h->rbtree, &data.iface);
377 	if (adt == IPSET_ADD) {
378 		if (!ret) {
379 			ret = iface_add(&h->rbtree, &data.iface);
380 			if (ret)
381 				return ret;
382 		}
383 	} else if (!ret)
384 		return ret;
385 
386 	if (tb[IPSET_ATTR_CADT_FLAGS]) {
387 		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
388 		if (cadt_flags & IPSET_FLAG_PHYSDEV)
389 			data.physdev = 1;
390 	}
391 
392 	if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
393 		data.ip = htonl(ip & ip_set_hostmask(data.cidr));
394 		ret = adtfn(set, &data, timeout, flags);
395 		return ip_set_eexist(ret, flags) ? 0 : ret;
396 	}
397 
398 	if (tb[IPSET_ATTR_IP_TO]) {
399 		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
400 		if (ret)
401 			return ret;
402 		if (ip_to < ip)
403 			swap(ip, ip_to);
404 		if (ip + UINT_MAX == ip_to)
405 			return -IPSET_ERR_HASH_RANGE;
406 	} else {
407 		ip_set_mask_from_to(ip, ip_to, data.cidr);
408 	}
409 
410 	if (retried)
411 		ip = h->next.ip;
412 	while (!after(ip, ip_to)) {
413 		data.ip = htonl(ip);
414 		last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
415 		ret = adtfn(set, &data, timeout, flags);
416 
417 		if (ret && !ip_set_eexist(ret, flags))
418 			return ret;
419 		else
420 			ret = 0;
421 		ip = last + 1;
422 	}
423 	return ret;
424 }
425 
426 static bool
hash_netiface_same_set(const struct ip_set * a,const struct ip_set * b)427 hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
428 {
429 	const struct ip_set_hash *x = a->data;
430 	const struct ip_set_hash *y = b->data;
431 
432 	/* Resizing changes htable_bits, so we ignore it */
433 	return x->maxelem == y->maxelem &&
434 	       x->timeout == y->timeout;
435 }
436 
437 /* The type variant functions: IPv6 */
438 
439 struct hash_netiface6_elem_hashed {
440 	union nf_inet_addr ip;
441 	u8 physdev;
442 	u8 cidr;
443 	u16 padding;
444 };
445 
446 #define HKEY_DATALEN	sizeof(struct hash_netiface6_elem_hashed)
447 
448 struct hash_netiface6_elem {
449 	union nf_inet_addr ip;
450 	u8 physdev;
451 	u8 cidr;
452 	u16 padding;
453 	const char *iface;
454 };
455 
456 struct hash_netiface6_telem {
457 	union nf_inet_addr ip;
458 	u8 physdev;
459 	u8 cidr;
460 	u16 padding;
461 	const char *iface;
462 	unsigned long timeout;
463 };
464 
465 static inline bool
hash_netiface6_data_equal(const struct hash_netiface6_elem * ip1,const struct hash_netiface6_elem * ip2,u32 * multi)466 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
467 			  const struct hash_netiface6_elem *ip2,
468 			  u32 *multi)
469 {
470 	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
471 	       ip1->cidr == ip2->cidr &&
472 	       (++*multi) &&
473 	       ip1->physdev == ip2->physdev &&
474 	       ip1->iface == ip2->iface;
475 }
476 
477 static inline bool
hash_netiface6_data_isnull(const struct hash_netiface6_elem * elem)478 hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
479 {
480 	return elem->cidr == 0;
481 }
482 
483 static inline void
hash_netiface6_data_copy(struct hash_netiface6_elem * dst,const struct hash_netiface6_elem * src)484 hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
485 			 const struct hash_netiface6_elem *src)
486 {
487 	memcpy(dst, src, sizeof(*dst));
488 }
489 
490 static inline void
hash_netiface6_data_zero_out(struct hash_netiface6_elem * elem)491 hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
492 {
493 }
494 
495 static inline void
ip6_netmask(union nf_inet_addr * ip,u8 prefix)496 ip6_netmask(union nf_inet_addr *ip, u8 prefix)
497 {
498 	ip->ip6[0] &= ip_set_netmask6(prefix)[0];
499 	ip->ip6[1] &= ip_set_netmask6(prefix)[1];
500 	ip->ip6[2] &= ip_set_netmask6(prefix)[2];
501 	ip->ip6[3] &= ip_set_netmask6(prefix)[3];
502 }
503 
504 static inline void
hash_netiface6_data_netmask(struct hash_netiface6_elem * elem,u8 cidr)505 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
506 {
507 	ip6_netmask(&elem->ip, cidr);
508 	elem->cidr = cidr;
509 }
510 
511 static bool
hash_netiface6_data_list(struct sk_buff * skb,const struct hash_netiface6_elem * data)512 hash_netiface6_data_list(struct sk_buff *skb,
513 			 const struct hash_netiface6_elem *data)
514 {
515 	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
516 
517 	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
518 	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
519 	NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
520 	if (flags)
521 		NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
522 	return 0;
523 
524 nla_put_failure:
525 	return 1;
526 }
527 
528 static bool
hash_netiface6_data_tlist(struct sk_buff * skb,const struct hash_netiface6_elem * data)529 hash_netiface6_data_tlist(struct sk_buff *skb,
530 			  const struct hash_netiface6_elem *data)
531 {
532 	const struct hash_netiface6_telem *e =
533 		(const struct hash_netiface6_telem *)data;
534 	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
535 
536 	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
537 	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
538 	NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
539 	if (flags)
540 		NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
541 	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
542 		      htonl(ip_set_timeout_get(e->timeout)));
543 	return 0;
544 
545 nla_put_failure:
546 	return 1;
547 }
548 
549 #undef PF
550 #undef HOST_MASK
551 
552 #define PF		6
553 #define HOST_MASK	128
554 #include <linux/netfilter/ipset/ip_set_ahash.h>
555 
556 static inline void
hash_netiface6_data_next(struct ip_set_hash * h,const struct hash_netiface6_elem * d)557 hash_netiface6_data_next(struct ip_set_hash *h,
558 			 const struct hash_netiface6_elem *d)
559 {
560 }
561 
562 static int
hash_netiface6_kadt(struct ip_set * set,const struct sk_buff * skb,const struct xt_action_param * par,enum ipset_adt adt,const struct ip_set_adt_opt * opt)563 hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
564 		    const struct xt_action_param *par,
565 		    enum ipset_adt adt, const struct ip_set_adt_opt *opt)
566 {
567 	struct ip_set_hash *h = set->data;
568 	ipset_adtfn adtfn = set->variant->adt[adt];
569 	struct hash_netiface6_elem data = {
570 		.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
571 	};
572 	int ret;
573 
574 	if (data.cidr == 0)
575 		return -EINVAL;
576 	if (adt == IPSET_TEST)
577 		data.cidr = HOST_MASK;
578 
579 	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
580 	ip6_netmask(&data.ip, data.cidr);
581 
582 	if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
583 #ifdef CONFIG_BRIDGE_NETFILTER
584 		const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
585 
586 		if (!nf_bridge)
587 			return -EINVAL;
588 		data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
589 		data.physdev = 1;
590 #else
591 		data.iface = NULL;
592 #endif
593 	} else
594 		data.iface = SRCDIR ? IFACE(in) : IFACE(out);
595 
596 	if (!data.iface)
597 		return -EINVAL;
598 	ret = iface_test(&h->rbtree, &data.iface);
599 	if (adt == IPSET_ADD) {
600 		if (!ret) {
601 			ret = iface_add(&h->rbtree, &data.iface);
602 			if (ret)
603 				return ret;
604 		}
605 	} else if (!ret)
606 		return ret;
607 
608 	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
609 }
610 
611 static int
hash_netiface6_uadt(struct ip_set * set,struct nlattr * tb[],enum ipset_adt adt,u32 * lineno,u32 flags,bool retried)612 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
613 		   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
614 {
615 	struct ip_set_hash *h = set->data;
616 	ipset_adtfn adtfn = set->variant->adt[adt];
617 	struct hash_netiface6_elem data = { .cidr = HOST_MASK };
618 	u32 timeout = h->timeout;
619 	char iface[IFNAMSIZ] = {};
620 	int ret;
621 
622 	if (unlikely(!tb[IPSET_ATTR_IP] ||
623 		     !tb[IPSET_ATTR_IFACE] ||
624 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
625 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
626 		return -IPSET_ERR_PROTOCOL;
627 	if (unlikely(tb[IPSET_ATTR_IP_TO]))
628 		return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
629 
630 	if (tb[IPSET_ATTR_LINENO])
631 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
632 
633 	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
634 	if (ret)
635 		return ret;
636 
637 	if (tb[IPSET_ATTR_CIDR])
638 		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
639 	if (!data.cidr)
640 		return -IPSET_ERR_INVALID_CIDR;
641 	ip6_netmask(&data.ip, data.cidr);
642 
643 	if (tb[IPSET_ATTR_TIMEOUT]) {
644 		if (!with_timeout(h->timeout))
645 			return -IPSET_ERR_TIMEOUT;
646 		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
647 	}
648 
649 	strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
650 	data.iface = iface;
651 	ret = iface_test(&h->rbtree, &data.iface);
652 	if (adt == IPSET_ADD) {
653 		if (!ret) {
654 			ret = iface_add(&h->rbtree, &data.iface);
655 			if (ret)
656 				return ret;
657 		}
658 	} else if (!ret)
659 		return ret;
660 
661 	if (tb[IPSET_ATTR_CADT_FLAGS]) {
662 		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
663 		if (cadt_flags & IPSET_FLAG_PHYSDEV)
664 			data.physdev = 1;
665 	}
666 
667 	ret = adtfn(set, &data, timeout, flags);
668 
669 	return ip_set_eexist(ret, flags) ? 0 : ret;
670 }
671 
672 /* Create hash:ip type of sets */
673 
674 static int
hash_netiface_create(struct ip_set * set,struct nlattr * tb[],u32 flags)675 hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
676 {
677 	struct ip_set_hash *h;
678 	u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
679 	u8 hbits;
680 
681 	if (!(set->family == AF_INET || set->family == AF_INET6))
682 		return -IPSET_ERR_INVALID_FAMILY;
683 
684 	if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
685 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
686 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
687 		return -IPSET_ERR_PROTOCOL;
688 
689 	if (tb[IPSET_ATTR_HASHSIZE]) {
690 		hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
691 		if (hashsize < IPSET_MIMINAL_HASHSIZE)
692 			hashsize = IPSET_MIMINAL_HASHSIZE;
693 	}
694 
695 	if (tb[IPSET_ATTR_MAXELEM])
696 		maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
697 
698 	h = kzalloc(sizeof(*h)
699 		    + sizeof(struct ip_set_hash_nets)
700 		      * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
701 	if (!h)
702 		return -ENOMEM;
703 
704 	h->maxelem = maxelem;
705 	get_random_bytes(&h->initval, sizeof(h->initval));
706 	h->timeout = IPSET_NO_TIMEOUT;
707 	h->ahash_max = AHASH_MAX_SIZE;
708 
709 	hbits = htable_bits(hashsize);
710 	h->table = ip_set_alloc(
711 			sizeof(struct htable)
712 			+ jhash_size(hbits) * sizeof(struct hbucket));
713 	if (!h->table) {
714 		kfree(h);
715 		return -ENOMEM;
716 	}
717 	h->table->htable_bits = hbits;
718 	h->rbtree = RB_ROOT;
719 
720 	set->data = h;
721 
722 	if (tb[IPSET_ATTR_TIMEOUT]) {
723 		h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
724 
725 		set->variant = set->family == AF_INET
726 			? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
727 
728 		if (set->family == AF_INET)
729 			hash_netiface4_gc_init(set);
730 		else
731 			hash_netiface6_gc_init(set);
732 	} else {
733 		set->variant = set->family == AF_INET
734 			? &hash_netiface4_variant : &hash_netiface6_variant;
735 	}
736 
737 	pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
738 		 set->name, jhash_size(h->table->htable_bits),
739 		 h->table->htable_bits, h->maxelem, set->data, h->table);
740 
741 	return 0;
742 }
743 
744 static struct ip_set_type hash_netiface_type __read_mostly = {
745 	.name		= "hash:net,iface",
746 	.protocol	= IPSET_PROTOCOL,
747 	.features	= IPSET_TYPE_IP | IPSET_TYPE_IFACE,
748 	.dimension	= IPSET_DIM_TWO,
749 	.family		= AF_UNSPEC,
750 	.revision_min	= 0,
751 	.create		= hash_netiface_create,
752 	.create_policy	= {
753 		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
754 		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
755 		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
756 		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
757 		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
758 		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
759 	},
760 	.adt_policy	= {
761 		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
762 		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
763 		[IPSET_ATTR_IFACE]	= { .type = NLA_NUL_STRING,
764 					    .len = IPSET_MAXNAMELEN - 1 },
765 		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
766 		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
767 		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
768 		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
769 	},
770 	.me		= THIS_MODULE,
771 };
772 
773 static int __init
hash_netiface_init(void)774 hash_netiface_init(void)
775 {
776 	return ip_set_type_register(&hash_netiface_type);
777 }
778 
779 static void __exit
hash_netiface_fini(void)780 hash_netiface_fini(void)
781 {
782 	ip_set_type_unregister(&hash_netiface_type);
783 }
784 
785 module_init(hash_netiface_init);
786 module_exit(hash_netiface_fini);
787