1/* Copyright (C) 2003-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,port 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 <net/ip.h>
17#include <net/ipv6.h>
18#include <net/netlink.h>
19
20#include <linux/netfilter.h>
21#include <linux/netfilter/ipset/pfxlen.h>
22#include <linux/netfilter/ipset/ip_set.h>
23#include <linux/netfilter/ipset/ip_set_getport.h>
24#include <linux/netfilter/ipset/ip_set_hash.h>
25
26#define REVISION_MIN	0
27/*			1    SCTP and UDPLITE support added */
28/*			2    Range as input support for IPv4 added */
29/*			3    nomatch flag support added */
30#define REVISION_MAX	4 /* Counters support added */
31
32MODULE_LICENSE("GPL");
33MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
34IP_SET_MODULE_DESC("hash:net,port", REVISION_MIN, REVISION_MAX);
35MODULE_ALIAS("ip_set_hash:net,port");
36
37/* Type specific function prefix */
38#define HTYPE		hash_netport
39#define IP_SET_HASH_WITH_PROTO
40#define IP_SET_HASH_WITH_NETS
41
42/* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0
43 * However this way we have to store internally cidr - 1,
44 * dancing back and forth.
45 */
46#define IP_SET_HASH_WITH_NETS_PACKED
47
48/* IPv4 variants */
49
50/* Member elements */
51struct hash_netport4_elem {
52	__be32 ip;
53	__be16 port;
54	u8 proto;
55	u8 cidr:7;
56	u8 nomatch:1;
57};
58
59struct hash_netport4t_elem {
60	__be32 ip;
61	__be16 port;
62	u8 proto;
63	u8 cidr:7;
64	u8 nomatch:1;
65	unsigned long timeout;
66};
67
68struct hash_netport4c_elem {
69	__be32 ip;
70	__be16 port;
71	u8 proto;
72	u8 cidr:7;
73	u8 nomatch:1;
74	struct ip_set_counter counter;
75};
76
77struct hash_netport4ct_elem {
78	__be32 ip;
79	__be16 port;
80	u8 proto;
81	u8 cidr:7;
82	u8 nomatch:1;
83	struct ip_set_counter counter;
84	unsigned long timeout;
85};
86
87/* Common functions */
88
89static inline bool
90hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
91			 const struct hash_netport4_elem *ip2,
92			 u32 *multi)
93{
94	return ip1->ip == ip2->ip &&
95	       ip1->port == ip2->port &&
96	       ip1->proto == ip2->proto &&
97	       ip1->cidr == ip2->cidr;
98}
99
100static inline int
101hash_netport4_do_data_match(const struct hash_netport4_elem *elem)
102{
103	return elem->nomatch ? -ENOTEMPTY : 1;
104}
105
106static inline void
107hash_netport4_data_set_flags(struct hash_netport4_elem *elem, u32 flags)
108{
109	elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
110}
111
112static inline void
113hash_netport4_data_reset_flags(struct hash_netport4_elem *elem, u8 *flags)
114{
115	swap(*flags, elem->nomatch);
116}
117
118static inline void
119hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
120{
121	elem->ip &= ip_set_netmask(cidr);
122	elem->cidr = cidr - 1;
123}
124
125static bool
126hash_netport4_data_list(struct sk_buff *skb,
127			const struct hash_netport4_elem *data)
128{
129	u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
130
131	if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
132	    nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
133	    nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) ||
134	    nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
135	    (flags &&
136	     nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
137		goto nla_put_failure;
138	return 0;
139
140nla_put_failure:
141	return 1;
142}
143
144static inline void
145hash_netport4_data_next(struct hash_netport4_elem *next,
146			const struct hash_netport4_elem *d)
147{
148	next->ip = d->ip;
149	next->port = d->port;
150}
151
152#define MTYPE		hash_netport4
153#define PF		4
154#define HOST_MASK	32
155#include "ip_set_hash_gen.h"
156
157static int
158hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
159		   const struct xt_action_param *par,
160		   enum ipset_adt adt, struct ip_set_adt_opt *opt)
161{
162	const struct hash_netport *h = set->data;
163	ipset_adtfn adtfn = set->variant->adt[adt];
164	struct hash_netport4_elem e = {
165		.cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
166	};
167	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
168
169	if (adt == IPSET_TEST)
170		e.cidr = HOST_MASK - 1;
171
172	if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
173				 &e.port, &e.proto))
174		return -EINVAL;
175
176	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
177	e.ip &= ip_set_netmask(e.cidr + 1);
178
179	return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
180}
181
182static int
183hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
184		   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
185{
186	const struct hash_netport *h = set->data;
187	ipset_adtfn adtfn = set->variant->adt[adt];
188	struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
189	struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
190	u32 port, port_to, p = 0, ip = 0, ip_to, last;
191	bool with_ports = false;
192	u8 cidr;
193	int ret;
194
195	if (unlikely(!tb[IPSET_ATTR_IP] ||
196		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
197		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
198		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
199		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
200		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
201		     !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
202		return -IPSET_ERR_PROTOCOL;
203
204	if (tb[IPSET_ATTR_LINENO])
205		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
206
207	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
208	      ip_set_get_extensions(set, tb, &ext);
209	if (ret)
210		return ret;
211
212	if (tb[IPSET_ATTR_CIDR]) {
213		cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
214		if (!cidr || cidr > HOST_MASK)
215			return -IPSET_ERR_INVALID_CIDR;
216		e.cidr = cidr - 1;
217	}
218
219	if (tb[IPSET_ATTR_PORT])
220		e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
221	else
222		return -IPSET_ERR_PROTOCOL;
223
224	if (tb[IPSET_ATTR_PROTO]) {
225		e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
226		with_ports = ip_set_proto_with_ports(e.proto);
227
228		if (e.proto == 0)
229			return -IPSET_ERR_INVALID_PROTO;
230	} else
231		return -IPSET_ERR_MISSING_PROTO;
232
233	if (!(with_ports || e.proto == IPPROTO_ICMP))
234		e.port = 0;
235
236	with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
237
238	if (tb[IPSET_ATTR_CADT_FLAGS]) {
239		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
240		if (cadt_flags & IPSET_FLAG_NOMATCH)
241			flags |= (IPSET_FLAG_NOMATCH << 16);
242	}
243
244	if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) {
245		e.ip = htonl(ip & ip_set_hostmask(e.cidr + 1));
246		ret = adtfn(set, &e, &ext, &ext, flags);
247		return ip_set_enomatch(ret, flags, adt) ? 1 :
248		       ip_set_eexist(ret, flags) ? 0 : ret;
249	}
250
251	port = port_to = ntohs(e.port);
252	if (tb[IPSET_ATTR_PORT_TO]) {
253		port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
254		if (port_to < port)
255			swap(port, port_to);
256	}
257	if (tb[IPSET_ATTR_IP_TO]) {
258		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
259		if (ret)
260			return ret;
261		if (ip_to < ip)
262			swap(ip, ip_to);
263		if (ip + UINT_MAX == ip_to)
264			return -IPSET_ERR_HASH_RANGE;
265	} else
266		ip_set_mask_from_to(ip, ip_to, e.cidr + 1);
267
268	if (retried)
269		ip = ntohl(h->next.ip);
270	while (!after(ip, ip_to)) {
271		e.ip = htonl(ip);
272		last = ip_set_range_to_cidr(ip, ip_to, &cidr);
273		e.cidr = cidr - 1;
274		p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
275						       : port;
276		for (; p <= port_to; p++) {
277			e.port = htons(p);
278			ret = adtfn(set, &e, &ext, &ext, flags);
279
280			if (ret && !ip_set_eexist(ret, flags))
281				return ret;
282			else
283				ret = 0;
284		}
285		ip = last + 1;
286	}
287	return ret;
288}
289
290/* IPv6 variants */
291
292struct hash_netport6_elem {
293	union nf_inet_addr ip;
294	__be16 port;
295	u8 proto;
296	u8 cidr:7;
297	u8 nomatch:1;
298};
299
300struct hash_netport6t_elem {
301	union nf_inet_addr ip;
302	__be16 port;
303	u8 proto;
304	u8 cidr:7;
305	u8 nomatch:1;
306	unsigned long timeout;
307};
308
309struct hash_netport6c_elem {
310	union nf_inet_addr ip;
311	__be16 port;
312	u8 proto;
313	u8 cidr:7;
314	u8 nomatch:1;
315	struct ip_set_counter counter;
316};
317
318struct hash_netport6ct_elem {
319	union nf_inet_addr ip;
320	__be16 port;
321	u8 proto;
322	u8 cidr:7;
323	u8 nomatch:1;
324	struct ip_set_counter counter;
325	unsigned long timeout;
326};
327
328/* Common functions */
329
330static inline bool
331hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
332			 const struct hash_netport6_elem *ip2,
333			 u32 *multi)
334{
335	return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
336	       ip1->port == ip2->port &&
337	       ip1->proto == ip2->proto &&
338	       ip1->cidr == ip2->cidr;
339}
340
341static inline int
342hash_netport6_do_data_match(const struct hash_netport6_elem *elem)
343{
344	return elem->nomatch ? -ENOTEMPTY : 1;
345}
346
347static inline void
348hash_netport6_data_set_flags(struct hash_netport6_elem *elem, u32 flags)
349{
350	elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
351}
352
353static inline void
354hash_netport6_data_reset_flags(struct hash_netport6_elem *elem, u8 *flags)
355{
356	swap(*flags, elem->nomatch);
357}
358
359static inline void
360hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr)
361{
362	ip6_netmask(&elem->ip, cidr);
363	elem->cidr = cidr - 1;
364}
365
366static bool
367hash_netport6_data_list(struct sk_buff *skb,
368			const struct hash_netport6_elem *data)
369{
370	u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
371
372	if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
373	    nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
374	    nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) ||
375	    nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
376	    (flags &&
377	     nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
378		goto nla_put_failure;
379	return 0;
380
381nla_put_failure:
382	return 1;
383}
384
385static inline void
386hash_netport6_data_next(struct hash_netport4_elem *next,
387			const struct hash_netport6_elem *d)
388{
389	next->port = d->port;
390}
391
392#undef MTYPE
393#undef PF
394#undef HOST_MASK
395
396#define MTYPE		hash_netport6
397#define PF		6
398#define HOST_MASK	128
399#define IP_SET_EMIT_CREATE
400#include "ip_set_hash_gen.h"
401
402static int
403hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
404		   const struct xt_action_param *par,
405		   enum ipset_adt adt, struct ip_set_adt_opt *opt)
406{
407	const struct hash_netport *h = set->data;
408	ipset_adtfn adtfn = set->variant->adt[adt];
409	struct hash_netport6_elem e = {
410		.cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1,
411	};
412	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
413
414	if (adt == IPSET_TEST)
415		e.cidr = HOST_MASK - 1;
416
417	if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
418				 &e.port, &e.proto))
419		return -EINVAL;
420
421	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
422	ip6_netmask(&e.ip, e.cidr + 1);
423
424	return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
425}
426
427static int
428hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
429		   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
430{
431	const struct hash_netport *h = set->data;
432	ipset_adtfn adtfn = set->variant->adt[adt];
433	struct hash_netport6_elem e = { .cidr = HOST_MASK  - 1 };
434	struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
435	u32 port, port_to;
436	bool with_ports = false;
437	u8 cidr;
438	int ret;
439
440	if (unlikely(!tb[IPSET_ATTR_IP] ||
441		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
442		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
443		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
444		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
445		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
446		     !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
447		return -IPSET_ERR_PROTOCOL;
448	if (unlikely(tb[IPSET_ATTR_IP_TO]))
449		return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
450
451	if (tb[IPSET_ATTR_LINENO])
452		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
453
454	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
455	      ip_set_get_extensions(set, tb, &ext);
456	if (ret)
457		return ret;
458
459	if (tb[IPSET_ATTR_CIDR]) {
460		cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
461		if (!cidr || cidr > HOST_MASK)
462			return -IPSET_ERR_INVALID_CIDR;
463		e.cidr = cidr - 1;
464	}
465	ip6_netmask(&e.ip, e.cidr + 1);
466
467	if (tb[IPSET_ATTR_PORT])
468		e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
469	else
470		return -IPSET_ERR_PROTOCOL;
471
472	if (tb[IPSET_ATTR_PROTO]) {
473		e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
474		with_ports = ip_set_proto_with_ports(e.proto);
475
476		if (e.proto == 0)
477			return -IPSET_ERR_INVALID_PROTO;
478	} else
479		return -IPSET_ERR_MISSING_PROTO;
480
481	if (!(with_ports || e.proto == IPPROTO_ICMPV6))
482		e.port = 0;
483
484	if (tb[IPSET_ATTR_CADT_FLAGS]) {
485		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
486		if (cadt_flags & IPSET_FLAG_NOMATCH)
487			flags |= (IPSET_FLAG_NOMATCH << 16);
488	}
489
490	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
491		ret = adtfn(set, &e, &ext, &ext, flags);
492		return ip_set_enomatch(ret, flags, adt) ? 1 :
493		       ip_set_eexist(ret, flags) ? 0 : ret;
494	}
495
496	port = ntohs(e.port);
497	port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
498	if (port > port_to)
499		swap(port, port_to);
500
501	if (retried)
502		port = ntohs(h->next.port);
503	for (; port <= port_to; port++) {
504		e.port = htons(port);
505		ret = adtfn(set, &e, &ext, &ext, flags);
506
507		if (ret && !ip_set_eexist(ret, flags))
508			return ret;
509		else
510			ret = 0;
511	}
512	return ret;
513}
514
515static struct ip_set_type hash_netport_type __read_mostly = {
516	.name		= "hash:net,port",
517	.protocol	= IPSET_PROTOCOL,
518	.features	= IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_NOMATCH,
519	.dimension	= IPSET_DIM_TWO,
520	.family		= NFPROTO_UNSPEC,
521	.revision_min	= REVISION_MIN,
522	.revision_max	= REVISION_MAX,
523	.create		= hash_netport_create,
524	.create_policy	= {
525		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
526		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
527		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
528		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
529		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
530		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
531		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
532	},
533	.adt_policy	= {
534		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
535		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
536		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
537		[IPSET_ATTR_PORT_TO]	= { .type = NLA_U16 },
538		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
539		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
540		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
541		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
542		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
543		[IPSET_ATTR_BYTES]	= { .type = NLA_U64 },
544		[IPSET_ATTR_PACKETS]	= { .type = NLA_U64 },
545	},
546	.me		= THIS_MODULE,
547};
548
549static int __init
550hash_netport_init(void)
551{
552	return ip_set_type_register(&hash_netport_type);
553}
554
555static void __exit
556hash_netport_fini(void)
557{
558	ip_set_type_unregister(&hash_netport_type);
559}
560
561module_init(hash_netport_init);
562module_exit(hash_netport_fini);
563