···11+#ifndef _IP_SET_H22+#define _IP_SET_H33+44+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>55+ * Patrick Schaaf <bof@bof.de>66+ * Martin Josefsson <gandalf@wlug.westbo.se>77+ * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>88+ *99+ * This program is free software; you can redistribute it and/or modify1010+ * it under the terms of the GNU General Public License version 2 as1111+ * published by the Free Software Foundation.1212+ */1313+1414+/* The protocol version */1515+#define IPSET_PROTOCOL 61616+1717+/* The max length of strings including NUL: set and type identifiers */1818+#define IPSET_MAXNAMELEN 321919+2020+/* Message types and commands */2121+enum ipset_cmd {2222+ IPSET_CMD_NONE,2323+ IPSET_CMD_PROTOCOL, /* 1: Return protocol version */2424+ IPSET_CMD_CREATE, /* 2: Create a new (empty) set */2525+ IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */2626+ IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */2727+ IPSET_CMD_RENAME, /* 5: Rename a set */2828+ IPSET_CMD_SWAP, /* 6: Swap two sets */2929+ IPSET_CMD_LIST, /* 7: List sets */3030+ IPSET_CMD_SAVE, /* 8: Save sets */3131+ IPSET_CMD_ADD, /* 9: Add an element to a set */3232+ IPSET_CMD_DEL, /* 10: Delete an element from a set */3333+ IPSET_CMD_TEST, /* 11: Test an element in a set */3434+ IPSET_CMD_HEADER, /* 12: Get set header data only */3535+ IPSET_CMD_TYPE, /* 13: Get set type */3636+ IPSET_MSG_MAX, /* Netlink message commands */3737+3838+ /* Commands in userspace: */3939+ IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */4040+ IPSET_CMD_HELP, /* 15: Get help */4141+ IPSET_CMD_VERSION, /* 16: Get program version */4242+ IPSET_CMD_QUIT, /* 17: Quit from interactive mode */4343+4444+ IPSET_CMD_MAX,4545+4646+ IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */4747+};4848+4949+/* Attributes at command level */5050+enum {5151+ IPSET_ATTR_UNSPEC,5252+ IPSET_ATTR_PROTOCOL, /* 1: Protocol version */5353+ IPSET_ATTR_SETNAME, /* 2: Name of the set */5454+ IPSET_ATTR_TYPENAME, /* 3: Typename */5555+ IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */5656+ IPSET_ATTR_REVISION, /* 4: Settype revision */5757+ IPSET_ATTR_FAMILY, /* 5: Settype family */5858+ IPSET_ATTR_FLAGS, /* 6: Flags at command level */5959+ IPSET_ATTR_DATA, /* 7: Nested attributes */6060+ IPSET_ATTR_ADT, /* 8: Multiple data containers */6161+ IPSET_ATTR_LINENO, /* 9: Restore lineno */6262+ IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */6363+ IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */6464+ __IPSET_ATTR_CMD_MAX,6565+};6666+#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)6767+6868+/* CADT specific attributes */6969+enum {7070+ IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,7171+ IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,7272+ IPSET_ATTR_IP_TO, /* 2 */7373+ IPSET_ATTR_CIDR, /* 3 */7474+ IPSET_ATTR_PORT, /* 4 */7575+ IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,7676+ IPSET_ATTR_PORT_TO, /* 5 */7777+ IPSET_ATTR_TIMEOUT, /* 6 */7878+ IPSET_ATTR_PROTO, /* 7 */7979+ IPSET_ATTR_CADT_FLAGS, /* 8 */8080+ IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */8181+ /* Reserve empty slots */8282+ IPSET_ATTR_CADT_MAX = 16,8383+ /* Create-only specific attributes */8484+ IPSET_ATTR_GC,8585+ IPSET_ATTR_HASHSIZE,8686+ IPSET_ATTR_MAXELEM,8787+ IPSET_ATTR_NETMASK,8888+ IPSET_ATTR_PROBES,8989+ IPSET_ATTR_RESIZE,9090+ IPSET_ATTR_SIZE,9191+ /* Kernel-only */9292+ IPSET_ATTR_ELEMENTS,9393+ IPSET_ATTR_REFERENCES,9494+ IPSET_ATTR_MEMSIZE,9595+9696+ __IPSET_ATTR_CREATE_MAX,9797+};9898+#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)9999+100100+/* ADT specific attributes */101101+enum {102102+ IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,103103+ IPSET_ATTR_NAME,104104+ IPSET_ATTR_NAMEREF,105105+ IPSET_ATTR_IP2,106106+ IPSET_ATTR_CIDR2,107107+ __IPSET_ATTR_ADT_MAX,108108+};109109+#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)110110+111111+/* IP specific attributes */112112+enum {113113+ IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,114114+ IPSET_ATTR_IPADDR_IPV6,115115+ __IPSET_ATTR_IPADDR_MAX,116116+};117117+#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)118118+119119+/* Error codes */120120+enum ipset_errno {121121+ IPSET_ERR_PRIVATE = 4096,122122+ IPSET_ERR_PROTOCOL,123123+ IPSET_ERR_FIND_TYPE,124124+ IPSET_ERR_MAX_SETS,125125+ IPSET_ERR_BUSY,126126+ IPSET_ERR_EXIST_SETNAME2,127127+ IPSET_ERR_TYPE_MISMATCH,128128+ IPSET_ERR_EXIST,129129+ IPSET_ERR_INVALID_CIDR,130130+ IPSET_ERR_INVALID_NETMASK,131131+ IPSET_ERR_INVALID_FAMILY,132132+ IPSET_ERR_TIMEOUT,133133+ IPSET_ERR_REFERENCED,134134+ IPSET_ERR_IPADDR_IPV4,135135+ IPSET_ERR_IPADDR_IPV6,136136+137137+ /* Type specific error codes */138138+ IPSET_ERR_TYPE_SPECIFIC = 4352,139139+};140140+141141+/* Flags at command level */142142+enum ipset_cmd_flags {143143+ IPSET_FLAG_BIT_EXIST = 0,144144+ IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),145145+};146146+147147+/* Flags at CADT attribute level */148148+enum ipset_cadt_flags {149149+ IPSET_FLAG_BIT_BEFORE = 0,150150+ IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),151151+};152152+153153+/* Commands with settype-specific attributes */154154+enum ipset_adt {155155+ IPSET_ADD,156156+ IPSET_DEL,157157+ IPSET_TEST,158158+ IPSET_ADT_MAX,159159+ IPSET_CREATE = IPSET_ADT_MAX,160160+ IPSET_CADT_MAX,161161+};162162+163163+#ifdef __KERNEL__164164+#include <linux/ip.h>165165+#include <linux/ipv6.h>166166+#include <linux/netlink.h>167167+#include <linux/netfilter.h>168168+#include <linux/vmalloc.h>169169+#include <net/netlink.h>170170+171171+/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t172172+ * and IPSET_INVALID_ID if you want to increase the max number of sets.173173+ */174174+typedef u16 ip_set_id_t;175175+176176+#define IPSET_INVALID_ID 65535177177+178178+enum ip_set_dim {179179+ IPSET_DIM_ZERO = 0,180180+ IPSET_DIM_ONE,181181+ IPSET_DIM_TWO,182182+ IPSET_DIM_THREE,183183+ /* Max dimension in elements.184184+ * If changed, new revision of iptables match/target is required.185185+ */186186+ IPSET_DIM_MAX = 6,187187+};188188+189189+/* Option flags for kernel operations */190190+enum ip_set_kopt {191191+ IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),192192+ IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),193193+ IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),194194+ IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),195195+};196196+197197+/* Set features */198198+enum ip_set_feature {199199+ IPSET_TYPE_IP_FLAG = 0,200200+ IPSET_TYPE_IP = (1 << IPSET_TYPE_IP_FLAG),201201+ IPSET_TYPE_PORT_FLAG = 1,202202+ IPSET_TYPE_PORT = (1 << IPSET_TYPE_PORT_FLAG),203203+ IPSET_TYPE_MAC_FLAG = 2,204204+ IPSET_TYPE_MAC = (1 << IPSET_TYPE_MAC_FLAG),205205+ IPSET_TYPE_IP2_FLAG = 3,206206+ IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),207207+ IPSET_TYPE_NAME_FLAG = 4,208208+ IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),209209+ /* Strictly speaking not a feature, but a flag for dumping:210210+ * this settype must be dumped last */211211+ IPSET_DUMP_LAST_FLAG = 7,212212+ IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG),213213+};214214+215215+struct ip_set;216216+217217+typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout);218218+219219+/* Set type, variant-specific part */220220+struct ip_set_type_variant {221221+ /* Kernelspace: test/add/del entries222222+ * returns negative error code,223223+ * zero for no match/success to add/delete224224+ * positive for matching element */225225+ int (*kadt)(struct ip_set *set, const struct sk_buff * skb,226226+ enum ipset_adt adt, u8 pf, u8 dim, u8 flags);227227+228228+ /* Userspace: test/add/del entries229229+ * returns negative error code,230230+ * zero for no match/success to add/delete231231+ * positive for matching element */232232+ int (*uadt)(struct ip_set *set, struct nlattr *tb[],233233+ enum ipset_adt adt, u32 *lineno, u32 flags);234234+235235+ /* Low level add/del/test functions */236236+ ipset_adtfn adt[IPSET_ADT_MAX];237237+238238+ /* When adding entries and set is full, try to resize the set */239239+ int (*resize)(struct ip_set *set, bool retried);240240+ /* Destroy the set */241241+ void (*destroy)(struct ip_set *set);242242+ /* Flush the elements */243243+ void (*flush)(struct ip_set *set);244244+ /* Expire entries before listing */245245+ void (*expire)(struct ip_set *set);246246+ /* List set header data */247247+ int (*head)(struct ip_set *set, struct sk_buff *skb);248248+ /* List elements */249249+ int (*list)(const struct ip_set *set, struct sk_buff *skb,250250+ struct netlink_callback *cb);251251+252252+ /* Return true if "b" set is the same as "a"253253+ * according to the create set parameters */254254+ bool (*same_set)(const struct ip_set *a, const struct ip_set *b);255255+};256256+257257+/* The core set type structure */258258+struct ip_set_type {259259+ struct list_head list;260260+261261+ /* Typename */262262+ char name[IPSET_MAXNAMELEN];263263+ /* Protocol version */264264+ u8 protocol;265265+ /* Set features to control swapping */266266+ u8 features;267267+ /* Set type dimension */268268+ u8 dimension;269269+ /* Supported family: may be AF_UNSPEC for both AF_INET/AF_INET6 */270270+ u8 family;271271+ /* Type revision */272272+ u8 revision;273273+274274+ /* Create set */275275+ int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags);276276+277277+ /* Attribute policies */278278+ const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1];279279+ const struct nla_policy adt_policy[IPSET_ATTR_ADT_MAX + 1];280280+281281+ /* Set this to THIS_MODULE if you are a module, otherwise NULL */282282+ struct module *me;283283+};284284+285285+/* register and unregister set type */286286+extern int ip_set_type_register(struct ip_set_type *set_type);287287+extern void ip_set_type_unregister(struct ip_set_type *set_type);288288+289289+/* A generic IP set */290290+struct ip_set {291291+ /* The name of the set */292292+ char name[IPSET_MAXNAMELEN];293293+ /* Lock protecting the set data */294294+ rwlock_t lock;295295+ /* References to the set */296296+ atomic_t ref;297297+ /* The core set type */298298+ struct ip_set_type *type;299299+ /* The type variant doing the real job */300300+ const struct ip_set_type_variant *variant;301301+ /* The actual INET family of the set */302302+ u8 family;303303+ /* The type specific data */304304+ void *data;305305+};306306+307307+/* register and unregister set references */308308+extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);309309+extern void ip_set_put_byindex(ip_set_id_t index);310310+extern const char * ip_set_name_byindex(ip_set_id_t index);311311+extern ip_set_id_t ip_set_nfnl_get(const char *name);312312+extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);313313+extern void ip_set_nfnl_put(ip_set_id_t index);314314+315315+/* API for iptables set match, and SET target */316316+extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,317317+ u8 family, u8 dim, u8 flags);318318+extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,319319+ u8 family, u8 dim, u8 flags);320320+extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,321321+ u8 family, u8 dim, u8 flags);322322+323323+/* Utility functions */324324+extern void * ip_set_alloc(size_t size);325325+extern void ip_set_free(void *members);326326+extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr);327327+extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);328328+329329+static inline int330330+ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)331331+{332332+ __be32 ip;333333+ int ret = ip_set_get_ipaddr4(nla, &ip);334334+335335+ if (ret)336336+ return ret;337337+ *ipaddr = ntohl(ip);338338+ return 0;339339+}340340+341341+/* Ignore IPSET_ERR_EXIST errors if asked to do so? */342342+static inline bool343343+ip_set_eexist(int ret, u32 flags)344344+{345345+ return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);346346+}347347+348348+/* Check the NLA_F_NET_BYTEORDER flag */349349+static inline bool350350+ip_set_attr_netorder(struct nlattr *tb[], int type)351351+{352352+ return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER);353353+}354354+355355+static inline bool356356+ip_set_optattr_netorder(struct nlattr *tb[], int type)357357+{358358+ return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER);359359+}360360+361361+/* Useful converters */362362+static inline u32363363+ip_set_get_h32(const struct nlattr *attr)364364+{365365+ return ntohl(nla_get_be32(attr));366366+}367367+368368+static inline u16369369+ip_set_get_h16(const struct nlattr *attr)370370+{371371+ return ntohs(nla_get_be16(attr));372372+}373373+374374+#define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED)375375+#define ipset_nest_end(skb, start) nla_nest_end(skb, start)376376+377377+#define NLA_PUT_IPADDR4(skb, type, ipaddr) \378378+do { \379379+ struct nlattr *__nested = ipset_nest_start(skb, type); \380380+ \381381+ if (!__nested) \382382+ goto nla_put_failure; \383383+ NLA_PUT_NET32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr); \384384+ ipset_nest_end(skb, __nested); \385385+} while (0)386386+387387+#define NLA_PUT_IPADDR6(skb, type, ipaddrptr) \388388+do { \389389+ struct nlattr *__nested = ipset_nest_start(skb, type); \390390+ \391391+ if (!__nested) \392392+ goto nla_put_failure; \393393+ NLA_PUT(skb, IPSET_ATTR_IPADDR_IPV6, \394394+ sizeof(struct in6_addr), ipaddrptr); \395395+ ipset_nest_end(skb, __nested); \396396+} while (0)397397+398398+/* Get address from skbuff */399399+static inline __be32400400+ip4addr(const struct sk_buff *skb, bool src)401401+{402402+ return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;403403+}404404+405405+static inline void406406+ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr)407407+{408408+ *addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;409409+}410410+411411+static inline void412412+ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr)413413+{414414+ memcpy(addr, src ? &ipv6_hdr(skb)->saddr : &ipv6_hdr(skb)->daddr,415415+ sizeof(*addr));416416+}417417+418418+/* Calculate the bytes required to store the inclusive range of a-b */419419+static inline int420420+bitmap_bytes(u32 a, u32 b)421421+{422422+ return 4 * ((((b - a + 8) / 8) + 3) / 4);423423+}424424+425425+/* Interface to iptables/ip6tables */426426+427427+#define SO_IP_SET 83428428+429429+union ip_set_name_index {430430+ char name[IPSET_MAXNAMELEN];431431+ ip_set_id_t index;432432+};433433+434434+#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */435435+struct ip_set_req_get_set {436436+ unsigned op;437437+ unsigned version;438438+ union ip_set_name_index set;439439+};440440+441441+#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */442442+/* Uses ip_set_req_get_set */443443+444444+#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */445445+struct ip_set_req_version {446446+ unsigned op;447447+ unsigned version;448448+};449449+450450+#endif /* __KERNEL__ */451451+452452+#endif /*_IP_SET_H */
+1074
include/linux/netfilter/ipset/ip_set_ahash.h
···11+#ifndef _IP_SET_AHASH_H22+#define _IP_SET_AHASH_H33+44+#include <linux/rcupdate.h>55+#include <linux/jhash.h>66+#include <linux/netfilter/ipset/ip_set_timeout.h>77+88+/* Hashing which uses arrays to resolve clashing. The hash table is resized99+ * (doubled) when searching becomes too long.1010+ * Internally jhash is used with the assumption that the size of the1111+ * stored data is a multiple of sizeof(u32). If storage supports timeout,1212+ * the timeout field must be the last one in the data structure - that field1313+ * is ignored when computing the hash key.1414+ *1515+ * Readers and resizing1616+ *1717+ * Resizing can be triggered by userspace command only, and those1818+ * are serialized by the nfnl mutex. During resizing the set is1919+ * read-locked, so the only possible concurrent operations are2020+ * the kernel side readers. Those must be protected by proper RCU locking.2121+ */2222+2323+/* Number of elements to store in an initial array block */2424+#define AHASH_INIT_SIZE 42525+/* Max number of elements to store in an array block */2626+#define AHASH_MAX_SIZE (3*4)2727+2828+/* A hash bucket */2929+struct hbucket {3030+ void *value; /* the array of the values */3131+ u8 size; /* size of the array */3232+ u8 pos; /* position of the first free entry */3333+};3434+3535+/* The hash table: the table size stored here in order to make resizing easy */3636+struct htable {3737+ u8 htable_bits; /* size of hash table == 2^htable_bits */3838+ struct hbucket bucket[0]; /* hashtable buckets */3939+};4040+4141+#define hbucket(h, i) &((h)->bucket[i])4242+4343+/* Book-keeping of the prefixes added to the set */4444+struct ip_set_hash_nets {4545+ u8 cidr; /* the different cidr values in the set */4646+ u32 nets; /* number of elements per cidr */4747+};4848+4949+/* The generic ip_set hash structure */5050+struct ip_set_hash {5151+ struct htable *table; /* the hash table */5252+ u32 maxelem; /* max elements in the hash */5353+ u32 elements; /* current element (vs timeout) */5454+ u32 initval; /* random jhash init value */5555+ u32 timeout; /* timeout value, if enabled */5656+ struct timer_list gc; /* garbage collection when timeout enabled */5757+#ifdef IP_SET_HASH_WITH_NETMASK5858+ u8 netmask; /* netmask value for subnets to store */5959+#endif6060+#ifdef IP_SET_HASH_WITH_NETS6161+ struct ip_set_hash_nets nets[0]; /* book-keeping of prefixes */6262+#endif6363+};6464+6565+/* Compute htable_bits from the user input parameter hashsize */6666+static u86767+htable_bits(u32 hashsize)6868+{6969+ /* Assume that hashsize == 2^htable_bits */7070+ u8 bits = fls(hashsize - 1);7171+ if (jhash_size(bits) != hashsize)7272+ /* Round up to the first 2^n value */7373+ bits = fls(hashsize);7474+7575+ return bits;7676+}7777+7878+#ifdef IP_SET_HASH_WITH_NETS7979+8080+#define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128)8181+8282+/* Network cidr size book keeping when the hash stores different8383+ * sized networks */8484+static void8585+add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)8686+{8787+ u8 i;8888+8989+ ++h->nets[cidr-1].nets;9090+9191+ pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets);9292+9393+ if (h->nets[cidr-1].nets > 1)9494+ return;9595+9696+ /* New cidr size */9797+ for (i = 0; i < host_mask && h->nets[i].cidr; i++) {9898+ /* Add in increasing prefix order, so larger cidr first */9999+ if (h->nets[i].cidr < cidr)100100+ swap(h->nets[i].cidr, cidr);101101+ }102102+ if (i < host_mask)103103+ h->nets[i].cidr = cidr;104104+}105105+106106+static void107107+del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)108108+{109109+ u8 i;110110+111111+ --h->nets[cidr-1].nets;112112+113113+ pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets);114114+115115+ if (h->nets[cidr-1].nets != 0)116116+ return;117117+118118+ /* All entries with this cidr size deleted, so cleanup h->cidr[] */119119+ for (i = 0; i < host_mask - 1 && h->nets[i].cidr; i++) {120120+ if (h->nets[i].cidr == cidr)121121+ h->nets[i].cidr = cidr = h->nets[i+1].cidr;122122+ }123123+ h->nets[i - 1].cidr = 0;124124+}125125+#endif126126+127127+/* Destroy the hashtable part of the set */128128+static void129129+ahash_destroy(struct htable *t)130130+{131131+ struct hbucket *n;132132+ u32 i;133133+134134+ for (i = 0; i < jhash_size(t->htable_bits); i++) {135135+ n = hbucket(t, i);136136+ if (n->size)137137+ /* FIXME: use slab cache */138138+ kfree(n->value);139139+ }140140+141141+ ip_set_free(t);142142+}143143+144144+/* Calculate the actual memory size of the set data */145145+static size_t146146+ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask)147147+{148148+ u32 i;149149+ struct htable *t = h->table;150150+ size_t memsize = sizeof(*h)151151+ + sizeof(*t)152152+#ifdef IP_SET_HASH_WITH_NETS153153+ + sizeof(struct ip_set_hash_nets) * host_mask154154+#endif155155+ + jhash_size(t->htable_bits) * sizeof(struct hbucket);156156+157157+ for (i = 0; i < jhash_size(t->htable_bits); i++)158158+ memsize += t->bucket[i].size * dsize;159159+160160+ return memsize;161161+}162162+163163+/* Flush a hash type of set: destroy all elements */164164+static void165165+ip_set_hash_flush(struct ip_set *set)166166+{167167+ struct ip_set_hash *h = set->data;168168+ struct htable *t = h->table;169169+ struct hbucket *n;170170+ u32 i;171171+172172+ for (i = 0; i < jhash_size(t->htable_bits); i++) {173173+ n = hbucket(t, i);174174+ if (n->size) {175175+ n->size = n->pos = 0;176176+ /* FIXME: use slab cache */177177+ kfree(n->value);178178+ }179179+ }180180+#ifdef IP_SET_HASH_WITH_NETS181181+ memset(h->nets, 0, sizeof(struct ip_set_hash_nets)182182+ * SET_HOST_MASK(set->family));183183+#endif184184+ h->elements = 0;185185+}186186+187187+/* Destroy a hash type of set */188188+static void189189+ip_set_hash_destroy(struct ip_set *set)190190+{191191+ struct ip_set_hash *h = set->data;192192+193193+ if (with_timeout(h->timeout))194194+ del_timer_sync(&h->gc);195195+196196+ ahash_destroy(h->table);197197+ kfree(h);198198+199199+ set->data = NULL;200200+}201201+202202+#define HKEY(data, initval, htable_bits) \203203+(jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval) \204204+ & jhash_mask(htable_bits))205205+206206+#endif /* _IP_SET_AHASH_H */207207+208208+#define CONCAT(a, b, c) a##b##c209209+#define TOKEN(a, b, c) CONCAT(a, b, c)210210+211211+/* Type/family dependent function prototypes */212212+213213+#define type_pf_data_equal TOKEN(TYPE, PF, _data_equal)214214+#define type_pf_data_isnull TOKEN(TYPE, PF, _data_isnull)215215+#define type_pf_data_copy TOKEN(TYPE, PF, _data_copy)216216+#define type_pf_data_zero_out TOKEN(TYPE, PF, _data_zero_out)217217+#define type_pf_data_netmask TOKEN(TYPE, PF, _data_netmask)218218+#define type_pf_data_list TOKEN(TYPE, PF, _data_list)219219+#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist)220220+221221+#define type_pf_elem TOKEN(TYPE, PF, _elem)222222+#define type_pf_telem TOKEN(TYPE, PF, _telem)223223+#define type_pf_data_timeout TOKEN(TYPE, PF, _data_timeout)224224+#define type_pf_data_expired TOKEN(TYPE, PF, _data_expired)225225+#define type_pf_data_timeout_set TOKEN(TYPE, PF, _data_timeout_set)226226+227227+#define type_pf_elem_add TOKEN(TYPE, PF, _elem_add)228228+#define type_pf_add TOKEN(TYPE, PF, _add)229229+#define type_pf_del TOKEN(TYPE, PF, _del)230230+#define type_pf_test_cidrs TOKEN(TYPE, PF, _test_cidrs)231231+#define type_pf_test TOKEN(TYPE, PF, _test)232232+233233+#define type_pf_elem_tadd TOKEN(TYPE, PF, _elem_tadd)234234+#define type_pf_del_telem TOKEN(TYPE, PF, _ahash_del_telem)235235+#define type_pf_expire TOKEN(TYPE, PF, _expire)236236+#define type_pf_tadd TOKEN(TYPE, PF, _tadd)237237+#define type_pf_tdel TOKEN(TYPE, PF, _tdel)238238+#define type_pf_ttest_cidrs TOKEN(TYPE, PF, _ahash_ttest_cidrs)239239+#define type_pf_ttest TOKEN(TYPE, PF, _ahash_ttest)240240+241241+#define type_pf_resize TOKEN(TYPE, PF, _resize)242242+#define type_pf_tresize TOKEN(TYPE, PF, _tresize)243243+#define type_pf_flush ip_set_hash_flush244244+#define type_pf_destroy ip_set_hash_destroy245245+#define type_pf_head TOKEN(TYPE, PF, _head)246246+#define type_pf_list TOKEN(TYPE, PF, _list)247247+#define type_pf_tlist TOKEN(TYPE, PF, _tlist)248248+#define type_pf_same_set TOKEN(TYPE, PF, _same_set)249249+#define type_pf_kadt TOKEN(TYPE, PF, _kadt)250250+#define type_pf_uadt TOKEN(TYPE, PF, _uadt)251251+#define type_pf_gc TOKEN(TYPE, PF, _gc)252252+#define type_pf_gc_init TOKEN(TYPE, PF, _gc_init)253253+#define type_pf_variant TOKEN(TYPE, PF, _variant)254254+#define type_pf_tvariant TOKEN(TYPE, PF, _tvariant)255255+256256+/* Flavour without timeout */257257+258258+/* Get the ith element from the array block n */259259+#define ahash_data(n, i) \260260+ ((struct type_pf_elem *)((n)->value) + (i))261261+262262+/* Add an element to the hash table when resizing the set:263263+ * we spare the maintenance of the internal counters. */264264+static int265265+type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value)266266+{267267+ if (n->pos >= n->size) {268268+ void *tmp;269269+270270+ if (n->size >= AHASH_MAX_SIZE)271271+ /* Trigger rehashing */272272+ return -EAGAIN;273273+274274+ tmp = kzalloc((n->size + AHASH_INIT_SIZE)275275+ * sizeof(struct type_pf_elem),276276+ GFP_ATOMIC);277277+ if (!tmp)278278+ return -ENOMEM;279279+ if (n->size) {280280+ memcpy(tmp, n->value,281281+ sizeof(struct type_pf_elem) * n->size);282282+ kfree(n->value);283283+ }284284+ n->value = tmp;285285+ n->size += AHASH_INIT_SIZE;286286+ }287287+ type_pf_data_copy(ahash_data(n, n->pos++), value);288288+ return 0;289289+}290290+291291+/* Resize a hash: create a new hash table with doubling the hashsize292292+ * and inserting the elements to it. Repeat until we succeed or293293+ * fail due to memory pressures. */294294+static int295295+type_pf_resize(struct ip_set *set, bool retried)296296+{297297+ struct ip_set_hash *h = set->data;298298+ struct htable *t, *orig = h->table;299299+ u8 htable_bits = orig->htable_bits;300300+ const struct type_pf_elem *data;301301+ struct hbucket *n, *m;302302+ u32 i, j;303303+ int ret;304304+305305+retry:306306+ ret = 0;307307+ htable_bits++;308308+ pr_debug("attempt to resize set %s from %u to %u, t %p\n",309309+ set->name, orig->htable_bits, htable_bits, orig);310310+ if (!htable_bits)311311+ /* In case we have plenty of memory :-) */312312+ return -IPSET_ERR_HASH_FULL;313313+ t = ip_set_alloc(sizeof(*t)314314+ + jhash_size(htable_bits) * sizeof(struct hbucket));315315+ if (!t)316316+ return -ENOMEM;317317+ t->htable_bits = htable_bits;318318+319319+ read_lock_bh(&set->lock);320320+ for (i = 0; i < jhash_size(orig->htable_bits); i++) {321321+ n = hbucket(orig, i);322322+ for (j = 0; j < n->pos; j++) {323323+ data = ahash_data(n, j);324324+ m = hbucket(t, HKEY(data, h->initval, htable_bits));325325+ ret = type_pf_elem_add(m, data);326326+ if (ret < 0) {327327+ read_unlock_bh(&set->lock);328328+ ahash_destroy(t);329329+ if (ret == -EAGAIN)330330+ goto retry;331331+ return ret;332332+ }333333+ }334334+ }335335+336336+ rcu_assign_pointer(h->table, t);337337+ read_unlock_bh(&set->lock);338338+339339+ /* Give time to other readers of the set */340340+ synchronize_rcu_bh();341341+342342+ pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,343343+ orig->htable_bits, orig, t->htable_bits, t);344344+ ahash_destroy(orig);345345+346346+ return 0;347347+}348348+349349+/* Add an element to a hash and update the internal counters when succeeded,350350+ * otherwise report the proper error code. */351351+static int352352+type_pf_add(struct ip_set *set, void *value, u32 timeout)353353+{354354+ struct ip_set_hash *h = set->data;355355+ struct htable *t;356356+ const struct type_pf_elem *d = value;357357+ struct hbucket *n;358358+ int i, ret = 0;359359+ u32 key;360360+361361+ if (h->elements >= h->maxelem)362362+ return -IPSET_ERR_HASH_FULL;363363+364364+ rcu_read_lock_bh();365365+ t = rcu_dereference_bh(h->table);366366+ key = HKEY(value, h->initval, t->htable_bits);367367+ n = hbucket(t, key);368368+ for (i = 0; i < n->pos; i++)369369+ if (type_pf_data_equal(ahash_data(n, i), d)) {370370+ ret = -IPSET_ERR_EXIST;371371+ goto out;372372+ }373373+374374+ ret = type_pf_elem_add(n, value);375375+ if (ret != 0)376376+ goto out;377377+378378+#ifdef IP_SET_HASH_WITH_NETS379379+ add_cidr(h, d->cidr, HOST_MASK);380380+#endif381381+ h->elements++;382382+out:383383+ rcu_read_unlock_bh();384384+ return ret;385385+}386386+387387+/* Delete an element from the hash: swap it with the last element388388+ * and free up space if possible.389389+ */390390+static int391391+type_pf_del(struct ip_set *set, void *value, u32 timeout)392392+{393393+ struct ip_set_hash *h = set->data;394394+ struct htable *t = h->table;395395+ const struct type_pf_elem *d = value;396396+ struct hbucket *n;397397+ int i;398398+ struct type_pf_elem *data;399399+ u32 key;400400+401401+ key = HKEY(value, h->initval, t->htable_bits);402402+ n = hbucket(t, key);403403+ for (i = 0; i < n->pos; i++) {404404+ data = ahash_data(n, i);405405+ if (!type_pf_data_equal(data, d))406406+ continue;407407+ if (i != n->pos - 1)408408+ /* Not last one */409409+ type_pf_data_copy(data, ahash_data(n, n->pos - 1));410410+411411+ n->pos--;412412+ h->elements--;413413+#ifdef IP_SET_HASH_WITH_NETS414414+ del_cidr(h, d->cidr, HOST_MASK);415415+#endif416416+ if (n->pos + AHASH_INIT_SIZE < n->size) {417417+ void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)418418+ * sizeof(struct type_pf_elem),419419+ GFP_ATOMIC);420420+ if (!tmp)421421+ return 0;422422+ n->size -= AHASH_INIT_SIZE;423423+ memcpy(tmp, n->value,424424+ n->size * sizeof(struct type_pf_elem));425425+ kfree(n->value);426426+ n->value = tmp;427427+ }428428+ return 0;429429+ }430430+431431+ return -IPSET_ERR_EXIST;432432+}433433+434434+#ifdef IP_SET_HASH_WITH_NETS435435+436436+/* Special test function which takes into account the different network437437+ * sizes added to the set */438438+static int439439+type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)440440+{441441+ struct ip_set_hash *h = set->data;442442+ struct htable *t = h->table;443443+ struct hbucket *n;444444+ const struct type_pf_elem *data;445445+ int i, j = 0;446446+ u32 key;447447+ u8 host_mask = SET_HOST_MASK(set->family);448448+449449+ pr_debug("test by nets\n");450450+ for (; j < host_mask && h->nets[j].cidr; j++) {451451+ type_pf_data_netmask(d, h->nets[j].cidr);452452+ key = HKEY(d, h->initval, t->htable_bits);453453+ n = hbucket(t, key);454454+ for (i = 0; i < n->pos; i++) {455455+ data = ahash_data(n, i);456456+ if (type_pf_data_equal(data, d))457457+ return 1;458458+ }459459+ }460460+ return 0;461461+}462462+#endif463463+464464+/* Test whether the element is added to the set */465465+static int466466+type_pf_test(struct ip_set *set, void *value, u32 timeout)467467+{468468+ struct ip_set_hash *h = set->data;469469+ struct htable *t = h->table;470470+ struct type_pf_elem *d = value;471471+ struct hbucket *n;472472+ const struct type_pf_elem *data;473473+ int i;474474+ u32 key;475475+476476+#ifdef IP_SET_HASH_WITH_NETS477477+ /* If we test an IP address and not a network address,478478+ * try all possible network sizes */479479+ if (d->cidr == SET_HOST_MASK(set->family))480480+ return type_pf_test_cidrs(set, d, timeout);481481+#endif482482+483483+ key = HKEY(d, h->initval, t->htable_bits);484484+ n = hbucket(t, key);485485+ for (i = 0; i < n->pos; i++) {486486+ data = ahash_data(n, i);487487+ if (type_pf_data_equal(data, d))488488+ return 1;489489+ }490490+ return 0;491491+}492492+493493+/* Reply a HEADER request: fill out the header part of the set */494494+static int495495+type_pf_head(struct ip_set *set, struct sk_buff *skb)496496+{497497+ const struct ip_set_hash *h = set->data;498498+ struct nlattr *nested;499499+ size_t memsize;500500+501501+ read_lock_bh(&set->lock);502502+ memsize = ahash_memsize(h, with_timeout(h->timeout)503503+ ? sizeof(struct type_pf_telem)504504+ : sizeof(struct type_pf_elem),505505+ set->family == AF_INET ? 32 : 128);506506+ read_unlock_bh(&set->lock);507507+508508+ nested = ipset_nest_start(skb, IPSET_ATTR_DATA);509509+ if (!nested)510510+ goto nla_put_failure;511511+ NLA_PUT_NET32(skb, IPSET_ATTR_HASHSIZE,512512+ htonl(jhash_size(h->table->htable_bits)));513513+ NLA_PUT_NET32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem));514514+#ifdef IP_SET_HASH_WITH_NETMASK515515+ if (h->netmask != HOST_MASK)516516+ NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask);517517+#endif518518+ NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,519519+ htonl(atomic_read(&set->ref) - 1));520520+ NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize));521521+ if (with_timeout(h->timeout))522522+ NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout));523523+ ipset_nest_end(skb, nested);524524+525525+ return 0;526526+nla_put_failure:527527+ return -EMSGSIZE;528528+}529529+530530+/* Reply a LIST/SAVE request: dump the elements of the specified set */531531+static int532532+type_pf_list(const struct ip_set *set,533533+ struct sk_buff *skb, struct netlink_callback *cb)534534+{535535+ const struct ip_set_hash *h = set->data;536536+ const struct htable *t = h->table;537537+ struct nlattr *atd, *nested;538538+ const struct hbucket *n;539539+ const struct type_pf_elem *data;540540+ u32 first = cb->args[2];541541+ /* We assume that one hash bucket fills into one page */542542+ void *incomplete;543543+ int i;544544+545545+ atd = ipset_nest_start(skb, IPSET_ATTR_ADT);546546+ if (!atd)547547+ return -EMSGSIZE;548548+ pr_debug("list hash set %s\n", set->name);549549+ for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) {550550+ incomplete = skb_tail_pointer(skb);551551+ n = hbucket(t, cb->args[2]);552552+ pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n);553553+ for (i = 0; i < n->pos; i++) {554554+ data = ahash_data(n, i);555555+ pr_debug("list hash %lu hbucket %p i %u, data %p\n",556556+ cb->args[2], n, i, data);557557+ nested = ipset_nest_start(skb, IPSET_ATTR_DATA);558558+ if (!nested) {559559+ if (cb->args[2] == first) {560560+ nla_nest_cancel(skb, atd);561561+ return -EMSGSIZE;562562+ } else563563+ goto nla_put_failure;564564+ }565565+ if (type_pf_data_list(skb, data))566566+ goto nla_put_failure;567567+ ipset_nest_end(skb, nested);568568+ }569569+ }570570+ ipset_nest_end(skb, atd);571571+ /* Set listing finished */572572+ cb->args[2] = 0;573573+574574+ return 0;575575+576576+nla_put_failure:577577+ nlmsg_trim(skb, incomplete);578578+ ipset_nest_end(skb, atd);579579+ if (unlikely(first == cb->args[2])) {580580+ pr_warning("Can't list set %s: one bucket does not fit into "581581+ "a message. Please report it!\n", set->name);582582+ cb->args[2] = 0;583583+ return -EMSGSIZE;584584+ }585585+ return 0;586586+}587587+588588+static int589589+type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,590590+ enum ipset_adt adt, u8 pf, u8 dim, u8 flags);591591+static int592592+type_pf_uadt(struct ip_set *set, struct nlattr *tb[],593593+ enum ipset_adt adt, u32 *lineno, u32 flags);594594+595595+static const struct ip_set_type_variant type_pf_variant = {596596+ .kadt = type_pf_kadt,597597+ .uadt = type_pf_uadt,598598+ .adt = {599599+ [IPSET_ADD] = type_pf_add,600600+ [IPSET_DEL] = type_pf_del,601601+ [IPSET_TEST] = type_pf_test,602602+ },603603+ .destroy = type_pf_destroy,604604+ .flush = type_pf_flush,605605+ .head = type_pf_head,606606+ .list = type_pf_list,607607+ .resize = type_pf_resize,608608+ .same_set = type_pf_same_set,609609+};610610+611611+/* Flavour with timeout support */612612+613613+#define ahash_tdata(n, i) \614614+ (struct type_pf_elem *)((struct type_pf_telem *)((n)->value) + (i))615615+616616+static inline u32617617+type_pf_data_timeout(const struct type_pf_elem *data)618618+{619619+ const struct type_pf_telem *tdata =620620+ (const struct type_pf_telem *) data;621621+622622+ return tdata->timeout;623623+}624624+625625+static inline bool626626+type_pf_data_expired(const struct type_pf_elem *data)627627+{628628+ const struct type_pf_telem *tdata =629629+ (const struct type_pf_telem *) data;630630+631631+ return ip_set_timeout_expired(tdata->timeout);632632+}633633+634634+static inline void635635+type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)636636+{637637+ struct type_pf_telem *tdata = (struct type_pf_telem *) data;638638+639639+ tdata->timeout = ip_set_timeout_set(timeout);640640+}641641+642642+static int643643+type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value,644644+ u32 timeout)645645+{646646+ struct type_pf_elem *data;647647+648648+ if (n->pos >= n->size) {649649+ void *tmp;650650+651651+ if (n->size >= AHASH_MAX_SIZE)652652+ /* Trigger rehashing */653653+ return -EAGAIN;654654+655655+ tmp = kzalloc((n->size + AHASH_INIT_SIZE)656656+ * sizeof(struct type_pf_telem),657657+ GFP_ATOMIC);658658+ if (!tmp)659659+ return -ENOMEM;660660+ if (n->size) {661661+ memcpy(tmp, n->value,662662+ sizeof(struct type_pf_telem) * n->size);663663+ kfree(n->value);664664+ }665665+ n->value = tmp;666666+ n->size += AHASH_INIT_SIZE;667667+ }668668+ data = ahash_tdata(n, n->pos++);669669+ type_pf_data_copy(data, value);670670+ type_pf_data_timeout_set(data, timeout);671671+ return 0;672672+}673673+674674+/* Delete expired elements from the hashtable */675675+static void676676+type_pf_expire(struct ip_set_hash *h)677677+{678678+ struct htable *t = h->table;679679+ struct hbucket *n;680680+ struct type_pf_elem *data;681681+ u32 i;682682+ int j;683683+684684+ for (i = 0; i < jhash_size(t->htable_bits); i++) {685685+ n = hbucket(t, i);686686+ for (j = 0; j < n->pos; j++) {687687+ data = ahash_tdata(n, j);688688+ if (type_pf_data_expired(data)) {689689+ pr_debug("expired %u/%u\n", i, j);690690+#ifdef IP_SET_HASH_WITH_NETS691691+ del_cidr(h, data->cidr, HOST_MASK);692692+#endif693693+ if (j != n->pos - 1)694694+ /* Not last one */695695+ type_pf_data_copy(data,696696+ ahash_tdata(n, n->pos - 1));697697+ n->pos--;698698+ h->elements--;699699+ }700700+ }701701+ if (n->pos + AHASH_INIT_SIZE < n->size) {702702+ void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)703703+ * sizeof(struct type_pf_telem),704704+ GFP_ATOMIC);705705+ if (!tmp)706706+ /* Still try to delete expired elements */707707+ continue;708708+ n->size -= AHASH_INIT_SIZE;709709+ memcpy(tmp, n->value,710710+ n->size * sizeof(struct type_pf_telem));711711+ kfree(n->value);712712+ n->value = tmp;713713+ }714714+ }715715+}716716+717717+static int718718+type_pf_tresize(struct ip_set *set, bool retried)719719+{720720+ struct ip_set_hash *h = set->data;721721+ struct htable *t, *orig = h->table;722722+ u8 htable_bits = orig->htable_bits;723723+ const struct type_pf_elem *data;724724+ struct hbucket *n, *m;725725+ u32 i, j;726726+ int ret;727727+728728+ /* Try to cleanup once */729729+ if (!retried) {730730+ i = h->elements;731731+ write_lock_bh(&set->lock);732732+ type_pf_expire(set->data);733733+ write_unlock_bh(&set->lock);734734+ if (h->elements < i)735735+ return 0;736736+ }737737+738738+retry:739739+ ret = 0;740740+ htable_bits++;741741+ if (!htable_bits)742742+ /* In case we have plenty of memory :-) */743743+ return -IPSET_ERR_HASH_FULL;744744+ t = ip_set_alloc(sizeof(*t)745745+ + jhash_size(htable_bits) * sizeof(struct hbucket));746746+ if (!t)747747+ return -ENOMEM;748748+ t->htable_bits = htable_bits;749749+750750+ read_lock_bh(&set->lock);751751+ for (i = 0; i < jhash_size(orig->htable_bits); i++) {752752+ n = hbucket(orig, i);753753+ for (j = 0; j < n->pos; j++) {754754+ data = ahash_tdata(n, j);755755+ m = hbucket(t, HKEY(data, h->initval, htable_bits));756756+ ret = type_pf_elem_tadd(m, data,757757+ type_pf_data_timeout(data));758758+ if (ret < 0) {759759+ read_unlock_bh(&set->lock);760760+ ahash_destroy(t);761761+ if (ret == -EAGAIN)762762+ goto retry;763763+ return ret;764764+ }765765+ }766766+ }767767+768768+ rcu_assign_pointer(h->table, t);769769+ read_unlock_bh(&set->lock);770770+771771+ /* Give time to other readers of the set */772772+ synchronize_rcu_bh();773773+774774+ ahash_destroy(orig);775775+776776+ return 0;777777+}778778+779779+static int780780+type_pf_tadd(struct ip_set *set, void *value, u32 timeout)781781+{782782+ struct ip_set_hash *h = set->data;783783+ struct htable *t = h->table;784784+ const struct type_pf_elem *d = value;785785+ struct hbucket *n;786786+ struct type_pf_elem *data;787787+ int ret = 0, i, j = AHASH_MAX_SIZE + 1;788788+ u32 key;789789+790790+ if (h->elements >= h->maxelem)791791+ /* FIXME: when set is full, we slow down here */792792+ type_pf_expire(h);793793+ if (h->elements >= h->maxelem)794794+ return -IPSET_ERR_HASH_FULL;795795+796796+ rcu_read_lock_bh();797797+ t = rcu_dereference_bh(h->table);798798+ key = HKEY(d, h->initval, t->htable_bits);799799+ n = hbucket(t, key);800800+ for (i = 0; i < n->pos; i++) {801801+ data = ahash_tdata(n, i);802802+ if (type_pf_data_equal(data, d)) {803803+ if (type_pf_data_expired(data))804804+ j = i;805805+ else {806806+ ret = -IPSET_ERR_EXIST;807807+ goto out;808808+ }809809+ } else if (j == AHASH_MAX_SIZE + 1 &&810810+ type_pf_data_expired(data))811811+ j = i;812812+ }813813+ if (j != AHASH_MAX_SIZE + 1) {814814+ data = ahash_tdata(n, j);815815+#ifdef IP_SET_HASH_WITH_NETS816816+ del_cidr(h, data->cidr, HOST_MASK);817817+ add_cidr(h, d->cidr, HOST_MASK);818818+#endif819819+ type_pf_data_copy(data, d);820820+ type_pf_data_timeout_set(data, timeout);821821+ goto out;822822+ }823823+ ret = type_pf_elem_tadd(n, d, timeout);824824+ if (ret != 0)825825+ goto out;826826+827827+#ifdef IP_SET_HASH_WITH_NETS828828+ add_cidr(h, d->cidr, HOST_MASK);829829+#endif830830+ h->elements++;831831+out:832832+ rcu_read_unlock_bh();833833+ return ret;834834+}835835+836836+static int837837+type_pf_tdel(struct ip_set *set, void *value, u32 timeout)838838+{839839+ struct ip_set_hash *h = set->data;840840+ struct htable *t = h->table;841841+ const struct type_pf_elem *d = value;842842+ struct hbucket *n;843843+ int i, ret = 0;844844+ struct type_pf_elem *data;845845+ u32 key;846846+847847+ key = HKEY(value, h->initval, t->htable_bits);848848+ n = hbucket(t, key);849849+ for (i = 0; i < n->pos; i++) {850850+ data = ahash_tdata(n, i);851851+ if (!type_pf_data_equal(data, d))852852+ continue;853853+ if (type_pf_data_expired(data))854854+ ret = -IPSET_ERR_EXIST;855855+ if (i != n->pos - 1)856856+ /* Not last one */857857+ type_pf_data_copy(data, ahash_tdata(n, n->pos - 1));858858+859859+ n->pos--;860860+ h->elements--;861861+#ifdef IP_SET_HASH_WITH_NETS862862+ del_cidr(h, d->cidr, HOST_MASK);863863+#endif864864+ if (n->pos + AHASH_INIT_SIZE < n->size) {865865+ void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)866866+ * sizeof(struct type_pf_telem),867867+ GFP_ATOMIC);868868+ if (!tmp)869869+ return 0;870870+ n->size -= AHASH_INIT_SIZE;871871+ memcpy(tmp, n->value,872872+ n->size * sizeof(struct type_pf_telem));873873+ kfree(n->value);874874+ n->value = tmp;875875+ }876876+ return 0;877877+ }878878+879879+ return -IPSET_ERR_EXIST;880880+}881881+882882+#ifdef IP_SET_HASH_WITH_NETS883883+static int884884+type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)885885+{886886+ struct ip_set_hash *h = set->data;887887+ struct htable *t = h->table;888888+ struct type_pf_elem *data;889889+ struct hbucket *n;890890+ int i, j = 0;891891+ u32 key;892892+ u8 host_mask = SET_HOST_MASK(set->family);893893+894894+ for (; j < host_mask && h->nets[j].cidr; j++) {895895+ type_pf_data_netmask(d, h->nets[j].cidr);896896+ key = HKEY(d, h->initval, t->htable_bits);897897+ n = hbucket(t, key);898898+ for (i = 0; i < n->pos; i++) {899899+ data = ahash_tdata(n, i);900900+ if (type_pf_data_equal(data, d))901901+ return !type_pf_data_expired(data);902902+ }903903+ }904904+ return 0;905905+}906906+#endif907907+908908+static int909909+type_pf_ttest(struct ip_set *set, void *value, u32 timeout)910910+{911911+ struct ip_set_hash *h = set->data;912912+ struct htable *t = h->table;913913+ struct type_pf_elem *data, *d = value;914914+ struct hbucket *n;915915+ int i;916916+ u32 key;917917+918918+#ifdef IP_SET_HASH_WITH_NETS919919+ if (d->cidr == SET_HOST_MASK(set->family))920920+ return type_pf_ttest_cidrs(set, d, timeout);921921+#endif922922+ key = HKEY(d, h->initval, t->htable_bits);923923+ n = hbucket(t, key);924924+ for (i = 0; i < n->pos; i++) {925925+ data = ahash_tdata(n, i);926926+ if (type_pf_data_equal(data, d))927927+ return !type_pf_data_expired(data);928928+ }929929+ return 0;930930+}931931+932932+static int933933+type_pf_tlist(const struct ip_set *set,934934+ struct sk_buff *skb, struct netlink_callback *cb)935935+{936936+ const struct ip_set_hash *h = set->data;937937+ const struct htable *t = h->table;938938+ struct nlattr *atd, *nested;939939+ const struct hbucket *n;940940+ const struct type_pf_elem *data;941941+ u32 first = cb->args[2];942942+ /* We assume that one hash bucket fills into one page */943943+ void *incomplete;944944+ int i;945945+946946+ atd = ipset_nest_start(skb, IPSET_ATTR_ADT);947947+ if (!atd)948948+ return -EMSGSIZE;949949+ for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) {950950+ incomplete = skb_tail_pointer(skb);951951+ n = hbucket(t, cb->args[2]);952952+ for (i = 0; i < n->pos; i++) {953953+ data = ahash_tdata(n, i);954954+ pr_debug("list %p %u\n", n, i);955955+ if (type_pf_data_expired(data))956956+ continue;957957+ pr_debug("do list %p %u\n", n, i);958958+ nested = ipset_nest_start(skb, IPSET_ATTR_DATA);959959+ if (!nested) {960960+ if (cb->args[2] == first) {961961+ nla_nest_cancel(skb, atd);962962+ return -EMSGSIZE;963963+ } else964964+ goto nla_put_failure;965965+ }966966+ if (type_pf_data_tlist(skb, data))967967+ goto nla_put_failure;968968+ ipset_nest_end(skb, nested);969969+ }970970+ }971971+ ipset_nest_end(skb, atd);972972+ /* Set listing finished */973973+ cb->args[2] = 0;974974+975975+ return 0;976976+977977+nla_put_failure:978978+ nlmsg_trim(skb, incomplete);979979+ ipset_nest_end(skb, atd);980980+ if (unlikely(first == cb->args[2])) {981981+ pr_warning("Can't list set %s: one bucket does not fit into "982982+ "a message. Please report it!\n", set->name);983983+ cb->args[2] = 0;984984+ return -EMSGSIZE;985985+ }986986+ return 0;987987+}988988+989989+static const struct ip_set_type_variant type_pf_tvariant = {990990+ .kadt = type_pf_kadt,991991+ .uadt = type_pf_uadt,992992+ .adt = {993993+ [IPSET_ADD] = type_pf_tadd,994994+ [IPSET_DEL] = type_pf_tdel,995995+ [IPSET_TEST] = type_pf_ttest,996996+ },997997+ .destroy = type_pf_destroy,998998+ .flush = type_pf_flush,999999+ .head = type_pf_head,10001000+ .list = type_pf_tlist,10011001+ .resize = type_pf_tresize,10021002+ .same_set = type_pf_same_set,10031003+};10041004+10051005+static void10061006+type_pf_gc(unsigned long ul_set)10071007+{10081008+ struct ip_set *set = (struct ip_set *) ul_set;10091009+ struct ip_set_hash *h = set->data;10101010+10111011+ pr_debug("called\n");10121012+ write_lock_bh(&set->lock);10131013+ type_pf_expire(h);10141014+ write_unlock_bh(&set->lock);10151015+10161016+ h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;10171017+ add_timer(&h->gc);10181018+}10191019+10201020+static void10211021+type_pf_gc_init(struct ip_set *set)10221022+{10231023+ struct ip_set_hash *h = set->data;10241024+10251025+ init_timer(&h->gc);10261026+ h->gc.data = (unsigned long) set;10271027+ h->gc.function = type_pf_gc;10281028+ h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;10291029+ add_timer(&h->gc);10301030+ pr_debug("gc initialized, run in every %u\n",10311031+ IPSET_GC_PERIOD(h->timeout));10321032+}10331033+10341034+#undef type_pf_data_equal10351035+#undef type_pf_data_isnull10361036+#undef type_pf_data_copy10371037+#undef type_pf_data_zero_out10381038+#undef type_pf_data_list10391039+#undef type_pf_data_tlist10401040+10411041+#undef type_pf_elem10421042+#undef type_pf_telem10431043+#undef type_pf_data_timeout10441044+#undef type_pf_data_expired10451045+#undef type_pf_data_netmask10461046+#undef type_pf_data_timeout_set10471047+10481048+#undef type_pf_elem_add10491049+#undef type_pf_add10501050+#undef type_pf_del10511051+#undef type_pf_test_cidrs10521052+#undef type_pf_test10531053+10541054+#undef type_pf_elem_tadd10551055+#undef type_pf_expire10561056+#undef type_pf_tadd10571057+#undef type_pf_tdel10581058+#undef type_pf_ttest_cidrs10591059+#undef type_pf_ttest10601060+10611061+#undef type_pf_resize10621062+#undef type_pf_tresize10631063+#undef type_pf_flush10641064+#undef type_pf_destroy10651065+#undef type_pf_head10661066+#undef type_pf_list10671067+#undef type_pf_tlist10681068+#undef type_pf_same_set10691069+#undef type_pf_kadt10701070+#undef type_pf_uadt10711071+#undef type_pf_gc10721072+#undef type_pf_gc_init10731073+#undef type_pf_variant10741074+#undef type_pf_tvariant
+31
include/linux/netfilter/ipset/ip_set_bitmap.h
···11+#ifndef __IP_SET_BITMAP_H22+#define __IP_SET_BITMAP_H33+44+/* Bitmap type specific error codes */55+enum {66+ /* The element is out of the range of the set */77+ IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,88+ /* The range exceeds the size limit of the set type */99+ IPSET_ERR_BITMAP_RANGE_SIZE,1010+};1111+1212+#ifdef __KERNEL__1313+#define IPSET_BITMAP_MAX_RANGE 0x0000FFFF1414+1515+/* Common functions */1616+1717+static inline u321818+range_to_mask(u32 from, u32 to, u8 *bits)1919+{2020+ u32 mask = 0xFFFFFFFE;2121+2222+ *bits = 32;2323+ while (--(*bits) > 0 && mask && (to & mask) != from)2424+ mask <<= 1;2525+2626+ return mask;2727+}2828+2929+#endif /* __KERNEL__ */3030+3131+#endif /* __IP_SET_BITMAP_H */
···11+#ifndef __IP_SET_HASH_H22+#define __IP_SET_HASH_H33+44+/* Hash type specific error codes */55+enum {66+ /* Hash is full */77+ IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,88+ /* Null-valued element */99+ IPSET_ERR_HASH_ELEM,1010+ /* Invalid protocol */1111+ IPSET_ERR_INVALID_PROTO,1212+ /* Protocol missing but must be specified */1313+ IPSET_ERR_MISSING_PROTO,1414+};1515+1616+#ifdef __KERNEL__1717+1818+#define IPSET_DEFAULT_HASHSIZE 10241919+#define IPSET_MIMINAL_HASHSIZE 642020+#define IPSET_DEFAULT_MAXELEM 655362121+#define IPSET_DEFAULT_PROBES 42222+#define IPSET_DEFAULT_RESIZE 1002323+2424+#endif /* __KERNEL__ */2525+2626+#endif /* __IP_SET_HASH_H */
+27
include/linux/netfilter/ipset/ip_set_list.h
···11+#ifndef __IP_SET_LIST_H22+#define __IP_SET_LIST_H33+44+/* List type specific error codes */55+enum {66+ /* Set name to be added/deleted/tested does not exist. */77+ IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,88+ /* list:set type is not permitted to add */99+ IPSET_ERR_LOOP,1010+ /* Missing reference set */1111+ IPSET_ERR_BEFORE,1212+ /* Reference set does not exist */1313+ IPSET_ERR_NAMEREF,1414+ /* Set is full */1515+ IPSET_ERR_LIST_FULL,1616+ /* Reference set is not added to the set */1717+ IPSET_ERR_REF_EXIST,1818+};1919+2020+#ifdef __KERNEL__2121+2222+#define IP_SET_LIST_DEFAULT_SIZE 82323+#define IP_SET_LIST_MIN_SIZE 42424+2525+#endif /* __KERNEL__ */2626+2727+#endif /* __IP_SET_LIST_H */
+127
include/linux/netfilter/ipset/ip_set_timeout.h
···11+#ifndef _IP_SET_TIMEOUT_H22+#define _IP_SET_TIMEOUT_H33+44+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License version 2 as88+ * published by the Free Software Foundation.99+ */1010+1111+#ifdef __KERNEL__1212+1313+/* How often should the gc be run by default */1414+#define IPSET_GC_TIME (3 * 60)1515+1616+/* Timeout period depending on the timeout value of the given set */1717+#define IPSET_GC_PERIOD(timeout) \1818+ ((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1)1919+2020+/* Set is defined without timeout support: timeout value may be 0 */2121+#define IPSET_NO_TIMEOUT UINT_MAX2222+2323+#define with_timeout(timeout) ((timeout) != IPSET_NO_TIMEOUT)2424+2525+static inline unsigned int2626+ip_set_timeout_uget(struct nlattr *tb)2727+{2828+ unsigned int timeout = ip_set_get_h32(tb);2929+3030+ /* Userspace supplied TIMEOUT parameter: adjust crazy size */3131+ return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;3232+}3333+3434+#ifdef IP_SET_BITMAP_TIMEOUT3535+3636+/* Bitmap specific timeout constants and macros for the entries */3737+3838+/* Bitmap entry is unset */3939+#define IPSET_ELEM_UNSET 04040+/* Bitmap entry is set with no timeout value */4141+#define IPSET_ELEM_PERMANENT (UINT_MAX/2)4242+4343+static inline bool4444+ip_set_timeout_test(unsigned long timeout)4545+{4646+ return timeout != IPSET_ELEM_UNSET &&4747+ (timeout == IPSET_ELEM_PERMANENT ||4848+ time_after(timeout, jiffies));4949+}5050+5151+static inline bool5252+ip_set_timeout_expired(unsigned long timeout)5353+{5454+ return timeout != IPSET_ELEM_UNSET &&5555+ timeout != IPSET_ELEM_PERMANENT &&5656+ time_before(timeout, jiffies);5757+}5858+5959+static inline unsigned long6060+ip_set_timeout_set(u32 timeout)6161+{6262+ unsigned long t;6363+6464+ if (!timeout)6565+ return IPSET_ELEM_PERMANENT;6666+6767+ t = timeout * HZ + jiffies;6868+ if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT)6969+ /* Bingo! */7070+ t++;7171+7272+ return t;7373+}7474+7575+static inline u327676+ip_set_timeout_get(unsigned long timeout)7777+{7878+ return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;7979+}8080+8181+#else8282+8383+/* Hash specific timeout constants and macros for the entries */8484+8585+/* Hash entry is set with no timeout value */8686+#define IPSET_ELEM_PERMANENT 08787+8888+static inline bool8989+ip_set_timeout_test(unsigned long timeout)9090+{9191+ return timeout == IPSET_ELEM_PERMANENT ||9292+ time_after(timeout, jiffies);9393+}9494+9595+static inline bool9696+ip_set_timeout_expired(unsigned long timeout)9797+{9898+ return timeout != IPSET_ELEM_PERMANENT &&9999+ time_before(timeout, jiffies);100100+}101101+102102+static inline unsigned long103103+ip_set_timeout_set(u32 timeout)104104+{105105+ unsigned long t;106106+107107+ if (!timeout)108108+ return IPSET_ELEM_PERMANENT;109109+110110+ t = timeout * HZ + jiffies;111111+ if (t == IPSET_ELEM_PERMANENT)112112+ /* Bingo! :-) */113113+ t++;114114+115115+ return t;116116+}117117+118118+static inline u32119119+ip_set_timeout_get(unsigned long timeout)120120+{121121+ return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;122122+}123123+#endif /* ! IP_SET_BITMAP_TIMEOUT */124124+125125+#endif /* __KERNEL__ */126126+127127+#endif /* _IP_SET_TIMEOUT_H */
···11091109 * we are loaded. Just set ip_vs_drop_rate to 'n' and11101110 * we start to drop 1/rate of the packets11111111 */11121112-extern int ip_vs_drop_rate;11131113-extern int ip_vs_drop_counter;1114111211151113static inline int ip_vs_todrop(struct netns_ipvs *ipvs)11161114{
···352352 ctmark), similarly to the packet mark (nfmark). Using this353353 target and match, you can set and match on this mark.354354355355+config NETFILTER_XT_SET356356+ tristate 'set target and match support'357357+ depends on IP_SET358358+ depends on NETFILTER_ADVANCED359359+ help360360+ This option adds the "SET" target and "set" match.361361+362362+ Using this target and match, you can add/delete and match363363+ elements in the sets created by ipset(8).364364+365365+ To compile it as a module, choose M here. If unsure, say N.366366+355367# alphabetically ordered list of targets356368357369comment "Xtables targets"···738726 If you want to compile it as a module, say M here and read739727 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.740728729729+config NETFILTER_XT_MATCH_DEVGROUP730730+ tristate '"devgroup" match support'731731+ depends on NETFILTER_ADVANCED732732+ help733733+ This options adds a `devgroup' match, which allows to match on the734734+ device group a network device is assigned to.735735+736736+ To compile it as a module, choose M here. If unsure, say N.737737+741738config NETFILTER_XT_MATCH_DSCP742739 tristate '"dscp" and "tos" match support'743740 depends on NETFILTER_ADVANCED···10721051endif # NETFILTER_XTABLES1073105210741053endmenu10541054+10551055+source "net/netfilter/ipset/Kconfig"1075105610761057source "net/netfilter/ipvs/Kconfig"
···11+menuconfig IP_SET22+ tristate "IP set support"33+ depends on INET && NETFILTER44+ help55+ This option adds IP set support to the kernel.66+ In order to define and use the sets, you need the userspace utility77+ ipset(8). You can use the sets in netfilter via the "set" match88+ and "SET" target.99+1010+ To compile it as a module, choose M here. If unsure, say N.1111+1212+if IP_SET1313+1414+config IP_SET_MAX1515+ int "Maximum number of IP sets"1616+ default 2561717+ range 2 655341818+ depends on IP_SET1919+ help2020+ You can define here default value of the maximum number 2121+ of IP sets for the kernel.2222+2323+ The value can be overriden by the 'max_sets' module2424+ parameter of the 'ip_set' module.2525+2626+config IP_SET_BITMAP_IP2727+ tristate "bitmap:ip set support"2828+ depends on IP_SET2929+ help3030+ This option adds the bitmap:ip set type support, by which one3131+ can store IPv4 addresses (or network addresse) from a range.3232+3333+ To compile it as a module, choose M here. If unsure, say N.3434+3535+config IP_SET_BITMAP_IPMAC3636+ tristate "bitmap:ip,mac set support"3737+ depends on IP_SET3838+ help3939+ This option adds the bitmap:ip,mac set type support, by which one4040+ can store IPv4 address and (source) MAC address pairs from a range.4141+4242+ To compile it as a module, choose M here. If unsure, say N.4343+4444+config IP_SET_BITMAP_PORT4545+ tristate "bitmap:port set support"4646+ depends on IP_SET4747+ help4848+ This option adds the bitmap:port set type support, by which one4949+ can store TCP/UDP port numbers from a range.5050+5151+ To compile it as a module, choose M here. If unsure, say N.5252+5353+config IP_SET_HASH_IP5454+ tristate "hash:ip set support"5555+ depends on IP_SET5656+ help5757+ This option adds the hash:ip set type support, by which one5858+ can store arbitrary IPv4 or IPv6 addresses (or network addresses)5959+ in a set.6060+6161+ To compile it as a module, choose M here. If unsure, say N.6262+6363+config IP_SET_HASH_IPPORT6464+ tristate "hash:ip,port set support"6565+ depends on IP_SET6666+ help6767+ This option adds the hash:ip,port set type support, by which one6868+ can store IPv4/IPv6 address and protocol/port pairs.6969+7070+ To compile it as a module, choose M here. If unsure, say N.7171+7272+config IP_SET_HASH_IPPORTIP7373+ tristate "hash:ip,port,ip set support"7474+ depends on IP_SET7575+ help7676+ This option adds the hash:ip,port,ip set type support, by which7777+ one can store IPv4/IPv6 address, protocol/port, and IPv4/IPv67878+ address triples in a set.7979+8080+ To compile it as a module, choose M here. If unsure, say N.8181+8282+config IP_SET_HASH_IPPORTNET8383+ tristate "hash:ip,port,net set support"8484+ depends on IP_SET8585+ help8686+ This option adds the hash:ip,port,net set type support, by which8787+ one can store IPv4/IPv6 address, protocol/port, and IPv4/IPv68888+ network address/prefix triples in a set.8989+9090+ To compile it as a module, choose M here. If unsure, say N.9191+9292+config IP_SET_HASH_NET9393+ tristate "hash:net set support"9494+ depends on IP_SET9595+ help9696+ This option adds the hash:net set type support, by which9797+ one can store IPv4/IPv6 network address/prefix elements in a set.9898+9999+ To compile it as a module, choose M here. If unsure, say N.100100+101101+config IP_SET_HASH_NETPORT102102+ tristate "hash:net,port set support"103103+ depends on IP_SET104104+ help105105+ This option adds the hash:net,port set type support, by which106106+ one can store IPv4/IPv6 network address/prefix and107107+ protocol/port pairs as elements in a set.108108+109109+ To compile it as a module, choose M here. If unsure, say N.110110+111111+config IP_SET_LIST_SET112112+ tristate "list:set set support"113113+ depends on IP_SET114114+ help115115+ This option adds the list:set set type support. In this116116+ kind of set one can store the name of other sets and it forms117117+ an ordered union of the member sets.118118+119119+ To compile it as a module, choose M here. If unsure, say N.120120+121121+endif # IP_SET