};
 
 /* Max range where every element is added/deleted in one step */
-#define IPSET_MAX_RANGE                (1<<20)
+#define IPSET_MAX_RANGE                (1<<14)
 
 /* The max revision number supported by any set type + 1 */
 #define IPSET_REVISION_MAX     9
 
                ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
                ip_set_unlock(set);
                retried = true;
-       } while (ret == -EAGAIN &&
-                set->variant->resize &&
-                (ret = set->variant->resize(set, retried)) == 0);
+       } while (ret == -ERANGE ||
+                (ret == -EAGAIN &&
+                 set->variant->resize &&
+                 (ret = set->variant->resize(set, retried)) == 0));
 
        if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
                return 0;
 
 hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
              enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
-       const struct hash_ip4 *h = set->data;
+       struct hash_ip4 *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ip4_elem e = { 0 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip = 0, ip_to = 0, hosts;
+       u32 ip = 0, ip_to = 0, hosts, i = 0;
        int ret = 0;
 
        if (tb[IPSET_ATTR_LINENO])
 
        hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
-       /* 64bit division is not allowed on 32bit */
-       if (((u64)ip_to - ip + 1) >> (32 - h->netmask) > IPSET_MAX_RANGE)
-               return -ERANGE;
-
        if (retried)
                ip = ntohl(h->next.ip);
-       for (; ip <= ip_to;) {
+       for (; ip <= ip_to; i++) {
                e.ip = htonl(ip);
+               if (i > IPSET_MAX_RANGE) {
+                       hash_ip4_data_next(&h->next, &e);
+                       return -ERANGE;
+               }
                ret = adtfn(set, &e, &ext, &ext, flags);
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
 
 hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
                  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
-       const struct hash_ipmark4 *h = set->data;
+       struct hash_ipmark4 *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipmark4_elem e = { };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip, ip_to = 0;
+       u32 ip, ip_to = 0, i = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
                ip_set_mask_from_to(ip, ip_to, cidr);
        }
 
-       if (((u64)ip_to - ip + 1) > IPSET_MAX_RANGE)
-               return -ERANGE;
-
        if (retried)
                ip = ntohl(h->next.ip);
-       for (; ip <= ip_to; ip++) {
+       for (; ip <= ip_to; ip++, i++) {
                e.ip = htonl(ip);
+               if (i > IPSET_MAX_RANGE) {
+                       hash_ipmark4_data_next(&h->next, &e);
+                       return -ERANGE;
+               }
                ret = adtfn(set, &e, &ext, &ext, flags);
 
                if (ret && !ip_set_eexist(ret, flags))
 
 hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
-       const struct hash_ipport4 *h = set->data;
+       struct hash_ipport4 *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipport4_elem e = { .ip = 0 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to = 0, p = 0, port, port_to, i = 0;
        bool with_ports = false;
        int ret;
 
                        swap(port, port_to);
        }
 
-       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
-               return -ERANGE;
-
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
                p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
                                                       : port;
-               for (; p <= port_to; p++) {
+               for (; p <= port_to; p++, i++) {
                        e.ip = htonl(ip);
                        e.port = htons(p);
+                       if (i > IPSET_MAX_RANGE) {
+                               hash_ipport4_data_next(&h->next, &e);
+                               return -ERANGE;
+                       }
                        ret = adtfn(set, &e, &ext, &ext, flags);
 
                        if (ret && !ip_set_eexist(ret, flags))
 
 hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
-       const struct hash_ipportip4 *h = set->data;
+       struct hash_ipportip4 *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportip4_elem e = { .ip = 0 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to = 0, p = 0, port, port_to, i = 0;
        bool with_ports = false;
        int ret;
 
                        swap(port, port_to);
        }
 
-       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
-               return -ERANGE;
-
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
                p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
                                                       : port;
-               for (; p <= port_to; p++) {
+               for (; p <= port_to; p++, i++) {
                        e.ip = htonl(ip);
                        e.port = htons(p);
+                       if (i > IPSET_MAX_RANGE) {
+                               hash_ipportip4_data_next(&h->next, &e);
+                               return -ERANGE;
+                       }
                        ret = adtfn(set, &e, &ext, &ext, flags);
 
                        if (ret && !ip_set_eexist(ret, flags))
 
 hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
-       const struct hash_ipportnet4 *h = set->data;
+       struct hash_ipportnet4 *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
        u32 ip = 0, ip_to = 0, p = 0, port, port_to;
-       u32 ip2_from = 0, ip2_to = 0, ip2;
+       u32 ip2_from = 0, ip2_to = 0, ip2, i = 0;
        bool with_ports = false;
        u8 cidr;
        int ret;
                        swap(port, port_to);
        }
 
-       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
-               return -ERANGE;
-
        ip2_to = ip2_from;
        if (tb[IPSET_ATTR_IP2_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
                for (; p <= port_to; p++) {
                        e.port = htons(p);
                        do {
+                               i++;
                                e.ip2 = htonl(ip2);
                                ip2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr);
                                e.cidr = cidr - 1;
+                               if (i > IPSET_MAX_RANGE) {
+                                       hash_ipportnet4_data_next(&h->next,
+                                                                 &e);
+                                       return -ERANGE;
+                               }
                                ret = adtfn(set, &e, &ext, &ext, flags);
 
                                if (ret && !ip_set_eexist(ret, flags))
 
 hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
               enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
-       const struct hash_net4 *h = set->data;
+       struct hash_net4 *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_net4_elem e = { .cidr = HOST_MASK };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip = 0, ip_to = 0, ipn, n = 0;
+       u32 ip = 0, ip_to = 0, i = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
                if (ip + UINT_MAX == ip_to)
                        return -IPSET_ERR_HASH_RANGE;
        }
-       ipn = ip;
-       do {
-               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
-               n++;
-       } while (ipn++ < ip_to);
-
-       if (n > IPSET_MAX_RANGE)
-               return -ERANGE;
 
        if (retried)
                ip = ntohl(h->next.ip);
        do {
+               i++;
                e.ip = htonl(ip);
+               if (i > IPSET_MAX_RANGE) {
+                       hash_net4_data_next(&h->next, &e);
+                       return -ERANGE;
+               }
                ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
                ret = adtfn(set, &e, &ext, &ext, flags);
                if (ret && !ip_set_eexist(ret, flags))
 
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip = 0, ip_to = 0, ipn, n = 0;
+       u32 ip = 0, ip_to = 0, i = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
        } else {
                ip_set_mask_from_to(ip, ip_to, e.cidr);
        }
-       ipn = ip;
-       do {
-               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
-               n++;
-       } while (ipn++ < ip_to);
-
-       if (n > IPSET_MAX_RANGE)
-               return -ERANGE;
 
        if (retried)
                ip = ntohl(h->next.ip);
        do {
+               i++;
                e.ip = htonl(ip);
+               if (i > IPSET_MAX_RANGE) {
+                       hash_netiface4_data_next(&h->next, &e);
+                       return -ERANGE;
+               }
                ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
                ret = adtfn(set, &e, &ext, &ext, flags);
 
 
 hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
-       const struct hash_netnet4 *h = set->data;
+       struct hash_netnet4 *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netnet4_elem e = { };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
        u32 ip = 0, ip_to = 0;
-       u32 ip2 = 0, ip2_from = 0, ip2_to = 0, ipn;
-       u64 n = 0, m = 0;
+       u32 ip2 = 0, ip2_from = 0, ip2_to = 0, i = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
        } else {
                ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
        }
-       ipn = ip;
-       do {
-               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]);
-               n++;
-       } while (ipn++ < ip_to);
-       ipn = ip2_from;
-       do {
-               ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]);
-               m++;
-       } while (ipn++ < ip2_to);
-
-       if (n*m > IPSET_MAX_RANGE)
-               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip[0]);
                e.ip[0] = htonl(ip);
                ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
                do {
+                       i++;
                        e.ip[1] = htonl(ip2);
+                       if (i > IPSET_MAX_RANGE) {
+                               hash_netnet4_data_next(&h->next, &e);
+                               return -ERANGE;
+                       }
                        ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
                        ret = adtfn(set, &e, &ext, &ext, flags);
                        if (ret && !ip_set_eexist(ret, flags))
 
 hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
-       const struct hash_netport4 *h = set->data;
+       struct hash_netport4 *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 port, port_to, p = 0, ip = 0, ip_to = 0, ipn;
-       u64 n = 0;
+       u32 port, port_to, p = 0, ip = 0, ip_to = 0, i = 0;
        bool with_ports = false;
        u8 cidr;
        int ret;
        } else {
                ip_set_mask_from_to(ip, ip_to, e.cidr + 1);
        }
-       ipn = ip;
-       do {
-               ipn = ip_set_range_to_cidr(ipn, ip_to, &cidr);
-               n++;
-       } while (ipn++ < ip_to);
-
-       if (n*(port_to - port + 1) > IPSET_MAX_RANGE)
-               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip);
                e.ip = htonl(ip);
                ip = ip_set_range_to_cidr(ip, ip_to, &cidr);
                e.cidr = cidr - 1;
-               for (; p <= port_to; p++) {
+               for (; p <= port_to; p++, i++) {
                        e.port = htons(p);
+                       if (i > IPSET_MAX_RANGE) {
+                               hash_netport4_data_next(&h->next, &e);
+                               return -ERANGE;
+                       }
                        ret = adtfn(set, &e, &ext, &ext, flags);
                        if (ret && !ip_set_eexist(ret, flags))
                                return ret;