X-Git-Url: http://git.onelab.eu/?p=linux-2.6.git;a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fip_set_nethash.c;h=8d5e9f64eb75d8188d3444f539bb56c772086064;hp=b78988f39f408f4b3ef26b6c121641966a559d70;hb=bd5a19dd4af64aaf2a1cc38033a2bd21a093a497;hpb=a030541d6dd71712d1989c26d9e63a698c64d5d8 diff --git a/net/ipv4/netfilter/ip_set_nethash.c b/net/ipv4/netfilter/ip_set_nethash.c index b78988f39..8d5e9f64e 100644 --- a/net/ipv4/netfilter/ip_set_nethash.c +++ b/net/ipv4/netfilter/ip_set_nethash.c @@ -25,6 +25,8 @@ #include #include +static int limit = MAX_RANGE; + static inline __u32 jhash_ip(const struct ip_set_nethash *map, uint16_t i, ip_set_ip_t ip) { @@ -74,13 +76,13 @@ __testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr, { struct ip_set_nethash *map = (struct ip_set_nethash *) set->data; - return (hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX); + return (ip && hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX); } static inline int __testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip) { - return (hash_id(set, ip, hash_ip) != UINT_MAX); + return (ip && hash_id(set, ip, hash_ip) != UINT_MAX); } static int @@ -128,6 +130,7 @@ __addip_base(struct ip_set_nethash *map, ip_set_ip_t ip) return -EEXIST; if (!*elem) { *elem = ip; + map->elements++; return 0; } } @@ -139,6 +142,9 @@ static inline int __addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr, ip_set_ip_t *hash_ip) { + if (!ip || map->elements > limit) + return -ERANGE; + *hash_ip = pack(ip, cidr); DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip)); @@ -246,6 +252,7 @@ static int retry(struct ip_set *set) return -ENOMEM; } tmp->hashsize = hashsize; + tmp->elements = 0; tmp->probes = map->probes; tmp->resize = map->resize; memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t)); @@ -283,14 +290,18 @@ static inline int __delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr, ip_set_ip_t *hash_ip) { - ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip); - ip_set_ip_t *elem; + ip_set_ip_t id, *elem; + if (!ip) + return -ERANGE; + + id = hash_id_cidr(map, ip, cidr, hash_ip); if (id == UINT_MAX) return -EEXIST; elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); *elem = 0; + map->elements--; return 0; } @@ -364,6 +375,7 @@ static int create(struct ip_set *set, const void *data, size_t size) } for (i = 0; i < req->probes; i++) get_random_bytes(((uint32_t *) map->initval)+i, 4); + map->elements = 0; map->hashsize = req->hashsize; map->probes = req->probes; map->resize = req->resize; @@ -394,6 +406,7 @@ static void flush(struct ip_set *set) struct ip_set_nethash *map = (struct ip_set_nethash *) set->data; harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t)); memset(map->cidr, 0, 30 * sizeof(unsigned char)); + map->elements = 0; } static void list_header(const struct ip_set *set, void *data) @@ -450,6 +463,8 @@ static struct ip_set_type ip_set_nethash = { MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); MODULE_DESCRIPTION("nethash type of IP sets"); +module_param(limit, int, 0600); +MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); static int __init init(void) {