📄 130-netfilter_ipset.patch
字号:
+ goto undo;+ memset(harray->arrays[i], 0, (hashsize - i * max_elements) * typesize);++ harray->max_elements = max_elements;+ harray->arrays[size] = NULL;+ + return (void *)harray;++ undo:+ for (j = 0; j < i; j++) {+ kfree(harray->arrays[j]);+ }+ kfree(harray);+ return NULL;+}++static inline void harray_free(void *h)+{+ struct harray *harray = (struct harray *) h;+ size_t i;+ + for (i = 0; harray->arrays[i] != NULL; i++)+ kfree(harray->arrays[i]);+ kfree(harray);+}++static inline void harray_flush(void *h, size_t hashsize, size_t typesize)+{+ struct harray *harray = (struct harray *) h;+ size_t i;+ + for (i = 0; harray->arrays[i+1] != NULL; i++)+ memset(harray->arrays[i], 0, harray->max_elements * typesize);+ memset(harray->arrays[i], 0, + (hashsize - i * harray->max_elements) * typesize);+}++#define HARRAY_ELEM(h, type, which) \+({ \+ struct harray *__h = (struct harray *)(h); \+ ((type)((__h)->arrays[(which)/(__h)->max_elements]) \+ + (which)%(__h)->max_elements); \+})++#endif /* __KERNEL__ */++#endif /*_IP_SET_MALLOC_H*/Index: linux-2.6.21.7/include/linux/netfilter_ipv4/ip_set_nethash.h===================================================================--- /dev/null+++ linux-2.6.21.7/include/linux/netfilter_ipv4/ip_set_nethash.h@@ -0,0 +1,55 @@+#ifndef __IP_SET_NETHASH_H+#define __IP_SET_NETHASH_H++#include <linux/netfilter_ipv4/ip_set.h>++#define SETTYPE_NAME "nethash"+#define MAX_RANGE 0x0000FFFF++struct ip_set_nethash {+ ip_set_ip_t *members; /* the nethash proper */+ uint32_t elements; /* number of elements */+ uint32_t hashsize; /* hash size */+ uint16_t probes; /* max number of probes */+ uint16_t resize; /* resize factor in percent */+ unsigned char cidr[30]; /* CIDR sizes */+ void *initval[0]; /* initvals for jhash_1word */+};++struct ip_set_req_nethash_create {+ uint32_t hashsize;+ uint16_t probes;+ uint16_t resize;+};++struct ip_set_req_nethash {+ ip_set_ip_t ip;+ unsigned char cidr;+};++static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};++static inline ip_set_ip_t +pack(ip_set_ip_t ip, unsigned char cidr)+{+ ip_set_ip_t addr, *paddr = &addr;+ unsigned char n, t, *a;++ addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));+#ifdef __KERNEL__+ DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);+#endif+ n = cidr / 8;+ t = cidr % 8; + a = &((unsigned char *)paddr)[n];+ *a = *a /(1 << (8 - t)) + shifts[t];+#ifdef __KERNEL__+ DP("n: %u, t: %u, a: %u", n, t, *a);+ DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",+ HIPQUAD(ip), cidr, NIPQUAD(addr));+#endif++ return ntohl(addr);+}++#endif /* __IP_SET_NETHASH_H */Index: linux-2.6.21.7/include/linux/netfilter_ipv4/ip_set_portmap.h===================================================================--- /dev/null+++ linux-2.6.21.7/include/linux/netfilter_ipv4/ip_set_portmap.h@@ -0,0 +1,25 @@+#ifndef __IP_SET_PORTMAP_H+#define __IP_SET_PORTMAP_H++#include <linux/netfilter_ipv4/ip_set.h>++#define SETTYPE_NAME "portmap"+#define MAX_RANGE 0x0000FFFF+#define INVALID_PORT (MAX_RANGE + 1)++struct ip_set_portmap {+ void *members; /* the portmap proper */+ ip_set_ip_t first_port; /* host byte order, included in range */+ ip_set_ip_t last_port; /* host byte order, included in range */+};++struct ip_set_req_portmap_create {+ ip_set_ip_t from;+ ip_set_ip_t to;+};++struct ip_set_req_portmap {+ ip_set_ip_t port;+};++#endif /* __IP_SET_PORTMAP_H */Index: linux-2.6.21.7/include/linux/netfilter_ipv4/ipt_set.h===================================================================--- /dev/null+++ linux-2.6.21.7/include/linux/netfilter_ipv4/ipt_set.h@@ -0,0 +1,21 @@+#ifndef _IPT_SET_H+#define _IPT_SET_H++#include <linux/netfilter_ipv4/ip_set.h>++struct ipt_set_info {+ ip_set_id_t index;+ u_int32_t flags[IP_SET_MAX_BINDINGS + 1];+};++/* match info */+struct ipt_set_info_match {+ struct ipt_set_info match_set;+};++struct ipt_set_info_target {+ struct ipt_set_info add_set;+ struct ipt_set_info del_set;+};++#endif /*_IPT_SET_H*/Index: linux-2.6.21.7/net/ipv4/netfilter/ip_set.c===================================================================--- /dev/null+++ linux-2.6.21.7/net/ipv4/netfilter/ip_set.c@@ -0,0 +1,2003 @@+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>+ * Patrick Schaaf <bof@bof.de>+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation. + */++/* Kernel module for IP set management */++#include <linux/version.h>+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)+#include <linux/config.h>+#endif+#include <linux/module.h>+#include <linux/moduleparam.h>+#include <linux/kmod.h>+#include <linux/ip.h>+#include <linux/skbuff.h>+#include <linux/random.h>+#include <linux/jhash.h>+#include <linux/netfilter_ipv4/ip_tables.h>+#include <linux/errno.h>+#include <asm/uaccess.h>+#include <asm/bitops.h>+#include <asm/semaphore.h>+#include <linux/spinlock.h>+#include <linux/vmalloc.h>++#define ASSERT_READ_LOCK(x)+#define ASSERT_WRITE_LOCK(x)+#include <linux/netfilter_ipv4/ip_set.h>++static struct list_head set_type_list; /* all registered sets */+static struct ip_set **ip_set_list; /* all individual sets */+static DEFINE_RWLOCK(ip_set_lock); /* protects the lists and the hash */+static DECLARE_MUTEX(ip_set_app_mutex); /* serializes user access */+static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;+static ip_set_id_t ip_set_bindings_hash_size = CONFIG_IP_NF_SET_HASHSIZE;+static struct list_head *ip_set_hash; /* hash of bindings */+static unsigned int ip_set_hash_random; /* random seed */++/*+ * Sets are identified either by the index in ip_set_list or by id.+ * The id never changes and is used to find a key in the hash. + * The index may change by swapping and used at all other places + * (set/SET netfilter modules, binding value, etc.)+ *+ * Userspace requests are serialized by ip_set_mutex and sets can+ * be deleted only from userspace. Therefore ip_set_list locking + * must obey the following rules:+ *+ * - kernel requests: read and write locking mandatory+ * - user requests: read locking optional, write locking mandatory+ */++static inline void+__ip_set_get(ip_set_id_t index)+{+ atomic_inc(&ip_set_list[index]->ref);+}++static inline void+__ip_set_put(ip_set_id_t index)+{+ atomic_dec(&ip_set_list[index]->ref);+}++/*+ * Binding routines+ */++static inline struct ip_set_hash *+__ip_set_find(u_int32_t key, ip_set_id_t id, ip_set_ip_t ip)+{+ struct ip_set_hash *set_hash;++ list_for_each_entry(set_hash, &ip_set_hash[key], list)+ if (set_hash->id == id && set_hash->ip == ip)+ return set_hash;+ + return NULL;+}++static ip_set_id_t+ip_set_find_in_hash(ip_set_id_t id, ip_set_ip_t ip)+{+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) + % ip_set_bindings_hash_size;+ struct ip_set_hash *set_hash;++ ASSERT_READ_LOCK(&ip_set_lock);+ IP_SET_ASSERT(ip_set_list[id]);+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); + + set_hash = __ip_set_find(key, id, ip);+ + DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, + HIPQUAD(ip),+ set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");++ return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID);+}++static inline void +__set_hash_del(struct ip_set_hash *set_hash)+{+ ASSERT_WRITE_LOCK(&ip_set_lock);+ IP_SET_ASSERT(ip_set_list[set_hash->binding]); ++ __ip_set_put(set_hash->binding);+ list_del(&set_hash->list);+ kfree(set_hash);+}++static int+ip_set_hash_del(ip_set_id_t id, ip_set_ip_t ip)+{+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)+ % ip_set_bindings_hash_size;+ struct ip_set_hash *set_hash;+ + IP_SET_ASSERT(ip_set_list[id]);+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); + write_lock_bh(&ip_set_lock);+ set_hash = __ip_set_find(key, id, ip);+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,+ HIPQUAD(ip),+ set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");++ if (set_hash != NULL)+ __set_hash_del(set_hash);+ write_unlock_bh(&ip_set_lock);+ return 0;+}++static int +ip_set_hash_add(ip_set_id_t id, ip_set_ip_t ip, ip_set_id_t binding)+{+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)+ % ip_set_bindings_hash_size;+ struct ip_set_hash *set_hash;+ int ret = 0;+ + IP_SET_ASSERT(ip_set_list[id]);+ IP_SET_ASSERT(ip_set_list[binding]);+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, + HIPQUAD(ip), ip_set_list[binding]->name);+ write_lock_bh(&ip_set_lock);+ set_hash = __ip_set_find(key, id, ip);+ if (!set_hash) {+ set_hash = kmalloc(sizeof(struct ip_set_hash), GFP_ATOMIC);+ if (!set_hash) {+ ret = -ENOMEM;+ goto unlock;+ }+ INIT_LIST_HEAD(&set_hash->list);+ set_hash->id = id;+ set_hash->ip = ip;+ list_add(&set_hash->list, &ip_set_hash[key]);+ } else {+ IP_SET_ASSERT(ip_set_list[set_hash->binding]); + DP("overwrite binding: %s",+ ip_set_list[set_hash->binding]->name);+ __ip_set_put(set_hash->binding);+ }+ set_hash->binding = binding;+ __ip_set_get(set_hash->binding);+ DP("stored: key %u, id %u (%s), ip %u.%u.%u.%u, binding %u (%s)",+ key, id, ip_set_list[id]->name,+ HIPQUAD(ip), binding, ip_set_list[binding]->name);+ unlock:+ write_unlock_bh(&ip_set_lock);+ return ret;+}++#define FOREACH_HASH_DO(fn, args...) \+({ \+ ip_set_id_t __key; \+ struct ip_set_hash *__set_hash; \+ \+ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \+ list_for_each_entry(__set_hash, &ip_set_hash[__key], list) \+ fn(__set_hash , ## args); \+ } \+})++#define FOREACH_HASH_RW_DO(fn, args...) \+({ \+ ip_set_id_t __key; \+ struct ip_set_hash *__set_hash, *__n; \+ \+ ASSERT_WRITE_LOCK(&ip_set_lock); \+ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \+ list_for_each_entry_safe(__set_hash, __n, &ip_set_hash[__key], list)\+ fn(__set_hash , ## args); \+ } \+})++/* Add, del and test set entries from kernel */++#define follow_bindings(index, set, ip) \+((index = ip_set_find_in_hash((set)->id, ip)) != IP_SET_INVALID_ID \+ || (index = (set)->binding) != IP_SET_INVALID_ID)++int+ip_set_testip_kernel(ip_set_id_t index,+ const struct sk_buff *skb,+ const u_int32_t *flags)+{+ struct ip_set *set;+ ip_set_ip_t ip;+ int res;+ unsigned char i = 0;+ + IP_SET_ASSERT(flags[i]);+ read_lock_bh(&ip_set_lock);+ do {+ set = ip_set_list[index];+ IP_SET_ASSERT(set);+ DP("set %s, index %u", set->name, index);+ read_lock_bh(&set->lock);+ res = set->type->testip_kernel(set, skb, &ip, flags, i++);+ read_unlock_bh(&set->lock);+ i += !!(set->type->features & IPSET_DATA_DOUBLE);+ } while (res > 0 + && flags[i] + && follow_bindings(index, set, ip));+ read_unlock_bh(&ip_set_lock);++ return res;+}++void+ip_set_addip_kernel(ip_set_id_t index,+ const struct sk_buff *skb,+ const u_int32_t *flags)+{+ struct ip_set *set;+ ip_set_ip_t ip;+ int res;+ unsigned char i = 0;++ IP_SET_ASSERT(flags[i]);+ retry:+ read_lock_bh(&ip_set_lock);+ do {+ set = ip_set_list[index];+ IP_SET_ASSERT(set);+ DP("set %s, index %u", set->name, index);+ write_lock_bh(&set->lock);+ res = set->type->addip_kernel(set, skb, &ip, flags, i++);+ write_unlock_bh(&set->lock);+ i += !!(set->type->features & IPSET_DATA_DOUBLE);+ } while ((res == 0 || res == -EEXIST)+ && flags[i] + && follow_bindings(index, set, ip));+ read_unlock_bh(&ip_set_lock);++ if (res == -EAGAIN+ && set->type->retry+ && (res = set->type->retry(set)) == 0)+ goto retry;+}++void+ip_set_delip_kernel(ip_set_id_t index,+ const struct sk_buff *skb,+ const u_int32_t *flags)+{+ struct ip_set *set;+ ip_set_ip_t ip;+ int res;+ unsigned char i = 0;++ IP_SET_ASSERT(flags[i]);+ read_lock_bh(&ip_set_lock);+ do {+ set = ip_set_list[index];+ IP_SET_ASSERT(set);+ DP("set %s, index %u", set->name, index);+ write_lock_bh(&set->lock);+ res = set->type->delip_kernel(set, skb, &ip, flags, i++);+ write_unlock_bh(&set->lock);+ i += !!(set->type->features & IPSET_DATA_DOUBLE);+ } while ((res == 0 || res == -EEXIST)+ && flags[i] + && follow_bindings(index, set, ip));+ read_unlock_bh(&ip_set_lock);+}++/* Register and deregister settype */++static inline struct ip_set_type *+find_set_type(const char *name)+{+ struct ip_set_type *set_type;++ list_for_each_entry(set_type, &set_type_list, list)+ if (!strncmp(set_type->typename, name, IP_SET_MAXNAMELEN - 1))+ return set_type;+ return NULL;+}++int +ip_set_register_set_type(struct ip_set_type *set_type)+{+ int ret = 0;+ + if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) {+ ip_set_printk("'%s' uses wrong protocol version %u (want %u)",+ set_type->typename,+ set_type->protocol_version,+ IP_SET_PROTOCOL_VERSION);+ return -EINVAL;+ }++ write_lock_bh(&ip_set_lock);+ if (find_set_type(set_type->typename)) {+ /* Duplicate! */+ ip_set_printk("'%s' already registered!", + set_type->typename);+ ret = -EINVAL;+ goto unlock;+ }+ if (!try_module_get(THIS_MODULE)) {+ ret = -EFAULT;+ goto unlock;+ }+ list_add(&set_type->list, &set_type_list);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -