From 62a05ab5fe3e5b60057fef9e669137cacab6b614 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 17 Dec 2010 21:28:18 +0100 Subject: Support adding/deleting multiple entries, kernel part. Support adding/deleting multiple entries in the kernel side of the hash:ip,port, hash:ip,port,ip, hash:ip,port,net and hash:net,port types. --- kernel/ip_set_hash_ipport.c | 76 +++++++++++++++++++++++++++++++++++++++--- kernel/ip_set_hash_ipportip.c | 76 +++++++++++++++++++++++++++++++++++++++--- kernel/ip_set_hash_ipportnet.c | 76 +++++++++++++++++++++++++++++++++++++++--- kernel/ip_set_hash_netport.c | 49 ++++++++++++++++++++++++--- 4 files changed, 261 insertions(+), 16 deletions(-) (limited to 'kernel') diff --git a/kernel/ip_set_hash_ipport.c b/kernel/ip_set_hash_ipport.c index d201adf..d9ee214 100644 --- a/kernel/ip_set_hash_ipport.c +++ b/kernel/ip_set_hash_ipport.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -155,7 +156,10 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb, static const struct nla_policy hash_ipport_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, @@ -169,6 +173,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len, struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport4_elem data = { }; + u32 ip, ip_to, p, port, port_to; u32 timeout = h->timeout; int ret; @@ -212,9 +217,52 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST + || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) + || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] + || tb[IPSET_ATTR_PORT_TO])) { + ret = adtfn(set, &data, timeout); + return ip_set_eexist(ret, flags) ? 0 : ret; + } + + ip = ntohl(data.ip); + if (tb[IPSET_ATTR_IP_TO]) { + ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + if (ret) + return ret; + ip_to = ntohl(ip_to); + if (ip > ip_to) + swap(ip, ip_to); + } else if (tb[IPSET_ATTR_CIDR]) { + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); + + if (cidr > 32) + return -IPSET_ERR_INVALID_CIDR; + ip &= HOSTMASK(cidr); + ip_to = ip | ~HOSTMASK(cidr); + } else + ip_to = ip; - return ip_set_eexist(ret, flags) ? 0 : ret; + port = ntohs(data.port); + if (tb[IPSET_ATTR_PORT_TO]) { + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (port > port_to) + swap(port, port_to); + } else + port_to = port; + + for (; !before(ip_to, ip); ip++) + for (p = port; p <= port_to; p++) { + data.ip = htonl(ip); + data.port = htons(p); + ret = adtfn(set, &data, timeout); + + if (ret && !ip_set_eexist(ret, flags)) + return ret; + else + ret = 0; + } + return ret; } static bool @@ -347,6 +395,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len, struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport6_elem data = { }; + u32 port, port_to; u32 timeout = h->timeout; int ret; @@ -390,9 +439,28 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST + || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) + || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout); + return ip_set_eexist(ret, flags) ? 0 : ret; + } - return ip_set_eexist(ret, flags) ? 0 : ret; + port = ntohs(data.port); + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (port > port_to) + swap(port, port_to); + + for (; port <= port_to; port++) { + data.port = htons(port); + ret = adtfn(set, &data, timeout); + + if (ret && !ip_set_eexist(ret, flags)) + return ret; + else + ret = 0; + } + return ret; } /* Create hash:ip type of sets */ diff --git a/kernel/ip_set_hash_ipportip.c b/kernel/ip_set_hash_ipportip.c index 53c9e7a..b0aaf08 100644 --- a/kernel/ip_set_hash_ipportip.c +++ b/kernel/ip_set_hash_ipportip.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -161,8 +162,11 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, static const struct nla_policy hash_ipportip_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, @@ -176,6 +180,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip4_elem data = { }; + u32 ip, ip_to, p, port, port_to; u32 timeout = h->timeout; int ret; @@ -223,9 +228,52 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST + || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) + || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] + || tb[IPSET_ATTR_PORT_TO])) { + ret = adtfn(set, &data, timeout); + return ip_set_eexist(ret, flags) ? 0 : ret; + } + + ip = ntohl(data.ip); + if (tb[IPSET_ATTR_IP_TO]) { + ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + if (ret) + return ret; + ip_to = ntohl(ip_to); + if (ip > ip_to) + swap(ip, ip_to); + } else if (tb[IPSET_ATTR_CIDR]) { + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); + + if (cidr > 32) + return -IPSET_ERR_INVALID_CIDR; + ip &= HOSTMASK(cidr); + ip_to = ip | ~HOSTMASK(cidr); + } else + ip_to = ip; - return ip_set_eexist(ret, flags) ? 0 : ret; + port = ntohs(data.port); + if (tb[IPSET_ATTR_PORT_TO]) { + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (port > port_to) + swap(port, port_to); + } else + port_to = port; + + for (; !before(ip_to, ip); ip++) + for (p = port; p <= port_to; p++) { + data.ip = htonl(ip); + data.port = htons(p); + ret = adtfn(set, &data, timeout); + + if (ret && !ip_set_eexist(ret, flags)) + return ret; + else + ret = 0; + } + return ret; } static bool @@ -364,6 +412,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip6_elem data = { }; + u32 port, port_to; u32 timeout = h->timeout; int ret; @@ -411,9 +460,28 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST + || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) + || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout); + return ip_set_eexist(ret, flags) ? 0 : ret; + } - return ip_set_eexist(ret, flags) ? 0 : ret; + port = ntohs(data.port); + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (port > port_to) + swap(port, port_to); + + for (; port <= port_to; port++) { + data.port = htons(port); + ret = adtfn(set, &data, timeout); + + if (ret && !ip_set_eexist(ret, flags)) + return ret; + else + ret = 0; + } + return ret; } /* Create hash:ip type of sets */ diff --git a/kernel/ip_set_hash_ipportnet.c b/kernel/ip_set_hash_ipportnet.c index 293fc31..6886aa8 100644 --- a/kernel/ip_set_hash_ipportnet.c +++ b/kernel/ip_set_hash_ipportnet.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -181,8 +182,11 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, static const struct nla_policy hash_ipportnet_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, [IPSET_ATTR_CIDR2] = { .type = NLA_U8 }, [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, @@ -197,6 +201,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len, struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; + u32 ip, ip_to, p, port, port_to; u32 timeout = h->timeout; int ret; @@ -252,9 +257,52 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST + || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) + || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] + || tb[IPSET_ATTR_PORT_TO])) { + ret = adtfn(set, &data, timeout); + return ip_set_eexist(ret, flags) ? 0 : ret; + } + + ip = ntohl(data.ip); + if (tb[IPSET_ATTR_IP_TO]) { + ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + if (ret) + return ret; + ip_to = ntohl(ip_to); + if (ip > ip_to) + swap(ip, ip_to); + } else if (tb[IPSET_ATTR_CIDR]) { + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); + + if (cidr > 32) + return -IPSET_ERR_INVALID_CIDR; + ip &= HOSTMASK(cidr); + ip_to = ip | ~HOSTMASK(cidr); + } else + ip_to = ip; - return ip_set_eexist(ret, flags) ? 0 : ret; + port = ntohs(data.port); + if (tb[IPSET_ATTR_PORT_TO]) { + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (port > port_to) + swap(port, port_to); + } else + port_to = port; + + for (; !before(ip_to, ip); ip++) + for (p = port; p <= port_to; p++) { + data.ip = htonl(ip); + data.port = htons(p); + ret = adtfn(set, &data, timeout); + + if (ret && !ip_set_eexist(ret, flags)) + return ret; + else + ret = 0; + } + return ret; } static bool @@ -419,6 +467,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len, struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; + u32 port, port_to; u32 timeout = h->timeout; int ret; @@ -474,9 +523,28 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST + || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) + || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout); + return ip_set_eexist(ret, flags) ? 0 : ret; + } - return ip_set_eexist(ret, flags) ? 0 : ret; + port = ntohs(data.port); + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (port > port_to) + swap(port, port_to); + + for (; port <= port_to; port++) { + data.port = htons(port); + ret = adtfn(set, &data, timeout); + + if (ret && !ip_set_eexist(ret, flags)) + return ret; + else + ret = 0; + } + return ret; } /* Create hash:ip type of sets */ diff --git a/kernel/ip_set_hash_netport.c b/kernel/ip_set_hash_netport.c index 71539d4..2c42c5b 100644 --- a/kernel/ip_set_hash_netport.c +++ b/kernel/ip_set_hash_netport.c @@ -178,6 +178,7 @@ static const struct nla_policy hash_netport_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, @@ -192,6 +193,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len, struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netport4_elem data = { .cidr = HOST_MASK }; + u32 port, port_to; u32 timeout = h->timeout; int ret; @@ -241,9 +243,28 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST + || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) + || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout); + return ip_set_eexist(ret, flags) ? 0 : ret; + } + + port = ntohs(data.port); + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (port > port_to) + swap(port, port_to); + + for (; port <= port_to; port++) { + data.port = htons(port); + ret = adtfn(set, &data, timeout); - return ip_set_eexist(ret, flags) ? 0 : ret; + if (ret && !ip_set_eexist(ret, flags)) + return ret; + else + ret = 0; + } + return ret; } static bool @@ -402,6 +423,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len, struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netport6_elem data = { .cidr = HOST_MASK }; + u32 port, port_to; u32 timeout = h->timeout; int ret; @@ -451,9 +473,28 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST + || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) + || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout); + return ip_set_eexist(ret, flags) ? 0 : ret; + } + + port = ntohs(data.port); + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (port > port_to) + swap(port, port_to); + + for (; port <= port_to; port++) { + data.port = htons(port); + ret = adtfn(set, &data, timeout); - return ip_set_eexist(ret, flags) ? 0 : ret; + if (ret && !ip_set_eexist(ret, flags)) + return ret; + else + ret = 0; + } + return ret; } /* Create hash:ip type of sets */ -- cgit v1.2.3