static inline int __ipmap_create(const struct ip_set_req_ipmap_create *req, struct ip_set_ipmap *map) { map->netmask = req->netmask; if (req->netmask == 0xFFFFFFFF) { map->hosts = 1; map->sizeid = map->last_ip - map->first_ip + 1; } else { unsigned int mask_bits, netmask_bits; ip_set_ip_t mask; map->first_ip &= map->netmask; /* Should we better bark? */ mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits); netmask_bits = mask_to_bits(map->netmask); if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF)) || netmask_bits <= mask_bits) return -ENOEXEC; DP("mask_bits %u, netmask_bits %u", mask_bits, netmask_bits); map->hosts = 2 << (32 - netmask_bits - 1); map->sizeid = 2 << (netmask_bits - mask_bits - 1); } if (map->sizeid > MAX_RANGE + 1) { ip_set_printk("range too big, %d elements (max %d)", map->sizeid, MAX_RANGE+1); return -ENOEXEC; } DP("hosts %u, sizeid %u", map->hosts, map->sizeid); return bitmap_bytes(0, map->sizeid - 1); }
static int create(struct ip_set *set, const void *data, size_t size) { int newbytes; struct ip_set_req_ipmap_create *req = (struct ip_set_req_ipmap_create *) data; struct ip_set_ipmap *map; if (size != sizeof(struct ip_set_req_ipmap_create)) { ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_ipmap_create), size); return -EINVAL; } DP("from %u.%u.%u.%u to %u.%u.%u.%u", HIPQUAD(req->from), HIPQUAD(req->to)); if (req->from > req->to) { DP("bad ip range"); return -ENOEXEC; } map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL); if (!map) { DP("out of memory for %d bytes", sizeof(struct ip_set_ipmap)); return -ENOMEM; } map->first_ip = req->from; map->last_ip = req->to; map->netmask = req->netmask; if (req->netmask == 0xFFFFFFFF) { map->hosts = 1; map->sizeid = map->last_ip - map->first_ip + 1; } else { unsigned int mask_bits, netmask_bits; ip_set_ip_t mask; map->first_ip &= map->netmask; /* Should we better bark? */ mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits); netmask_bits = mask_to_bits(map->netmask); if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF)) || netmask_bits <= mask_bits) return -ENOEXEC; DP("mask_bits %u, netmask_bits %u", mask_bits, netmask_bits); map->hosts = 2 << (32 - netmask_bits - 1); map->sizeid = 2 << (netmask_bits - mask_bits - 1); } if (map->sizeid > MAX_RANGE + 1) { ip_set_printk("range too big (max %d addresses)", MAX_RANGE+1); kfree(map); return -ENOEXEC; } DP("hosts %u, sizeid %u", map->hosts, map->sizeid); newbytes = bitmap_bytes(0, map->sizeid - 1); map->members = kmalloc(newbytes, GFP_KERNEL); if (!map->members) { DP("out of memory for %d bytes", newbytes); kfree(map); return -ENOMEM; } memset(map->members, 0, newbytes); set->data = map; return 0; }