17d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik/* Copyright (C) 2008-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik * 3f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik * This program is free software; you can redistribute it and/or modify 4f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik * it under the terms of the GNU General Public License version 2 as 5f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik * published by the Free Software Foundation. 6f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik */ 7f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 8f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik/* Kernel module implementing an IP set type: the list:set type */ 9f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 10f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik#include <linux/module.h> 11f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik#include <linux/ip.h> 12f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik#include <linux/skbuff.h> 13f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik#include <linux/errno.h> 14f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 15f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik#include <linux/netfilter/ipset/ip_set.h> 16f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik#include <linux/netfilter/ipset/ip_set_list.h> 17f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 1835b8dcf8c3a0be1feb1c8b29b22e1685ba0c2e14Jozsef Kadlecsik#define IPSET_TYPE_REV_MIN 0 1981b10bb4bd16ea975c007f9bb2c2676cef6ade10Oliver Smith/* 1 Counters support added */ 20cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov/* 2 Comments support added */ 21cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov#define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */ 2210111a6ef373c377e87730749a0f68210c3fd062Jozsef Kadlecsik 23f830837f0eed0f9e371b8fd65169365780814bb1Jozsef KadlecsikMODULE_LICENSE("GPL"); 24f830837f0eed0f9e371b8fd65169365780814bb1Jozsef KadlecsikMODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 2535b8dcf8c3a0be1feb1c8b29b22e1685ba0c2e14Jozsef KadlecsikIP_SET_MODULE_DESC("list:set", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); 26f830837f0eed0f9e371b8fd65169365780814bb1Jozsef KadlecsikMODULE_ALIAS("ip_set_list:set"); 27f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 287d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik/* Member elements */ 29f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstruct set_elem { 30f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik ip_set_id_t id; 31f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik}; 32f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 337d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikstruct set_adt_elem { 347d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ip_set_id_t id; 357d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ip_set_id_t refid; 367d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik int before; 377d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik}; 387d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 39f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik/* Type structure */ 40f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstruct list_set { 41f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik u32 size; /* size of set list array */ 42f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct timer_list gc; /* garbage collection */ 431785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov struct net *net; /* namespace */ 44f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct set_elem members[0]; /* the set members */ 45f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik}; 46f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 47ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik#define list_set_elem(set, map, id) \ 48ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik (struct set_elem *)((void *)(map)->members + (id) * (set)->dsize) 49f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 507d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikstatic int 517d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_ktest(struct ip_set *set, const struct sk_buff *skb, 527d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik const struct xt_action_param *par, 537d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct ip_set_adt_opt *opt, const struct ip_set_ext *ext) 54f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 557d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct list_set *map = set->data; 567d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_elem *e; 576e01781d1c80e2e8263471252a631e86165b15c5Jozsef Kadlecsik u32 i, cmdflags = opt->cmdflags; 587d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik int ret; 59f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 606e01781d1c80e2e8263471252a631e86165b15c5Jozsef Kadlecsik /* Don't lookup sub-counters at all */ 616e01781d1c80e2e8263471252a631e86165b15c5Jozsef Kadlecsik opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS; 626e01781d1c80e2e8263471252a631e86165b15c5Jozsef Kadlecsik if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE) 636e01781d1c80e2e8263471252a631e86165b15c5Jozsef Kadlecsik opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE; 647d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik for (i = 0; i < map->size; i++) { 65ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 667d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e->id == IPSET_INVALID_ID) 677d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 0; 687d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (SET_WITH_TIMEOUT(set) && 69ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_expired(ext_timeout(e, set))) 707d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik continue; 717d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = ip_set_test(e->id, skb, par, opt); 72de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik if (ret > 0) { 73de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik if (SET_WITH_COUNTER(set)) 74ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_update_counter(ext_counter(e, set), 75de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik ext, &opt->ext, 766e01781d1c80e2e8263471252a631e86165b15c5Jozsef Kadlecsik cmdflags); 77cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov if (SET_WITH_SKBINFO(set)) 78cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov ip_set_get_skbinfo(ext_skbinfo(e, set), 79cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov ext, &opt->ext, 80cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov cmdflags); 817d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return ret; 82de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik } 837d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik } 847d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 0; 85f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 86f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 877d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikstatic int 887d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_kadd(struct ip_set *set, const struct sk_buff *skb, 897d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik const struct xt_action_param *par, 907d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct ip_set_adt_opt *opt, const struct ip_set_ext *ext) 91f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 927d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct list_set *map = set->data; 937d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_elem *e; 947d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik u32 i; 957d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik int ret; 96f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 977d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik for (i = 0; i < map->size; i++) { 98ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 997d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e->id == IPSET_INVALID_ID) 1007d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 0; 1017d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (SET_WITH_TIMEOUT(set) && 102ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_expired(ext_timeout(e, set))) 1037d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik continue; 1047d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = ip_set_add(e->id, skb, par, opt); 1057d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (ret == 0) 1067d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return ret; 1077d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik } 1087d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 0; 109f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 110f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 111f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic int 1127d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_kdel(struct ip_set *set, const struct sk_buff *skb, 113b66554cf03fe866b3fb7b9f40f430b8ba09f41c8Jozsef Kadlecsik const struct xt_action_param *par, 1147d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct ip_set_adt_opt *opt, const struct ip_set_ext *ext) 115f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 116f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct list_set *map = set->data; 1177d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_elem *e; 118f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik u32 i; 119f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik int ret; 120f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 121f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik for (i = 0; i < map->size; i++) { 122ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 1237d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e->id == IPSET_INVALID_ID) 124f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return 0; 1257d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (SET_WITH_TIMEOUT(set) && 126ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_expired(ext_timeout(e, set))) 127f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik continue; 1287d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = ip_set_del(e->id, skb, par, opt); 1297d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (ret == 0) 1307d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return ret; 1317d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik } 1327d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 0; 1337d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik} 1347d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 1357d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikstatic int 1367d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_kadt(struct ip_set *set, const struct sk_buff *skb, 1377d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik const struct xt_action_param *par, 1387d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik enum ipset_adt adt, struct ip_set_adt_opt *opt) 1397d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik{ 140ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 1417d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 1427d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik switch (adt) { 1437d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik case IPSET_TEST: 1447d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return list_set_ktest(set, skb, par, opt, &ext); 1457d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik case IPSET_ADD: 1467d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return list_set_kadd(set, skb, par, opt, &ext); 1477d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik case IPSET_DEL: 1487d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return list_set_kdel(set, skb, par, opt, &ext); 1497d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik default: 1507d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik break; 151f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 152f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return -EINVAL; 153f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 154f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 155f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic bool 1567d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikid_eq(const struct ip_set *set, u32 i, ip_set_id_t id) 157f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 1587d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik const struct list_set *map = set->data; 1597d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik const struct set_elem *e; 1607d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 1617d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (i >= map->size) 1627d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 0; 163f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 164ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 1657d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return !!(e->id == id && 1667d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik !(SET_WITH_TIMEOUT(set) && 167ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_expired(ext_timeout(e, set)))); 1687d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik} 1697d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 1707d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikstatic int 1717d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_add(struct ip_set *set, u32 i, struct set_adt_elem *d, 1727d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik const struct ip_set_ext *ext) 1737d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik{ 1747d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct list_set *map = set->data; 175ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik struct set_elem *e = list_set_elem(set, map, i); 1767d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 1777d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e->id != IPSET_INVALID_ID) { 17840cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik if (i == map->size - 1) { 1797d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik /* Last element replaced: e.g. add new,before,last */ 1801785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov ip_set_put_byindex(map->net, e->id); 18140cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik ip_set_ext_destroy(set, e); 18240cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik } else { 183ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik struct set_elem *x = list_set_elem(set, map, 184ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik map->size - 1); 1857d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 1867d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik /* Last element pushed off */ 18740cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik if (x->id != IPSET_INVALID_ID) { 1881785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov ip_set_put_byindex(map->net, x->id); 18940cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik ip_set_ext_destroy(set, x); 19040cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik } 191ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik memmove(list_set_elem(set, map, i + 1), e, 192ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik set->dsize * (map->size - (i + 1))); 1938ec81f9a4db94fa5638c55793365b896dd9daeccJozsef Kadlecsik /* Extensions must be initialized to zero */ 1948ec81f9a4db94fa5638c55793365b896dd9daeccJozsef Kadlecsik memset(e, 0, set->dsize); 1957d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik } 1965416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik } 1975416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik 1987d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik e->id = d->id; 1997d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (SET_WITH_TIMEOUT(set)) 200ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_set(ext_timeout(e, set), ext->timeout); 201de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik if (SET_WITH_COUNTER(set)) 202ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_init_counter(ext_counter(e, set), ext); 2038ec81f9a4db94fa5638c55793365b896dd9daeccJozsef Kadlecsik if (SET_WITH_COMMENT(set)) 20481b10bb4bd16ea975c007f9bb2c2676cef6ade10Oliver Smith ip_set_init_comment(ext_comment(e, set), ext); 205cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov if (SET_WITH_SKBINFO(set)) 206cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov ip_set_init_skbinfo(ext_skbinfo(e, set), ext); 2075416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik return 0; 2085416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik} 2095416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik 2107d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikstatic int 2117d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_del(struct ip_set *set, u32 i) 2125416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik{ 2137d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct list_set *map = set->data; 214ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik struct set_elem *e = list_set_elem(set, map, i); 2155416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik 2161785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov ip_set_put_byindex(map->net, e->id); 21740cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik ip_set_ext_destroy(set, e); 218f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 2197d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (i < map->size - 1) 220ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik memmove(e, list_set_elem(set, map, i + 1), 221ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik set->dsize * (map->size - (i + 1))); 2227d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 2237d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik /* Last element */ 224ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, map->size - 1); 2257d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik e->id = IPSET_INVALID_ID; 226f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return 0; 227f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 228f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 229f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic void 2307d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikset_cleanup_entries(struct ip_set *set) 231f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 2327d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct list_set *map = set->data; 233f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct set_elem *e; 234b91b396d5e35eef9938a56e781cb0171a53907caJozsef Kadlecsik u32 i = 0; 235f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 236b91b396d5e35eef9938a56e781cb0171a53907caJozsef Kadlecsik while (i < map->size) { 237ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 2387d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e->id != IPSET_INVALID_ID && 239ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_expired(ext_timeout(e, set))) 2407d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik list_set_del(set, i); 241b91b396d5e35eef9938a56e781cb0171a53907caJozsef Kadlecsik /* Check element moved to position i in next loop */ 242b91b396d5e35eef9938a56e781cb0171a53907caJozsef Kadlecsik else 243b91b396d5e35eef9938a56e781cb0171a53907caJozsef Kadlecsik i++; 244f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 245f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 246f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 2477d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikstatic int 2487d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext, 2497d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct ip_set_ext *mext, u32 flags) 250f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 2517d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct list_set *map = set->data; 2527d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_adt_elem *d = value; 2537d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_elem *e; 2547d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik u32 i; 2557d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik int ret; 256f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 2577d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik for (i = 0; i < map->size; i++) { 258ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 259f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (e->id == IPSET_INVALID_ID) 2607d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 0; 2617d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (SET_WITH_TIMEOUT(set) && 262ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_expired(ext_timeout(e, set))) 2637d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik continue; 2647d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (e->id != d->id) 2657d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik continue; 2667d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 2677d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (d->before == 0) 2687d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 1; 2697d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (d->before > 0) 2707d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = id_eq(set, i + 1, d->refid); 2717d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else 2727d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = i > 0 && id_eq(set, i - 1, d->refid); 2737d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return ret; 274f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 2757d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 0; 276f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 277f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 2787d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 279f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic int 2807d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext, 2817d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct ip_set_ext *mext, u32 flags) 282f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 2837d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct list_set *map = set->data; 2847d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_adt_elem *d = value; 2857d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_elem *e; 2867d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik bool flag_exist = flags & IPSET_FLAG_EXIST; 2877d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik u32 i, ret = 0; 288f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 28940cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik if (SET_WITH_TIMEOUT(set)) 29040cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik set_cleanup_entries(set); 29140cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik 2927d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik /* Check already added element */ 2937d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik for (i = 0; i < map->size; i++) { 294ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 2957d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e->id == IPSET_INVALID_ID) 2967d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik goto insert; 2977d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (e->id != d->id) 2987d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik continue; 29902f815cb6d3f57914228be84df9613ee5a01c2e6Jozsef Kadlecsik 3007d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if ((d->before > 1 && !id_eq(set, i + 1, d->refid)) || 3017d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik (d->before < 0 && 3027d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik (i == 0 || !id_eq(set, i - 1, d->refid)))) 3037d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik /* Before/after doesn't match */ 3047d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return -IPSET_ERR_REF_EXIST; 3057d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (!flag_exist) 3067d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik /* Can't re-add */ 3077d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return -IPSET_ERR_EXIST; 3087d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik /* Update extensions */ 30940cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik ip_set_ext_destroy(set, e); 31040cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik 3117d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (SET_WITH_TIMEOUT(set)) 312ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_set(ext_timeout(e, set), ext->timeout); 313de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik if (SET_WITH_COUNTER(set)) 314ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_init_counter(ext_counter(e, set), ext); 31581b10bb4bd16ea975c007f9bb2c2676cef6ade10Oliver Smith if (SET_WITH_COMMENT(set)) 31681b10bb4bd16ea975c007f9bb2c2676cef6ade10Oliver Smith ip_set_init_comment(ext_comment(e, set), ext); 317cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov if (SET_WITH_SKBINFO(set)) 318cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov ip_set_init_skbinfo(ext_skbinfo(e, set), ext); 3197d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik /* Set is already added to the list */ 3201785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov ip_set_put_byindex(map->net, d->id); 3217d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return 0; 3227d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik } 3237d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikinsert: 3247d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = -IPSET_ERR_LIST_FULL; 3257d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) { 326ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 3277d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e->id == IPSET_INVALID_ID) 3287d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = d->before != 0 ? -IPSET_ERR_REF_EXIST 3297d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik : list_set_add(set, i, d, ext); 3307d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (e->id != d->refid) 3317d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik continue; 3327d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (d->before > 0) 3337d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = list_set_add(set, i, d, ext); 3347d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (i + 1 < map->size) 3357d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = list_set_add(set, i + 1, d, ext); 33602f815cb6d3f57914228be84df9613ee5a01c2e6Jozsef Kadlecsik } 337f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 3387d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return ret; 339f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 340f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 341f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic int 3427d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_udel(struct ip_set *set, void *value, const struct ip_set_ext *ext, 3437d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct ip_set_ext *mext, u32 flags) 344f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 3457d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct list_set *map = set->data; 3467d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_adt_elem *d = value; 3477d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_elem *e; 3485416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik u32 i; 3495416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik 3505416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik for (i = 0; i < map->size; i++) { 351ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 3527d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e->id == IPSET_INVALID_ID) 3537d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return d->before != 0 ? -IPSET_ERR_REF_EXIST 3547d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik : -IPSET_ERR_EXIST; 3557d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (SET_WITH_TIMEOUT(set) && 356ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_expired(ext_timeout(e, set))) 3577d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik continue; 3587d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (e->id != d->id) 3597d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik continue; 3607d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik 3617d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (d->before == 0) 3627d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return list_set_del(set, i); 3637d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else if (d->before > 0) { 3647d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (!id_eq(set, i + 1, d->refid)) 3657d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return -IPSET_ERR_REF_EXIST; 3667d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return list_set_del(set, i); 3677d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik } else if (i == 0 || !id_eq(set, i - 1, d->refid)) 3687d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return -IPSET_ERR_REF_EXIST; 3697d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik else 3707d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return list_set_del(set, i); 3715416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik } 3727d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return -IPSET_ERR_EXIST; 3735416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik} 3745416219e5ca4504ea80d662fdda7337e52e86ee5Jozsef Kadlecsik 375f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic int 376f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiklist_set_uadt(struct ip_set *set, struct nlattr *tb[], 3773d14b171f004f75c2d1e82e10545966f94132705Jozsef Kadlecsik enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 378f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 3791785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov struct list_set *map = set->data; 3807d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ipset_adtfn adtfn = set->variant->adt[adt]; 3817d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_adt_elem e = { .refid = IPSET_INVALID_ID }; 382ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 383f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct ip_set *s; 384f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik int ret = 0; 385f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 386f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (unlikely(!tb[IPSET_ATTR_NAME] || 387f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 388de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 389de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 390cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 391cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) || 392cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) || 393cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE))) 394f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return -IPSET_ERR_PROTOCOL; 395f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 396f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (tb[IPSET_ATTR_LINENO]) 397f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 398f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 3997d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = ip_set_get_extensions(set, tb, &ext); 4007d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (ret) 4017d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik return ret; 4021785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov e.id = ip_set_get_byname(map->net, nla_data(tb[IPSET_ATTR_NAME]), &s); 4037d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e.id == IPSET_INVALID_ID) 404f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return -IPSET_ERR_NAME; 405f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik /* "Loop detection" */ 406f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (s->type->features & IPSET_TYPE_NAME) { 407f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik ret = -IPSET_ERR_LOOP; 408f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik goto finish; 409f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 410f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 411f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (tb[IPSET_ATTR_CADT_FLAGS]) { 412f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 4137d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik e.before = f & IPSET_FLAG_BEFORE; 414f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 415f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 4167d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e.before && !tb[IPSET_ATTR_NAMEREF]) { 417f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik ret = -IPSET_ERR_BEFORE; 418f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik goto finish; 419f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 420f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 421f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (tb[IPSET_ATTR_NAMEREF]) { 4221785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov e.refid = ip_set_get_byname(map->net, 4231785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov nla_data(tb[IPSET_ATTR_NAMEREF]), 4247d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik &s); 4257d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e.refid == IPSET_INVALID_ID) { 426f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik ret = -IPSET_ERR_NAMEREF; 427f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik goto finish; 428f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 4297d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (!e.before) 4307d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik e.before = -1; 431f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 4327d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (adt != IPSET_TEST && SET_WITH_TIMEOUT(set)) 4337d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik set_cleanup_entries(set); 434f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 4357d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik ret = adtfn(set, &e, &ext, &ext, flags); 436f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 437f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikfinish: 4387d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e.refid != IPSET_INVALID_ID) 4391785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov ip_set_put_byindex(map->net, e.refid); 440f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (adt != IPSET_ADD || ret) 4411785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov ip_set_put_byindex(map->net, e.id); 442f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 443f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return ip_set_eexist(ret, flags) ? 0 : ret; 444f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 445f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 446f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic void 447f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiklist_set_flush(struct ip_set *set) 448f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 449f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct list_set *map = set->data; 4507d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik struct set_elem *e; 451f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik u32 i; 452f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 453f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik for (i = 0; i < map->size; i++) { 454ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 4557d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (e->id != IPSET_INVALID_ID) { 4561785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov ip_set_put_byindex(map->net, e->id); 45740cd63bf33b21ef4d43776b1d49c605f876fe32cJozsef Kadlecsik ip_set_ext_destroy(set, e); 4587d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik e->id = IPSET_INVALID_ID; 459f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 460f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 461f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 462f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 463f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic void 464f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiklist_set_destroy(struct ip_set *set) 465f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 466f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct list_set *map = set->data; 467f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 4687d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (SET_WITH_TIMEOUT(set)) 469f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik del_timer_sync(&map->gc); 470f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik list_set_flush(set); 471f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik kfree(map); 472f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 473f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik set->data = NULL; 474f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 475f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 476f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic int 477f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiklist_set_head(struct ip_set *set, struct sk_buff *skb) 478f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 479f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik const struct list_set *map = set->data; 480f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct nlattr *nested; 481f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 482f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 483f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (!nested) 484f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik goto nla_put_failure; 4857cf7899d9ee31c88c86ea8459fc4db4bd11cc240David S. Miller if (nla_put_net32(skb, IPSET_ATTR_SIZE, htonl(map->size)) || 4867cf7899d9ee31c88c86ea8459fc4db4bd11cc240David S. Miller nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || 4877cf7899d9ee31c88c86ea8459fc4db4bd11cc240David S. Miller nla_put_net32(skb, IPSET_ATTR_MEMSIZE, 488ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik htonl(sizeof(*map) + map->size * set->dsize))) 4897cf7899d9ee31c88c86ea8459fc4db4bd11cc240David S. Miller goto nla_put_failure; 49081b10bb4bd16ea975c007f9bb2c2676cef6ade10Oliver Smith if (unlikely(ip_set_put_flags(skb, set))) 49181b10bb4bd16ea975c007f9bb2c2676cef6ade10Oliver Smith goto nla_put_failure; 492f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik ipset_nest_end(skb, nested); 493f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 494f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return 0; 495f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiknla_put_failure: 496f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return -EMSGSIZE; 497f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 498f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 499f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic int 500f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiklist_set_list(const struct ip_set *set, 501f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct sk_buff *skb, struct netlink_callback *cb) 502f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 503f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik const struct list_set *map = set->data; 504f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct nlattr *atd, *nested; 50593302880d8a3e5dc6b7da3f9825beb839152c940Jozsef Kadlecsik u32 i, first = cb->args[IPSET_CB_ARG0]; 506f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik const struct set_elem *e; 507f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 508f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik atd = ipset_nest_start(skb, IPSET_ATTR_ADT); 509f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (!atd) 510f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return -EMSGSIZE; 51193302880d8a3e5dc6b7da3f9825beb839152c940Jozsef Kadlecsik for (; cb->args[IPSET_CB_ARG0] < map->size; 51293302880d8a3e5dc6b7da3f9825beb839152c940Jozsef Kadlecsik cb->args[IPSET_CB_ARG0]++) { 51393302880d8a3e5dc6b7da3f9825beb839152c940Jozsef Kadlecsik i = cb->args[IPSET_CB_ARG0]; 514ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 515f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (e->id == IPSET_INVALID_ID) 516f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik goto finish; 5177d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik if (SET_WITH_TIMEOUT(set) && 518ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik ip_set_timeout_expired(ext_timeout(e, set))) 519f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik continue; 520f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 521f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (!nested) { 522f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (i == first) { 523f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik nla_nest_cancel(skb, atd); 524f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return -EMSGSIZE; 525f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } else 526f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik goto nla_put_failure; 527f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 5287cf7899d9ee31c88c86ea8459fc4db4bd11cc240David S. Miller if (nla_put_string(skb, IPSET_ATTR_NAME, 5291785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov ip_set_name_byindex(map->net, e->id))) 5307cf7899d9ee31c88c86ea8459fc4db4bd11cc240David S. Miller goto nla_put_failure; 5313fd986b3d99e3847f1cce6fc36043d0f16508e1dJozsef Kadlecsik if (ip_set_put_extensions(skb, set, e, true)) 53281b10bb4bd16ea975c007f9bb2c2676cef6ade10Oliver Smith goto nla_put_failure; 533f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik ipset_nest_end(skb, nested); 534f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 535f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikfinish: 536f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik ipset_nest_end(skb, atd); 537f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik /* Set listing finished */ 53893302880d8a3e5dc6b7da3f9825beb839152c940Jozsef Kadlecsik cb->args[IPSET_CB_ARG0] = 0; 539f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return 0; 540f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 541f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiknla_put_failure: 542f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik nla_nest_cancel(skb, nested); 543f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (unlikely(i == first)) { 54493302880d8a3e5dc6b7da3f9825beb839152c940Jozsef Kadlecsik cb->args[IPSET_CB_ARG0] = 0; 545f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return -EMSGSIZE; 546f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 547122ebbf24c33ac13a9243248c9b8da0fa4c012bdJozsef Kadlecsik ipset_nest_end(skb, atd); 548f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return 0; 549f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 550f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 551f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic bool 552f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiklist_set_same_set(const struct ip_set *a, const struct ip_set *b) 553f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 554f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik const struct list_set *x = a->data; 555f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik const struct list_set *y = b->data; 556f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 557f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return x->size == y->size && 558ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik a->timeout == b->timeout && 5597d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik a->extensions == b->extensions; 560f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 561f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 5627d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsikstatic const struct ip_set_type_variant set_variant = { 563f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .kadt = list_set_kadt, 564f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .uadt = list_set_uadt, 5657d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik .adt = { 5667d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik [IPSET_ADD] = list_set_uadd, 5677d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik [IPSET_DEL] = list_set_udel, 5687d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik [IPSET_TEST] = list_set_utest, 5697d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik }, 570f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .destroy = list_set_destroy, 571f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .flush = list_set_flush, 572f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .head = list_set_head, 573f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .list = list_set_list, 574f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .same_set = list_set_same_set, 575f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik}; 576f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 577f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic void 578f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiklist_set_gc(unsigned long ul_set) 579f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 580f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct ip_set *set = (struct ip_set *) ul_set; 581f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct list_set *map = set->data; 5822f9f28b212a2bd4948c8ceaaec33ce0123632129Jozsef Kadlecsik 583512d06b5b64fb422d90f199b1be188082729edf9Jozsef Kadlecsik write_lock_bh(&set->lock); 5847d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik set_cleanup_entries(set); 585512d06b5b64fb422d90f199b1be188082729edf9Jozsef Kadlecsik write_unlock_bh(&set->lock); 586f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 587ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik map->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ; 588f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik add_timer(&map->gc); 589f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 590f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 591f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic void 5927d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsiklist_set_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set)) 593f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 594f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct list_set *map = set->data; 595f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 596f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik init_timer(&map->gc); 597f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik map->gc.data = (unsigned long) set; 5987d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik map->gc.function = gc; 599ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik map->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ; 600f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik add_timer(&map->gc); 601f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 602f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 603f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik/* Create list:set type of sets */ 604f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 60503c8b234e61a9a3aab8d970b3bf681934ecfe443Jozsef Kadlecsikstatic bool 6061785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrovinit_list_set(struct net *net, struct ip_set *set, u32 size) 607f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 608f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct list_set *map; 609f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik struct set_elem *e; 610f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik u32 i; 611f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 6121b05756c48ea07ced9604ef01d11194d936da163Jozsef Kadlecsik map = kzalloc(sizeof(*map) + 6131b05756c48ea07ced9604ef01d11194d936da163Jozsef Kadlecsik min_t(u32, size, IP_SET_LIST_MAX_SIZE) * set->dsize, 6141b05756c48ea07ced9604ef01d11194d936da163Jozsef Kadlecsik GFP_KERNEL); 615f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (!map) 61603c8b234e61a9a3aab8d970b3bf681934ecfe443Jozsef Kadlecsik return false; 617f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 618f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik map->size = size; 6191785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov map->net = net; 620f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik set->data = map; 621f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 622f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik for (i = 0; i < size; i++) { 623ca134ce86451f3f5ac45ffbf1494a1f42110bf93Jozsef Kadlecsik e = list_set_elem(set, map, i); 624f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik e->id = IPSET_INVALID_ID; 625f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 626f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 62703c8b234e61a9a3aab8d970b3bf681934ecfe443Jozsef Kadlecsik return true; 628f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 629f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 630f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic int 6311785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrovlist_set_create(struct net *net, struct ip_set *set, struct nlattr *tb[], 6321785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov u32 flags) 633f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 63403c8b234e61a9a3aab8d970b3bf681934ecfe443Jozsef Kadlecsik u32 size = IP_SET_LIST_DEFAULT_SIZE; 635f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 636f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) || 637de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 638de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 639f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return -IPSET_ERR_PROTOCOL; 640f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 641f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (tb[IPSET_ATTR_SIZE]) 642f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]); 643f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik if (size < IP_SET_LIST_MIN_SIZE) 644f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik size = IP_SET_LIST_MIN_SIZE; 645f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 6467d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik set->variant = &set_variant; 64703c8b234e61a9a3aab8d970b3bf681934ecfe443Jozsef Kadlecsik set->dsize = ip_set_elem_len(set, tb, sizeof(struct set_elem)); 6481785e8f473082aa60d62c7165856cf6484077b99Vitaly Lavrov if (!init_list_set(net, set, size)) 64903c8b234e61a9a3aab8d970b3bf681934ecfe443Jozsef Kadlecsik return -ENOMEM; 65003c8b234e61a9a3aab8d970b3bf681934ecfe443Jozsef Kadlecsik if (tb[IPSET_ATTR_TIMEOUT]) { 65103c8b234e61a9a3aab8d970b3bf681934ecfe443Jozsef Kadlecsik set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 6527d47d972b5d154e143bb24a795af92bbb3c95532Jozsef Kadlecsik list_set_gc_init(set, list_set_gc); 653f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik } 654f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return 0; 655f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 656f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 657f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic struct ip_set_type list_set_type __read_mostly = { 658f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .name = "list:set", 659f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .protocol = IPSET_PROTOCOL, 660f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .features = IPSET_TYPE_NAME | IPSET_DUMP_LAST, 661f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .dimension = IPSET_DIM_ONE, 662c15f1c83251049182b1771da004d14f29683ab97Jan Engelhardt .family = NFPROTO_UNSPEC, 66335b8dcf8c3a0be1feb1c8b29b22e1685ba0c2e14Jozsef Kadlecsik .revision_min = IPSET_TYPE_REV_MIN, 66435b8dcf8c3a0be1feb1c8b29b22e1685ba0c2e14Jozsef Kadlecsik .revision_max = IPSET_TYPE_REV_MAX, 665f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .create = list_set_create, 666f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .create_policy = { 667f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik [IPSET_ATTR_SIZE] = { .type = NLA_U32 }, 668f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 669de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 670f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik }, 671f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .adt_policy = { 672f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik [IPSET_ATTR_NAME] = { .type = NLA_STRING, 673f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .len = IPSET_MAXNAMELEN }, 674f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik [IPSET_ATTR_NAMEREF] = { .type = NLA_STRING, 675f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .len = IPSET_MAXNAMELEN }, 676f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 677f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 678f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 679de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 680de76303c5a30e4754cd566dd4b9f3c26170fcf26Jozsef Kadlecsik [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 68181b10bb4bd16ea975c007f9bb2c2676cef6ade10Oliver Smith [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 682cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, 683cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, 684cbee93d7b71bf9d73382e503a4f60848eec60ea8Anton Danilov [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, 685f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik }, 686f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik .me = THIS_MODULE, 687f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik}; 688f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 689f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic int __init 690f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiklist_set_init(void) 691f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 692f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik return ip_set_type_register(&list_set_type); 693f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 694f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 695f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikstatic void __exit 696f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsiklist_set_fini(void) 697f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik{ 698f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik ip_set_type_unregister(&list_set_type); 699f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik} 700f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsik 701f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikmodule_init(list_set_init); 702f830837f0eed0f9e371b8fd65169365780814bb1Jozsef Kadlecsikmodule_exit(list_set_fini); 703