1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (C) 2011-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3  */
4 
5 /* Kernel module implementing an IP set type: the hash:net,iface type */
6 
7 #include <linux/jhash.h>
8 #include <linux/module.h>
9 #include <linux/ip.h>
10 #include <linux/skbuff.h>
11 #include <linux/errno.h>
12 #include <linux/random.h>
13 #include <net/ip.h>
14 #include <net/ipv6.h>
15 #include <net/netlink.h>
16 
17 #include <linux/netfilter.h>
18 #include <linux/netfilter_bridge.h>
19 #include <linux/netfilter/ipset/pfxlen.h>
20 #include <linux/netfilter/ipset/ip_set.h>
21 #include <linux/netfilter/ipset/ip_set_hash.h>
22 
23 #define IPSET_TYPE_REV_MIN	0
24 /*				1    nomatch flag support added */
25 /*				2    /0 support added */
26 /*				3    Counters support added */
27 /*				4    Comments support added */
28 /*				5    Forceadd support added */
29 #define IPSET_TYPE_REV_MAX	6 /* skbinfo support added */
30 
31 MODULE_LICENSE("GPL");
32 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
33 IP_SET_MODULE_DESC("hash:net,iface", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
34 MODULE_ALIAS("ip_set_hash:net,iface");
35 
36 /* Type specific function prefix */
37 #define HTYPE		hash_netiface
38 #define IP_SET_HASH_WITH_NETS
39 #define IP_SET_HASH_WITH_MULTI
40 #define IP_SET_HASH_WITH_NET0
41 
42 #define STRLCPY(a, b)	strlcpy(a, b, IFNAMSIZ)
43 
44 /* IPv4 variant */
45 
46 struct hash_netiface4_elem_hashed {
47 	__be32 ip;
48 	u8 physdev;
49 	u8 cidr;
50 	u8 nomatch;
51 	u8 elem;
52 };
53 
54 /* Member elements */
55 struct hash_netiface4_elem {
56 	__be32 ip;
57 	u8 physdev;
58 	u8 cidr;
59 	u8 nomatch;
60 	u8 elem;
61 	char iface[IFNAMSIZ];
62 };
63 
64 /* Common functions */
65 
66 static inline bool
67 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
68 			  const struct hash_netiface4_elem *ip2,
69 			  u32 *multi)
70 {
71 	return ip1->ip == ip2->ip &&
72 	       ip1->cidr == ip2->cidr &&
73 	       (++*multi) &&
74 	       ip1->physdev == ip2->physdev &&
75 	       strcmp(ip1->iface, ip2->iface) == 0;
76 }
77 
78 static inline int
79 hash_netiface4_do_data_match(const struct hash_netiface4_elem *elem)
80 {
81 	return elem->nomatch ? -ENOTEMPTY : 1;
82 }
83 
84 static inline void
85 hash_netiface4_data_set_flags(struct hash_netiface4_elem *elem, u32 flags)
86 {
87 	elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
88 }
89 
90 static inline void
91 hash_netiface4_data_reset_flags(struct hash_netiface4_elem *elem, u8 *flags)
92 {
93 	swap(*flags, elem->nomatch);
94 }
95 
96 static inline void
97 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
98 {
99 	elem->ip &= ip_set_netmask(cidr);
100 	elem->cidr = cidr;
101 }
102 
103 static bool
104 hash_netiface4_data_list(struct sk_buff *skb,
105 			 const struct hash_netiface4_elem *data)
106 {
107 	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
108 
109 	if (data->nomatch)
110 		flags |= IPSET_FLAG_NOMATCH;
111 	if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
112 	    nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
113 	    nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
114 	    (flags &&
115 	     nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
116 		goto nla_put_failure;
117 	return false;
118 
119 nla_put_failure:
120 	return true;
121 }
122 
123 static inline void
124 hash_netiface4_data_next(struct hash_netiface4_elem *next,
125 			 const struct hash_netiface4_elem *d)
126 {
127 	next->ip = d->ip;
128 }
129 
130 #define MTYPE		hash_netiface4
131 #define HOST_MASK	32
132 #define HKEY_DATALEN	sizeof(struct hash_netiface4_elem_hashed)
133 #include "ip_set_hash_gen.h"
134 
135 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
136 static const char *get_physindev_name(const struct sk_buff *skb)
137 {
138 	struct net_device *dev = nf_bridge_get_physindev(skb);
139 
140 	return dev ? dev->name : NULL;
141 }
142 
143 static const char *get_physoutdev_name(const struct sk_buff *skb)
144 {
145 	struct net_device *dev = nf_bridge_get_physoutdev(skb);
146 
147 	return dev ? dev->name : NULL;
148 }
149 #endif
150 
151 static int
152 hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
153 		    const struct xt_action_param *par,
154 		    enum ipset_adt adt, struct ip_set_adt_opt *opt)
155 {
156 	struct hash_netiface4 *h = set->data;
157 	ipset_adtfn adtfn = set->variant->adt[adt];
158 	struct hash_netiface4_elem e = {
159 		.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
160 		.elem = 1,
161 	};
162 	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
163 
164 	if (adt == IPSET_TEST)
165 		e.cidr = HOST_MASK;
166 
167 	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
168 	e.ip &= ip_set_netmask(e.cidr);
169 
170 #define IFACE(dir)	(par->state->dir ? par->state->dir->name : "")
171 #define SRCDIR		(opt->flags & IPSET_DIM_TWO_SRC)
172 
173 	if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
174 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
175 		const char *eiface = SRCDIR ? get_physindev_name(skb) :
176 					      get_physoutdev_name(skb);
177 
178 		if (!eiface)
179 			return -EINVAL;
180 		STRLCPY(e.iface, eiface);
181 		e.physdev = 1;
182 #endif
183 	} else {
184 		STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out));
185 	}
186 
187 	if (strlen(e.iface) == 0)
188 		return -EINVAL;
189 	return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
190 }
191 
192 static int
193 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
194 		    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
195 {
196 	struct hash_netiface4 *h = set->data;
197 	ipset_adtfn adtfn = set->variant->adt[adt];
198 	struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
199 	struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
200 	u32 ip = 0, ip_to = 0;
201 	int ret;
202 
203 	if (tb[IPSET_ATTR_LINENO])
204 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
205 
206 	if (unlikely(!tb[IPSET_ATTR_IP] ||
207 		     !tb[IPSET_ATTR_IFACE] ||
208 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
209 		return -IPSET_ERR_PROTOCOL;
210 
211 	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
212 	if (ret)
213 		return ret;
214 
215 	ret = ip_set_get_extensions(set, tb, &ext);
216 	if (ret)
217 		return ret;
218 
219 	if (tb[IPSET_ATTR_CIDR]) {
220 		e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
221 		if (e.cidr > HOST_MASK)
222 			return -IPSET_ERR_INVALID_CIDR;
223 	}
224 	nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ);
225 
226 	if (tb[IPSET_ATTR_CADT_FLAGS]) {
227 		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
228 
229 		if (cadt_flags & IPSET_FLAG_PHYSDEV)
230 			e.physdev = 1;
231 		if (cadt_flags & IPSET_FLAG_NOMATCH)
232 			flags |= (IPSET_FLAG_NOMATCH << 16);
233 	}
234 	if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
235 		e.ip = htonl(ip & ip_set_hostmask(e.cidr));
236 		ret = adtfn(set, &e, &ext, &ext, flags);
237 		return ip_set_enomatch(ret, flags, adt, set) ? -ret :
238 		       ip_set_eexist(ret, flags) ? 0 : ret;
239 	}
240 
241 	if (tb[IPSET_ATTR_IP_TO]) {
242 		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
243 		if (ret)
244 			return ret;
245 		if (ip_to < ip)
246 			swap(ip, ip_to);
247 		if (ip + UINT_MAX == ip_to)
248 			return -IPSET_ERR_HASH_RANGE;
249 	} else {
250 		ip_set_mask_from_to(ip, ip_to, e.cidr);
251 	}
252 
253 	if (retried)
254 		ip = ntohl(h->next.ip);
255 	do {
256 		e.ip = htonl(ip);
257 		ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
258 		ret = adtfn(set, &e, &ext, &ext, flags);
259 
260 		if (ret && !ip_set_eexist(ret, flags))
261 			return ret;
262 
263 		ret = 0;
264 	} while (ip++ < ip_to);
265 	return ret;
266 }
267 
268 /* IPv6 variant */
269 
270 struct hash_netiface6_elem_hashed {
271 	union nf_inet_addr ip;
272 	u8 physdev;
273 	u8 cidr;
274 	u8 nomatch;
275 	u8 elem;
276 };
277 
278 struct hash_netiface6_elem {
279 	union nf_inet_addr ip;
280 	u8 physdev;
281 	u8 cidr;
282 	u8 nomatch;
283 	u8 elem;
284 	char iface[IFNAMSIZ];
285 };
286 
287 /* Common functions */
288 
289 static inline bool
290 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
291 			  const struct hash_netiface6_elem *ip2,
292 			  u32 *multi)
293 {
294 	return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
295 	       ip1->cidr == ip2->cidr &&
296 	       (++*multi) &&
297 	       ip1->physdev == ip2->physdev &&
298 	       strcmp(ip1->iface, ip2->iface) == 0;
299 }
300 
301 static inline int
302 hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem)
303 {
304 	return elem->nomatch ? -ENOTEMPTY : 1;
305 }
306 
307 static inline void
308 hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags)
309 {
310 	elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
311 }
312 
313 static inline void
314 hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags)
315 {
316 	swap(*flags, elem->nomatch);
317 }
318 
319 static inline void
320 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
321 {
322 	ip6_netmask(&elem->ip, cidr);
323 	elem->cidr = cidr;
324 }
325 
326 static bool
327 hash_netiface6_data_list(struct sk_buff *skb,
328 			 const struct hash_netiface6_elem *data)
329 {
330 	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
331 
332 	if (data->nomatch)
333 		flags |= IPSET_FLAG_NOMATCH;
334 	if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
335 	    nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
336 	    nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
337 	    (flags &&
338 	     nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
339 		goto nla_put_failure;
340 	return false;
341 
342 nla_put_failure:
343 	return true;
344 }
345 
346 static inline void
347 hash_netiface6_data_next(struct hash_netiface6_elem *next,
348 			 const struct hash_netiface6_elem *d)
349 {
350 }
351 
352 #undef MTYPE
353 #undef HOST_MASK
354 
355 #define MTYPE		hash_netiface6
356 #define HOST_MASK	128
357 #define HKEY_DATALEN	sizeof(struct hash_netiface6_elem_hashed)
358 #define IP_SET_EMIT_CREATE
359 #include "ip_set_hash_gen.h"
360 
361 static int
362 hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
363 		    const struct xt_action_param *par,
364 		    enum ipset_adt adt, struct ip_set_adt_opt *opt)
365 {
366 	struct hash_netiface6 *h = set->data;
367 	ipset_adtfn adtfn = set->variant->adt[adt];
368 	struct hash_netiface6_elem e = {
369 		.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
370 		.elem = 1,
371 	};
372 	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
373 
374 	if (adt == IPSET_TEST)
375 		e.cidr = HOST_MASK;
376 
377 	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
378 	ip6_netmask(&e.ip, e.cidr);
379 
380 	if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
381 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
382 		const char *eiface = SRCDIR ? get_physindev_name(skb) :
383 					      get_physoutdev_name(skb);
384 
385 		if (!eiface)
386 			return -EINVAL;
387 		STRLCPY(e.iface, eiface);
388 		e.physdev = 1;
389 #endif
390 	} else {
391 		STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out));
392 	}
393 
394 	if (strlen(e.iface) == 0)
395 		return -EINVAL;
396 
397 	return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
398 }
399 
400 static int
401 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
402 		    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
403 {
404 	ipset_adtfn adtfn = set->variant->adt[adt];
405 	struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 };
406 	struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
407 	int ret;
408 
409 	if (tb[IPSET_ATTR_LINENO])
410 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
411 
412 	if (unlikely(!tb[IPSET_ATTR_IP] ||
413 		     !tb[IPSET_ATTR_IFACE] ||
414 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
415 		return -IPSET_ERR_PROTOCOL;
416 	if (unlikely(tb[IPSET_ATTR_IP_TO]))
417 		return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
418 
419 	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip);
420 	if (ret)
421 		return ret;
422 
423 	ret = ip_set_get_extensions(set, tb, &ext);
424 	if (ret)
425 		return ret;
426 
427 	if (tb[IPSET_ATTR_CIDR]) {
428 		e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
429 		if (e.cidr > HOST_MASK)
430 			return -IPSET_ERR_INVALID_CIDR;
431 	}
432 
433 	ip6_netmask(&e.ip, e.cidr);
434 
435 	nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ);
436 
437 	if (tb[IPSET_ATTR_CADT_FLAGS]) {
438 		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
439 
440 		if (cadt_flags & IPSET_FLAG_PHYSDEV)
441 			e.physdev = 1;
442 		if (cadt_flags & IPSET_FLAG_NOMATCH)
443 			flags |= (IPSET_FLAG_NOMATCH << 16);
444 	}
445 
446 	ret = adtfn(set, &e, &ext, &ext, flags);
447 
448 	return ip_set_enomatch(ret, flags, adt, set) ? -ret :
449 	       ip_set_eexist(ret, flags) ? 0 : ret;
450 }
451 
452 static struct ip_set_type hash_netiface_type __read_mostly = {
453 	.name		= "hash:net,iface",
454 	.protocol	= IPSET_PROTOCOL,
455 	.features	= IPSET_TYPE_IP | IPSET_TYPE_IFACE |
456 			  IPSET_TYPE_NOMATCH,
457 	.dimension	= IPSET_DIM_TWO,
458 	.family		= NFPROTO_UNSPEC,
459 	.revision_min	= IPSET_TYPE_REV_MIN,
460 	.revision_max	= IPSET_TYPE_REV_MAX,
461 	.create		= hash_netiface_create,
462 	.create_policy	= {
463 		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
464 		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
465 		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
466 		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
467 		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
468 		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
469 		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
470 	},
471 	.adt_policy	= {
472 		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
473 		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
474 		[IPSET_ATTR_IFACE]	= { .type = NLA_NUL_STRING,
475 					    .len  = IFNAMSIZ - 1 },
476 		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
477 		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
478 		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
479 		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
480 		[IPSET_ATTR_BYTES]	= { .type = NLA_U64 },
481 		[IPSET_ATTR_PACKETS]	= { .type = NLA_U64 },
482 		[IPSET_ATTR_COMMENT]	= { .type = NLA_NUL_STRING,
483 					    .len  = IPSET_MAX_COMMENT_SIZE },
484 		[IPSET_ATTR_SKBMARK]	= { .type = NLA_U64 },
485 		[IPSET_ATTR_SKBPRIO]	= { .type = NLA_U32 },
486 		[IPSET_ATTR_SKBQUEUE]	= { .type = NLA_U16 },
487 	},
488 	.me		= THIS_MODULE,
489 };
490 
491 static int __init
492 hash_netiface_init(void)
493 {
494 	return ip_set_type_register(&hash_netiface_type);
495 }
496 
497 static void __exit
498 hash_netiface_fini(void)
499 {
500 	rcu_barrier();
501 	ip_set_type_unregister(&hash_netiface_type);
502 }
503 
504 module_init(hash_netiface_init);
505 module_exit(hash_netiface_fini);
506