11 #include <linux/module.h>
14 #include <linux/errno.h>
15 #include <linux/random.h>
21 #include <linux/netfilter.h>
23 #include <linux/netfilter/ipset/ip_set.h>
26 #include <linux/netfilter/ipset/ip_set_hash.h>
28 #define REVISION_MIN 0
29 #define REVISION_MAX 1
37 #define TYPE hash_ipport
40 hash_ipport_same_set(
const struct ip_set *
a,
const struct ip_set *
b);
42 #define hash_ipport4_same_set hash_ipport_same_set
43 #define hash_ipport6_same_set hash_ipport_same_set
69 return ip1->
ip == ip2->
ip &&
77 return elem->
proto == 0;
102 goto nla_put_failure;
110 hash_ipport4_data_tlist(
struct sk_buff *skb,
121 goto nla_put_failure;
141 hash_ipport4_kadt(
struct ip_set *
set,
const struct sk_buff *skb,
155 return adtfn(
set, &data, opt_timeout(opt, h), opt->
cmdflags);
167 bool with_ports =
false;
177 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
184 data.
port = nla_get_be16(tb[IPSET_ATTR_PORT]);
189 data.
proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
190 with_ports = ip_set_proto_with_ports(data.
proto);
203 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
209 ret = adtfn(
set, &data, timeout, flags);
210 return ip_set_eexist(ret, flags) ? 0 :
ret;
215 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
221 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
223 if (!cidr || cidr > 32)
229 if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
230 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
237 for (; !before(ip_to, ip); ip++) {
240 for (; p <= port_to; p++) {
243 ret = adtfn(
set, &data, timeout, flags);
245 if (ret && !ip_set_eexist(ret, flags))
255 hash_ipport_same_set(
const struct ip_set *
a,
const struct ip_set *
b)
287 return ipv6_addr_cmp(&ip1->
ip.
in6, &ip2->
ip.
in6) == 0 &&
295 return elem->
proto == 0;
302 memcpy(dst, src,
sizeof(*dst));
312 hash_ipport6_data_list(
struct sk_buff *skb,
316 nla_put_net16(skb, IPSET_ATTR_PORT, data->
port) ||
317 nla_put_u8(skb, IPSET_ATTR_PROTO, data->
proto))
318 goto nla_put_failure;
326 hash_ipport6_data_tlist(
struct sk_buff *skb,
333 nla_put_net16(skb, IPSET_ATTR_PORT, data->
port) ||
334 nla_put_u8(skb, IPSET_ATTR_PROTO, data->
proto) ||
335 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
337 goto nla_put_failure;
348 #define HOST_MASK 128
359 hash_ipport6_kadt(
struct ip_set *
set,
const struct sk_buff *skb,
373 return adtfn(
set, &data, opt_timeout(opt, h), opt->
cmdflags);
377 hash_ipport6_uadt(
struct ip_set *
set,
struct nlattr *tb[],
385 bool with_ports =
false;
389 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
390 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
391 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
392 tb[IPSET_ATTR_IP_TO] ||
393 tb[IPSET_ATTR_CIDR]))
396 if (tb[IPSET_ATTR_LINENO])
397 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
403 if (tb[IPSET_ATTR_PORT])
404 data.
port = nla_get_be16(tb[IPSET_ATTR_PORT]);
408 if (tb[IPSET_ATTR_PROTO]) {
409 data.
proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
410 with_ports = ip_set_proto_with_ports(data.
proto);
420 if (tb[IPSET_ATTR_TIMEOUT]) {
423 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
426 if (adt ==
IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
427 ret = adtfn(
set, &data, timeout, flags);
428 return ip_set_eexist(ret, flags) ? 0 :
ret;
432 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
438 for (; port <= port_to; port++) {
440 ret = adtfn(
set, &data, timeout, flags);
442 if (ret && !ip_set_eexist(ret, flags))
465 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
469 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
475 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
485 hbits = htable_bits(hashsize);
486 hsize = htable_size(hbits);
496 h->
table->htable_bits = hbits;
500 if (tb[IPSET_ATTR_TIMEOUT]) {
501 h->
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
504 ? &hash_ipport4_tvariant : &hash_ipport6_tvariant;
507 hash_ipport4_gc_init(
set);
509 hash_ipport6_gc_init(
set);
512 ? &hash_ipport4_variant : &hash_ipport6_variant;
515 pr_debug(
"create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
523 .name =
"hash:ip,port",
530 .create = hash_ipport_create,
553 hash_ipport_init(
void)
559 hash_ipport_fini(
void)