static inline int bitmap_ipmac_exist(const struct ipmac_telem *elem) { return elem->match == MAC_UNSET || (elem->match == MAC_FILLED && !ip_set_timeout_expired(elem->timeout)); }
static inline bool list_set_expired(const struct list_set *map, u32 id) { const struct set_telem *elem = list_set_telem(map, id); return ip_set_timeout_expired(elem->timeout); }
static inline bool bitmap_expired(const struct bitmap_ipmac *map, u32 id) { const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id); return ip_set_timeout_expired(elem->timeout); }
static int list_set_udel(struct ip_set *set, void *value, const struct ip_set_ext *ext, struct ip_set_ext *mext, u32 flags) { struct list_set *map = set->data; struct set_adt_elem *d = value; struct set_elem *e; u32 i; for (i = 0; i < map->size; i++) { e = list_set_elem(set, map, i); if (e->id == IPSET_INVALID_ID) return d->before != 0 ? -IPSET_ERR_REF_EXIST : -IPSET_ERR_EXIST; else if (SET_WITH_TIMEOUT(set) && ip_set_timeout_expired(ext_timeout(e, set))) continue; else if (e->id != d->id) continue; if (d->before == 0) return list_set_del(set, i); else if (d->before > 0) { if (!id_eq(set, i + 1, d->refid)) return -IPSET_ERR_REF_EXIST; return list_set_del(set, i); } else if (i == 0 || !id_eq(set, i - 1, d->refid)) return -IPSET_ERR_REF_EXIST; else return list_set_del(set, i); } return -IPSET_ERR_EXIST; }
static int list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext, struct ip_set_ext *mext, u32 flags) { struct list_set *map = set->data; struct set_adt_elem *d = value; struct set_elem *e; u32 i; int ret; for (i = 0; i < map->size; i++) { e = list_set_elem(set, map, i); if (e->id == IPSET_INVALID_ID) return 0; else if (SET_WITH_TIMEOUT(set) && ip_set_timeout_expired(ext_timeout(e, set))) continue; else if (e->id != d->id) continue; if (d->before == 0) return 1; else if (d->before > 0) ret = id_eq(set, i + 1, d->refid); else ret = i > 0 && id_eq(set, i - 1, d->refid); return ret; } return 0; }
static int list_set_ktest(struct ip_set *set, const struct sk_buff *skb, const struct xt_action_param *par, struct ip_set_adt_opt *opt, const struct ip_set_ext *ext) { struct list_set *map = set->data; struct set_elem *e; u32 i, cmdflags = opt->cmdflags; int ret; /* Don't lookup sub-counters at all */ opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS; if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE) opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE; for (i = 0; i < map->size; i++) { e = list_set_elem(set, map, i); if (e->id == IPSET_INVALID_ID) return 0; if (SET_WITH_TIMEOUT(set) && ip_set_timeout_expired(ext_timeout(e, set))) continue; ret = ip_set_test(e->id, skb, par, opt); if (ret > 0) { if (SET_WITH_COUNTER(set)) ip_set_update_counter(ext_counter(e, set), ext, &opt->ext, cmdflags); return ret; } } return 0; }
static int list_set_list(const struct ip_set *set, struct sk_buff *skb, struct netlink_callback *cb) { const struct list_set *map = set->data; struct nlattr *atd, *nested; u32 i, first = cb->args[IPSET_CB_ARG0]; const struct set_elem *e; atd = ipset_nest_start(skb, IPSET_ATTR_ADT); if (!atd) return -EMSGSIZE; for (; cb->args[IPSET_CB_ARG0] < map->size; cb->args[IPSET_CB_ARG0]++) { i = cb->args[IPSET_CB_ARG0]; e = list_set_elem(set, map, i); if (e->id == IPSET_INVALID_ID) goto finish; if (SET_WITH_TIMEOUT(set) && ip_set_timeout_expired(ext_timeout(e, set))) continue; nested = ipset_nest_start(skb, IPSET_ATTR_DATA); if (!nested) { if (i == first) { nla_nest_cancel(skb, atd); return -EMSGSIZE; } else goto nla_put_failure; } if (nla_put_string(skb, IPSET_ATTR_NAME, ip_set_name_byindex(map->net, e->id))) goto nla_put_failure; if (ip_set_put_extensions(skb, set, e, true)) goto nla_put_failure; ipset_nest_end(skb, nested); } finish: ipset_nest_end(skb, atd); /* Set listing finished */ cb->args[IPSET_CB_ARG0] = 0; return 0; nla_put_failure: nla_nest_cancel(skb, nested); if (unlikely(i == first)) { cb->args[IPSET_CB_ARG0] = 0; return -EMSGSIZE; } ipset_nest_end(skb, atd); return 0; }
static bool id_eq(const struct ip_set *set, u32 i, ip_set_id_t id) { const struct list_set *map = set->data; const struct set_elem *e; if (i >= map->size) return 0; e = list_set_elem(set, map, i); return !!(e->id == id && !(SET_WITH_TIMEOUT(set) && ip_set_timeout_expired(ext_timeout(e, set)))); }
static void set_cleanup_entries(struct ip_set *set) { struct list_set *map = set->data; struct set_elem *e; u32 i = 0; while (i < map->size) { e = list_set_elem(set, map, i); if (e->id != IPSET_INVALID_ID && ip_set_timeout_expired(ext_timeout(e, set))) list_set_del(set, i); /* Check element moved to position i in next loop */ else i++; } }
static void bitmap_ip_gc(unsigned long ul_set) { struct ip_set *set = (struct ip_set *) ul_set; struct bitmap_ip *map = set->data; unsigned long *table = map->members; u32 id; /* We run parallel with other readers (test element) * but adding/deleting new entries is locked out */ read_lock_bh(&set->lock); for (id = 0; id < map->elements; id++) if (ip_set_timeout_expired(table[id])) table[id] = IPSET_ELEM_UNSET; read_unlock_bh(&set->lock); map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; add_timer(&map->gc); }
static void bitmap_ipmac_gc(unsigned long ul_set) { struct ip_set *set = (struct ip_set *) ul_set; struct bitmap_ipmac *map = set->data; struct ipmac_telem *elem; u32 id, last = map->last_ip - map->first_ip; /* We run parallel with other readers (test element) * but adding/deleting new entries is locked out */ read_lock_bh(&set->lock); for (id = 0; id <= last; id++) { elem = bitmap_ipmac_elem(map, id); if (elem->match == MAC_FILLED && ip_set_timeout_expired(elem->timeout)) elem->match = MAC_EMPTY; } read_unlock_bh(&set->lock); map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; add_timer(&map->gc); }
static int list_set_kadd(struct ip_set *set, const struct sk_buff *skb, const struct xt_action_param *par, struct ip_set_adt_opt *opt, const struct ip_set_ext *ext) { struct list_set *map = set->data; struct set_elem *e; u32 i; int ret; for (i = 0; i < map->size; i++) { e = list_set_elem(set, map, i); if (e->id == IPSET_INVALID_ID) return 0; if (SET_WITH_TIMEOUT(set) && ip_set_timeout_expired(ext_timeout(e, set))) continue; ret = ip_set_add(e->id, skb, par, opt); if (ret == 0) return ret; } return 0; }