⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 130-netfilter_ipset.patch

📁 Linux Home Server 是专门为家庭和SOHO/SMB 设计的高性价比的ISCSI 存储服务器, 具有如下的特色: 强大的iscsi 存储服务器软件; 混合iscsi 和NAS 服务;
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+	DP("'%s' registered.", set_type->typename);+   unlock:+	write_unlock_bh(&ip_set_lock);+	return ret;+}++void+ip_set_unregister_set_type(struct ip_set_type *set_type)+{+	write_lock_bh(&ip_set_lock);+	if (!find_set_type(set_type->typename)) {+		ip_set_printk("'%s' not registered?",+			      set_type->typename);+		goto unlock;+	}+	list_del(&set_type->list);+	module_put(THIS_MODULE);+	DP("'%s' unregistered.", set_type->typename);+   unlock:+	write_unlock_bh(&ip_set_lock);++}++/*+ * Userspace routines+ */++/*+ * Find set by name, reference it once. The reference makes sure the+ * thing pointed to, does not go away under our feet. Drop the reference+ * later, using ip_set_put().+ */+ip_set_id_t+ip_set_get_byname(const char *name)+{+	ip_set_id_t i, index = IP_SET_INVALID_ID;+	+	down(&ip_set_app_mutex);+	for (i = 0; i < ip_set_max; i++) {+		if (ip_set_list[i] != NULL+		    && strcmp(ip_set_list[i]->name, name) == 0) {+			__ip_set_get(i);+			index = i;+			break;+		}+	}+	up(&ip_set_app_mutex);+	return index;+}++/*+ * Find set by index, reference it once. The reference makes sure the+ * thing pointed to, does not go away under our feet. Drop the reference+ * later, using ip_set_put().+ */+ip_set_id_t+ip_set_get_byindex(ip_set_id_t index)+{+	down(&ip_set_app_mutex);++	if (index >= ip_set_max)+		return IP_SET_INVALID_ID;+	+	if (ip_set_list[index])+		__ip_set_get(index);+	else+		index = IP_SET_INVALID_ID;+		+	up(&ip_set_app_mutex);+	return index;+}++/*+ * If the given set pointer points to a valid set, decrement+ * reference count by 1. The caller shall not assume the index+ * to be valid, after calling this function.+ */+void ip_set_put(ip_set_id_t index)+{+	down(&ip_set_app_mutex);+	if (ip_set_list[index])+		__ip_set_put(index);+	up(&ip_set_app_mutex);+}++/* Find a set by name or index */+static ip_set_id_t+ip_set_find_byname(const char *name)+{+	ip_set_id_t i, index = IP_SET_INVALID_ID;+	+	for (i = 0; i < ip_set_max; i++) {+		if (ip_set_list[i] != NULL+		    && strcmp(ip_set_list[i]->name, name) == 0) {+			index = i;+			break;+		}+	}+	return index;+}++static ip_set_id_t+ip_set_find_byindex(ip_set_id_t index)+{+	if (index >= ip_set_max || ip_set_list[index] == NULL)+		index = IP_SET_INVALID_ID;+	+	return index;+}++/*+ * Add, del, test, bind and unbind+ */++static inline int+__ip_set_testip(struct ip_set *set,+	        const void *data,+	        size_t size,+	        ip_set_ip_t *ip)+{+	int res;++	read_lock_bh(&set->lock);+	res = set->type->testip(set, data, size, ip);+	read_unlock_bh(&set->lock);++	return res;+}++static int+__ip_set_addip(ip_set_id_t index,+	       const void *data,+	       size_t size)+{+	struct ip_set *set = ip_set_list[index];+	ip_set_ip_t ip;+	int res;+	+	IP_SET_ASSERT(set);+	do {+		write_lock_bh(&set->lock);+		res = set->type->addip(set, data, size, &ip);+		write_unlock_bh(&set->lock);+	} while (res == -EAGAIN+		 && set->type->retry+		 && (res = set->type->retry(set)) == 0);++	return res;+}++static int+ip_set_addip(ip_set_id_t index,+	     const void *data,+	     size_t size)+{++	return __ip_set_addip(index,+			      data + sizeof(struct ip_set_req_adt),+			      size - sizeof(struct ip_set_req_adt));+}++static int+ip_set_delip(ip_set_id_t index,+	     const void *data,+	     size_t size)+{+	struct ip_set *set = ip_set_list[index];+	ip_set_ip_t ip;+	int res;+	+	IP_SET_ASSERT(set);+	write_lock_bh(&set->lock);+	res = set->type->delip(set,+			       data + sizeof(struct ip_set_req_adt),+			       size - sizeof(struct ip_set_req_adt),+			       &ip);+	write_unlock_bh(&set->lock);++	return res;+}++static int+ip_set_testip(ip_set_id_t index,+	      const void *data,+	      size_t size)+{+	struct ip_set *set = ip_set_list[index];+	ip_set_ip_t ip;+	int res;++	IP_SET_ASSERT(set);+	res = __ip_set_testip(set,+			      data + sizeof(struct ip_set_req_adt),+			      size - sizeof(struct ip_set_req_adt),+			      &ip);++	return (res > 0 ? -EEXIST : res);+}++static int+ip_set_bindip(ip_set_id_t index,+	      const void *data,+	      size_t size)+{+	struct ip_set *set = ip_set_list[index];+	struct ip_set_req_bind *req_bind;+	ip_set_id_t binding;+	ip_set_ip_t ip;+	int res;++	IP_SET_ASSERT(set);+	if (size < sizeof(struct ip_set_req_bind))+		return -EINVAL;+		+	req_bind = (struct ip_set_req_bind *) data;+	req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';++	if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {+		/* Default binding of a set */+		char *binding_name;+		+		if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)+			return -EINVAL;++		binding_name = (char *)(data + sizeof(struct ip_set_req_bind));	+		binding_name[IP_SET_MAXNAMELEN - 1] = '\0';++		binding = ip_set_find_byname(binding_name);+		if (binding == IP_SET_INVALID_ID)+			return -ENOENT;++		write_lock_bh(&ip_set_lock);+		/* Sets as binding values are referenced */+		if (set->binding != IP_SET_INVALID_ID)+			__ip_set_put(set->binding);+		set->binding = binding;+		__ip_set_get(set->binding);+		write_unlock_bh(&ip_set_lock);++		return 0;+	}+	binding = ip_set_find_byname(req_bind->binding);+	if (binding == IP_SET_INVALID_ID)+		return -ENOENT;++	res = __ip_set_testip(set,+			      data + sizeof(struct ip_set_req_bind),+			      size - sizeof(struct ip_set_req_bind),+			      &ip);+	DP("set %s, ip: %u.%u.%u.%u, binding %s",+	   set->name, HIPQUAD(ip), ip_set_list[binding]->name);+	+	if (res >= 0)+		res = ip_set_hash_add(set->id, ip, binding);++	return res;+}++#define FOREACH_SET_DO(fn, args...) 				\+({								\+	ip_set_id_t __i;					\+	struct ip_set *__set;					\+								\+	for (__i = 0; __i < ip_set_max; __i++) {		\+		__set = ip_set_list[__i];			\+		if (__set != NULL)				\+			fn(__set , ##args);			\+	}							\+})++static inline void+__set_hash_del_byid(struct ip_set_hash *set_hash, ip_set_id_t id)+{+	if (set_hash->id == id)+		__set_hash_del(set_hash);+}++static inline void+__unbind_default(struct ip_set *set)+{+	if (set->binding != IP_SET_INVALID_ID) {+		/* Sets as binding values are referenced */+		__ip_set_put(set->binding);+		set->binding = IP_SET_INVALID_ID;+	}+}++static int+ip_set_unbindip(ip_set_id_t index,+	        const void *data,+	        size_t size)+{+	struct ip_set *set;+	struct ip_set_req_bind *req_bind;+	ip_set_ip_t ip;+	int res;++	DP("");+	if (size < sizeof(struct ip_set_req_bind))+		return -EINVAL;+		+	req_bind = (struct ip_set_req_bind *) data;+	req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';+	+	DP("%u %s", index, req_bind->binding);+	if (index == IP_SET_INVALID_ID) {+		/* unbind :all: */+		if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {+			/* Default binding of sets */+			write_lock_bh(&ip_set_lock);+			FOREACH_SET_DO(__unbind_default);+			write_unlock_bh(&ip_set_lock);+			return 0;+		} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {+			/* Flush all bindings of all sets*/+			write_lock_bh(&ip_set_lock);+			FOREACH_HASH_RW_DO(__set_hash_del);+			write_unlock_bh(&ip_set_lock);+			return 0;+		}+		DP("unreachable reached!");+		return -EINVAL;+	}+	+	set = ip_set_list[index];+	IP_SET_ASSERT(set);+	if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {+		/* Default binding of set */+		ip_set_id_t binding = ip_set_find_byindex(set->binding);++		if (binding == IP_SET_INVALID_ID)+			return -ENOENT;+			+		write_lock_bh(&ip_set_lock);+		/* Sets in hash values are referenced */+		__ip_set_put(set->binding);+		set->binding = IP_SET_INVALID_ID;+		write_unlock_bh(&ip_set_lock);++		return 0;+	} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {+		/* Flush all bindings */++		write_lock_bh(&ip_set_lock);+		FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);+		write_unlock_bh(&ip_set_lock);+		return 0;+	}+	+	res = __ip_set_testip(set,+			      data + sizeof(struct ip_set_req_bind),+			      size - sizeof(struct ip_set_req_bind),+			      &ip);++	DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));+	if (res >= 0)+		res = ip_set_hash_del(set->id, ip);++	return res;+}++static int+ip_set_testbind(ip_set_id_t index,+	        const void *data,+	        size_t size)+{+	struct ip_set *set = ip_set_list[index];+	struct ip_set_req_bind *req_bind;+	ip_set_id_t binding;+	ip_set_ip_t ip;+	int res;++	IP_SET_ASSERT(set);+	if (size < sizeof(struct ip_set_req_bind))+		return -EINVAL;+		+	req_bind = (struct ip_set_req_bind *) data;+	req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';++	if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {+		/* Default binding of set */+		char *binding_name;+		+		if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)+			return -EINVAL;++		binding_name = (char *)(data + sizeof(struct ip_set_req_bind));	+		binding_name[IP_SET_MAXNAMELEN - 1] = '\0';++		binding = ip_set_find_byname(binding_name);+		if (binding == IP_SET_INVALID_ID)+			return -ENOENT;+		+		res = (set->binding == binding) ? -EEXIST : 0;++		return res;+	}+	binding = ip_set_find_byname(req_bind->binding);+	if (binding == IP_SET_INVALID_ID)+		return -ENOENT;+		+	+	res = __ip_set_testip(set,+			      data + sizeof(struct ip_set_req_bind),+			      size - sizeof(struct ip_set_req_bind),+			      &ip);+	DP("set %s, ip: %u.%u.%u.%u, binding %s",+	   set->name, HIPQUAD(ip), ip_set_list[binding]->name);+	   +	if (res >= 0)+		res = (ip_set_find_in_hash(set->id, ip) == binding)+			? -EEXIST : 0;++	return res;+}++static struct ip_set_type *+find_set_type_rlock(const char *typename)+{+	struct ip_set_type *type;+	+	read_lock_bh(&ip_set_lock);+	type = find_set_type(typename);+	if (type == NULL)+		read_unlock_bh(&ip_set_lock);++	return type;+}++static int+find_free_id(const char *name,+	     ip_set_id_t *index,+	     ip_set_id_t *id)+{+	ip_set_id_t i;++	*id = IP_SET_INVALID_ID;+	for (i = 0;  i < ip_set_max; i++) {+		if (ip_set_list[i] == NULL) {+			if (*id == IP_SET_INVALID_ID)+				*id = *index = i;+		} else if (strcmp(name, ip_set_list[i]->name) == 0)+			/* Name clash */+			return -EEXIST;+	}+	if (*id == IP_SET_INVALID_ID)+		/* No free slot remained */+		return -ERANGE;+	/* Check that index is usable as id (swapping) */+    check:	+	for (i = 0;  i < ip_set_max; i++) {+		if (ip_set_list[i] != NULL+		    && ip_set_list[i]->id == *id) {+		    *id = i;+		    goto check;+		}+	}+	return 0;+}++/*+ * Create a set+ */+static int+ip_set_create(const char *name,+	      const char *typename,+	      ip_set_id_t restore,+	      const void *data,+	      size_t size)+{+	struct ip_set *set;+	ip_set_id_t index = 0, id;+	int res = 0;++	DP("setname: %s, typename: %s, id: %u", name, typename, restore);+	/*+	 * First, and without any locks, allocate and initialize+	 * a normal base set structure.+	 */+	set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);+	if (!set)+		return -ENOMEM;+	set->lock = RW_LOCK_UNLOCKED;+	strncpy(set->name, name, IP_SET_MAXNAMELEN);+	set->binding = IP_SET_INVALID_ID;+	atomic_set(&set->ref, 0);++	/*+	 * Next, take the &ip_set_lock, check that we know the type,+	 * and take a reference on the type, to make sure it+	 * stays available while constructing our new set.+	 *+	 * After referencing the type, we drop the &ip_set_lock,+	 * and let the new set construction run without locks.+	 */+	set->type = find_set_type_rlock(typename);+	if (set->type == NULL) {+		/* Try loading the module */+		char modulename[IP_SET_MAXNAMELEN + strlen("ip_set_") + 1];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -