diff -urN ipset-4.2-orig/ipset.c ipset-4.2/ipset.c
--- ipset-4.2-orig/ipset.c	2011-01-10 18:42:44.468237650 +0800
+++ ipset-4.2/ipset.c	2011-01-10 19:01:35.187500000 +0800
@@ -148,6 +148,18 @@
 	 /*VERSION*/ {'x', 'x', 'x', ' ', 'x'},
 };
 
+struct pprot {
+	char *name;
+	unsigned int num;
+};
+
+static const struct pprot chain_protos[] = {
+	{ "tcp",  IPPROTO_TCP },
+	{ "udp",  IPPROTO_UDP },
+	{ "icmp", IPPROTO_ICMP },
+	{ "igmp", IPPROTO_IGMP }
+};
+
 /* Main parser function */
 int parse_commandline(int argc, char *argv[]);
 
@@ -722,6 +734,62 @@
 	return -1;
 }
 
+int strings_to_index(const char *strs[], int strs_size, const char *str, ip_set_ip_t *port)
+{
+	int i;
+	for (i = 0; i < strs_size; i++) 
+	{
+		if (strcmp(strs[i], str) == 0) 
+		{
+			*port = i;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void strings_print(const char *strs[], int strs_size, const char *str)
+{
+	int i;
+	for (i = 0; i < strs_size; i++) 
+	{
+		printf(str, strs[i]);	
+	}
+}
+
+unsigned char parse_protocol(const char *s)
+{
+    unsigned int proto = 0;
+    unsigned int i;
+
+    if (string_to_number(s, 0, 255, &proto) == -1) {
+        for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++) {
+            if (strcasecmp(s, chain_protos[i].name) == 0) {
+                proto = chain_protos[i].num;
+                break;
+            }
+        }
+    }
+
+    return (unsigned char)proto;
+}
+
+char* protocol_to_string(unsigned int proto)
+{
+	char *s;
+	unsigned int i;
+	for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++) {
+		if (proto == chain_protos[i].num) {
+			s = chain_protos[i].name;
+			break;
+		}
+	}
+	if (i == sizeof(chain_protos)/sizeof(struct pprot))
+		return (char *) 0;
+
+	return s;
+}
+
 static int
 string_to_port(const char *str, ip_set_ip_t *port)
 {
diff -urN ipset-4.2-orig/ipset.h ipset-4.2/ipset.h
--- ipset-4.2-orig/ipset.h	2011-01-10 18:42:44.468237650 +0800
+++ ipset-4.2/ipset.h	2011-01-10 19:01:44.078125000 +0800
@@ -174,6 +174,10 @@
 extern void parse_port(const char *str, ip_set_ip_t * port);
 extern int string_to_number(const char *str, unsigned int min, unsigned int max,
 		            ip_set_ip_t *port);
+extern int strings_to_index(const char *strs[], int strs_size, const char *str, ip_set_ip_t *port);
+extern void strings_print(const char *strs[], int strs_size, const char *str);
+extern unsigned char parse_protocol(const char *s);
+extern char* protocol_to_string(unsigned int proto);
 
 extern void *ipset_malloc(size_t size);
 extern char *ipset_strdup(const char *);
diff -urN ipset-4.2-orig/kernel/include/linux/netfilter_ipv4/ip_set.h ipset-4.2/kernel/include/linux/netfilter_ipv4/ip_set.h
--- ipset-4.2-orig/kernel/include/linux/netfilter_ipv4/ip_set.h	2011-01-10 18:42:44.452237377 +0800
+++ ipset-4.2/kernel/include/linux/netfilter_ipv4/ip_set.h	2011-01-11 13:59:16.269921000 +0800
@@ -80,6 +80,11 @@
 #define IPSET_SRC 		0x01	/* Source match/add */
 #define IPSET_DST		0x02	/* Destination match/add */
 #define IPSET_MATCH_INV		0x04	/* Inverse matching */
+#define IPSET_MATCH_LOG		0x08	/* Inverse matching */
+#define IPSET_MATCH_DEBUG		0x10	/* Inverse matching */
+#define IPSET_MATCH_REJ   0x20	/* Reject target matching */
+#define IPSET_MATCH_PASS  0x40	/* Accpet flag for syslog print */
+#define IPSET_MATCH_DRP 0x80
 
 /*
  * Set features
@@ -91,6 +96,7 @@
 #define IPSET_DATA_TRIPLE	0x10	/* Triple data storage */
 #define IPSET_TYPE_IP1		0x20	/* IP address type of set */
 #define IPSET_TYPE_SETNAME	0x40	/* setname type of set */
+#define IPSET_TYPE_LIST		0x80	/* setname type of set */
 
 /* Reserved keywords */
 #define IPSET_TOKEN_DEFAULT	":default:"
diff -urN ipset-4.2-orig/kernel/include/linux/netfilter_ipv4/ipt_set.h ipset-4.2/kernel/include/linux/netfilter_ipv4/ipt_set.h
--- ipset-4.2-orig/kernel/include/linux/netfilter_ipv4/ipt_set.h	2011-01-10 18:42:44.452237377 +0800
+++ ipset-4.2/kernel/include/linux/netfilter_ipv4/ipt_set.h	2011-01-14 14:35:34.889250000 +0800
@@ -3,6 +3,8 @@
 
 #include <linux/netfilter_ipv4/ip_set.h>
 
+#define MAXSET 32
+
 struct ipt_set_info {
 	ip_set_id_t index;
 	u_int32_t flags[IP_SET_MAX_BINDINGS + 1];
@@ -13,6 +15,11 @@
 	struct ipt_set_info match_set;
 };
 
+/* multi match info */
+struct ipt_mset_info_match {
+	struct ipt_set_info match_set[MAXSET];
+};
+
 struct ipt_set_info_target {
 	struct ipt_set_info add_set;
 	struct ipt_set_info del_set;
diff -urN ipset-4.2-orig/kernel/ip_set.c ipset-4.2/kernel/ip_set.c
--- ipset-4.2-orig/kernel/ip_set.c	2011-01-10 18:42:44.299487698 +0800
+++ ipset-4.2/kernel/ip_set.c	2011-02-21 14:11:38.437375000 +0800
@@ -84,9 +84,13 @@
 
 	read_lock_bh(&ip_set_lock);
 	set = ip_set_list[index];
+	if(!set || !set->name){
+		read_unlock_bh(&ip_set_lock);
+		printk(IPFLOG_ALERT "[CSM]IP_SET_ASSERT: %s:%i(%s)\n",__FILE__, __LINE__, __FUNCTION__);
+		return 0;
+	}	
 	IP_SET_ASSERT(set);
 	DP("set %s, index %u", set->name, index);
-
 	read_lock_bh(&set->lock);
 	res = set->type->testip_kernel(set, skb, flags);
 	read_unlock_bh(&set->lock);
diff -urN ipset-4.2-orig/kernel/Kbuild ipset-4.2/kernel/Kbuild
--- ipset-4.2-orig/kernel/Kbuild	2011-01-10 18:42:44.311487808 +0800
+++ ipset-4.2/kernel/Kbuild	2011-01-25 15:49:52.256344740 +0800
@@ -2,12 +2,13 @@
 	-DCONFIG_IP_NF_SET_MAX=$(IP_NF_SET_MAX) \
 	-DCONFIG_IP_NF_SET_HASHSIZE=$(IP_NF_SET_HASHSIZE)
 
-obj-m += ip_set.o ipt_set.o ipt_SET.o
+obj-m += ip_set.o ipt_set.o ipt_SET.o ipt_mset.o
 obj-m += ip_set_ipmap.o ip_set_macipmap.o ip_set_portmap.o
 obj-m += ip_set_iphash.o ip_set_nethash.o ip_set_ipporthash.o
 obj-m += ip_set_ipportiphash.o ip_set_ipportnethash.o
 obj-m += ip_set_iptree.o ip_set_iptreemap.o
 obj-m += ip_set_setlist.o
+obj-m +=ip_set_webcategory.o
 
 # It's for me...
 incdirs := $(M) $(M)/include/linux/netfilter_ipv4
diff -urN ipset-4.2-orig/kernel/Kconfig.ipset ipset-4.2/kernel/Kconfig.ipset
--- ipset-4.2-orig/kernel/Kconfig.ipset	2011-01-10 18:42:44.436237236 +0800
+++ ipset-4.2/kernel/Kconfig.ipset	2011-01-25 15:50:24.551887000 +0800
@@ -55,6 +55,14 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_SET_WEBCATEGORY
+	tristate "webcategory set support"
+	depends on IP_NF_SET
+	help
+	  This option adds the webcategory set type support.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_SET_IPHASH
 	tristate "iphash set support"
 	depends on IP_NF_SET
@@ -128,6 +136,15 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_MATCH_MSET
+	tristate "mset match support"
+	depends on IP_NF_SET
+	help
+	  Multi Set matching matches against given IP sets.
+	  You need the ipset utility to create and set up the sets.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_TARGET_SET
 	tristate "SET target support"
 	depends on IP_NF_SET
@@ -137,4 +154,3 @@
 	  You need the ipset utility to create and set up the sets.
 
 	  To compile it as a module, choose M here.  If unsure, say N.
-
diff -urN ipset-4.2-orig/kernel/Makefile.ipset ipset-4.2/kernel/Makefile.ipset
--- ipset-4.2-orig/kernel/Makefile.ipset	2011-01-10 18:42:44.327737291 +0800
+++ ipset-4.2/kernel/Makefile.ipset	2011-01-25 16:04:28.828595294 +0800
@@ -11,7 +11,9 @@
 obj-$(CONFIG_IP_NF_SET_IPTREE) += ip_set_iptree.o
 obj-$(CONFIG_IP_NF_SET_IPTREEMAP) += ip_set_iptreemap.o
 obj-$(CONFIG_IP_NF_SET_SETLIST) += ip_set_setlist.o
+obj-$(CONFIG_IP_NF_SET_WEBCATEGORY) += ip_set_webcategory.o
 
 # match and target
 obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o
 obj-$(CONFIG_IP_NF_TARGET_SET) += ipt_SET.o
+obj-$(CONFIG_IP_NF_MATCH_MSET) += ipt_mset.o
diff -urN ipset-4.2-orig/libipt_set.h ipset-4.2/libipt_set.h
--- ipset-4.2-orig/libipt_set.h	2011-01-10 18:42:44.291487329 +0800
+++ ipset-4.2/libipt_set.h	2011-01-10 19:01:59.953125000 +0800
@@ -29,9 +29,19 @@
 			info->flags[i++] |= IPSET_SRC;
 		else if (strncmp(ptr, "dst", 3) == 0)
 			info->flags[i++] |= IPSET_DST;
+		else if (strncmp(ptr, "log", 3) == 0)
+			info->flags[0] |= IPSET_MATCH_LOG;
+		else if (strncmp(ptr, "debug", 5) == 0)
+			info->flags[0] |= IPSET_MATCH_DEBUG;		
+		else if (strncmp(ptr, "rej", 3) == 0)
+			info->flags[0] |= IPSET_MATCH_REJ;		
+		else if (strncmp(ptr, "pass", 4) == 0)
+			info->flags[0] |= IPSET_MATCH_PASS;		
+		else if (strncmp(ptr, "drop", 4) == 0)
+			info->flags[0] |= IPSET_MATCH_DRP;
 		else
 			exit_error(PARAMETER_PROBLEM,
-				   "You must spefify (the comma separated list of) 'src' or 'dst'.");
+				   "You must specify (the comma separated list of) 'src', 'dst', 'debug', or 'log'");
 	}
 
 	if (tmp)
diff -urN ipset-4.2-orig/Makefile ipset-4.2/Makefile
--- ipset-4.2-orig/Makefile	2011-01-10 18:42:44.468237650 +0800
+++ ipset-4.2/Makefile	2011-01-18 18:30:53.802158485 +0800
@@ -67,7 +67,7 @@
 CFLAGS:=$(ABI_FLAGS) $(COPT_FLAGS) $(WARN_FLAGS) -Ikernel/include -I. # -g -DIPSET_DEBUG
 SH_CFLAGS:=$(CFLAGS) -fPIC
 LDFLAGS:=$(ABI_FLAGS)
-SETTYPES:=ipmap portmap macipmap
+SETTYPES:=ipmap portmap macipmap webcategory
 SETTYPES+=iptree iptreemap
 SETTYPES+=iphash nethash ipporthash ipportiphash ipportnethash
 SETTYPES+=setlist
