首页 > 代码库 > 可编译易用的模块化nf-HiPAC移植成功

可编译易用的模块化nf-HiPAC移植成功

由于早在上周三对这个周末就有了别的安排,要折腾空气压缩机,突然接到通知又要陪老婆去考试,幸亏周四靠晚上的时间完成了nf-HiPAC的移植工作。
       模块化nf-HiPAC的工作只能排在晚上完成,周四晚上折腾到12点终于算是完成了。效果也还不错,最初的tar包放到了下载频道“模块化的nf-HiPAC”,也会有另外的人放在github上,下载频道的主要是为了使用,而github上的主要是为了更新,这主要鉴于nf-hipac在还有很多TODO的情况下就停止了更新,这些TODO在其网页http://www.hipac.org/status/todo.html是可以查到的。

       主要的TODO列表如下(主要是怕以上这个网页也不在了...):


Planned Features:

    implement better algorithmic core: The new core will dramatically reduce memory usage while at the same time improving the running time of insert and delete operations. The lookup performance will be improved radically too, especially for bigger rulesets. The concepts and the design are already developed, but the implementation is still in its very early stages
    add support for transactions
    add support for ipv6
    add support for MAC matches
    add functionality similar to iptables-restore
    add native support for set of ranges (e.g. ippools). Each native match is not a single range but instead a set of ranges, which makes a single rule more expressive
    consider making HiPAC available for NAT and mangle tables
    consider removing "rule prefix mismatch" limitation
    the next big step in the far future will be to extend the HiPAC algorithm to do classification with several stages. The HiPAC algorithm will then be capable of combining several classification problems in one data structure, e.g. it will be possible to solve routing, firewalling and traffic control with one HiPAC lookup. The idea is to shorten the packet forwarding path by combining e.g. fib_lookup and iptables filter lookup into one HiPAC query

Outstanding Bugfixes:

    fix handling of jump rules containing iptables matches (currently only some known iptables matches are allowed in jump rules)
    in the current version the number of rule updates per second is limited by the number of synchronize_rcu() calls per second. This slows down rule updates dramatically. Future releases will work around this problem and will offer full rule update speed again

Other Stuff:

    man page for userspace tool
    add more documentation
    more in-depth performance tests

模块化后的nf-hipac可以直接编译出一个ko文件以及一个用户态的工具nf-hipac程序。值得注意的是,我在移植过程中,去掉了和iptables模块的联动机制,这有两方面的原因,第一是因为这方面的移植比较复杂,iptables的内核API在内核版本之间变化太大了;另一方面就是还真的不怎么会用到iptables的match/target模块,如果使用了大量的iptables match/target模块,还不如直接就用iptables呢,再者说,iptables模块只是延展了nf-hipac的功能,对其性能是一个打折的过程。
       以下是模块化移植工作遇到的一些问题:

1.iptables模块的问题

需要将match/target操作进行移植,内核API变化太大,砍去。

2.netlink接口问题

这部分比较容易。2.6.13版本的netlink的input回调函数参数是一个socket,创建者需要自己创建内核线程来从该socket的queue中持续获取skb并且维护queue本身,这部分工作在高版本内核中得到了简化,因为input回调函数的参数就是skb本身,队列的维护由netlink系统完成。

3.内存问题

在原始的nf-hipac中,为了节省内存,用了两套内存管理方案,即mini alloc/free以及big alloc/free,在调试这部分的时候遇到了不少问题,加之现在内存没必要那么节省,我就统一采用了big alloc/free,也就是说统一在vmalloc区域进行分配。

4.net namespace问题

说实话,2.6.32内核对net namespace的支持也只是个半吊子,但无论如何接口已经适配了,这就是说我必须按照net namespace的要求来处理proc_net。

5.其它

我只是测试了2.6.32内核和3.9.6内核,对于其它版本的内核并没有测试,这种风格也是拜ipset-6.23所赐,要知道,我也是一个很较真儿的人,有时候也会有点书生气。
...

即便是不下载tgz压缩包,也可以通过打patch的方式构建编译目录。
新建一个nf-hipac空目录并cd到它,然后执行:
patch -p1 < $path/nfhipac-1.0.0.patch

就会将所有的文件和目录置于该目录下,然后make;make install即可。注意,编译的时候需要准备好你的当前内核版本头文件,链接到/lib/modules/`uname -r`/build。 最后给出一个比较长的patch,即nfhipac-1.0.0.patch文件:

diff -uNr nf-hipac/INSTALL nfhipac/INSTALL
--- nf-hipac/INSTALL	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/INSTALL	2014-11-21 13:00:42.000000000 +0800
@@ -0,0 +1,3 @@
+
+
+make install
diff -uNr nf-hipac/kernel/dimtree.c nfhipac/kernel/dimtree.c
--- nf-hipac/kernel/dimtree.c	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/dimtree.c	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,4308 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#include "global.h"
+#include "ihash.h"
+#include "rlp.h"
+#include "dimtree.h"
+
+
+#define HAS_DT_MATCH(rule)      ((rule)->dt_match_len > 0)
+#define ITH_DT_MATCH(rule, i)   ((rule)->first_dt_match + (i))
+#define LAST_DT_MATCH(rule)     ITH_DT_MATCH(rule, (rule)->dt_match_len - 1)
+#define LEN(array)              (sizeof(array) / sizeof(*(array)))
+
+/*
+ * newspec keeps track of the rlps and elementary intervals that have been
+ * newly allocated during a series of dimtree operations;
+ * orgspec keeps track of the rlps and elementary intervals that can be
+ * freed after the series of dimtree operations has been successfully finished
+ */
+static struct ptrlist orgspec = {LIST_HEAD_INIT(orgspec.head), 0};
+static struct ihash *newspec  = NULL;
+
+
+
+static inline void
+elem_free(struct dt_elem *e)
+{
+	if (unlikely(e == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	hp_free(e);
+}
+
+
+/* free s which can be an elemtary interval or a rlp */
+static inline void
+rlp_elem_free(struct gen_spec *s)
+{
+	if (unlikely(s == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	if (IS_RLP(s)) {
+		rlp_free((struct rlp_spec *) s);
+	} else {
+		/* s must be elemtary interval */
+		assert(IS_ELEM(s));
+		elem_free((struct dt_elem *) s);
+	}
+}
+
+/* set newspec bit of s which can be an elementary interval or a rlp to 0 */
+static inline void
+rlp_elem_newspec_set(struct gen_spec *s, int newspec_set)
+{
+	if (unlikely(s == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	if (IS_RLP(s)) {
+		((struct rlp_spec *) s)->newspec = !!newspec_set;
+	} else {
+		/* s must be elemtary interval */
+		assert(IS_ELEM(s));
+		((struct dt_elem_spec *) s)->newspec = !!newspec_set;
+	}
+}
+
+/* call rlp_elem_free for each member of orgspec and empty orgspec */
+static inline void
+orgspec_dofree(void)
+{
+	struct list_head *lh;
+	struct ptrlist_entry* e;
+
+	for (lh = orgspec.head.next; lh != &orgspec.head;) {
+		e = list_entry(lh, struct ptrlist_entry, head);
+		lh = lh->next;
+		assert((IS_RLP(e->p) &&
+			!((struct rlp_spec *) e->p)->newspec) ||
+		       (IS_ELEM(e->p) &&
+			!((struct dt_elem_spec *) e->p)->newspec));
+		rlp_elem_free(e->p);
+		mini_free(e);
+	}
+	INIT_LIST_HEAD(&orgspec.head);
+	orgspec.len = 0;
+}
+
+/* call rlp_elem_free for each member of newspec and empty newspec */
+static inline void
+newspec_dofree(void)
+{
+	if (unlikely(newspec == NULL)) {
+		return;
+	}
+	IHASH_KEY_ITERATE(newspec, struct gen_spec *, rlp_elem_free);
+	ihash_free(newspec);
+	newspec = NULL;
+}
+
+/* add s to orgspec;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+static inline hipac_error
+orgspec_add(struct gen_spec *s)
+{
+	if (unlikely(s == NULL)) {
+		ARG_ERR;
+	}
+	assert((IS_RLP(s) && !((struct rlp_spec *) s)->newspec) ||
+	       (IS_ELEM(s) && !((struct dt_elem_spec *) s)->newspec));
+#ifdef DEBUG
+	return ptrlist_add(&orgspec, s, 1);
+#else
+	return ptrlist_add(&orgspec, s, 0);
+#endif
+}
+
+/* empty orgspec */
+static inline void
+orgspec_flush(void)
+{
+	ptrlist_flush(&orgspec);
+}
+
+/* empty newspec; if newspec_reset is not 0 the newspec bit is set
+   to 0 for each element of newspec */
+static inline void
+newspec_flush(int newspec_reset)
+{
+	if (unlikely(newspec == NULL)) {
+		return;
+	}
+	if (newspec_reset) {
+		IHASH_KEY_ITERATE(newspec, struct gen_spec *,
+				  rlp_elem_newspec_set, 0);
+	}
+	ihash_free(newspec);
+	newspec = NULL;
+}
+
+
+/*
+ * history operations
+ */
+
+static void
+history_undo(void)
+{
+	newspec_dofree();
+	orgspec_flush();
+}
+
+static void
+history_commit(int newspec_set)
+{
+	orgspec_dofree();
+	newspec_flush(newspec_set);
+}
+
+#ifdef DEBUG
+/* return 1 if orgspec and newspec are empty and 0 otherwise */
+static int
+history_is_empty(void)
+{
+	return newspec == NULL && list_empty(&orgspec.head);
+}
+#endif
+
+/* s is a new rlp or elementary interval layer which does __not__
+   replace another */
+static hipac_error
+history_new(struct gen_spec *s, int newspec_set)
+{
+	int stat;
+
+	if (unlikely(s == NULL)) {
+		ARG_ERR;
+	}
+
+	assert((IS_RLP(s) || IS_ELEM(s)));
+	if (unlikely(newspec == NULL)) {
+		newspec = ihash_new(INITIAL_NEWSPEC_LEN, 0,
+				    NEWSPEC_AVRG_ELEM_PER_BUCKET,
+				    ihash_func_val, eq_val);
+		if (newspec == NULL) {
+			return HE_LOW_MEMORY;
+		}
+	}
+	stat = ihash_insert(&newspec, s, NULL);
+	if (stat < 0) {
+		return stat;
+	}
+	if (newspec_set) {
+		rlp_elem_newspec_set(s, 1);
+	}
+	return stat;
+}
+
+static hipac_error
+history_replace(struct gen_spec *old, struct gen_spec *new, int newspec_set)
+{
+	int stat;
+
+	if (unlikely(old == NULL || new == NULL)) {
+		ARG_ERR;
+	}
+
+	assert((IS_RLP(old) && IS_RLP(new)) ||
+	       (IS_ELEM(old) && IS_ELEM(new)));
+	assert(newspec_set ||
+	       (IS_RLP(old) && !((struct rlp_spec *) old)->newspec) ||
+	       (IS_ELEM(old) && !((struct dt_elem_spec *) old)->newspec));
+	assert(newspec_set ||
+	       (IS_RLP(new) && !((struct rlp_spec *) new)->newspec) ||
+	       (IS_ELEM(new) && !((struct dt_elem_spec *) new)->newspec));
+	if (unlikely(newspec == NULL)) {
+		if (newspec_set &&
+		    ((IS_RLP(old) &&
+		      ((struct rlp_spec *) old)->newspec) ||
+		     (IS_ELEM(old) &&
+		      ((struct dt_elem_spec *) old)->newspec))) {
+			IMPOSSIBLE_CONDITION("old must be contained in new"
+					     "spec but newspec is empty");
+		}
+		newspec = ihash_new(INITIAL_NEWSPEC_LEN, 0,
+				    NEWSPEC_AVRG_ELEM_PER_BUCKET,
+				    ihash_func_val, eq_val);
+		if (newspec == NULL) {
+			return HE_LOW_MEMORY;
+		}
+	}
+	if (newspec_set &&
+	    ((IS_RLP(old) && ((struct rlp_spec *) old)->newspec) ||
+	     (IS_ELEM(old) && ((struct dt_elem_spec *) old)->newspec))) {
+		
+		stat = ihash_replace(&newspec, old, NULL, new, NULL);
+		if (stat == HE_OK) {
+			rlp_elem_newspec_set(new, 1);
+			rlp_elem_free(old);
+		}
+	} else {
+		stat = orgspec_add(old);
+		if (stat < 0) {
+			return stat;
+		}
+		stat = ihash_insert(&newspec, new, NULL);
+		if (stat < 0) {
+			return stat;
+		}
+		if (newspec_set) {
+			rlp_elem_newspec_set(new, 1);
+		}
+	}
+	return stat;
+}
+
+/* s is an obsolete rlp or elementary interval layer */
+static hipac_error
+history_obsolete(struct gen_spec *s, int newspec_set)
+{
+	if (unlikely(s == NULL)) {
+		ARG_ERR;
+	}
+
+	assert((IS_RLP(s) || IS_ELEM(s)));
+	assert(newspec_set ||
+	       (IS_RLP(s) && !((struct rlp_spec *) s)->newspec) ||
+	       (IS_ELEM(s) && !((struct dt_elem_spec *) s)->newspec));
+	if (unlikely(newspec == NULL && newspec_set &&
+		     ((IS_RLP(s) && ((struct rlp_spec *) s)->newspec) ||
+		      (IS_ELEM(s) && ((struct dt_elem_spec *) s)->newspec)))) {
+		IMPOSSIBLE_CONDITION("s is obsolete, newspec_set is not 0 and"
+				     " the newspec bit of s is set __but__ s "
+				     "is not contained in newspec");
+	}
+	if (newspec_set &&
+	    ((IS_RLP(s) && ((struct rlp_spec *) s)->newspec) ||
+	     (IS_ELEM(s) && ((struct dt_elem_spec *) s)->newspec))) {
+		if (ihash_delete(newspec, s, NULL) < 0) {
+			IMPOSSIBLE_CONDITION("unable to remove s from "
+					     "newspec");
+		}
+		rlp_elem_free(s);
+		return HE_OK;
+	}
+	return orgspec_add(s);
+}
+
+/* hp_realloc can result in a pointer becoming invalid; this function is used
+   to apply this fact to the history */
+static void
+history_del_invalid(struct gen_spec *s)
+{
+	if (unlikely(s == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	if (ihash_delete(newspec, s, NULL) < 0) {
+		ERR("unable to remove invalid pointer from newspec");
+	}
+}
+
+
+
+/*
+ * termrule operations
+ */
+
+/* insert ‘rule‘ in ‘term‘ in sorted order (sorted after pointer addresses);
+   ‘term‘ must be sorted before */
+static inline hipac_error
+termrule_insert(struct ptrblock **term, struct dt_rule *rule)
+{
+	__u32 i;
+
+	if (unlikely(term == NULL || rule == NULL)) {
+		ARG_ERR;
+	}
+
+	if (*term == NULL) {
+		*term = ptrblock_new(rule, 1);
+		if (*term == NULL) {
+			return HE_LOW_MEMORY;
+		}
+		return HE_OK;
+	}
+
+#ifdef BIT32_ARCH
+	for (i = 0; i < (*term)->len && 
+		     (__u32) (*term)->p[i] < (__u32) rule; i++);
+#else
+	for (i = 0; i < (*term)->len && 
+		     (__u64) (*term)->p[i] < (__u64) rule; i++);
+#endif
+	if (i < (*term)->len && (*term)->p[i] == rule) {
+		IMPOSSIBLE_CONDITION("rule is already contained in term");
+	}
+	return ptrblock_insert(term, rule, i);
+}
+
+/* delete ‘rule‘ from ‘term‘ which must be in sorted order (sorted after
+   pointer addresses) */
+static inline hipac_error
+termrule_delete(struct ptrblock **term, const struct dt_rule *rule)
+{
+	__u32 i;
+
+	if (unlikely(term == NULL || rule == NULL)) {
+		ARG_ERR;
+	}
+	if (*term == NULL) {
+		/* rule is not in term */
+		return HE_OK;
+	}
+
+#ifdef BIT32_ARCH
+	for (i = 0; i < (*term)->len && 
+		     (__u32) (*term)->p[i] < (__u32) rule; i++);
+#else
+	for (i = 0; i < (*term)->len && 
+		     (__u64) (*term)->p[i] < (__u64) rule; i++);
+#endif
+	
+	if (i >= (*term)->len || (*term)->p[i] != rule) {
+		/* rule is not in term */
+		return HE_OK;
+	}
+	return ptrblock_delete_pos(term, i);
+}
+
+/* delete those rules from ‘term‘ whose match boundaries in dimension ‘dimid‘
+   lie completely within [‘left‘, ‘right‘] */
+static inline hipac_error
+termrule_delete_ovl(struct ptrblock **term, __u32 left, __u32 right,
+		    __u8 dimid)
+{
+	__u32 i, curleft, curight;
+	struct dt_match *match;
+	int stat;
+
+	if (unlikely(term == NULL || left > right ||
+		     left > MAXKEY(dim2btype[dimid]) ||
+		     right > MAXKEY(dim2btype[dimid]))) {
+		ARG_ERR;
+	}
+	if (*term == NULL) {
+		return HE_OK;
+	}
+
+       	for (i = 0; i < (*term)->len;) {
+		match = HAS_DT_MATCH((struct dt_rule *) (*term)->p[i]) ?
+			LAST_DT_MATCH((struct dt_rule *) (*term)->p[i]) : NULL;
+		if (match != NULL && match->dimid == dimid) {
+			assert(match->left > 0 ||
+			       match->right < MAXKEY(dim2btype[dimid]));
+			curleft = match->left;
+			curight = match->right;
+		} else {
+			curleft = 0;
+			curight = MAXKEY(dim2btype[dimid]);
+		}
+		if (curleft >= left && curight <= right) {
+			stat = ptrblock_delete_pos(term, i);
+			if (stat < 0) {
+				return stat;
+			}
+			if (*term == NULL) {
+				return HE_OK;
+			}
+		} else {
+			i++;
+		}
+	}
+	return HE_OK;
+}
+
+/* returns 1 if there is a rule in ‘term‘ whose last match m produces the
+   interval represented by ‘right‘ and dimid(m) == ‘dimid‘ */
+static inline int
+termrule_exists(const struct ptrblock *term, __u8 dimid, __u32 right)
+{
+	struct dt_match *match;
+	struct dt_rule **rule;
+	__u32 i;
+	
+	if (unlikely(right > MAXKEY(dim2btype[dimid]))) {
+		ARG_MSG;
+		return 0;
+	}
+	if (term == NULL) {
+		return 0;
+	}
+
+	rule = (struct dt_rule **) term->p;
+	for (i = 0; i < term->len; i++) {
+		match = HAS_DT_MATCH(*rule) ? LAST_DT_MATCH(*rule) : NULL;
+		if (match != NULL && match->dimid == dimid &&
+		    (match->right == right ||
+		     (match->left > 0 && match->left - 1 == right))) {
+			return 1;
+		}
+		rule++;
+	}
+	return 0;
+}
+
+/* return 1 if ‘rule‘ terminates in the elementary interval described by 
+   ‘right‘ resp. ‘wildcard‘ and ‘dimid‘; otherwise 0 is returned */
+static inline int
+rule_term(const struct dt_rule *rule, __u32 right, __u8 wildcard, __u8 dimid)
+{
+	__u32 lbound, ubound;
+	const struct dt_match *match;
+	__u8 match_wc, match_nwc1, match_nwc2;
+
+	if (unlikely(rule == NULL || (wildcard && !HAS_WILDCARD_DIM(dimid)))) {
+		ARG_MSG;
+		return 0;
+	}
+
+	match = HAS_DT_MATCH(rule) ? LAST_DT_MATCH(rule) : NULL;
+	if (match != NULL && match->dimid == dimid) {
+		assert(match->left > 0 ||
+		       match->right < MAXKEY(dim2btype[dimid]));
+		lbound = match->left;
+		ubound = match->right;
+	} else if (match == NULL || match->dimid < dimid) {
+		lbound = 0;
+		ubound = MAXKEY(dim2btype[dimid]);
+	} else {
+		return 0;
+	}
+	
+	match_wc   = wildcard && (match == NULL || match->dimid < dimid);
+	
+	match_nwc1 = !wildcard && HAS_WILDCARD_DIM(dimid) &&
+		match != NULL && match->dimid == dimid && ubound >= right &&
+		lbound <= right;
+	
+	match_nwc2 = !wildcard && !HAS_WILDCARD_DIM(dimid) &&
+		ubound >= right && lbound <= right;
+	
+	return match_wc || match_nwc1 || match_nwc2;
+}
+
+/* store the subset of rules from ‘term‘ that terminate in the elemtary
+   interval represented by ‘right‘ resp. ‘wildcard‘ in dimension ‘dimid‘
+   in ‘subterm‘ */
+static inline hipac_error
+termrule_subset(const struct ptrblock *term, struct ptrblock **subterm,
+		__u32 right, __u8 wildcard, __u8 dimid)
+{
+	struct dt_rule **rule;
+	int stat;
+	__u32 i;
+
+	if (unlikely(subterm == NULL)) {
+		ARG_ERR;
+	}
+
+	*subterm = NULL;
+	if (term == NULL) {
+		return HE_OK;
+	}
+
+	rule = (struct dt_rule **) term->p;
+	for (i = 0; i < term->len; i++, rule++) {
+		if (rule_term(*rule, right, wildcard, dimid)) {
+			stat = ptrblock_insert(
+				subterm, *rule, *subterm == NULL ? 0 :
+				(*subterm)->len);
+			if (stat < 0) {
+				if (*subterm != NULL) {
+					ptrblock_free(*subterm);
+				}
+				*subterm = NULL;
+				return stat;
+			}
+		}
+	}
+	return HE_OK;
+}
+
+/* merge ‘tmpterm‘ into ‘term‘ so that there are no duplicates;
+   ‘tmpterm‘ is freed even if termrule_merge fails */
+static inline hipac_error
+termrule_merge(struct ptrblock **term, struct ptrlist *tmpterm)
+{
+	struct ptrlist_entry *e;
+	struct list_head *lh;
+	int stat;
+	__u32 i;
+	
+	if (unlikely(term == NULL || tmpterm == NULL)) {
+		ARG_ERR;
+	}
+
+	if (ptrlist_is_empty(tmpterm)) {
+		ptrlist_free(tmpterm);
+		return HE_OK;
+	}
+
+	for (lh = tmpterm->head.next, i = 0; lh != &tmpterm->head;) {
+		e = list_entry(lh, struct ptrlist_entry, head);
+#ifdef BIT32_ARCH
+		for (; *term != NULL && i < (*term)->len &&
+			     (__u32) (*term)->p[i] < (__u32) e->p; i++);
+#else
+		for (; *term != NULL && i < (*term)->len &&
+			     (__u64) (*term)->p[i] < (__u64) e->p; i++);
+#endif
+		if (*term == NULL || i == (*term)->len) {
+			/* append rest of tmpterm to term */
+			do {
+				stat = ptrblock_insert(
+					term, e->p, *term == NULL ? 0 :
+					(*term)->len);
+				if (stat < 0) {
+					goto error;
+				}
+				lh = lh->next;
+				ptrlist_free_entry(e);
+				e = list_entry(lh, struct ptrlist_entry, head);
+			} while (lh != &tmpterm->head);
+			break;
+		}
+		if (e->p != (*term)->p[i]) {
+			stat = ptrblock_insert(term, e->p, i++);
+			if (stat < 0) {
+				goto error;
+			}
+		}
+		lh = lh->next;
+		ptrlist_free_entry(e);
+	}
+	ptrlist_free(tmpterm);
+	return HE_OK;
+
+ error:
+	ptrlist_free(tmpterm);
+	return stat;
+}
+
+/* remove all elements of ‘delterm‘ from ‘term‘; ‘delterm‘ must be completely
+   contained in ‘term‘ */
+static inline hipac_error
+termrule_cut(struct ptrblock **term, struct ptrblock *delterm)
+{
+	__u32 i, j;
+	int stat;
+	
+	if (unlikely(term == NULL)) {
+		ARG_ERR;
+	}
+
+	if (delterm == NULL) {
+		return HE_OK;
+	}
+	if (unlikely(*term == NULL)) {
+		IMPOSSIBLE_CONDITION("unable to cut elements from empty "
+				     "termrule block");
+	}
+
+	for (i = 0, j = 0; *term != NULL && i < (*term)->len &&
+		     j < delterm->len; j++) {
+#ifdef BIT32_ARCH
+		for (; i < (*term)->len &&
+			     (__u32) (*term)->p[i] < (__u32) delterm->p[j];
+		     i++);
+#else
+		for (; i < (*term)->len &&
+			     (__u64) (*term)->p[i] < (__u64) delterm->p[j];
+		     i++);
+#endif
+		if (i >= (*term)->len || (*term)->p[i] != delterm->p[j]) {
+			goto error;
+		}
+		stat = ptrblock_delete_pos(term, i);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	if (j >= delterm->len) {
+		return HE_OK;
+	}
+
+ error:
+	IMPOSSIBLE_CONDITION("delterm contains elements which are not "
+			     "contained in term");
+}
+
+/* return the terminal rule (terminal target + no function based matches)
+   from ‘term‘ which dominates the elementary interval represented by ‘right‘
+   resp. ‘wildcard‘ in the dimension specified by ‘dimid‘ and which does not
+   equal ‘rule‘ */
+static inline struct dt_rule *
+termrule_find_best_term(const struct ptrblock *term,
+			const struct dt_rule *rule,
+			__u32 right, __u8 wildcard, __u8 dimid)
+{
+	struct dt_rule *best = NULL;
+	__u32 nextpos = (__u32) ULONG_MAX;
+	struct dt_rule *tr;
+	__u32 i;
+
+	if (unlikely(term == NULL || rule == NULL ||
+		     right > MAXKEY(dim2btype[dimid]) ||
+		     (wildcard && !HAS_WILDCARD_DIM(dimid)))) {
+		ARG_MSG;
+		return NULL;
+	}
+	
+	for (i = 0; i < term->len; i++) {
+		tr = term->p[i];
+		if (!IS_RULE_TERM(tr) || tr == rule) {
+			continue;
+		}
+		if (rule_term(tr, right, wildcard, dimid) &&
+		    tr->spec.pos < nextpos) {
+			nextpos = tr->spec.pos;
+			best = tr;
+		}
+	}
+	return best;
+}
+
+/* return the number(*) of non-terminal rules (non-terminal target or function
+   based matches) in ‘term‘ not equal to ‘rule‘ which terminate in the
+   elementary interval represented by ‘right‘ resp. ‘wildcard‘ in the
+   dimension specified by ‘dimid‘ and whose position is < term_rule->spec.pos
+   if term_rule != NULL; if there is exactly one such non-terminal rule it is
+   stored in ‘ntm_rule‘;
+   (*) the return value ret is 0, 1 or 2; ret == 0 || ret == 1 means there are
+       exactly ret non-terminal rules; ret == 2 means there are >= 2
+       non-terminal rules */
+static inline __u32
+termrule_num_ntm(struct dt_rule **ntm_rule, const struct ptrblock *term,
+		 const struct dt_rule *term_rule, const struct dt_rule *rule,
+		 __u32 right, __u8 wildcard, __u8 dimid)
+{
+	__u32 num = 0;
+	struct dt_rule *tr;
+	__u32 i;
+
+	if (unlikely(ntm_rule == NULL || term == NULL || rule == NULL ||
+		     right > MAXKEY(dim2btype[dimid]) ||
+		     (wildcard && !HAS_WILDCARD_DIM(dimid)))) {
+		ARG_MSG;
+		return 0;
+	}
+	
+	*ntm_rule = NULL;
+	for (i = 0; i < term->len; i++) {
+		tr = term->p[i];
+		if (IS_RULE_TERM(tr) || tr == rule ||
+		    (term_rule != NULL &&
+		     tr->spec.pos >= term_rule->spec.pos)) {
+			continue;
+		}
+		if (rule_term(tr, right, wildcard, dimid)) {
+			*ntm_rule = tr;
+			if (++num == 2) {
+				/* there are at least 2 non-terminal rules
+				   => stop searching */
+				*ntm_rule = NULL;
+				return num;
+			}
+		}
+	}
+	if (num > 1) {
+		*ntm_rule = NULL;
+	}
+	return num;
+}
+
+/* store all non-terminating rules (non-terminal target or function based
+   matches) from ‘term‘ not equal to rule in ‘e‘ which terminate in the
+   elementary interval represented by ‘right‘ resp. ‘wildcard‘ in the
+   dimension specified by ‘dimid‘ and whose position is < max_rule->spec.pos
+   if max_rule != NULL and > min_rule->spec.pos if min_rule != NULL;
+   the rules are stored in e->ntm_rules in sorted order (sorted after their
+   positions) */
+static inline hipac_error
+termrule_insert_ntm(struct dt_elem **e, const struct ptrblock *term,
+		    const struct dt_rule *min_rule,
+		    const struct dt_rule *max_rule,
+		    const struct dt_rule *rule,
+		    __u32 right, __u8 wildcard, __u8 dimid)
+{
+	struct dt_rule *tr;
+	__u32 i, j, stat;
+
+	if (unlikely(e == NULL || *e == NULL || term == NULL ||
+		     right > MAXKEY(dim2btype[dimid]) ||
+		     (wildcard && !HAS_WILDCARD_DIM(dimid)))) {
+		ARG_ERR;
+	}
+	
+	for (i = 0; i < term->len; i++) {
+		tr = term->p[i];
+		if (IS_RULE_TERM(tr) || tr == rule ||
+		    (min_rule != NULL &&
+		     (tr->spec.pos <= min_rule->spec.pos)) ||
+		    (max_rule != NULL &&
+		     (tr->spec.pos >= max_rule->spec.pos))) {
+			continue;
+		}
+		if (rule_term(tr, right, wildcard, dimid)) {
+			for (j = 0; j < (*e)->ntm_rules.len &&
+				     ((struct dt_rule *)
+				      (*e)->ntm_rules.p[j])->spec.pos <
+				     tr->spec.pos; j++);
+			stat = ptrblock_insert_embed((void **) e,
+						     offsetof(struct dt_elem,
+							      ntm_rules),
+						     tr, j);
+			if (stat < 0) {
+				return stat;
+			}
+		}
+	}
+	return HE_OK;
+}
+
+
+
+/*
+ * tmp_termrule operations
+ */
+
+static inline struct ptrlist *
+tmp_termrule_new(void)
+{
+	return ptrlist_new();
+}
+
+static inline void
+tmp_termrule_free(struct ptrlist *tmpterm)
+{
+	return ptrlist_free(tmpterm);
+}
+
+/* merge ‘term‘ into ‘tmpterm‘ so that there are no duplicates */
+static inline hipac_error
+tmp_termrule_merge(struct ptrlist *tmpterm, struct ptrblock *term)
+{
+	struct ptrlist_entry *e;
+	struct list_head *lh;
+	int stat;
+	__u32 i;
+	
+	if (unlikely(tmpterm == NULL)) {
+		ARG_ERR;
+	}
+
+	if (term == NULL) {
+		return HE_OK;
+	}
+
+	for (i = 0, lh = tmpterm->head.next; i < term->len; i++) {
+#ifdef BIT32_ARCH
+		for (; lh != &tmpterm->head &&
+			     (__u32) list_entry(lh, struct ptrlist_entry,
+						head)->p <
+			     (__u32) term->p[i]; lh = lh->next);
+#else
+		for (; lh != &tmpterm->head &&
+			     (__u64) list_entry(lh, struct ptrlist_entry,
+						head)->p <
+			     (__u64) term->p[i]; lh = lh->next);
+#endif
+		if (lh == &tmpterm->head) {
+			/* append rest of term to tmpterm */
+			for (; i < term->len; i++) {
+				stat = ptrlist_add(tmpterm, term->p[i], 0);
+				if (stat < 0) {
+					return stat;
+				}
+			}
+			break;
+		}
+		e = list_entry(lh, struct ptrlist_entry, head);
+		if (e->p != term->p[i]) {
+			e = ptrlist_new_entry(term->p[i]);
+			if (e == NULL) {
+				return HE_LOW_MEMORY;
+			}
+			list_add_tail(&e->head, lh);
+			tmpterm->len++;
+		}
+	}
+	return HE_OK;
+}
+
+
+
+/*
+ * elementary interval operations
+ */
+
+/* create new elementary interval layer with ntm_len non-terminal rules
+   which are stored in ntm_rules sorted after their positions */
+static inline struct dt_elem *
+elem_new(struct dt_rule *term_rule, struct dt_rule *ntm_rules[], __u32 ntm_len)
+{
+	struct dt_elem *e;
+	__u32 i;
+
+	if (unlikely(ntm_len == 0 || ntm_rules == NULL || *ntm_rules == NULL ||
+		     (termrule == NULL && ntm_len <= 1))) {
+		ARG_MSG;
+		return NULL;
+	}
+
+	e = hp_alloc(sizeof(*e) + ntm_len * sizeof(*e->ntm_rules.p), 1);
+	if (e == NULL) {
+		return NULL;
+	}
+	e->spec.rlp = 0;
+	e->spec.rtype = RT_ELEM;
+	e->spec.newspec = 0;
+	e->term_rule = term_rule;
+	e->ntm_rules.len = ntm_len;
+	for (i = 0; i < ntm_len; i++) {
+		e->ntm_rules.p[i] = ntm_rules[i];
+	}
+	return e;
+}
+
+/* create new elementary interval layer with 0 non-terminal rules; notice that
+   the resulting elementary interval is not valid because it __must__ contain
+   at least one non-terminal rule */
+static inline struct dt_elem *
+elem_new_empty(struct dt_rule *term_rule)
+{
+	struct dt_elem *e;
+	
+	e = hp_alloc(sizeof(*e), 1);
+	if (e == NULL) {
+		return NULL;
+	}
+	e->spec.rlp = 0;
+	e->spec.rtype = RT_ELEM;
+	e->spec.newspec = 0;
+	e->term_rule = term_rule;
+	e->ntm_rules.len = 0;
+	return e;
+}
+
+static inline int
+elem_eq(const struct dt_elem *e1, const struct dt_elem *e2)
+{
+	if (e1 == NULL || e2 == NULL || !IS_ELEM(e1) || !IS_ELEM(e2)) {
+		ARG_MSG;
+		return 0;
+	}
+	if (e1->term_rule != e2->term_rule ||
+	    !ptrblock_eq(&e1->ntm_rules, &e2->ntm_rules)) {
+		return 0;
+	}
+	return 1;
+}
+
+static inline hipac_error
+elem_clone(struct dt_elem *e, struct dt_elem **clone)
+{
+	if (e == NULL || clone == NULL) {
+		ARG_ERR;
+	}
+
+	*clone = hp_alloc(sizeof(*e) + e->ntm_rules.len *
+			  sizeof(*e->ntm_rules.p), 1);
+	if (*clone == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	memcpy(*clone, e, sizeof(*e) + e->ntm_rules.len *
+	       sizeof(*e->ntm_rules.p));
+	return HE_OK;
+}
+
+/* forward declaration */
+static int 
+rlp_eq_rec(const struct rlp_spec *spec1, const struct rlp_spec *spec2);
+
+/* return 1 if g1 and g2 are equal and rules;
+   return 2 if g1 and g2 are equal and elementary intervals;
+   return 3 if g1 and g2 are equal and rlps;
+   return 0 otherwise */
+static inline int
+rlp_rule_elem_eq(const struct gen_spec *g1, const struct gen_spec *g2)
+{
+	if (g1 == NULL || g2 == NULL ||
+	    (IS_RULE(g1) && IS_RULE(g2))) {
+		return g1 == g2;
+	} else if (IS_ELEM(g1) && IS_ELEM(g2)) {
+		struct dt_elem *e1 = (struct dt_elem *) g1;
+		struct dt_elem *e2 = (struct dt_elem *) g2;
+
+		if (e1->ntm_rules.len != e2->ntm_rules.len) {
+			return 0;
+		}
+		return elem_eq(e1, e2) ? 2 : 0;
+	} else if (IS_RLP(g1) && IS_RLP(g2)) {
+		struct rlp_spec *b1 = (struct rlp_spec *) g1;
+		struct rlp_spec *b2 = (struct rlp_spec *) g2;
+
+		return (rlp_spec_eq(b1, b2) && rlp_eq_rec(b1, b2)) ? 3 : 0;
+	}
+	return 0;
+}
+
+/* insert rule into rule_elem which can be a rule or an elementary interval
+   layer; the result which can be a rule or an elementary interval layer
+   is directly written to rule_elem */
+static inline hipac_error
+rule_elem_insert(struct dt_rule_elem_spec **rule_elem, struct dt_rule *rule,
+		 int newspec_set)
+{
+	int stat;
+
+	if (unlikely(rule_elem == NULL || rule == NULL)) {
+		ARG_ERR;
+	}
+
+	if (*rule_elem == NULL) {
+		*rule_elem = (struct dt_rule_elem_spec *) rule;
+		return HE_OK;
+	}
+
+	assert(IS_RULE(*rule_elem) || IS_ELEM(*rule_elem));
+	assert(!IS_ELEM(*rule_elem) ||
+	       ((struct dt_elem *) *rule_elem)->ntm_rules.len > 0);
+	assert(!IS_ELEM(*rule_elem) ||
+	       ((struct dt_elem *) *rule_elem)->term_rule != NULL ||
+	       ((struct dt_elem *) *rule_elem)->ntm_rules.len > 1);
+
+	if (IS_RULE(*rule_elem)) {
+		struct dt_rule *r = (struct dt_rule *) *rule_elem;
+		
+		if (IS_RULE_TERM(rule) && IS_RULE_TERM(r)) {
+			if (rule->spec.pos < r->spec.pos) {
+				*rule_elem = (struct dt_rule_elem_spec *) rule;
+			}
+			return HE_OK;
+		
+		} else if (!IS_RULE_TERM(rule) && !IS_RULE_TERM(r)) {
+			struct dt_rule *ntm[2];
+			struct dt_elem *e;
+			if (r->spec.pos < rule->spec.pos) {
+				ntm[0] = r;
+				ntm[1] = rule;
+			} else {
+				ntm[0] = rule;
+				ntm[1] = r;
+			}
+			e = elem_new(NULL, ntm, sizeof(ntm) / sizeof(*ntm));
+			if (e == NULL) {
+				return HE_LOW_MEMORY;
+			}
+			stat = history_new((struct gen_spec *) e, newspec_set);
+			if (stat < 0) {
+				elem_free(e);
+				return stat;
+			}
+			*rule_elem = (struct dt_rule_elem_spec *) e;
+			return HE_OK;
+			
+		} else {
+			struct dt_rule *term_rule, *ntm_rule;
+			struct dt_elem *e;
+			if (IS_RULE_TERM(rule)) {
+				term_rule = rule;
+				ntm_rule = r;
+			} else {
+				term_rule = r;
+				ntm_rule = rule;
+			}
+			if (term_rule->spec.pos < ntm_rule->spec.pos) {
+				*rule_elem = (struct dt_rule_elem_spec *)
+					term_rule;
+				return HE_OK;
+			}
+			e = elem_new(term_rule, &ntm_rule, 1);
+			if (e == NULL) {
+				return HE_LOW_MEMORY;
+			}
+			stat = history_new((struct gen_spec *) e, newspec_set);
+			if (stat < 0) {
+				elem_free(e);
+				return stat;
+			}
+			*rule_elem = (struct dt_rule_elem_spec *) e;
+			return HE_OK;
+		}
+	} else {
+		/* IS_ELEM(*rule_elem) */
+		struct dt_elem *e = (struct dt_elem *) *rule_elem;
+		__u32 i;
+		
+		if (e->term_rule != NULL && 
+		    rule->spec.pos > e->term_rule->spec.pos) {
+			/* rule is never matched */
+			return HE_OK;
+		}
+		if (IS_RULE_TERM(rule)) {
+			/* find still matching rules if any */
+			if (((struct dt_rule *) e->ntm_rules.p[0])->spec.pos >
+			    rule->spec.pos) {
+				stat = history_obsolete((struct gen_spec *) e,
+							newspec_set);
+				if (stat < 0) {
+					return stat;
+				}
+				*rule_elem = (struct dt_rule_elem_spec *) rule;
+				return HE_OK;
+			}
+			e->term_rule = rule;
+			i = e->ntm_rules.len;
+			do {
+				i--;
+				if (((struct dt_rule *)
+				     e->ntm_rules.p[i])->spec.pos <
+				    rule->spec.pos) {
+					break;
+				}
+			} while (i > 0);
+			assert(((struct dt_rule *)
+				e->ntm_rules.p[i])->spec.pos < rule->spec.pos);
+			if (i < e->ntm_rules.len - 1) {
+				struct dt_elem *e2;
+				e2 = hp_realloc(e, sizeof(*e) + (i + 1) *
+						sizeof(*e->ntm_rules.p));
+				if (e2 == NULL) {
+					/* this should never happen as we
+					   shrink e */
+					return HE_LOW_MEMORY;
+				}
+				if (e != e2) {
+					history_del_invalid(
+						(struct gen_spec *) e);
+					stat = history_new(
+						(struct gen_spec *) e2,
+						newspec_set);
+					if (stat < 0) {
+						elem_free(e2);
+						return stat;
+					}
+				}
+				e2->ntm_rules.len = i + 1;
+				*rule_elem = (struct dt_rule_elem_spec *) e2;
+			}
+			return HE_OK;
+
+		} else {
+			/* !IS_RULE_TERM(rule) */
+			for (i = 0; i < e->ntm_rules.len &&
+				     ((struct dt_rule *)
+				      e->ntm_rules.p[i])->spec.pos <
+				     rule->spec.pos; i++);
+			stat = ptrblock_insert_embed((void **) rule_elem,
+						     offsetof(struct dt_elem,
+							      ntm_rules),
+						     rule, i);
+			if (stat < 0) {
+				return stat;
+			}
+			if (e != (struct dt_elem *) *rule_elem) {
+				history_del_invalid((struct gen_spec *) e);
+				stat = history_new((struct gen_spec *)
+						   *rule_elem, newspec_set);
+				if (stat < 0) {
+					elem_free((struct dt_elem *)
+						  *rule_elem);
+					return stat;
+				}
+			}
+			return HE_OK;
+		}
+	}
+}
+
+/* delete rule from rule_elem which can be a rule or an elementary interval
+   layer; if rule is not contained in rule_elem nothing happens;
+   the result which can be a rule or an elementary interval layer is directly
+   written to rule_elem; term, right, wildcard and dimid must be given to
+   find the next best rule(s) if necessary */
+static inline hipac_error
+rule_elem_delete(struct dt_rule_elem_spec **rule_elem,
+		 const struct dt_rule *rule, const struct ptrblock *term,
+		 __u32 right, __u8 wildcard, __u8 dimid, int newspec_set)
+{
+	int stat;
+
+	if (unlikely(rule_elem == NULL || rule == NULL || term == NULL ||
+		     right > MAXKEY(dim2btype[dimid]) ||
+		     (wildcard && !HAS_WILDCARD_DIM(dimid)))) {
+		ARG_ERR;
+	}
+
+	if (*rule_elem == NULL) {
+		/* rule is not contained in rule_elem */
+		return HE_OK;
+	}
+
+	assert(IS_RULE(*rule_elem) || IS_ELEM(*rule_elem));
+	assert(!IS_ELEM(*rule_elem) ||
+	       ((struct dt_elem *) *rule_elem)->ntm_rules.len > 0);
+	assert(!IS_ELEM(*rule_elem) ||
+	       ((struct dt_elem *) *rule_elem)->term_rule != NULL ||
+	       ((struct dt_elem *) *rule_elem)->ntm_rules.len > 1);
+
+	if (IS_RULE(*rule_elem)) {
+		struct dt_rule *r = (struct dt_rule *) *rule_elem;
+		struct dt_rule *term_rule, *ntm_rule = NULL;
+		__u32 ntm_num;
+
+		if (r != rule) {
+			/* rule is not contained in rule_elem */
+			return HE_OK;
+		}
+
+		/* in fact it would suffice to call termrule_find_best_term
+		   only if IS_RULE_TERM(r) */
+		term_rule = termrule_find_best_term(term, rule, right,
+						    wildcard, dimid);
+		ntm_num = termrule_num_ntm(&ntm_rule, term, term_rule, rule,
+					   right, wildcard, dimid);
+		if (term_rule == NULL && ntm_num <= 1) {
+			*rule_elem = (struct dt_rule_elem_spec *) ntm_rule;
+			return HE_OK;
+		} else if (term_rule != NULL && ntm_num == 0) {
+			*rule_elem = (struct dt_rule_elem_spec *) term_rule;
+			return HE_OK;
+		} else {
+			struct dt_elem *e = elem_new_empty(term_rule);
+			if (e == NULL) {
+				return HE_LOW_MEMORY;
+			}
+			stat = termrule_insert_ntm(&e, term, NULL, term_rule,
+						   rule, right, wildcard,
+						   dimid);
+			if (stat < 0) {
+				hp_free(e);
+				return stat;
+			}
+			assert(e->ntm_rules.len > 0);
+			stat = history_new((struct gen_spec *) e, newspec_set);
+			if (stat < 0) {
+				elem_free(e);
+				return stat;
+			}
+			*rule_elem = (struct dt_rule_elem_spec *) e;
+			return HE_OK;
+		}
+	} else {
+		/* IS_ELEM(*rule_elem) */
+		struct dt_elem *e = (struct dt_elem *) *rule_elem;
+		__u32 i;
+		
+		if (e->term_rule == rule) {
+			struct dt_rule *term_rule;
+			term_rule = termrule_find_best_term(
+				term, rule, right, wildcard, dimid);
+			stat = termrule_insert_ntm(
+				(struct dt_elem **) rule_elem, term,
+				e->ntm_rules.p[e->ntm_rules.len - 1],
+				term_rule, rule, right, wildcard, dimid);
+			if (stat < 0) {
+				/* we only care about rule_elem if its address
+				   has changed; otherwise rule_elem is 
+				   handled by the history */
+				if (e != (struct dt_elem *) *rule_elem) {
+					history_del_invalid((struct gen_spec *)
+							    e);
+					elem_free((struct dt_elem *)
+						  *rule_elem);
+				}
+				return stat;
+			}
+			if (e != (struct dt_elem *) *rule_elem) {
+				history_del_invalid((struct gen_spec *) e);
+				stat = history_new((struct gen_spec *)
+						   *rule_elem, newspec_set);
+				if (stat < 0) {
+					elem_free((struct dt_elem *)
+						  *rule_elem);
+					return stat;
+				}
+			}
+			e = (struct dt_elem *) *rule_elem;
+			if (term_rule == NULL && e->ntm_rules.len == 1) {
+				struct dt_rule_elem_spec *ntm =
+					e->ntm_rules.p[0];
+				stat = history_obsolete((struct gen_spec *) e,
+							newspec_set);
+				if (stat < 0) {
+					return stat;
+				}
+				*rule_elem = ntm;
+				return HE_OK;
+			}
+			e->term_rule = term_rule;
+			return HE_OK;
+		} else {
+			for (i = 0; i < e->ntm_rules.len &&
+				     ((struct dt_rule *)
+				      e->ntm_rules.p[i])->spec.pos <
+				     rule->spec.pos; i++);
+			if (i >= e->ntm_rules.len ||
+			    e->ntm_rules.p[i] != rule) {
+				/* rule is not contained in rule_elem */
+				return HE_OK;
+			}
+			if (e->ntm_rules.len == 1) {
+				struct dt_rule_elem_spec *tm =
+					(struct dt_rule_elem_spec *)
+					e->term_rule;
+				stat = history_obsolete((struct gen_spec *) e,
+							newspec_set);
+				if (stat < 0) {
+					return stat;
+				}
+				*rule_elem = tm;
+				return HE_OK;
+			} else if (e->term_rule == NULL &&
+				   e->ntm_rules.len == 2) {
+				struct dt_rule_elem_spec *ntm =
+					(struct dt_rule_elem_spec *)
+					e->ntm_rules.p[(i + 1) % 2];
+				stat = history_obsolete((struct gen_spec *) e,
+							newspec_set);
+				if (stat < 0) {
+					return stat;
+				}
+				*rule_elem = ntm;
+				return HE_OK;
+			} else {
+				stat = ptrblock_delete_pos_embed(
+					(void **) rule_elem,
+					offsetof(struct dt_elem, ntm_rules),
+					i);
+				if (stat < 0) {
+					return stat;
+				}
+				if (e != (struct dt_elem *) *rule_elem) {
+					history_del_invalid(
+						(struct gen_spec *) e);
+					stat = history_new((struct gen_spec *)
+							   *rule_elem,
+							   newspec_set);
+					if (stat < 0) {
+						elem_free((struct dt_elem *)
+							  *rule_elem);
+						return stat;
+					}
+				}
+				return HE_OK;
+			}
+		}
+	}
+}
+
+
+
+/*
+ * recursive rlp operations
+ */
+
+/* necessary forward declaration */
+static hipac_error
+rlp_clone_rec(const struct rlp_spec *spec, struct rlp_spec **clone,
+	      int newspec_set);
+
+static inline hipac_error
+rlp_clone_help(struct gen_spec **g, int newspec_set)
+{
+	int stat = HE_OK;
+
+	if (*g == NULL) {
+		return HE_OK;
+	}
+	if (IS_RLP(*g)) {
+		stat = rlp_clone_rec((struct rlp_spec *) *g,
+				     (struct rlp_spec **) g,
+				     newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	} else if (IS_ELEM(*g)) {
+		struct dt_elem *clone;
+		stat = elem_clone((struct dt_elem *) *g, &clone);
+		if (stat < 0) {
+			return stat;
+		}
+		stat = history_new((struct gen_spec *) clone,
+				   newspec_set);
+		if (stat < 0) {
+			elem_free(clone);
+			return stat;
+		}
+		*g = (struct gen_spec *) clone;
+	}
+	return HE_OK;
+}
+
+/* clone spec including the elementary interval layers recursively and call
+   history_new for each clone;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+static hipac_error
+rlp_clone_rec(const struct rlp_spec *spec, struct rlp_spec **clone,
+	      int newspec_set)
+{
+	struct gen_spec **nextspec = NULL;
+	__u32 size;
+	int stat;
+	__u16 n;
+       
+	if (unlikely(spec == NULL || clone == NULL)) {
+		ARG_ERR;
+	}
+	
+	size = rlp_size(spec);
+	*clone = hp_alloc(size, 1);
+	if (*clone == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	
+	memcpy(*clone, spec, size);
+	stat = ptrblock_clone(*termrule(spec), termrule(*clone));
+	if (stat < 0) {
+		hp_free(*clone);
+		return stat;
+	}
+	
+	stat = history_new((struct gen_spec *) *clone, newspec_set);
+	if (stat < 0) {
+		hp_free(*termrule(*clone));
+		hp_free(*clone);
+		return stat;
+	}
+	
+	nextspec = rlp_nextspec(*clone);
+	assert(nextspec != NULL);
+	
+	for (n = 0; n < (*clone)->num; n++) {
+		stat = rlp_clone_help(nextspec + n, newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	
+	if (HAS_WILDCARD_SPEC(*clone)) {
+		stat = rlp_clone_help(WILDCARD(*clone), newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	return HE_OK;
+}
+
+/* necessary forward declaration */
+static hipac_error
+rlp_free_rec(struct rlp_spec *spec, int newspec_set, int direct_free);
+
+static inline hipac_error
+rlp_free_help(struct gen_spec *g, int newspec_set, int direct_free)
+{
+	int stat;
+
+	if (g == NULL) {
+		return HE_OK;
+	}
+	if (IS_RLP(g)) {
+		stat = rlp_free_rec((struct rlp_spec *) g, newspec_set,
+				    direct_free);
+		if (stat < 0) {
+			return stat;
+		}
+	} else if (IS_ELEM(g)) {
+		if (direct_free) {
+			rlp_elem_free(g);
+		} else {
+			stat = history_obsolete(g, newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+		}
+	}
+	return HE_OK;
+}
+
+/* ‘free‘ spec including the elementary interval layers recursively;
+   if direct_free is 0 ‘free‘ means to call history_obsolete for each element;
+   otherwise the elements are directly freed by rlp_elem_free;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+static hipac_error
+rlp_free_rec(struct rlp_spec *spec, int newspec_set, int direct_free)
+{
+	struct gen_spec **nextspec = NULL;
+	int stat;
+	__u16 n;
+	
+	if (unlikely(spec == NULL)) {
+		ARG_ERR;
+	}
+	
+	nextspec = rlp_nextspec(spec);
+	assert(nextspec != NULL);
+	
+	for (n = 0; n < spec->num; n++) {
+		stat = rlp_free_help(*(nextspec + n), newspec_set,
+				     direct_free);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+
+	if (HAS_WILDCARD_SPEC(spec)) {
+		stat = rlp_free_help(*WILDCARD(spec), newspec_set,
+				     direct_free);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+
+	if (direct_free) {
+		rlp_elem_free((struct gen_spec *) spec);
+		return HE_OK;
+	}
+	return history_obsolete((struct gen_spec *) spec, newspec_set);
+}
+
+/* return 1 if spec1 and spec2 are recursively equal; the headers spec1 and
+   spec2 are assumed to be equal */
+static int
+rlp_eq_rec(const struct rlp_spec *spec1, const struct rlp_spec *spec2)
+{
+	struct gen_spec **nextspec1 = NULL, **nextspec2 = NULL;
+	__u16 n;
+	
+	if (unlikely(spec1 == NULL || spec2 == NULL)) {
+		ARG_ERR;
+	}
+
+	assert(IS_RLP(spec1));
+	assert(IS_RLP(spec2));
+	assert(rlp_spec_eq(spec1, spec2));
+
+	if (!ptrblock_eq(*termrule(spec1), *termrule(spec2))) {
+		return 0;
+	}
+	nextspec1 = rlp_nextspec(spec1);
+	assert(nextspec1 != NULL);
+	nextspec2 = rlp_nextspec(spec2);
+	assert(nextspec2 != NULL);
+
+	/* we don‘t need to compare the keys of spec1 and spec2 because for
+	   each corresponding rlp pair the termrule blocks are compared
+	   which means that if rlp_eq_rec finally returns 1 the same rules
+	   terminate in the subtree rooted by the top level rlp spec1 and in
+	   the subtree rooted by the top level rlp spec2; since all leaves
+	   of the subtrees are terminal (NULL, rule or elementary interval
+	   layer) we can conclude that there is no other rule except those in
+	   the termrule blocks that have created keys in the rlps */
+	for (n = 0; n < spec1->num; n++) {
+		if (!rlp_rule_elem_eq(*(nextspec1 + n), *(nextspec2 + n))) {
+			return 0;
+		}
+	}
+
+	if (HAS_WILDCARD_SPEC(spec1) &&
+	    !rlp_rule_elem_eq(*WILDCARD(spec1), *WILDCARD(spec2))) {
+		return 0;
+	}
+	return 1;
+}
+
+
+
+/*
+ * internal dimtree operations
+ */
+
+static inline hipac_error
+rlp_clone_ifneeded(struct rlp_spec *b, struct rlp_spec **newb,
+		     int newspec_set)
+{
+	int stat;
+
+	if (unlikely(b == NULL || newb == NULL)) {
+		ARG_ERR;
+	}
+
+	if (b->newspec == 0) {
+		/* we must clone because b is visible for packet matching */
+		stat = rlp_clone(b, newb);
+		if (stat < 0) {
+			return stat;
+		}
+		stat = history_replace((struct gen_spec *) b,
+				       (struct gen_spec *) *newb, newspec_set);
+		if (stat < 0) {
+			rlp_free(*newb);
+			return stat;
+		}
+	} else {
+		/* b can be modified directly */
+		*newb = b;
+	}
+	return HE_OK;
+}
+
+static inline hipac_error
+elem_clone_ifneeded(struct dt_elem *e, struct dt_elem **newe,
+		    int newspec_set)
+{
+	int stat;
+
+	if (unlikely(e == NULL || newe == NULL)) {
+		ARG_ERR;
+	}
+
+	if (e->spec.newspec == 0) {
+		/* we must clone because e is visible for packet matching */
+		stat = elem_clone(e, newe);
+		if (stat < 0) {
+			return stat;
+		}
+		stat = history_replace((struct gen_spec *) e,
+				       (struct gen_spec *) *newe, newspec_set);
+		if (stat < 0) {
+			elem_free(*newe);
+			return stat;
+		}
+	} else {
+		/* e can be modified directly */
+		*newe = e;
+	}
+	return HE_OK;
+}
+
+#ifdef DEBUG
+static void
+print_elem(struct dt_elem *e)
+{
+	int i;
+
+	DPRINT(DEBUG_DIMTREE, "term_rule: %p, ntm_rules:", e->term_rule);
+	if (e->ntm_rules.len == 0) {
+		DPRINT(DEBUG_DIMTREE, " <none> => BUG");
+		return;
+	}
+	for (i = 0; i < e->ntm_rules.len; i++) {
+		DPRINT(DEBUG_DIMTREE, " %p", e->ntm_rules.p[i]);
+	}
+}
+
+static void
+print_rlp(struct rlp_spec *rlp)
+{
+	__u32 key = 0;
+	struct locate_inf inf;
+	int i;
+
+	if (rlp == NULL) {
+		DPRINT(DEBUG_DIMTREE, "rlp: %p (this might not be what you "
+		       "expected)\n", rlp);
+		return;
+	}
+	if (!IS_RLP(rlp)) {
+		DPRINT(DEBUG_DIMTREE, "rlp: %p is __NOT__ a rlp => FATAL "
+		       "ERROR\n", rlp);
+		return;
+	}
+	DPRINT(DEBUG_DIMTREE, "rlp: %p  -  bittype: %d, dimid: %d, "
+	       "newspec: %d, num: %d\n", rlp, rlp->bittype, rlp->dimid,
+	       rlp->newspec, rlp->num);
+	DPRINT(DEBUG_DIMTREE, "   content:");
+	if (HAS_WILDCARD_DIM(rlp->dimid)) {
+		if (*WILDCARD(rlp) != NULL && IS_RULE(*WILDCARD(rlp))) {
+			DPRINT(DEBUG_DIMTREE, " (wc, %p: rule)",
+			       *WILDCARD(rlp));
+		} else if (*WILDCARD(rlp) != NULL && IS_ELEM(*WILDCARD(rlp))) {
+			DPRINT(DEBUG_DIMTREE, " (wc, %p: ", *WILDCARD(rlp));
+			print_elem((struct dt_elem *) *WILDCARD(rlp));
+			DPRINT(DEBUG_DIMTREE, ")");
+		} else {
+			DPRINT(DEBUG_DIMTREE, " (wc, %p)", *WILDCARD(rlp));
+		}
+	}
+	do {
+		if (rlp_locate(rlp, &inf, key) < 0) {
+			DPRINT(DEBUG_DIMTREE, "\n%s: no memory for locate "
+			       "info\n", __FUNCTION__);
+			return;
+		}
+		if (*inf.nextspec != NULL && IS_RULE(*inf.nextspec)) {
+			DPRINT(DEBUG_DIMTREE, " (%u, %p: rule)", inf.key,
+			       *inf.nextspec);
+		} else if (*inf.nextspec != NULL && 
+			   IS_ELEM(*inf.nextspec)) {
+			DPRINT(DEBUG_DIMTREE, " (%u, %p: ", inf.key,
+			       *inf.nextspec);
+			print_elem((struct dt_elem *) *inf.nextspec);
+			DPRINT(DEBUG_DIMTREE, ")");
+		} else {
+			DPRINT(DEBUG_DIMTREE, " (%u, %p)", inf.key,
+			       *inf.nextspec);
+		}
+		key = inf.key + 1;
+	} while (inf.key < MAXKEY(dim2btype[rlp->dimid]));
+	DPRINT(DEBUG_DIMTREE, "\n   term:");
+	if (*termrule(rlp) == NULL) {
+		DPRINT(DEBUG_DIMTREE, " <empty>\n");
+	} else {
+		for (i = 0; i < (*termrule(rlp))->len; i++) {
+			DPRINT(DEBUG_DIMTREE, " %p", (*termrule(rlp))->p[i]);
+		}
+		DPRINT(DEBUG_DIMTREE, "\n");
+	}
+}
+#endif
+
+static inline hipac_error
+segment_insert_help(struct locate_inf *inf, __u8 *ins_num,
+		    struct gen_spec* new_nextspec[], int newspec_set)
+{
+	int stat;
+
+	if (*inf->nextspec == NULL || IS_RULE(*inf->nextspec)) {
+		new_nextspec[*ins_num] = *inf->nextspec;
+	} else if (IS_ELEM(*inf->nextspec)) {
+		struct dt_elem *e;
+		stat = elem_clone((struct dt_elem *) *inf->nextspec, &e);
+		if (stat < 0) {
+			return stat;
+		}
+		stat = history_new((struct gen_spec *) e, newspec_set);
+		if (stat < 0) {
+			elem_free(e);
+			return stat;
+		}
+		new_nextspec[*ins_num] = (struct gen_spec *) e;
+	} else {
+		assert(IS_RLP(*inf->nextspec));
+		stat = rlp_clone_rec(
+			(struct rlp_spec *) *inf->nextspec,
+			(struct rlp_spec **) &new_nextspec[*ins_num],
+			newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	(*ins_num)++;
+	return HE_OK;
+}
+
+/* segment [left, right] is inserted into spec which causes at most two new
+   elementary intervals being created; for every new elementary interval
+   the neighbour interval is cloned recursively */
+static inline hipac_error
+segment_insert(struct rlp_spec **spec, __u32 left, __u32 right,
+	       int newspec_set)
+{  	
+	__u8 ins_num = 0;
+	struct gen_spec* new_nextspec[2];
+	struct locate_inf inf;
+	__u32 new_key[2];
+	int stat;
+
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: left: %u, right: %u, newspec_set: %d\n",
+	       __FUNCTION__, left, right, newspec_set);
+#ifdef DEBUG
+	print_rlp(*spec);
+#endif
+	if (left > 0) {
+		stat = rlp_locate(*spec, &inf, left - 1);
+		if (stat < 0) {
+			return stat;
+		}
+		if (inf.key != left - 1) {
+			new_key[ins_num] = left - 1;
+			stat = segment_insert_help(&inf, &ins_num,
+						   new_nextspec, newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+		}
+	}
+	
+	stat = rlp_locate(*spec, &inf, right);
+	if (stat < 0) {
+		return stat;
+	}
+	if (inf.key != right) {
+		new_key[ins_num] = right;
+		stat = segment_insert_help(&inf, &ins_num, new_nextspec,
+					   newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+
+	if (ins_num > 0) {
+		struct rlp_spec *b;
+		assert(ins_num == 1 || new_key[0] != new_key[1]);
+		if (ins_num == 1) {
+			DPRINT(DEBUG_DIMTREE, "new key: %u\n", new_key[0]);
+		} else {
+			DPRINT(DEBUG_DIMTREE, "new keys: %u, %u\n", new_key[0],
+			       new_key[1]);
+		}
+		stat = rlp_insert(*spec, ins_num, new_key, new_nextspec, &b);
+		if (stat < 0) {
+			return stat;
+		}
+		stat = history_replace((struct gen_spec *) *spec,
+				       (struct gen_spec *) b, newspec_set);
+		if (stat < 0) {
+			rlp_free(b);
+			return stat;
+		}
+		*spec = b;
+#ifdef DEBUG
+		print_rlp(*spec);
+#endif
+	} else {
+		/* we clone the rlp anyway if necessary */
+		struct rlp_spec *b;
+		stat = rlp_clone_ifneeded(*spec, &b, newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+		*spec = b;
+	}
+	return HE_OK;
+}
+
+/* forward declaration */
+static hipac_error
+dimtree_insrec(struct rlp_spec **spec, struct dt_rule *rule,
+	       __u8 match_num, int newspec_set);
+
+static hipac_error
+dimtree_insrec_null(struct rlp_spec **spec, struct dt_rule *rule,
+		    __u8 match_num, int newspec_set)
+{
+	const struct dt_match *match = ITH_DT_MATCH(rule, match_num);
+	__u8 bittype = dim2btype[match->dimid];
+	struct gen_spec *nextspec[] = {NULL};
+	__u32 key = MAXKEY(bittype);
+	struct locate_inf inf;
+	int stat;
+
+	/* create new rlp that defaults to policy and insert match
+	   recursively */
+	assert(spec != NULL && *spec == NULL);
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: match_num: %d, newspec_set: %d, match: "
+	       "(dimid: %d, left: %u, right: %u)\n", __FUNCTION__, match_num,
+	       newspec_set, match->dimid, match->left, match->right);
+	DPRINT(DEBUG_DIMTREE, "%s: new rlp: bittype: %d, dimid: %d, key: "
+	       "%u, nextspec: %p\n", __FUNCTION__, bittype, match->dimid, key,
+	       *nextspec);
+	*spec = rlp_new(bittype, match->dimid, 1, &key, nextspec);
+	if (*spec == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	stat = history_new((struct gen_spec *) *spec, newspec_set);
+	if (stat < 0) {
+		rlp_free(*spec);
+		return stat;
+	}
+
+	/* match must be non-wildcard */
+	assert(match->left > 0 || match->right < MAXKEY((*spec)->bittype));
+	stat = segment_insert(spec, match->left, match->right, newspec_set);
+	if (stat < 0) {
+		return stat;
+	}
+	stat = rlp_locate(*spec, &inf, match->right);
+	if (stat < 0) {
+		return stat;
+	}
+	if (match_num == rule->dt_match_len - 1) {
+		/* final match of rule -> insert rule into termrule block */
+		struct ptrblock **term = termrule(*spec);
+		stat = termrule_insert(term, rule);
+		if (stat < 0) {
+			return stat;
+		}
+		*inf.nextspec = (struct gen_spec *) rule;
+	} else {
+		/* before final match -> insert next match by recursion */
+		stat = dimtree_insrec_null((struct rlp_spec **)
+					   inf.nextspec, rule, match_num + 1,
+					   newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	return HE_OK;
+}
+
+static hipac_error
+dimtree_insrec_rule_elem(struct dt_rule_elem_spec **spec, struct dt_rule *rule,
+			 __u8 match_num, struct ptrblock *term_prop,
+			 int newspec_set)
+{
+	struct dt_match *match = ITH_DT_MATCH(rule, match_num);
+	__u8 bittype = dim2btype[match->dimid];
+	__u32 key = MAXKEY(bittype);
+	struct gen_spec *nextspec[1];
+	struct rlp_spec *newspec;
+	struct ptrblock **term;
+	struct locate_inf inf;
+	int stat;
+
+	assert(spec != NULL);
+	assert(*spec != NULL);
+	assert(IS_RULE(*spec) || IS_ELEM(*spec));
+	assert(match->left > 0 || match->right < MAXKEY(bittype));
+
+	/* create new rlp and insert match recursively; term_prop propagates
+	   through all dimension while remaining in each dimension as
+	   termrule block; if anything goes wrong before term_prop is
+	   attached to newspec term_prop will be freed; later it is treated
+	   by the history */
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: match_num: %d, newspec_set: %d, match: "
+	       "(dimid: %d, left: %u, right: %u)\n", __FUNCTION__, match_num,
+	       newspec_set, match->dimid, match->left, match->right);
+	if (HAS_WILDCARD_DIM(match->dimid)) {
+		nextspec[0] = NULL;
+		DPRINT(DEBUG_DIMTREE, "%s: new rlp: bittype: %d, dimid: %d,"
+		       " key: %u, nextspec: %p\n", __FUNCTION__, bittype,
+		       match->dimid, key, *nextspec);
+		newspec = rlp_new(bittype, match->dimid, 1, &key, nextspec);
+		if (newspec == NULL) {
+			if (term_prop != NULL) {
+				ptrblock_free(term_prop);
+			}
+			return HE_LOW_MEMORY;
+		}
+		*WILDCARD(newspec) = (struct gen_spec *) *spec;
+	} else {
+		nextspec[0] = (struct gen_spec *) *spec;
+		DPRINT(DEBUG_DIMTREE, "%s: new rlp: bittype: %d, dimid: %d,"
+		       " key: %u, nextspec: %p\n", __FUNCTION__, bittype,
+		       match->dimid, key, *nextspec);
+		newspec = rlp_new(bittype, match->dimid, 1, &key, nextspec);
+		if (newspec == NULL) {
+			if (term_prop != NULL) {
+				ptrblock_free(term_prop);
+			}
+			return HE_LOW_MEMORY;
+		}
+	}
+	stat = history_new((struct gen_spec *) newspec, newspec_set);
+	if (stat < 0) {
+		rlp_free(newspec);
+		if (term_prop != NULL) {
+			ptrblock_free(term_prop);
+		}
+		return stat;
+	}
+	stat = segment_insert(&newspec, match->left, match->right,
+			      newspec_set);
+	if (stat < 0) {
+		if (term_prop != NULL) {
+			ptrblock_free(term_prop);
+		}
+		return stat;
+	}
+	/* attach term_prop to newspec -> if anything goes wrong from now on
+	   term_prop must not be freed here */
+	term = termrule(newspec);
+	*term = term_prop;
+	stat = rlp_locate(newspec, &inf, match->right);
+	if (stat < 0) {
+		return stat;
+	}
+       
+	if (match_num == rule->dt_match_len - 1) {
+		/* final match of rule -> insert rule into termrule block */
+		stat = termrule_insert(term, rule);
+		if (stat < 0) {
+			return stat;
+		}
+		if (HAS_WILDCARD_DIM(match->dimid)) {
+			assert(*inf.nextspec == NULL);
+			*inf.nextspec = (struct gen_spec *) rule;
+		} else {
+			stat = rule_elem_insert((struct dt_rule_elem_spec **)
+						inf.nextspec, rule,
+						newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+		}
+	} else {
+		/* before final match -> insert next match by recursion */
+		if (*inf.nextspec == NULL) {
+                        stat = dimtree_insrec_null((struct rlp_spec **)
+						   inf.nextspec, rule,
+						   match_num + 1, newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+                } else {
+			struct ptrblock *term_prop_clone = NULL;
+			if (term_prop != NULL) {
+				stat = ptrblock_clone(term_prop,
+						      &term_prop_clone);
+				if (stat < 0) {
+					return stat;
+				}
+			}
+			stat = dimtree_insrec_rule_elem(
+				(struct dt_rule_elem_spec **) inf.nextspec,
+				rule, match_num + 1, term_prop_clone,
+				newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+		}
+	}
+	/* newspec is a rlp (not struct dt_rule_elem_spec *); the cast is
+	   anyway necessary because of spec */
+	*spec = (struct dt_rule_elem_spec *) newspec;
+	return HE_OK;
+}
+
+static inline hipac_error
+dimtree_insrec_curdimid_sm_help(struct rlp_spec *spec, struct gen_spec **g,
+				struct dt_rule *rule, __u8 match_num,
+				__u32 right, __u8 wildcard, int newspec_set,
+				int do_cut)
+{
+	int stat;
+
+	if (*g == NULL) {
+		/* insert rule into policy interval */
+		stat = dimtree_insrec_null((struct rlp_spec **) g, rule,
+					   match_num, newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	} else if (IS_RLP(*g)) {
+		/* non-terminal case */
+		struct rlp_spec *b = (struct rlp_spec *) *g;
+
+		/* we don‘t have to clone if dimtree_insrec_curdimid_eq is
+		   called by dimtree_insrec because segment_insert clones
+		   the rlp anyway if necessary */
+		if ((b->dimid != ITH_DT_MATCH(rule, match_num)->dimid)) {
+			stat = rlp_clone_ifneeded(b, &b, newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+		}
+		stat = dimtree_insrec(&b, rule, match_num, newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+		*g = (struct gen_spec *) b;
+	} else {
+		/* the rules that terminate in g will propagate to termrule
+		   blocks in below dimensions */
+		struct dt_rule_elem_spec **re;
+		struct ptrblock *term_prop;
+		assert(IS_ELEM(*g) || IS_RULE(*g));
+		stat = termrule_subset(*termrule(spec), &term_prop, right,
+				       wildcard, spec->dimid);
+		if (stat < 0) {
+			return stat;
+		}
+		if (do_cut && *termrule(spec) != NULL && term_prop != NULL) {
+			/* remove all rules in term_prop from current
+			   termrule block */
+			stat = termrule_cut(termrule(spec), term_prop);
+			if (stat < 0) {
+				ptrblock_free(term_prop);
+				return stat;
+			}
+		}
+
+		re = (struct dt_rule_elem_spec **) g;
+		if (IS_ELEM(*re)) {
+			struct dt_elem *e;
+			stat = elem_clone_ifneeded((struct dt_elem *) *re, &e,
+						   newspec_set);
+			if (stat < 0) {
+				if (term_prop != NULL) {
+					ptrblock_free(term_prop);
+				}
+				return stat;
+			}
+			*re = (struct dt_rule_elem_spec *) e;
+		}
+		stat = dimtree_insrec_rule_elem(re, rule, match_num,
+						term_prop, newspec_set);
+		if (stat < 0) {
+			/* term_prop was freed by
+			   dimtree_insrec_rule_elem */
+			return stat;
+		}
+	}
+	return HE_OK;
+}
+
+static hipac_error
+dimtree_insrec_curdimid_sm(struct rlp_spec **spec, struct dt_rule *rule,
+			   __u8 match_num, int newspec_set)
+{
+	__u32 key = 0;
+	__u32 maxkey = MAXKEY((*spec)->bittype);
+	struct locate_inf inf;
+	int stat;
+
+	assert(spec != NULL);
+	assert(*spec != NULL);
+	assert(IS_RLP(*spec));
+	assert(match_num < rule->dt_match_len);
+	/* insert it into every elementary interval respectively the wildcard
+	   pointer */
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: match_num: %d, newspec_set: %d\n",
+	       __FUNCTION__, match_num, newspec_set);
+#ifdef DEBUG
+	print_rlp(*spec);
+#endif
+	if (HAS_WILDCARD_SPEC(*spec)) {
+		return dimtree_insrec_curdimid_sm_help(
+			*spec, WILDCARD(*spec), rule, match_num, 0, 1,
+			newspec_set, 1);
+	}
+
+	do {
+		stat = rlp_locate(*spec, &inf, key);
+		if (stat < 0) {
+			return stat;
+		}
+		key  = inf.key + 1;
+		stat = dimtree_insrec_curdimid_sm_help(
+			*spec, inf.nextspec, rule, match_num, inf.key, 0,
+			newspec_set, 0);
+		if (stat < 0) {
+			return stat;
+		}
+	} while (inf.key < maxkey);
+	
+	if (*termrule(*spec) != NULL) {
+		/* by inserting rule into every elementary interval the
+		   dimension becomes completely nonterminating */
+		ptrblock_free(*termrule(*spec));
+		*termrule(*spec) = NULL;
+	}
+	return HE_OK;
+}
+
+/* necessary forward declaration */
+static hipac_error
+dimtree_insrec_curdimid_eq_tm(struct rlp_spec **spec, struct dt_rule *rule,
+			      __u32 left, __u32 right, int newspec_set);
+
+static inline hipac_error
+dimtree_insrec_curdimid_eq_tm_help(struct gen_spec **g, struct dt_rule *rule,
+				   struct ptrblock **term, __u8 *ins_termrule,
+				   int newspec_set)
+{
+	int stat;
+
+	if (*g != NULL && IS_RLP(*g)) {
+		/* non-terminal case */
+		struct rlp_spec *b;
+
+		stat = rlp_clone_ifneeded((struct rlp_spec *) *g, &b,
+					  newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+		stat = dimtree_insrec_curdimid_eq_tm(
+			&b, rule, 0, MAXKEY(b->bittype), newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+		*g = (struct gen_spec *) b;
+	} else {
+		/* beyond final match of rule -> insert rule into
+		   termrule block if not already inserted */
+		struct dt_rule_elem_spec **re;
+		if (*ins_termrule) {
+			stat = termrule_insert(term, rule);
+			if (stat < 0) {
+				return stat;
+			}
+			*ins_termrule = 0;
+		}
+		
+		re = (struct dt_rule_elem_spec **) g;
+		if (*re != NULL && IS_ELEM(*re)) {
+			struct dt_elem *e;
+			stat = elem_clone_ifneeded((struct dt_elem *) *re, &e,
+						   newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+			*re = (struct dt_rule_elem_spec *) e;
+		}
+		stat = rule_elem_insert(re, rule, newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	return HE_OK;
+}
+
+static hipac_error
+dimtree_insrec_curdimid_eq_tm(struct rlp_spec **spec, struct dt_rule *rule,
+			      __u32 left, __u32 right, int newspec_set)
+{
+	__u8 ins_termrule = 1;
+	struct ptrblock **term = termrule(*spec);
+	struct locate_inf inf;
+	__u32 key = left;
+	int stat;
+
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: left: %u, right: %u, newspec_set: %d\n",
+	       __FUNCTION__, left, right, newspec_set);
+#ifdef DEBUG
+	print_rlp(*spec);
+#endif
+	if (HAS_WILDCARD_SPEC(*spec) && left == 0 &&
+	    right == MAXKEY((*spec)->bittype)) {
+		/* insert wildcard match into wildcard dimension */
+		return dimtree_insrec_curdimid_eq_tm_help(
+			WILDCARD(*spec), rule, term, &ins_termrule,
+			newspec_set);
+	}
+
+	/* iterate over every elementary interval between left and right
+	   and check if rule is better than the current or recurse if
+	   elementary interval is non-terminating */
+	do {
+		stat = rlp_locate(*spec, &inf, key);
+		if (stat < 0) {
+			return stat;
+		}
+		key  = inf.key + 1;
+		stat = dimtree_insrec_curdimid_eq_tm_help(
+			inf.nextspec, rule, term, &ins_termrule,
+			newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	} while (inf.key < right);
+	return HE_OK;
+}
+
+static hipac_error
+dimtree_insrec_curdimid_eq(struct rlp_spec **spec, struct dt_rule *rule,
+			   const struct dt_match *match, __u8 match_num,
+			   int newspec_set)
+{
+	__u32 key = match->left;
+	struct locate_inf inf;
+	int stat;
+
+	/* match must be non-wildcard */
+	assert(match->left > 0 || match->right < MAXKEY((*spec)->bittype));
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: match_num: %d, newspec_set: %d, match: "
+	       "(dimid: %d, left: %u, right: %u)\n", __FUNCTION__, match_num,
+	       newspec_set, match->dimid, match->left, match->right);
+#ifdef DEBUG
+	print_rlp(*spec);
+#endif
+	stat = segment_insert(spec, match->left, match->right, newspec_set);
+	if (stat < 0) {
+		return stat;
+	}
+
+	/* insert match and iterate over every overlapped interval */
+	if (match_num == rule->dt_match_len - 1) {
+		/* final match of rule */
+		stat = dimtree_insrec_curdimid_eq_tm(
+			spec, rule, match->left, match->right, newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	} else {
+		/* before final match of rule */
+		do {
+			stat = rlp_locate(*spec, &inf, key);
+			if (stat < 0) {
+				return stat;
+			}
+			key = inf.key + 1;
+			
+			if (*inf.nextspec == NULL) {
+				/* insert rule into policy interval */
+				stat = dimtree_insrec_null(
+					(struct rlp_spec **) inf.nextspec,
+					rule, match_num + 1, newspec_set);
+				if (stat < 0) {
+					return stat;
+				}
+			} else if (IS_RLP(*inf.nextspec)) {
+				/* non-terminal case */
+				struct rlp_spec *b = (struct rlp_spec *)
+					*inf.nextspec;
+				
+				/* we don‘t have to clone if
+				   dimtree_insrec_curdimid_eq is called by
+				   dimtree_insrec because segment_insert
+				   clones the rlp anyway if necessary */
+				if (b->dimid !=
+				    ITH_DT_MATCH(rule, match_num + 1)->dimid) {
+					stat = rlp_clone_ifneeded(
+						(struct rlp_spec *)
+						*inf.nextspec, &b,
+						newspec_set);
+					if (stat < 0) {
+						return stat;
+					}
+				}
+				stat = dimtree_insrec(
+					&b, rule, match_num + 1, newspec_set);
+				if (stat < 0) {
+					return stat;
+				}
+				*inf.nextspec = (struct gen_spec *) b;
+			} else {
+				/* the rules that terminate in the current
+				   elementary interval will propagate to
+				   termrule blocks in below dimensions */
+				struct dt_rule_elem_spec **re;
+				struct ptrblock *term_prop;
+				stat = termrule_subset(
+					*termrule(*spec), &term_prop, inf.key,
+					0, (*spec)->dimid);
+				if (stat < 0) {
+					if (term_prop != NULL) {
+						ptrblock_free(term_prop);
+					}
+					return stat;
+				}
+				re = (struct dt_rule_elem_spec **)
+					inf.nextspec;
+				if (IS_ELEM(*re)) {
+					struct dt_elem *e;
+					stat = elem_clone_ifneeded(
+						(struct dt_elem *) *re, &e,
+						newspec_set);
+					if (stat < 0) {
+						if (term_prop != NULL) {
+							ptrblock_free(
+							      term_prop);
+						}
+						return stat;
+					}
+					*re = (struct dt_rule_elem_spec *) e;
+				}
+				stat = dimtree_insrec_rule_elem(
+					re, rule, match_num + 1, term_prop,
+					newspec_set);
+				if (stat < 0) {
+					/* term_prop was freed by
+					   dimtree_insrec_rule_elem */
+					return stat;
+				}
+			}
+		} while (inf.key < match->right);
+
+		/* as the rule continues we can be sure that every terminating
+		   rule whose match in the current dimension is completely
+		   overlapped by match can be removed from the termrule block;
+		   we possibly forget to remove rules with partially overlapped
+		   matches but this does NOT cause any harm and the case should
+		   be very rare */
+		stat = termrule_delete_ovl(termrule(*spec), match->left,
+					   match->right, (*spec)->dimid);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	return HE_OK;
+}
+
+static hipac_error
+dimtree_insrec_curdimid_gr(struct rlp_spec **spec, struct dt_rule *rule,
+			   const struct dt_match *match, __u8 match_num,
+			   int newspec_set)
+{
+	__u8 bittype = dim2btype[match->dimid];
+	__u32 key = MAXKEY(bittype);	
+	struct gen_spec *nextspec[1];
+	struct rlp_spec *newspec;
+	int stat;
+
+	/* create missing dimension and insert current match by recursion */
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: match_num: %d, newspec_set: %d, match: "
+	       "(dimid: %d, left: %u, right: %u)\n", __FUNCTION__, match_num,
+	       newspec_set, match->dimid, match->left, match->right);
+#ifdef DEBUG
+	print_rlp(*spec);
+#endif
+	if (HAS_WILDCARD_DIM(match->dimid)) {
+		nextspec[0] = NULL;
+		DPRINT(DEBUG_DIMTREE, "%s: new rlp: bittype: %d, dimid: %d,"
+		       " key: %u, nextspec: %p\n", __FUNCTION__, bittype,
+		       match->dimid, key, *nextspec);
+		newspec = rlp_new(bittype, match->dimid, 1, &key, nextspec);
+		if (newspec == NULL) {
+			return HE_LOW_MEMORY;
+		}
+		*WILDCARD(newspec) = (struct gen_spec *) *spec;
+	} else {
+		nextspec[0] = (struct gen_spec *) *spec;
+		DPRINT(DEBUG_DIMTREE, "%s: new rlp: bittype: %d, dimid: %d,"
+		       " key: %u, nextspec: %p\n", __FUNCTION__, bittype,
+		       match->dimid, key, *nextspec);
+		newspec = rlp_new(bittype, match->dimid, 1, &key, nextspec);
+		if (newspec == NULL) {
+			return HE_LOW_MEMORY;
+		}
+	}
+	stat = history_new((struct gen_spec *) newspec, newspec_set);
+	if (stat < 0) {
+		rlp_free(newspec);
+		return stat;
+	}
+	*spec = newspec;
+	return dimtree_insrec(spec, rule, match_num, newspec_set);
+}
+
+static hipac_error
+dimtree_insrec(struct rlp_spec **spec, struct dt_rule *rule,
+	       __u8 match_num, int newspec_set)
+{
+	struct dt_match *match;
+
+	/* spec non-terminating	*/
+	assert(spec != NULL);
+	assert(*spec != NULL);
+	assert(IS_RLP(*spec));
+
+	/* rule is not finished yet */
+	assert(match_num < rule->dt_match_len);
+
+	match = ITH_DT_MATCH(rule, match_num);
+
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: match_num: %d, newspec_set: %d, match: "
+	       "(dimid: %d,  left: %u, right: %u)\n", __FUNCTION__, match_num,
+	       newspec_set, match->dimid, match->left, match->right);
+#ifdef DEBUG
+	print_rlp(*spec);
+#endif
+	if ((*spec)->dimid < match->dimid) {
+		/* match in current dimension treated as wildcard because there
+		   is no match for the current dimension */
+		return dimtree_insrec_curdimid_sm(spec, rule, match_num,
+						  newspec_set);
+	} else if ((*spec)->dimid == match->dimid) {
+		/* there is a match in the current dimension which is per
+		   default no wildcard */
+		return dimtree_insrec_curdimid_eq(spec, rule, match,
+						  match_num, newspec_set);
+		
+	} else {
+		/* the dimension of the current match has not yet been
+		   created */
+		return dimtree_insrec_curdimid_gr(spec, rule, match,
+						  match_num, newspec_set);
+	}
+}
+
+static inline hipac_error
+segment_delete_help(struct rlp_spec *spec, struct locate_inf *bound1,
+		    __u32 lkey, __u32 dkey, __u32 del_key[], __u8 *del_num,
+		    int newspec_set)
+{
+	struct gen_spec *current1, *current2;
+	struct locate_inf bound2;
+	int stat;
+
+	stat = rlp_locate(spec, &bound2, lkey);
+	if (stat < 0) {
+		return stat;
+	}
+	current1 = *bound1->nextspec;
+	current2 = *bound2.nextspec;
+	switch (rlp_rule_elem_eq(current1, current2)) {
+	    case 1:
+		    if (current1 == NULL ||
+			!termrule_exists(*termrule(spec), spec->dimid, dkey)) {
+			    del_key[(*del_num)++] = dkey;
+		    }
+		    break;
+	    case 2:
+		    if (!termrule_exists(*termrule(spec), spec->dimid, dkey)) {
+			    history_obsolete(current1, newspec_set);
+			    del_key[(*del_num)++] = dkey;
+		    }
+		    break;
+	    case 3:
+		    del_key[(*del_num)++] = dkey;
+		    stat = rlp_free_rec((struct rlp_spec *) current1,
+					newspec_set, 0);
+		    if (stat < 0) {
+			    return stat;
+		    }
+		    break;
+	    default:
+		    break;
+	}
+	return HE_OK;
+}
+
+/* segment [left, right] is deleted from spec if the neighbours of left and
+   right point to the same spec; at most two elementary intervals can be
+   deleted */
+static inline hipac_error
+segment_delete(struct rlp_spec **spec, __u32 left, __u32 right,
+	       int newspec_set)
+{
+	__u8 del_num = 0;
+	__u32 maxkey = MAXKEY((*spec)->bittype);
+	__u32 del_key[2] = {0, 0};
+	struct locate_inf bound1;
+	int stat;
+	
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: left: %u, right: %u, newspec_set: %d\n",
+	       __FUNCTION__, left, right, newspec_set);
+#ifdef DEBUG
+	print_rlp(*spec);
+#endif
+	if (left > 0) {
+		stat = rlp_locate(*spec, &bound1, left - 1);
+		if (stat < 0) {
+			return stat;
+		}
+		assert(bound1.key == left - 1);
+		stat = segment_delete_help(*spec, &bound1, left, left - 1,
+					   del_key, &del_num, newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+
+	if (right < maxkey) {
+		stat = rlp_locate(*spec, &bound1, right);
+		if (stat < 0) {
+			return stat;
+		}
+		assert(bound1.key == right);
+		stat = segment_delete_help(*spec, &bound1, right + 1, right,
+					   del_key, &del_num, newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	
+	if (del_num > 0) {
+		struct rlp_spec *b;
+		assert(del_num == 1 || del_key[0] < del_key[1]);
+		if (del_num == 1) {
+			DPRINT(DEBUG_DIMTREE, "del key: %u\n", del_key[0]);
+		} else {
+			DPRINT(DEBUG_DIMTREE, "del keys: %u, %u\n",
+			       del_key[0], del_key[1]);
+		}
+		stat = rlp_delete(*spec, del_num, del_key, &b);
+		if (stat < 0) {
+			return stat;
+		}
+		stat = history_replace((struct gen_spec *) *spec,
+				       (struct gen_spec *) b, newspec_set);
+		if (stat < 0) {
+			rlp_free(b);
+			return stat;
+		}
+		*spec = b;
+	}
+	return HE_OK;
+}
+
+/* forward declaration needed for dimtree_delrec_interval */
+static hipac_error
+dimtree_delrec(struct rlp_spec **spec, const struct dt_rule *rule,
+	       __u8 match_num, struct ptrlist *term_prop, int newspec_set);
+
+static inline hipac_error
+dimtree_delrec_interval(struct gen_spec **spec, const struct dt_rule *rule,
+			__u8 match_num, struct ptrlist *tmpterm,
+			struct ptrblock **term, __u32 right, __u8 wildcard,
+			__u8 dimid, int newspec_set)
+{
+	int stat;
+
+	assert(*spec != NULL);
+	if (IS_RLP(*spec)) {
+		/* non-terminal case */
+		struct rlp_spec *b;
+
+		stat = rlp_clone_ifneeded((struct rlp_spec *) *spec, &b,
+					  newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+		stat = dimtree_delrec(&b, rule, match_num, tmpterm,
+				      newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+		*spec = (struct gen_spec *) b;
+	} else {
+		struct dt_rule_elem_spec **re =
+			(struct dt_rule_elem_spec **) spec;
+
+		if (IS_ELEM(*re)) {
+			struct dt_elem *e;
+			stat = elem_clone_ifneeded((struct dt_elem *) *re, &e,
+						   newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+			*re = (struct dt_rule_elem_spec *) e;
+		}
+		stat = rule_elem_delete(re, rule, *term, right, wildcard,
+					dimid, newspec_set);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	return HE_OK;
+}
+
+static hipac_error
+dimtree_delrec(struct rlp_spec **spec, const struct dt_rule *rule,
+	       __u8 match_num, struct ptrlist *term_prop, int newspec_set)
+{	
+	/* current match is initialized as wildcard */
+	__u32 left   = 0;	
+	__u32 key    = 0;
+	__u32 maxkey = MAXKEY((*spec)->bittype);
+	__u8 match_is_wildcard = 1;
+
+	/* collects all terminating specs from the below dimension */
+	struct ptrlist *tmpterm;
+	struct ptrblock **term;
+	struct locate_inf inf;
+	int stat;
+	
+#ifdef DEBUG
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	if (match_num < rule->dt_match_len) {
+		const struct dt_match *match = ITH_DT_MATCH(rule, match_num);
+		DPRINT(DEBUG_DIMTREE, "%s: match_num: %d, newspec_set: %d, "
+		       "le: %p, match: (dimid: %d, left: %u, right: %u)\n",
+		       __FUNCTION__, match_num, newspec_set, rule,
+		       match->dimid, match->left, match->right);
+	} else {
+		DPRINT(DEBUG_DIMTREE, "%s: match_num: %d, newspec_set: %d, "
+		       "rule: %p, match: <none>\n", __FUNCTION__, match_num,
+		       newspec_set, rule);
+	}
+	print_rlp(*spec);
+#endif
+	tmpterm = tmp_termrule_new();
+	if (tmpterm == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	term = termrule(*spec);
+
+	/* dimtree_delrec is never called for terminal cases */
+	assert(*spec != NULL);
+	assert(IS_RLP(*spec));
+
+	if (match_num < rule->dt_match_len) {
+		/* rule is not finished yet */
+		const struct dt_match *match = ITH_DT_MATCH(rule, match_num);
+		
+		if ((*spec)->dimid == match->dimid) {
+			/* match must be non-wildcard */
+			assert(match->left > 0 ||
+			       match->right < MAXKEY((*spec)->bittype));
+			key = left = match->left;
+			maxkey = match->right;
+			match_is_wildcard = 0;
+			match_num++;
+		}
+	}
+	
+	if (HAS_WILDCARD_SPEC(*spec) && match_is_wildcard) {
+		assert(*WILDCARD(*spec) != NULL);
+		stat = dimtree_delrec_interval(
+			WILDCARD(*spec), rule, match_num, tmpterm, term,
+			0, 1, (*spec)->dimid, newspec_set);
+		if (stat < 0) {
+			goto error;
+		}
+	} else {
+		do {
+			stat = rlp_locate(*spec, &inf, key);
+			if (stat < 0) {
+				goto error;
+			}
+			key = inf.key + 1;
+			assert(*inf.nextspec != NULL);
+			stat = dimtree_delrec_interval(
+				inf.nextspec, rule, match_num, tmpterm, term,
+				inf.key, 0, (*spec)->dimid, newspec_set);
+			if (stat < 0) {
+				goto error;
+			}
+		} while (inf.key < maxkey);
+	}
+		
+	/* delete rule from termrule block if it is there */
+	stat = termrule_delete(term, rule);
+	if (stat < 0) {
+		goto error;
+	}
+
+	/* merge temporary termrule list with termrule block */
+	stat = termrule_merge(term, tmpterm);
+	if (stat < 0) {
+		return stat;
+	}
+
+	if (!match_is_wildcard) {
+		/* remove surrounding elementary intervals represented by left
+		   and maxkey if necessary */
+		stat = segment_delete(spec, left, maxkey, newspec_set);
+		if (stat < 0) {
+			/* tmpterm is already freed */
+			return stat;
+		}
+		term = termrule(*spec);
+	}
+	
+	if ((*spec)->num == 1) {
+		/* spec is empty => drop it */
+		struct gen_spec *nextspec;
+
+		if (HAS_WILDCARD_SPEC(*spec)) {
+			assert((stat = rlp_locate(*spec, &inf, 0),
+				stat < 0 ? 1 : *inf.nextspec == NULL));
+			nextspec = *WILDCARD(*spec);
+		} else {
+			stat = rlp_locate(*spec, &inf, 0);
+			if (stat < 0) {
+				/* tmpterm is already freed */
+				return stat;
+			}
+			nextspec = *inf.nextspec;
+		}
+		
+		if (*term != NULL && term_prop != NULL) {
+			stat = tmp_termrule_merge(term_prop, *term);
+			if (stat < 0) {
+				/* tmpterm is already freed */
+				return stat;
+			}
+		}
+		stat = history_obsolete((struct gen_spec *) *spec,
+					newspec_set);
+		if (stat < 0) {
+			/* tmpterm is already freed */
+			return stat;
+		}
+
+		if (nextspec == NULL || IS_RULE(nextspec)) {
+			*spec = (struct rlp_spec *) nextspec;
+		} else if (IS_RLP(nextspec)) {
+			struct rlp_spec *b;
+
+			stat = rlp_clone_ifneeded((struct rlp_spec *)
+						  nextspec, &b, newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+			*spec = (struct rlp_spec *) b;
+		} else {
+			struct dt_elem *e;
+			assert(IS_ELEM(nextspec));
+			stat = elem_clone_ifneeded((struct dt_elem *)
+						   nextspec, &e, newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+			*spec = (struct rlp_spec *) e;
+		}
+	}
+	return HE_OK;
+
+ error:
+	tmp_termrule_free(tmpterm);
+	return stat;
+}
+
+
+
+/*
+ * public dimtree operations
+ */
+
+hipac_error
+dimtree_new(struct dimtree **newdt, __u32 origin, const char *chain_name,
+	    struct dt_rule *dummy, struct dt_rule *policy)
+{
+	struct dt_chain *chain;
+
+	if (unlikely(newdt == NULL || chain_name == NULL || dummy == NULL ||
+		     policy == NULL || dummy->spec.action != TARGET_DUMMY ||
+		     !IS_RULE_TERM(policy) || policy->dt_match_len != 0)) {
+		ARG_ERR;
+	}
+	*newdt = hp_alloc(sizeof(**newdt), 1);
+	if (*newdt == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	chain = hp_alloc(sizeof(*chain), 1);
+	if (chain == NULL) {
+		hp_free(*newdt);
+		*newdt = NULL;
+		return HE_LOW_MEMORY;
+	}
+	INIT_LIST_HEAD(&chain->head);
+	strncpy(chain->name, chain_name, sizeof(chain->name));
+	chain->name[sizeof(chain->name) - 1] = ‘\0‘;
+	chain->first = policy;
+	chain->len = 2;
+	list_add(&policy->head, &chain->head);
+	list_add(&dummy->head, &chain->head);
+
+	(*newdt)->origin = origin;
+        (*newdt)->top = (struct gen_spec *) policy;
+	(*newdt)->top_new = NULL;
+        (*newdt)->need_commit = 0;
+	(*newdt)->chain = chain;
+	return HE_OK;
+}
+
+void
+dimtree_free(struct dimtree *dt)
+{
+	struct list_head *lh;
+	struct dt_rule *rule;
+
+	if (unlikely(dt == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	if (dt->top != NULL) {
+		if (IS_RLP(dt->top)) {
+			rlp_free_rec((struct rlp_spec *) dt->top, 0, 1);
+		} else if (IS_ELEM(dt->top)) {
+			elem_free((struct dt_elem *) dt->top);
+		}
+	}
+	for (lh = dt->chain->head.next; lh != &dt->chain->head;) {
+		rule = list_entry(lh, struct dt_rule, head);
+		lh = lh->next;
+		if (rule->exec_match != NULL) {
+			ptrblock_free(rule->exec_match);
+		}
+		hp_free(rule);
+	}
+	hp_free(dt->chain);
+	hp_free(dt);
+}
+
+void
+dimtree_flush(struct dimtree *dt)
+{
+	struct gen_spec *top;
+	struct list_head *lh;
+	struct dt_rule *rule;
+
+	if (unlikely(dt == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	assert(dt->chain->len >= 2);
+	assert(list_entry(dt->chain->head.next,
+			  struct dt_rule, head)->spec.action == TARGET_DUMMY);
+	top = dt->top;
+	dt->top = (struct gen_spec *) list_entry(dt->chain->head.prev,
+						 struct dt_rule, head);
+	((struct dt_rule *) dt->top)->spec.pos = 1;
+	dt->need_commit = 0;
+	synchronize_rcu();
+	if (top != NULL) {
+		if (IS_RLP(top)) {
+			rlp_free_rec((struct rlp_spec *) top, 0, 1);
+		} else  if (IS_ELEM(top)) {
+			elem_free((struct dt_elem *) top);
+		}
+	}
+	for (lh = dt->chain->head.next->next; lh != dt->chain->head.prev;) {
+		rule = list_entry(lh, struct dt_rule, head);
+		lh = lh->next;
+		list_del(lh->prev);
+		if (rule->exec_match != NULL) {
+			ptrblock_free(rule->exec_match);
+		}
+		hp_free(rule);
+	}
+	dt->chain->first = list_entry(dt->chain->head.prev, struct dt_rule,
+				      head);
+	dt->chain->len = 2;
+}
+
+const char *
+dimtree_get_chain_name(const struct dimtree *dt)
+{
+	if (unlikely(dt == NULL)) {
+		ARG_MSG;
+		return NULL;
+	}
+	return dt->chain->name;
+}
+
+static hipac_error
+dimtree_insert_intern(struct dimtree *dt, struct dt_rule *rule, __u32 origin,
+		      int inc, int insert_chain, int commit)
+{
+	struct gen_spec *top;
+	struct list_head *lh;
+	struct dt_rule *r;
+	int stat;
+	
+	if (unlikely(dt == NULL || rule == NULL ||
+		     rule->spec.pos <= 0 ||
+		     rule->spec.pos >
+		     list_entry(dt->chain->head.prev,
+				struct dt_rule, head)->spec.pos ||
+		     (IS_TARGET_DUMMY(rule) && !insert_chain))) {
+		ARG_ERR;
+	}
+	
+	/* insert rule into dt_chain */
+	assert(!rule->deleted);
+	if (insert_chain) {
+		if (likely(inc)) {
+			for (lh = dt->chain->head.prev; lh != &dt->chain->head;
+			     lh = lh->prev) {
+				r = list_entry(lh, struct dt_rule, head);
+				if (r->spec.pos < rule->spec.pos) {
+					break;
+				}
+				r->spec.pos++;
+			}
+			list_add(&rule->head, lh);
+		} else {
+			__u32 maxpos = list_entry(dt->chain->head.prev,
+						  struct dt_rule,
+						  head)->spec.pos;
+			if (((maxpos + 1) * rule->spec.pos) / dt->chain->len <
+			    dt->chain->len >> 1) {
+				list_for_each (lh, &dt->chain->head) {
+					r = list_entry(lh, struct dt_rule,
+						       head);
+					if (r->spec.pos > rule->spec.pos) {
+						break;
+					}
+				}
+				list_add_tail(&rule->head, lh);
+			} else {
+				for (lh = dt->chain->head.prev;
+				     lh != &dt->chain->head; lh = lh->prev) {
+					r = list_entry(lh, struct dt_rule,
+						       head);
+					if (r->spec.pos <= rule->spec.pos) {
+						break;
+					}
+				}
+				list_add(&rule->head, lh);
+			}
+		}
+		dt->chain->len++;
+		if (IS_TARGET_DUMMY(rule)) {
+			return HE_OK;
+		}
+	}
+
+	/* origin check */
+	if (!(dt->origin & origin)) {
+		return HE_RULE_ORIGIN_MISMATCH;
+	}
+
+	if (!dt->need_commit) {
+		/* first operation in a series => clone top level structure
+		   if necessary */
+		if (dt->top == NULL) {
+			top = NULL;
+		} else if (IS_RLP(dt->top)) {
+			stat = rlp_clone((struct rlp_spec *) dt->top,
+					 (struct rlp_spec **) &top);
+			if (stat < 0) {
+				return stat;
+			}
+			stat = history_replace(dt->top, top, !commit);
+			if (stat < 0) {
+				rlp_free((struct rlp_spec *) top);
+				history_undo();
+				return stat;
+			}
+		} else if (IS_ELEM(dt->top)) {
+			stat = elem_clone((struct dt_elem *) dt->top,
+					  (struct dt_elem **) &top);
+			if (stat < 0) {
+				return stat;
+			}
+			stat = history_replace(dt->top, top, !commit);
+			if (stat < 0) {
+				elem_free((struct dt_elem *) top);
+				history_undo();
+				return stat;
+			}
+		} else {
+			assert(IS_RULE(dt->top));
+			top = dt->top;
+		}
+	} else {
+		top = dt->top_new;
+	}
+
+	/* insert rule into rlp */
+	if (rule->dt_match_len == 0) {
+		/* rule has no native matches at all */
+		if (top != NULL && IS_RLP(top)) {
+			stat = dimtree_insrec_curdimid_eq_tm(
+				(struct rlp_spec **) &top, rule, 0,
+				MAXKEY(dim2btype[((struct rlp_spec *)
+						  top)->dimid]), !commit);
+		} else {
+			stat = rule_elem_insert((struct dt_rule_elem_spec **)
+						&top, rule, !commit);
+		}
+	} else {
+		/* rule has at least one native match */
+		if (top == NULL) {
+			stat = dimtree_insrec_null((struct rlp_spec **) &top,
+						   rule, 0, !commit);
+		} else if (IS_RLP(top)) {
+			stat = dimtree_insrec((struct rlp_spec **) &top,
+					      rule, 0, !commit);
+		} else {
+			/* construct termrule block containing all
+			   non TARGET_DUMMY rules except the inserted rule
+			   from dt->chain */
+			struct ptrblock *term_prop = NULL;
+			struct list_head *lh;
+			struct dt_rule *r;
+			
+			stat = HE_OK;
+			list_for_each (lh, &dt->chain->head) {
+				r = list_entry(lh, struct dt_rule, head);
+				if (r->spec.action == TARGET_DUMMY ||
+				    r == rule || r->deleted) {
+					continue;
+				}
+				assert(r->dt_match_len == 0);
+				stat = termrule_insert(&term_prop, r);
+				if (stat < 0) {
+					if (term_prop != NULL) {
+						ptrblock_free(term_prop);
+					}
+					break;
+				}
+			}
+			if (stat == HE_OK) {
+				stat = dimtree_insrec_rule_elem(
+					(struct dt_rule_elem_spec **) &top,
+					rule, 0, term_prop, !commit);
+			}
+		}
+	}
+	if (stat < 0) {
+		history_undo();
+		dt->top_new = NULL;
+		return stat;
+	}
+	if (commit) {
+#ifdef DEBUG
+		if (rule_occur(dt->top, rule, 1)) {
+			DPRINT(DEBUG_DIMTREE, "rule present in original"
+			       "structure\n");
+			return HE_IMPOSSIBLE_CONDITION;
+		}
+#endif
+		dt->top = top;
+		dt->top_new = NULL;
+		synchronize_rcu();
+		history_commit(0);
+		assert(history_is_empty());
+	} else {
+		assert((IS_RULE(top) && IS_RULE(dt->top)) ||
+		       !history_is_empty());
+		dt->need_commit = 1;
+		dt->top_new = top;
+	}
+	return HE_OK;
+}
+
+#ifdef DEBUG
+void
+dt_rule_print(const struct dt_rule *rule);
+#endif
+
+hipac_error
+dimtree_insert(struct dimtree *dt, struct dt_rule *rule, __u32 origin,
+	       int inc, int commit)
+{
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: origin: %X, inc: %d, commit: %d\n",
+	       __FUNCTION__, origin, inc, commit);
+	DPRINT(DEBUG_DIMTREE, "dt: origin: %X, need_commit: %u,"
+	       " chain: %s (len: %u)\n", dt->origin, dt->need_commit,
+	       dt->chain->name, dt->chain->len);
+#ifdef DEBUG
+	if (dt->top_new == NULL) {
+		if (dt->top != NULL) {
+			if (IS_RLP(dt->top)) {
+				print_rlp((struct rlp_spec *) dt->top);
+			} else if (IS_ELEM(dt->top)) {
+				print_elem((struct dt_elem *) dt->top);
+				DPRINT(DEBUG_DIMTREE, "\n");
+			} else {
+				DPRINT(DEBUG_DIMTREE, "top level rule: %p\n",
+				       dt->top);
+			}
+		}
+	} else {
+		if (IS_RLP(dt->top_new)) {
+			print_rlp((struct rlp_spec *) dt->top_new);
+		} else if (IS_ELEM(dt->top_new)) {
+				print_elem((struct dt_elem *) dt->top_new);
+				DPRINT(DEBUG_DIMTREE, "\n");
+		} else {
+			DPRINT(DEBUG_DIMTREE, "top level rule: %p\n",
+			       dt->top_new);
+		}
+	}
+	if (hipac_debug & DEBUG_DIMTREE) {
+		dt_rule_print(rule);
+	}
+#endif
+	return dimtree_insert_intern(dt, rule, origin, inc, 1, commit);
+}
+
+static struct dt_rule *
+dimtree_delete_find_best_term(struct dimtree *dt,
+			      const struct dt_rule *term_rule, __u32 *ntm_num)
+{
+	struct list_head *lh;
+	struct dt_rule *cr;
+	
+	if (unlikely(dt == NULL || term_rule == NULL || ntm_num == NULL)) {
+		ARG_MSG;
+		return NULL;
+	}
+
+	*ntm_num = 0;
+	for (lh = term_rule->head.next; lh != &dt->chain->head;
+	     lh = lh->next) {
+		cr = list_entry(lh, struct dt_rule, head);
+		if (cr->deleted) {
+			continue;
+		}
+		if (IS_RULE_TERM(cr)) {
+			return cr;
+		} else if (cr->spec.action != TARGET_DUMMY) {
+			(*ntm_num)++;
+		}
+	}
+	return NULL;
+}
+
+/* from and to are exclusive */
+static hipac_error
+dimtree_delete_insert_ntm(struct dimtree *dt, struct dt_elem **e,
+			  const struct dt_rule *from, const struct dt_rule *to)
+{
+	struct list_head *lh;
+	struct dt_rule *cr;
+	int stat;
+	
+	if (unlikely(dt == NULL || e == NULL || *e == NULL || to == NULL)) {
+		ARG_ERR;
+	}
+
+	for (lh = (from == NULL ? dt->chain->head.next : from->head.next);
+	     lh != &to->head; lh = lh->next) {
+		cr = list_entry(lh, struct dt_rule, head);
+		if (cr->deleted || cr->spec.action == TARGET_DUMMY) {
+			continue;
+		}
+		assert(cr->spec.pos < to->spec.pos);
+		assert(!IS_RULE_TERM(cr));
+		stat = ptrblock_insert_embed((void **) e,
+					     offsetof(struct dt_elem,
+						      ntm_rules), cr,
+					     (*e)->ntm_rules.len);
+		if (stat < 0) {
+			return stat;
+		}
+	}
+	return HE_OK;
+}
+
+static hipac_error
+dimtree_delete_rule_elem(struct dt_rule_elem_spec **rule_elem,
+			 const struct dt_rule *rule, struct dimtree *dt,
+			 int newspec_set)
+{
+	struct dt_elem *e;
+	int stat;
+	__u32 i;
+	
+	if (IS_RULE(*rule_elem)) {
+		struct dt_rule *r = (struct dt_rule *) *rule_elem;
+		struct dt_rule *term_rule;
+		__u32 ntm_num;
+		
+		if (r != rule) {
+			/* deleted rule must have a higher position than r */
+			return HE_OK;
+		}
+		term_rule = dimtree_delete_find_best_term(dt, rule, &ntm_num);
+		if (term_rule == NULL) {
+			IMPOSSIBLE_CONDITION("attempt to delete the only "
+					     "terminal rule");
+		}
+		if (ntm_num == 0) {
+			*rule_elem = (struct dt_rule_elem_spec *) term_rule;
+			return HE_OK;
+		} else {
+			struct dt_elem *e = elem_new_empty(term_rule);
+			if (e == NULL) {
+				return HE_LOW_MEMORY;
+			}
+			stat = dimtree_delete_insert_ntm(dt, &e, rule,
+							 term_rule);
+			if (stat < 0) {
+				elem_free(e);
+				return stat;
+			}
+			assert(e->ntm_rules.len > 0);
+			stat = history_new((struct gen_spec *) e, newspec_set);
+			if (stat < 0) {
+				elem_free(e);
+				return stat;
+			}
+			*rule_elem = (struct dt_rule_elem_spec *) e;
+			return HE_OK;
+		}
+	}
+
+	assert(IS_ELEM(*rule_elem));
+	e = (struct dt_elem *) *rule_elem;
+	assert(e->term_rule != NULL);
+	if (IS_RULE_TERM(rule)) {
+		struct dt_rule *term_rule;
+		__u32 ntm_num;
+
+		if (e->term_rule != rule) {
+			/* deleted rule must have a higher position than
+			   e->term_rule */
+			assert(rule->spec.pos > e->term_rule->spec.pos);
+			return HE_OK;
+		}
+		term_rule = dimtree_delete_find_best_term(dt, rule, &ntm_num);
+		if (term_rule == NULL) {
+			IMPOSSIBLE_CONDITION("attempt to delete the only "
+					     "terminal rule");
+		}
+		stat = dimtree_delete_insert_ntm(
+			 dt, (struct dt_elem **) rule_elem, rule, term_rule);
+		if (stat < 0) {
+			/* we only care about rule_elem if its address has
+			   changed; otherwise rule_elem is handled by the
+			   history */
+			if (e != (struct dt_elem *) *rule_elem) {
+				history_del_invalid((struct gen_spec *) e);
+				elem_free((struct dt_elem *) *rule_elem);
+			}
+			return stat;
+		}
+		if (e != (struct dt_elem *) *rule_elem) {
+			history_del_invalid((struct gen_spec *) e);
+			stat = history_new((struct gen_spec *)
+					   *rule_elem, newspec_set);
+			if (stat < 0) {
+				elem_free((struct dt_elem *) *rule_elem);
+				return stat;
+			}
+		}
+		(*(struct dt_elem **) rule_elem)->term_rule = term_rule;
+		return HE_OK;
+	} else {
+		for (i = 0; i < e->ntm_rules.len &&
+			     ((struct dt_rule *)
+			      e->ntm_rules.p[i])->spec.pos <
+			     rule->spec.pos; i++);
+		if (i >= e->ntm_rules.len || e->ntm_rules.p[i] != rule) {
+			/* deleted rule must have a higher position than
+			   e->ntm_rules.p[e->ntm_rules.len - 1] */
+			return HE_OK;
+		}
+		if (e->ntm_rules.len == 1) {
+			struct dt_rule_elem_spec *tm =
+				(struct dt_rule_elem_spec *)
+				e->term_rule;
+			stat = history_obsolete((struct gen_spec *) e,
+						newspec_set);
+			if (stat < 0) {
+				return stat;
+			}
+			*rule_elem = tm;
+			return HE_OK;
+		} else {
+			stat = ptrblock_delete_pos_embed(
+				 (void **) rule_elem,
+				 offsetof(struct dt_elem, ntm_rules),
+				 i);
+			if (stat < 0) {
+				/* we only care about rule_elem if its address
+				   has changed; otherwise rule_elem is 
+				   handled by the history */
+				if (e != (struct dt_elem *) *rule_elem) {
+					history_del_invalid((struct gen_spec *)
+							    e);
+					elem_free((struct dt_elem *)
+						  *rule_elem);
+				}
+				return stat;
+			}
+			if (e != (struct dt_elem *) *rule_elem) {
+				history_del_invalid((struct gen_spec *) e);
+				stat = history_new((struct gen_spec *)
+						   *rule_elem, newspec_set);
+				if (stat < 0) {
+					elem_free((struct dt_elem *)
+						  *rule_elem);
+					return stat;
+				}
+			}
+			return HE_OK;
+		}
+	}
+}
+
+hipac_error
+dimtree_delete(struct dimtree *dt, struct dt_rule *rule, int commit)
+{
+	struct gen_spec *top;
+	int stat;
+
+	if (unlikely(dt == NULL || rule == NULL || rule->deleted ||
+		     rule == list_entry(dt->chain->head.next,
+					struct dt_rule, head) ||
+		     rule == list_entry(dt->chain->head.prev,
+					struct dt_rule, head))) {
+		ARG_ERR;
+	}
+
+	assert(dt->top != NULL);
+	DPRINT(DEBUG_DIMTREE,
+	       "----------------------------------------------------------\n");
+	DPRINT(DEBUG_DIMTREE, "%s: commit: %d\n", __FUNCTION__, commit);
+	DPRINT(DEBUG_DIMTREE, "dt: origin: %X, need_commit: %u,"
+	       " chain: %s (len: %u)\n", dt->origin, dt->need_commit,
+	       dt->chain->name, dt->chain->len);
+#ifdef DEBUG
+	if (dt->top_new == NULL) {
+		if (dt->top != NULL) {
+			if (IS_RLP(dt->top)) {
+				print_rlp((struct rlp_spec *) dt->top);
+			} else if (IS_ELEM(dt->top)) {
+				print_elem((struct dt_elem *) dt->top);
+				DPRINT(DEBUG_DIMTREE, "\n");
+			} else {
+				DPRINT(DEBUG_DIMTREE, "top level rule: %p\n",
+				       dt->top);
+			}
+		}
+	} else {
+		if (IS_RLP(dt->top_new)) {
+			print_rlp((struct rlp_spec *) dt->top_new);
+		} else if (IS_ELEM(dt->top_new)) {
+				print_elem((struct dt_elem *) dt->top_new);
+				DPRINT(DEBUG_DIMTREE, "\n");
+		} else {
+			DPRINT(DEBUG_DIMTREE, "top level rule: %p\n",
+			       dt->top_new);
+		}
+	}
+	if (hipac_debug & DEBUG_DIMTREE) {
+		dt_rule_print(rule);
+	}
+#endif
+
+	if (!dt->need_commit) {
+		/* first operation in a series => clone top level structure
+		   if necessary */
+		if (IS_RLP(dt->top)) {
+			stat = rlp_clone((struct rlp_spec *) dt->top,
+					 (struct rlp_spec **) &top);
+			if (stat < 0) {
+				return stat;
+			}
+			stat = history_replace(dt->top, top, !commit);
+			if (stat < 0) {
+				rlp_free((struct rlp_spec *) top);
+				history_undo();
+				return stat;
+			}
+		} else if (IS_ELEM(dt->top)) {
+			stat = elem_clone((struct dt_elem *) dt->top,
+					  (struct dt_elem **) &top);
+			if (stat < 0) {
+				return stat;
+			}
+			stat = history_replace(dt->top, top, !commit);
+			if (stat < 0) {
+				elem_free((struct dt_elem *) top);
+				history_undo();
+				return stat;
+			}
+		} else {
+			assert(IS_RULE(dt->top));
+			top = dt->top;
+		}
+	} else {
+		top = dt->top_new;
+	}
+
+	/* delete rule from rlp / elementary interval */
+	if (IS_RLP(top)) {
+		stat = dimtree_delrec((struct rlp_spec **) &top, rule,
+				      0, NULL, !commit);
+	} else {
+		stat = dimtree_delete_rule_elem((struct dt_rule_elem_spec **)
+						&top, rule, dt, !commit);
+	}
+	if (stat < 0) {
+		history_undo();
+		return stat;
+	}
+	
+	if (commit) {
+#ifdef DEBUG
+		if (dt->top != NULL && IS_RLP(dt->top) &&
+		    !rule_occur(dt->top, rule, 0)) {
+			/* this check only works if the top level structure is
+			   a rlp */
+			DPRINT(DEBUG_DIMTREE, "rule %p not present in "
+			       "original rlp\n", rule);
+			return HE_IMPOSSIBLE_CONDITION;
+		}
+#endif
+		dt->top = top;
+		dt->top_new = NULL;
+		synchronize_rcu();
+		history_commit(0);
+		assert(history_is_empty());
+	} else {
+		assert((IS_RULE(top) && IS_RULE(dt->top)) ||
+		       !history_is_empty());
+		dt->need_commit = 1;
+		dt->top_new = top;
+		rule->deleted = 1;
+	}
+	return HE_OK;
+}
+
+void
+dimtree_commit(struct ptrblock *dt_block)
+{
+	struct dimtree *dt;
+	__u32 i;
+	
+	if (unlikely(dt_block == NULL)) {
+		ARG_MSG;
+		return;
+	}
+
+	for (i = 0; i < dt_block->len; i++) {
+		dt = (struct dimtree *) dt_block->p[i];
+		if (dt->need_commit) {
+			dt->top = dt->top_new;
+			dt->top_new = NULL;
+			dt->need_commit = 0;
+		}
+	}
+	synchronize_rcu();
+	history_commit(1);
+	assert(history_is_empty());
+}
+
+void
+dimtree_failed(struct ptrblock *dt_block)
+{
+	struct list_head *lh;
+	struct dimtree *dt;
+	__u32 i;
+	
+	if (unlikely(dt_block == NULL)) {
+		ARG_MSG;
+		return;
+	}
+
+	for (i = 0; i < dt_block->len; i++) {
+		dt = (struct dimtree *) dt_block->p[i];
+		if (dt->need_commit) {
+			dt->need_commit = 0;
+			dt->top_new = NULL;
+			list_for_each (lh, &dt->chain->head) {
+				list_entry(lh, struct dt_rule,
+					   head)->deleted = 0;
+			}
+		}
+		assert(dt->need_commit || dt->top_new == NULL);
+	}
+	history_undo();
+}
+
+void
+dimtree_chain_fix(struct ptrblock *dt_block)
+{
+	struct list_head *lh;
+	struct dt_rule *rule;
+	__u32 i, prevpos_new, prevpos_org;
+	struct dimtree *dt;
+	
+	if (unlikely(dt_block == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	
+	for (i = 0; i < dt_block->len; i++) {
+		dt = (struct dimtree *) dt_block->p[i];
+		assert(!list_empty(&dt->chain->head));
+		if (dt->chain->first == NULL) {
+			lh = dt->chain->head.next;
+			prevpos_org = list_entry(lh, struct dt_rule,
+						 head)->spec.pos;
+			prevpos_new = list_entry(lh, struct dt_rule,
+						 head)->spec.pos = 0;
+			lh = lh->next;
+		} else {
+			lh = dt->chain->first->head.next;
+			prevpos_org = prevpos_new = dt->chain->first->spec.pos;
+		}
+		dt->chain->first = list_entry(dt->chain->head.prev,
+					      struct dt_rule, head);
+		for (; lh != &dt->chain->head; lh = lh->next) {
+			rule = list_entry(lh, struct dt_rule, head);
+			if (unlikely(rule->spec.pos == prevpos_org)) {
+				rule->spec.pos = prevpos_new;
+			} else {
+				prevpos_org = rule->spec.pos;
+				rule->spec.pos = ++prevpos_new;
+			}
+		}
+	}
+}
+
+static hipac_error
+hipac_get_rlp_stat_rec(struct gen_spec *g, struct hipac_rlp_stat *stat,
+		       __u8 depth, __u8 parent_dimid)
+{
+	struct gen_spec **nextspec = NULL;
+	struct rlp_spec *rlp;
+	int ret;
+	__u16 n;
+
+	if (g == NULL) {
+		return HE_OK;
+	}
+	if (IS_RULE(g) || IS_ELEM(g)) {
+		if (depth < 1) {
+			return HE_OK;
+		}
+		stat->termptr_num++;
+		if (parent_dimid >= LEN(stat->termptr_dimid_num)) {
+			IMPOSSIBLE_CONDITION("termptr_dimid_num too small");
+		}
+		stat->termptr_dimid_num[parent_dimid]++;
+		if (depth - 1 >= LEN(stat->termptr_depth_num)) {
+			IMPOSSIBLE_CONDITION("termptr_depth_num too small");
+		}
+		stat->termptr_depth_num[depth - 1]++;
+		if (IS_ELEM(g)) {
+			struct dt_elem *e = (struct dt_elem *) g;
+			__u32 ptr_num;
+			stat->dt_elem_num++;
+			ptr_num = e->ntm_rules.len +
+				(e->term_rule == NULL ? 0 : 1);
+			stat->dt_elem_ptr_num += ptr_num;
+			stat_distribution_add(stat->dt_elem_stat,
+					      LEN(stat->dt_elem_stat),
+					      ptr_num);
+		}
+		return HE_OK;
+	}
+	
+	/* rlp statistics */
+	rlp = (struct rlp_spec *) g;
+	if (hp_size(rlp, &stat->rlp_mem_real, &stat->rlp_mem_tight) < 0) {
+		return HE_IMPOSSIBLE_CONDITION;
+	}
+	if (hp_size(*termrule(rlp), &stat->termrule_mem_real,
+		    &stat->termrule_mem_tight) < 0) {
+		return HE_IMPOSSIBLE_CONDITION;
+	}
+	stat->rlp_num++;
+	if (rlp->dimid >= LEN(stat->rlp_dimid_num)) {
+		IMPOSSIBLE_CONDITION("rlp_dimid_num too small");
+	}
+	stat->rlp_dimid_num[rlp->dimid]++;
+	if (depth >= LEN(stat->rlp_depth_num)) {
+		IMPOSSIBLE_CONDITION("rlp_depth_num too small");
+	}
+	stat->rlp_depth_num[depth]++;
+	if (*termrule(rlp) != NULL) {
+		stat->termrule_num++;
+		stat->termrule_ptr_num += (*termrule(rlp))->len;
+	}
+	stat->keys_num += rlp->num;
+       	if (rlp->dimid >= LEN(stat->rlp_dimid_keys_stat)) {
+		IMPOSSIBLE_CONDITION("rlp_dimid_keys_stat too small");
+	}
+	stat_distribution_add(stat->rlp_dimid_keys_stat[rlp->dimid],
+			      LEN(*stat->rlp_dimid_keys_stat), rlp->num);
+	if (depth > 0) {
+		stat->nontermptr_num++;
+		if (parent_dimid >= LEN(stat->nontermptr_dimid_num)) {
+			IMPOSSIBLE_CONDITION("nontermptr_dimid_num too small");
+		}
+		stat->nontermptr_dimid_num[parent_dimid]++;
+		if (depth - 1 >= LEN(stat->nontermptr_depth_num)) {
+			IMPOSSIBLE_CONDITION("nontermptr_depth_num too small");
+		}
+		stat->nontermptr_depth_num[depth - 1]++;
+	}
+
+	/* recursion */
+	nextspec = rlp_nextspec(rlp);
+	assert(nextspec != NULL);
+	
+	for (n = 0; n < rlp->num; n++) {
+		ret = hipac_get_rlp_stat_rec(*(nextspec + n), stat,
+					     depth + 1, rlp->dimid);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+	if (HAS_WILDCARD_SPEC(rlp)) {
+		ret = hipac_get_rlp_stat_rec(*WILDCARD(rlp), stat,
+					     depth + 1, rlp->dimid);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+	return HE_OK;
+}
+
+hipac_error
+hipac_get_rlp_stat(void *hipac, struct hipac_rlp_stat *stat)
+{
+	struct dimtree *dt = hipac;
+
+	if (dt == NULL || stat == NULL) {
+		ARG_ERR;
+	}
+
+	memset(stat, 0, sizeof(*stat));
+	stat->total_mem_tight = mem_current_tight;
+	stat->total_mem_real = mem_current_real;
+	if (dt->top == NULL) {
+		IMPOSSIBLE_CONDITION("top level rlp NULL");
+	}
+	return hipac_get_rlp_stat_rec(dt->top, stat, 0, 0);
+}
+
+hipac_error
+hipac_get_dimtree_stat(void *hipac, struct hipac_dimtree_stat *stat)
+{
+	struct dimtree *dt = hipac;
+	struct list_head *lh;
+	struct dt_rule *r;
+	__u32 pos, num;
+
+	if (dt == NULL || stat == NULL) {
+		ARG_ERR;
+	}
+
+	memset(stat, 0, sizeof(*stat));
+	if (hp_size(dt->chain, &stat->chain_mem_real,
+		    &stat->chain_mem_tight) < 0) {
+		return HE_IMPOSSIBLE_CONDITION;
+	}
+	stat->rule_num = dt->chain->len;
+	pos = num = 0;
+	list_for_each (lh, &dt->chain->head) {
+		r = list_entry(lh, struct dt_rule, head);
+		if (r->spec.pos == pos) {
+			num++;
+		} else {
+			if (num > 1) {
+				stat_distribution_add(
+				      stat->rules_same_pos_stat,
+				      LEN(stat->rules_same_pos_stat), num);
+			}
+			num = 1;
+			pos = r->spec.pos;
+		}
+		if (hp_size(r, &stat->chain_mem_real,
+			    &stat->chain_mem_tight) < 0) {
+			return HE_IMPOSSIBLE_CONDITION;
+		}
+		if (HAS_EXEC_MATCH(r)) {
+			stat->rules_with_exec_matches++;
+		}
+		if (IS_TARGET_EXEC(r)) {
+			stat->rules_with_exec_target++;
+		}
+		if (r->dt_match_len >= LEN(stat->dt_match_stat)) {
+			IMPOSSIBLE_CONDITION("dt_match_stat too small");
+		}
+		stat->dt_match_stat[r->dt_match_len]++;
+	}
+	if (num > 1) {
+		stat_distribution_add(stat->rules_same_pos_stat,
+				      LEN(stat->rules_same_pos_stat), num);
+	}
+	return HE_OK;
+}
+
+
+
+/*
+ * hipac matching algorithm
+ */
+
+
+#ifdef SINGLE_PATH
+
+/* match packet against the rlp in dt and return the terminal action
+   (TARGET_ACCEPT or TARGET_DROP) of the highest priority terminal rule or
+   the policy if there is no such rule */
+hipac_target_t
+hipac_match(void *hipac, const void *packet)
+{
+	struct dt_rule *rule;
+	struct gen_spec *t;
+	__u8 action, i, j;
+	int hotdrop = 0;
+
+	t = ((struct dimtree *) hipac)->top;
+	assert(t != NULL);
+	assert(packet != NULL);
+
+ 	while (!hotdrop && IS_RLP(t)) {
+		t = ((struct rlp_spec *) t)->locate((struct rlp_spec *) t,
+						    packet, &hotdrop);
+	}
+	if (hotdrop)
+		return TARGET_DROP;
+
+	if (likely(IS_RULE(t))) {
+		assert(IS_RULE_TERM((struct dt_rule *) t));
+		return ((struct dt_rule *) t)->spec.action;
+	}
+	
+	/* initialization required to prevent compiler warning */
+	action = 0;
+
+	assert(IS_ELEM(t));
+	assert(((struct dt_elem *) t)->term_rule != NULL);
+	assert(IS_RULE_TERM(((struct dt_elem *) t)->term_rule));
+	assert(((struct dt_elem *) t)->ntm_rules.p != NULL);
+	for (i = 0; i < ((struct dt_elem *) t)->ntm_rules.len; i++) {
+		rule = ((struct dt_elem *) t)->ntm_rules.p[i];
+		if (HAS_EXEC_MATCH(rule)) {
+			assert(!(rule->exec_match->len & 1));
+			assert(rule->exec_match->len >= 2);
+			for (j = 0; j < rule->exec_match->len; j += 2) {
+				action = match_fn(packet, 
+						  rule->exec_match->p[j],
+						  rule->exec_match->p[j + 1]);
+				if (action != MATCH_YES) {
+					break;
+				}
+			}
+			if (action == MATCH_NO) {
+				continue;
+			}
+			if (action == MATCH_HOTDROP) {
+				return TARGET_DROP;
+			}
+		}
+		action = IS_TARGET_EXEC(rule) ?
+			target_fn(packet, rule->exec_target) 
+			: rule->spec.action;
+		if (action != TARGET_NONE) {
+			assert(action == TARGET_ACCEPT ||
+			       action == TARGET_DROP);
+			return action;
+		}
+	}
+
+	/* terminal rule or policy matches */
+	return ((struct dt_elem *) t)->term_rule->spec.action;
+}
+
+#  ifdef DEBUG
+
+/*
+ * debugging version of hipac_match (single path)
+ */
+
+/* return the matched rules in order - for verification purposes only */
+struct ptrblock *
+hipac_match_debug(struct dimtree *hipac, const void *packet)
+{
+	struct ptrblock *b = NULL;
+	struct dt_rule *rule;
+	struct gen_spec *t;
+	__u8 action, i, j;
+	int hotdrop = 0;
+
+	t = ((struct dimtree *) hipac)->top;
+	assert(t != NULL);
+	assert(packet != NULL);
+
+	while (!hotdrop && IS_RLP(t)) {
+		t = ((struct rlp_spec *) t)->locate((struct rlp_spec *) t,
+						    packet, &hotdrop);
+	}
+	if (hotdrop)
+		return b;
+
+	if (likely(IS_RULE(t))) {
+		assert(IS_RULE_TERM((struct dt_rule *) t));
+		if (ptrblock_append(&b, t) < 0) {
+			ERR("ptrblock_append failed");
+		}
+		return b;
+	}
+	
+	/* initialization required to prevent compiler warning */
+	action = 0;
+
+	assert(IS_ELEM(t));
+	assert(((struct dt_elem *) t)->term_rule != NULL);
+	assert(IS_RULE_TERM(((struct dt_elem *) t)->term_rule));
+	assert(((struct dt_elem *) t)->ntm_rules.p != NULL);
+	for (i = 0; i < ((struct dt_elem *) t)->ntm_rules.len; i++) {
+		rule = ((struct dt_elem *) t)->ntm_rules.p[i];
+		if (HAS_EXEC_MATCH(rule)) {
+			assert(!(rule->exec_match->len & 1));
+			assert(rule->exec_match->len >= 2);
+			for (j = 0; j < rule->exec_match->len; j += 2) {
+				action = match_fn(packet, 
+						  rule->exec_match->p[j],
+						  rule->exec_match->p[j + 1]);
+				if (action != MATCH_YES) {
+					break;
+				}
+			}
+			if (action == MATCH_NO) {
+				continue;
+			}
+			if (action == MATCH_HOTDROP) {
+				return b;
+			}
+		}
+		if (ptrblock_append(&b, rule) < 0) {
+			ERR("ptrblock_append failed");
+			return b;
+		}
+		action = IS_TARGET_EXEC(rule) ?
+			target_fn(packet, rule->exec_target) 
+			: rule->spec.action;
+		if (action != TARGET_NONE){
+			assert(action == TARGET_ACCEPT ||
+			       action == TARGET_DROP);
+			return b;
+		}
+	}
+
+	/* terminal rule or policy matches */
+	if (ptrblock_append(&b, ((struct dt_elem *) t)->term_rule) < 0) {
+		ERR("ptrblock_append failed");
+	}
+	return b;
+}
+
+#  endif   // DEBUG
+
+#else      // SINGLE_PATH
+
+static inline hipac_target_t
+match_packet(const struct dimtree *dt, const void *packet,
+	     struct dt_rule *rule)
+{
+	__u32 i;
+
+	if (HAS_EXEC_MATCH(rule)) {
+		assert(!(rule->exec_match->len & 1));
+		assert(rule->exec_match->len >= 2);
+		for (i = 0; i < rule->exec_match->len; i += 2) {
+			switch (match_fn(packet, rule->exec_match->p[i],
+					 rule->exec_match->p[i + 1])) {
+			    case MATCH_YES:
+				    break;
+
+			    case MATCH_NO:
+				    return TARGET_NONE;
+
+			    case MATCH_HOTDROP: 
+				    return TARGET_DROP;
+			}
+		}
+	}
+	return IS_TARGET_EXEC(rule) ?
+		target_fn(packet, rule->exec_target) : rule->spec.action;
+}
+
+
+/* match packet against the rlp in dt and return the terminal action
+   (TARGET_ACCEPT or TARGET_DROP) of the highest priority terminal rule or
+   the policy if there is no such rule */
+hipac_target_t
+hipac_match(void *hipac, const void *packet)
+{
+#       define NUM_LEAVES 4
+	/* UINT_MAX - 1 is required because of
+	   if (likely(term_pos < nonterm_pos)) {...} optimization */
+	__u32 term_pos = UINT_MAX - 1;
+	__u32 nonterm_pos = UINT_MAX;
+	struct dt_rule *term_rule = NULL;
+	struct dt_rule_elem_spec *rule_elem[NUM_LEAVES];
+	struct dt_rule **ntm_rule[NUM_LEAVES];
+	struct dt_rule **ntm_end[NUM_LEAVES];
+	struct gen_spec *t;
+	__u32 ntm_next_pos, new_next;
+	__u8 ntm_rule_sz, ntm_cur_ind;
+	__u8 action, i, len, max;
+	int hotdrop = 0;
+	
+	max = 1;
+	i = len = 0;
+	rule_elem[0] = (struct dt_rule_elem_spec *) 
+		((struct dimtree *) hipac)->top;
+	assert(packet != NULL);
+	assert(rule_elem[0] != NULL);
+	assert(!IS_RULE(rule_elem[0]) ||
+	       IS_RULE_TERM(((struct dt_rule *) rule_elem[0])));
+	assert(!IS_ELEM(rule_elem[0]) ||
+	       (IS_RULE_TERM(((struct dt_elem *) rule_elem[0])->term_rule) &&
+		((struct dt_elem *) rule_elem[0])->ntm_rules.len > 0));
+	
+	do {
+		t = (struct gen_spec *) rule_elem[i++];
+		while (!hotdrop && t && IS_RLP(t)) {
+			t = ((struct rlp_spec *) t)->locate(
+				(struct rlp_spec *) t, packet, &hotdrop,
+				(struct gen_spec **) rule_elem, &max);
+		};
+		if (hotdrop)
+			return TARGET_DROP;
+		assert(max <= NUM_LEAVES);
+		if (unlikely(t == NULL)) {
+			continue;
+		}
+		rule_elem[len++] = (struct dt_rule_elem_spec *) t;
+		if (likely(IS_RULE(t))) {
+			if (likely(IS_RULE_TERM((struct dt_rule *) t))) {
+				if (((struct dt_rule *) t)->spec.pos <
+				    term_pos) {
+					term_rule = (struct dt_rule *) t;
+					term_pos = term_rule->spec.pos;
+				}
+			} else if (((struct dt_rule *) t)->spec.pos <
+				   nonterm_pos) {
+				nonterm_pos = ((struct dt_rule *)
+					       t)->spec.pos;
+			}
+		} else {
+			if (((struct dt_elem *) t)->term_rule != NULL &&
+			    ((struct dt_elem *) t)->term_rule->spec.pos <
+			    term_pos) {
+				term_rule = ((struct dt_elem *)
+					     t)->term_rule;
+				term_pos = term_rule->spec.pos;
+				assert(IS_RULE_TERM(term_rule));
+			}
+			assert(((struct dt_elem *) t)->ntm_rules.len > 0);
+			if (((struct dt_rule *)
+			     ((struct dt_elem *) t)->ntm_rules.p[0])->spec.pos
+			    < nonterm_pos) {
+				nonterm_pos = ((struct dt_rule *)
+					       ((struct dt_elem *)
+						t)->ntm_rules.p[0])->spec.pos;
+			}
+		}
+	} while (i < max);
+		
+	/* optimization for the ideal case that no non-terminal rules
+	   (function based matches or no terminal target) exist */
+	if (likely(term_pos < nonterm_pos)) {
+		assert(term_rule != NULL);
+		action = term_rule->spec.action;
+		return action;
+	}
+
+	/* initialize ntm_rule, ntm_end, ntm_rule_sz, ntm_cur_ind and
+	   ntm_next_pos now that term_pos is given */
+	ntm_rule_sz = ntm_cur_ind = 0;
+	ntm_next_pos = UINT_MAX;
+	for (i = 0; i < len; i++) {
+		assert(rule_elem[i] != NULL);
+		if (likely(IS_RULE(rule_elem[i]))) {
+			struct dt_rule **r = (struct dt_rule **) &rule_elem[i];
+			__u32 pos = (*r)->spec.pos;
+			if (!IS_RULE_TERM(*r) && pos < term_pos) {
+				if (pos == nonterm_pos) {
+					ntm_cur_ind = ntm_rule_sz;
+				} else if (pos < ntm_next_pos) {
+					ntm_next_pos = pos;
+				}
+				ntm_rule[ntm_rule_sz] = r;
+				ntm_end[ntm_rule_sz++] = r;
+			}
+		} else {
+			struct dt_elem *e = (struct dt_elem *) rule_elem[i];
+			__u32 pos = ((struct dt_rule *)
+				     *e->ntm_rules.p)->spec.pos;
+			if (pos < term_pos) {
+				if (pos == nonterm_pos) {
+					ntm_cur_ind = ntm_rule_sz;
+				} else if (pos < ntm_next_pos) {
+					ntm_next_pos = pos;
+				}
+				ntm_rule[ntm_rule_sz] =
+					(struct dt_rule **) e->ntm_rules.p;
+				ntm_end[ntm_rule_sz++] = (struct dt_rule **)
+					&e->ntm_rules.p[e->ntm_rules.len - 1];
+			}
+		}
+	}
+	assert(ntm_rule_sz > 0);
+	
+	/* process non-terminal rules in order up to term_pos */
+	ntm_next_pos = ntm_next_pos < term_pos ? ntm_next_pos : term_pos;
+	while (ntm_rule_sz > 0 &&
+	       (*ntm_rule[ntm_cur_ind])->spec.pos < ntm_next_pos) {
+		
+		/* match packet against current block of rules */
+		for (; (ntm_rule[ntm_cur_ind] <= ntm_end[ntm_cur_ind] &&
+			(*ntm_rule[ntm_cur_ind])->spec.pos < ntm_next_pos);
+		     ntm_rule[ntm_cur_ind]++) {
+
+			switch (action =
+				match_packet((struct dimtree *) hipac, packet,
+					     *ntm_rule[ntm_cur_ind])) {
+
+			    case TARGET_NONE:
+				    break;
+			    default:
+				    assert(action == TARGET_ACCEPT ||
+					   action == TARGET_DROP);
+				    return action;
+			}
+		}
+
+		/* remove current block of rules if no rule is left that may
+		   be matched */
+		if (ntm_rule[ntm_cur_ind] > ntm_end[ntm_cur_ind] ||
+		    (*ntm_rule[ntm_cur_ind])->spec.pos >= term_pos) {
+			ntm_rule_sz--;
+			assert(ntm_cur_ind <= ntm_rule_sz);
+			ntm_rule[ntm_cur_ind] = ntm_rule[ntm_rule_sz];
+			ntm_end[ntm_cur_ind] = ntm_end[ntm_rule_sz];
+		}
+
+		/* set ntm_cur_ind and ntm_next_pos for next run */
+		new_next = term_pos;
+		for (i = 0; i < ntm_rule_sz; i++) {
+			if ((*ntm_rule[i])->spec.pos == ntm_next_pos) {
+				ntm_cur_ind = i;
+			} else if ((*ntm_rule[i])->spec.pos < new_next) {
+				new_next = (*ntm_rule[i])->spec.pos;
+			}
+		}
+		ntm_next_pos = new_next;
+	}
+	
+	/* terminal rule or policy matches */
+	assert(term_rule != NULL);
+	action = term_rule->spec.action;
+	return action;
+}
+
+#  ifdef DEBUG
+
+/*
+ * debugging version of hipac_match (multi path)
+ */
+
+/* for verification purposes only */
+static inline hipac_target_t
+match_packet_debug(struct ptrblock **b, const struct dimtree *dt,
+		   const void *packet, struct dt_rule *rule)
+{
+	__u32 i;
+
+	if (HAS_EXEC_MATCH(rule)) {
+		assert(!(rule->exec_match->len & 1));
+		assert(rule->exec_match->len >= 2);
+		for (i = 0; i < rule->exec_match->len; i += 2) {
+			switch (match_fn(packet, rule->exec_match->p[i],
+					 rule->exec_match->p[i + 1])) {
+			    case MATCH_YES:
+				    break;
+
+			    case MATCH_NO:
+				    return TARGET_NONE;
+
+			    case MATCH_HOTDROP: 
+				    return TARGET_DROP;
+			}
+		}
+	}
+	if (ptrblock_append(b, rule) < 0) {
+		ERR("ptrblock_append failed");
+	}
+	return IS_TARGET_EXEC(rule) ?
+		target_fn(packet, rule->exec_target) : rule->spec.action;
+}
+
+/* return the matched rules in order - for verification purposes only */
+struct ptrblock *
+hipac_match_debug(struct dimtree *hipac, const void *packet)
+{
+#       define NUM_LEAVES 4
+	struct ptrblock *b = NULL;
+	/* UINT_MAX - 1 is required because of
+	   if (likely(term_pos < nonterm_pos)) {...} optimization */
+	__u32 term_pos = UINT_MAX - 1;
+	__u32 nonterm_pos = UINT_MAX;
+	struct dt_rule *term_rule = NULL;
+	struct dt_rule_elem_spec *rule_elem[NUM_LEAVES];
+	struct dt_rule **ntm_rule[NUM_LEAVES];
+	struct dt_rule **ntm_end[NUM_LEAVES];
+	struct gen_spec *t;
+	__u32 ntm_next_pos, new_next;
+	__u8 ntm_rule_sz, ntm_cur_ind;
+	__u8 action, i, len, max;
+	int hotdrop = 0;
+
+	max = 1;
+	i = len = 0;
+	rule_elem[0] = (struct dt_rule_elem_spec *) 
+		((struct dimtree *) hipac)->top;
+	assert(packet != NULL);
+	assert(rule_elem[0] != NULL);
+	assert(!IS_RULE(rule_elem[0]) ||
+	       IS_RULE_TERM(((struct dt_rule *) rule_elem[0])));
+	assert(!IS_ELEM(rule_elem[0]) ||
+	       (IS_RULE_TERM(((struct dt_elem *) rule_elem[0])->term_rule) &&
+		((struct dt_elem *) rule_elem[0])->ntm_rules.len > 0));
+ 
+       	do {
+		t = (struct gen_spec *) rule_elem[i++];
+		while (!hotdrop && t && IS_RLP(t)) {
+			t = ((struct rlp_spec *) t)->locate(
+				(struct rlp_spec *) t, packet, &hotdrop,
+				(struct gen_spec **) rule_elem, &max);
+		};
+		if (hotdrop)
+			return b;
+		assert(max <= NUM_LEAVES);
+		if (unlikely(t == NULL)) {
+			continue;
+		}
+		rule_elem[len++] = (struct dt_rule_elem_spec *) t;
+		if (likely(IS_RULE(t))) {
+			if (likely(IS_RULE_TERM((struct dt_rule *) t))) {
+				if (((struct dt_rule *) t)->spec.pos <
+				    term_pos) {
+					term_rule = (struct dt_rule *) t;
+					term_pos = term_rule->spec.pos;
+				}
+			} else if (((struct dt_rule *) t)->spec.pos <
+				   nonterm_pos) {
+				nonterm_pos = ((struct dt_rule *)
+					       t)->spec.pos;
+			}
+		} else {
+			if (((struct dt_elem *) t)->term_rule != NULL &&
+			    ((struct dt_elem *) t)->term_rule->spec.pos <
+			    term_pos) {
+				term_rule = ((struct dt_elem *)
+					     t)->term_rule;
+				term_pos = term_rule->spec.pos;
+				assert(IS_RULE_TERM(term_rule));
+			}
+			assert(((struct dt_elem *) t)->ntm_rules.len > 0);
+			if (((struct dt_rule *)
+			     ((struct dt_elem *) t)->ntm_rules.p[0])->spec.pos
+			    < nonterm_pos) {
+				nonterm_pos = ((struct dt_rule *)
+					       ((struct dt_elem *)
+						t)->ntm_rules.p[0])->spec.pos;
+			}
+		}
+	} while (i < max);
+		
+	/* optimization for the ideal case that no non-terminal rules
+	   (function based matches or no terminal target) exist */
+	if (likely(term_pos < nonterm_pos)) {
+		assert(term_rule != NULL);
+		if (ptrblock_append(&b, term_rule) < 0) {
+			ERR("ptrblock_append failed");
+		}
+		return b;
+	}
+
+	/* initialize ntm_rule, ntm_end, ntm_rule_sz, ntm_cur_ind and
+	   ntm_next_pos now that term_pos is given */
+	ntm_rule_sz = ntm_cur_ind = 0;
+	ntm_next_pos = UINT_MAX;
+	for (i = 0; i < len; i++) {
+		assert(rule_elem[i] != NULL);
+		if (likely(IS_RULE(rule_elem[i]))) {
+			struct dt_rule **r = (struct dt_rule **) &rule_elem[i];
+			__u32 pos = (*r)->spec.pos;
+			if (!IS_RULE_TERM(*r) && pos < term_pos) {
+				if (pos == nonterm_pos) {
+					ntm_cur_ind = ntm_rule_sz;
+				} else if (pos < ntm_next_pos) {
+					ntm_next_pos = pos;
+				}
+				ntm_rule[ntm_rule_sz] = r;
+				ntm_end[ntm_rule_sz++] = r;
+			}
+		} else {
+			struct dt_elem *e = (struct dt_elem *) rule_elem[i];
+			__u32 pos = ((struct dt_rule *)
+				     *e->ntm_rules.p)->spec.pos;
+			if (pos < term_pos) {
+				if (pos == nonterm_pos) {
+					ntm_cur_ind = ntm_rule_sz;
+				} else if (pos < ntm_next_pos) {
+					ntm_next_pos = pos;
+				}
+				ntm_rule[ntm_rule_sz] =
+					(struct dt_rule **) e->ntm_rules.p;
+				ntm_end[ntm_rule_sz++] = (struct dt_rule **)
+					&e->ntm_rules.p[e->ntm_rules.len - 1];
+			}
+		}
+	}
+	assert(ntm_rule_sz > 0);
+	
+	/* process non-terminal rules in order up to term_pos */
+	ntm_next_pos = ntm_next_pos < term_pos ? ntm_next_pos : term_pos;
+	while (ntm_rule_sz > 0 &&
+	       (*ntm_rule[ntm_cur_ind])->spec.pos < ntm_next_pos) {
+		
+		/* match packet against current block of rules */
+		for (; (ntm_rule[ntm_cur_ind] <= ntm_end[ntm_cur_ind] &&
+			(*ntm_rule[ntm_cur_ind])->spec.pos < ntm_next_pos);
+		     ntm_rule[ntm_cur_ind]++) {
+
+			switch (action =
+				match_packet_debug(&b,
+						   (struct dimtree *) hipac,
+						   packet, 
+						   *ntm_rule[ntm_cur_ind])) {
+
+			    case TARGET_NONE:
+				    break;
+			    default:
+				    assert(action == TARGET_ACCEPT ||
+					   action == TARGET_DROP);
+				    return b;
+			}
+		}
+
+		/* remove current block of rules if no rule is left that may
+		   be matched */
+		if (ntm_rule[ntm_cur_ind] > ntm_end[ntm_cur_ind] ||
+		    (*ntm_rule[ntm_cur_ind])->spec.pos >= term_pos) {
+			ntm_rule_sz--;
+			assert(ntm_cur_ind <= ntm_rule_sz);
+			ntm_rule[ntm_cur_ind] = ntm_rule[ntm_rule_sz];
+			ntm_end[ntm_cur_ind] = ntm_end[ntm_rule_sz];
+		}
+
+		/* set ntm_cur_ind and ntm_next_pos for next run */
+		new_next = term_pos;
+		for (i = 0; i < ntm_rule_sz; i++) {
+			if ((*ntm_rule[i])->spec.pos == ntm_next_pos) {
+				ntm_cur_ind = i;
+			} else if ((*ntm_rule[i])->spec.pos < new_next) {
+				new_next = (*ntm_rule[i])->spec.pos;
+			}
+		}
+		ntm_next_pos = new_next;
+	}
+
+	/* terminal rule or policy matches */
+	assert(term_rule != NULL);
+	if (ptrblock_append(&b, term_rule) < 0) {
+		ERR("ptrblock_append failed");
+	}
+	return b;
+}
+
+#  endif  // DEBUG
+
+#endif    // SINGLE_PATH
diff -uNr nf-hipac/kernel/dimtree.h nfhipac/kernel/dimtree.h
--- nf-hipac/kernel/dimtree.h	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/dimtree.h	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,280 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#ifndef _DIMTREE_H
+#define _DIMTREE_H
+
+#include "global.h"
+#include "rlp.h"
+
+/* upper bound for matches of the given bit type */
+#define MAXKEY(bittype) +((bittype) == BIT_U16 ? 0xffff : 0xffffffff)
+
+/* used to distinguish a rule from an elementary interval */
+#define RT_RULE 0
+#define RT_ELEM 1
+
+
+/* header for dimtree rules and elementary intervals */
+struct dt_rule_elem_spec
+{
+	unsigned rlp    : 1; // must be 0	
+	unsigned rtype  : 1; // {RT_RULE, RT_ELEM}
+};
+
+/* header for dimtree rules */
+struct dt_rule_spec
+{
+	unsigned rlp    :  1; // must be 0	
+	unsigned rtype  :  1; // must be RT_RULE
+	unsigned action :  4; // packet action
+	unsigned pos    : 26; // position of the rule in the chain
+};
+
+/* dt_match represents the native interval match [left, right] associated
+   with dimension dimid whereby [left, right] may not be a wildcard match */
+struct dt_match
+{
+        __u8 dimid;
+        __u32 left, right;
+	char next_match[0];
+};
+
+/* dt_rule is an entry in the dt_chain; at the end of the struct we have
+   dt_match_len >= 0 dt_matches
+   if the rule has a function based target then exec_target points to the
+   target‘s data which is handled by target_fn;
+   the rule‘s exec_match pointer block references >= 0 blocks each of >= 1
+   function based matches, called fblocks;
+   the (2 * i)-th pointer of exec_match points to the beginning of the i-th
+   fblock;
+   the (2 * i + 1)-th pointer of exec_match points to the end of the i-th
+   fblock;
+   the start and end pointers are handed to match_fn */
+struct dt_rule
+{
+        struct dt_rule_spec spec;
+	struct list_head head;
+	struct ptrblock *exec_match;
+	void *exec_target;
+	__u32 exec_target_size;
+	__u8 deleted;
+	__u8 dt_match_len;
+	struct dt_match first_dt_match[0];
+};
+
+#define IS_RULE(r) (!IS_RLP(r) &&                                         +		    ((struct dt_rule_elem_spec *) (r))->rtype == RT_RULE)
+#define HAS_EXEC_MATCH(r)  ((r)->exec_match != NULL)
+#define IS_TARGET_DUMMY(r) ((r)->spec.action == TARGET_DUMMY)
+#define IS_TARGET_NONE(r)  ((r)->spec.action == TARGET_NONE)
+#define IS_TARGET_EXEC(r)  ((r)->spec.action == TARGET_EXEC)
+#define IS_TARGET_TERM(r)  ((r)->spec.action == TARGET_ACCEPT || +			    (r)->spec.action == TARGET_DROP)
+#define IS_RULE_TERM(r)    (IS_TARGET_TERM(r) && !HAS_EXEC_MATCH(r))
+
+/* return the size of a dt_rule with dt_match_len dt_matches */
+static inline __u32
+dt_rule_size(__u8 dt_match_len)
+{
+	return (sizeof(struct dt_rule) + 
+		dt_match_len * sizeof(struct dt_match));
+}
+
+/* head of the list of rules */
+struct dt_chain
+{
+	struct list_head head;
+	char name[HIPAC_CHAIN_NAME_MAX_LEN];
+	struct dt_rule *first; // optimization of dimtree_chain_fix
+	__u32 len;
+};
+
+
+
+/* header for elementary intervals */
+struct dt_elem_spec
+{
+	unsigned rlp     : 1; // must be 0
+	unsigned rtype   : 1; // must be RT_ELEM
+	unsigned newspec : 1; // indicates whether the elementary interval is
+	                      // contained in newspec
+};
+
+/* elementary interval */
+struct dt_elem
+{
+	struct dt_elem_spec spec;
+	/* terminating target (TARGET_ACCEPT, TARGET_DROP) without function
+	   based matches */
+	struct dt_rule *term_rule;
+	/* block of non-terminating rules (function based matches or no
+	   terminal target) whose position is < term_rule->spec.pos */
+	struct ptrblock ntm_rules;
+};
+
+#define IS_ELEM(e) (!IS_RLP(e) &&                                         +		    ((struct dt_rule_elem_spec *) (e))->rtype == RT_ELEM)
+
+
+
+struct dimtree
+{
+	__u32 origin;
+        struct gen_spec *top;
+	struct gen_spec *top_new;    // new not yet active top level structure
+	int need_commit;             // 1 if top_new is valid
+        struct dt_chain *chain;
+};
+
+
+
+/* create new dimtree and store it in *newdt; chain_name is copied to
+   dt->chain->name; memory for newdt is allocated within dimtree_new;
+   origin is a bit vector where exactly one bit is set; it is used to
+   uniquely define the "origin property" of newdt; dummy and policy
+   define the base ruleset; dummy must have TARGET_DUMMY as target,
+   policy must be a terminal rule without any dt_matches;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+dimtree_new(struct dimtree **newdt, __u32 origin, const char *chain_name,
+	    struct dt_rule *dummy, struct dt_rule *policy);
+
+/* free memory for dt and all embedded structures; make sure that no packet
+   matching occurs on dt any more */
+void
+dimtree_free(struct dimtree *dt);
+
+/* remove all rules except the first and the last one from dt->chain and
+   free them; set dt->top to the last rule in the chain */
+void
+dimtree_flush(struct dimtree *dt);
+
+const char *
+dimtree_get_chain_name(const struct dimtree *dt);
+
+/* insert rule into the dt_chain and the rlps; inc indicates whether all
+   rule positions >= rule->spec.pos should be incremented by 1;
+   if commit is not 0 then the top level structure in dt is replaced by the
+   new one and the old rlps and elementary intervals are freed;
+   in case of a fault all newly created rlps and elementary intervals
+   are freed; origin is a bit vector describing the allowed dimtrees
+   into which rule may be inserted; if rule must not be inserted into dt
+   it is anyway inserted into dt->chain (so take care to remove it from
+   there);
+   NOTICE: if commit is not 0 it is assumed that this operation is the
+           first one (at all or directly after a previously committed
+           operation or series of operations (-> dimtree_commit))
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION,
+                    HE_RULE_ORIGIN_MISMATCH */
+hipac_error
+dimtree_insert(struct dimtree *dt, struct dt_rule *rule, __u32 origin,
+	       int inc, int commit);
+
+/* delete rule from rlp, _NOT_ from the dt_chain; ‘rule‘ must point to a
+   rule in dt->chain; if commit is not 0 then the top level structure in dt
+   is replaced by the new one and the old rlps and elementary intervals
+   are freed; in case of a fault all newly created rlps and elementary
+   intervals are freed;
+   NOTICE: if commit is not 0 it is assumed that this operation is the
+           first one (at all or directly after a previously committed
+           operation or series of operations (-> dimtree_commit))
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+dimtree_delete(struct dimtree *dt, struct dt_rule *rule, int commit);
+
+/* called at the end of a successful series of dimtree_insert and/or
+   dimtree_delete operation(s) to make the result visible, i.e. set dt->top
+   to dt->top_new for each dimtree dt in dt_block and free the old rlps
+   and elementary intervals */
+void
+dimtree_commit(struct ptrblock *dt_block);
+
+/* called at the end of an unsuccessful series of dimtree_insert and/or
+   dimtree_delete operation(s) to undo the changes, i.e. set dt->top_new
+   to NULL and need_commit to 0 for each dimtree dt in dt_block and free the
+   new rlps and elementary intervals */
+void
+dimtree_failed(struct ptrblock *dt_block);
+
+#ifdef DEBUG
+int
+rule_occur(struct gen_spec *g, struct dt_rule *rule, int print);
+#endif
+
+/* remove all rules between start and the rule(s) r with position end_pos inc.
+   start and r themselves; the positions of the rules behind r are not
+   changed */
+static inline void
+dimtree_chain_delete(struct dimtree *dt, struct dt_rule *start, __u32 end_pos)
+{
+	struct dt_rule *rule;
+       	struct list_head *lh;
+
+	if (unlikely(dt == NULL || start == NULL ||
+		     start->spec.pos > end_pos)) {
+		ARG_MSG;
+		return;
+	}
+
+	assert(dt->need_commit == 0);
+	if (start->head.prev == &dt->chain->head) {
+		/* start is the first element => dt->chain->first stays
+		   NULL until dimtree_chain_fix has been called */
+		dt->chain->first = NULL;
+	} else if (dt->chain->first != NULL &&
+		   dt->chain->first->spec.pos >= start->spec.pos) {
+		dt->chain->first = list_entry(start->head.prev,
+					      struct dt_rule, head);
+	}
+	for (lh = &start->head, rule = start; lh != &dt->chain->head &&
+		     rule->spec.pos <= end_pos;) {
+		lh = lh->next;
+		list_del(lh->prev);
+#ifdef DEBUG
+		if (rule_occur(dt->top, rule, 1)) {
+			ERR("rule present in original structure");
+			return;
+		}
+#endif
+		if (rule->exec_match != NULL) {
+			ptrblock_free(rule->exec_match);
+		}
+		hp_free(rule);
+		dt->chain->len--;
+		rule = list_entry(lh, struct dt_rule, head);
+	}
+}
+
+/* iterate over the dt_chain in dt and tighten the position numbers */
+void
+dimtree_chain_fix(struct ptrblock *dt_block);
+
+#ifdef DEBUG
+/* matching algorithm used for correctness checks; the returned ptrblock
+   contains the rules matching the packet ordered after their positions;
+   the last rule should always have TARGET_ACCEPT or TARGET_DROP as action
+   and may not contain exec_matches */
+struct ptrblock *
+hipac_match_debug(struct dimtree *dt, const void *packet);
+#endif
+
+#endif
Binary files nf-hipac/kernel/dimtree.o and nfhipac/kernel/dimtree.o differ
diff -uNr nf-hipac/kernel/.dimtree.o.cmd nfhipac/kernel/.dimtree.o.cmd
--- nf-hipac/kernel/.dimtree.o.cmd	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/.dimtree.o.cmd	2014-11-21 12:54:42.000000000 +0800
@@ -0,0 +1,589 @@
+cmd_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.o := gcc -Wp,-MD,/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.dimtree.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include -Iinclude  -I/usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include -include include/linux/autoconf.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -Wframe-larger-than=2048 -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-dwarf2-cfi-asm -fconserve-stack -D SINGLE_PATH  -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(dimtree)"  -D"KBUILD_MODNAME=KBUILD_STR(nf_hipac)"  -c -o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.tmp_dimtree.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.c
+
+deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.o := +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.c +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/mode.h +    $(wildcard include/config/uml/net.h) +    $(wildcard include/config/host/2g/2g.h) +    $(wildcard include/config/nest/level.h) +    $(wildcard include/config/kernel/half/gigs.h) +  include/linux/stddef.h +  include/linux/compiler.h +    $(wildcard include/config/trace/branch/profiling.h) +    $(wildcard include/config/profile/all/branches.h) +    $(wildcard include/config/enable/must/check.h) +    $(wildcard include/config/enable/warn/deprecated.h) +  include/linux/compiler-gcc.h +    $(wildcard include/config/arch/supports/optimized/inlining.h) +    $(wildcard include/config/optimize/inlining.h) +  include/linux/compiler-gcc4.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page.h +    $(wildcard include/config/x86/64.h) +  include/linux/types.h +    $(wildcard include/config/uid16.h) +    $(wildcard include/config/lbdaf.h) +    $(wildcard include/config/phys/addr/t/64bit.h) +    $(wildcard include/config/64bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/types.h +    $(wildcard include/config/highmem64g.h) +  include/asm-generic/types.h +  include/asm-generic/int-ll64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitsperlong.h +  include/asm-generic/bitsperlong.h +  include/linux/posix_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types.h +    $(wildcard include/config/x86/32.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_types.h +  include/linux/const.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64_types.h +    $(wildcard include/config/physical/start.h) +    $(wildcard include/config/physical/align.h) +    $(wildcard include/config/flatmem.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64.h +  include/asm-generic/memory_model.h +    $(wildcard include/config/discontigmem.h) +    $(wildcard include/config/sparsemem/vmemmap.h) +    $(wildcard include/config/sparsemem.h) +  include/asm-generic/getorder.h +  include/linux/slab.h +    $(wildcard include/config/slab/debug.h) +    $(wildcard include/config/debug/objects.h) +    $(wildcard include/config/kmemcheck.h) +    $(wildcard include/config/slub.h) +    $(wildcard include/config/slob.h) +    $(wildcard include/config/numa.h) +    $(wildcard include/config/debug/slab.h) +  include/linux/gfp.h +    $(wildcard include/config/highmem.h) +    $(wildcard include/config/zone/dma.h) +    $(wildcard include/config/zone/dma32.h) +    $(wildcard include/config/debug/vm.h) +  include/linux/mmzone.h +    $(wildcard include/config/force/max/zoneorder.h) +    $(wildcard include/config/smp.h) +    $(wildcard include/config/memory/hotplug.h) +    $(wildcard include/config/arch/populates/node/map.h) +    $(wildcard include/config/flat/node/mem/map.h) +    $(wildcard include/config/cgroup/mem/res/ctlr.h) +    $(wildcard include/config/have/memory/present.h) +    $(wildcard include/config/need/node/memmap/size.h) +    $(wildcard include/config/need/multiple/nodes.h) +    $(wildcard include/config/have/arch/early/pfn/to/nid.h) +    $(wildcard include/config/sparsemem/extreme.h) +    $(wildcard include/config/nodes/span/other/nodes.h) +    $(wildcard include/config/holes/in/zone.h) +    $(wildcard include/config/arch/has/holes/memorymodel.h) +  include/linux/spinlock.h +    $(wildcard include/config/debug/spinlock.h) +    $(wildcard include/config/generic/lockbreak.h) +    $(wildcard include/config/preempt.h) +    $(wildcard include/config/debug/lock/alloc.h) +  include/linux/typecheck.h +  include/linux/preempt.h +    $(wildcard include/config/debug/preempt.h) +    $(wildcard include/config/preempt/tracer.h) +    $(wildcard include/config/preempt/notifiers.h) +  include/linux/thread_info.h +    $(wildcard include/config/compat.h) +  include/linux/bitops.h +    $(wildcard include/config/generic/find/first/bit.h) +    $(wildcard include/config/generic/find/last/bit.h) +    $(wildcard include/config/generic/find/next/bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitops.h +    $(wildcard include/config/x86/cmov.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/alternative.h +    $(wildcard include/config/paravirt.h) +  include/linux/stringify.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/asm.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpufeature.h +    $(wildcard include/config/x86/invlpg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/required-features.h +    $(wildcard include/config/x86/minimum/cpu/family.h) +    $(wildcard include/config/math/emulation.h) +    $(wildcard include/config/x86/pae.h) +    $(wildcard include/config/x86/cmpxchg64.h) +    $(wildcard include/config/x86/use/3dnow.h) +    $(wildcard include/config/x86/p6/nop.h) +  include/asm-generic/bitops/sched.h +  include/asm-generic/bitops/hweight.h +  include/asm-generic/bitops/fls64.h +  include/asm-generic/bitops/ext2-non-atomic.h +  include/asm-generic/bitops/le.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/byteorder.h +  include/linux/byteorder/little_endian.h +  include/linux/swab.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swab.h +    $(wildcard include/config/x86/bswap.h) +  include/linux/byteorder/generic.h +  include/asm-generic/bitops/minix.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/thread_info.h +    $(wildcard include/config/debug/stack/usage.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor.h +    $(wildcard include/config/x86/vsmp.h) +    $(wildcard include/config/cc/stackprotector.h) +    $(wildcard include/config/m386.h) +    $(wildcard include/config/m486.h) +    $(wildcard include/config/x86/debugctlmsr.h) +    $(wildcard include/config/cpu/sup/amd.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor-flags.h +    $(wildcard include/config/vm86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vm86.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace.h +    $(wildcard include/config/x86/ptrace/bts.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace-abi.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/segment.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cache.h +    $(wildcard include/config/x86/l1/cache/shift.h) +  include/linux/linkage.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/linkage.h +    $(wildcard include/config/x86/alignment/16.h) +  include/linux/init.h +    $(wildcard include/config/modules.h) +    $(wildcard include/config/hotplug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/math_emu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sigcontext.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/current.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/percpu.h +    $(wildcard include/config/x86/64/smp.h) +  include/linux/kernel.h +    $(wildcard include/config/preempt/voluntary.h) +    $(wildcard include/config/debug/spinlock/sleep.h) +    $(wildcard include/config/prove/locking.h) +    $(wildcard include/config/printk.h) +    $(wildcard include/config/dynamic/debug.h) +    $(wildcard include/config/ring/buffer.h) +    $(wildcard include/config/tracing.h) +    $(wildcard include/config/ftrace/mcount/record.h) +  /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h +  include/linux/log2.h +    $(wildcard include/config/arch/has/ilog2/u32.h) +    $(wildcard include/config/arch/has/ilog2/u64.h) +  include/linux/ratelimit.h +  include/linux/param.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/param.h +  include/asm-generic/param.h +    $(wildcard include/config/hz.h) +  include/linux/dynamic_debug.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bug.h +    $(wildcard include/config/bug.h) +    $(wildcard include/config/debug/bugverbose.h) +  include/asm-generic/bug.h +    $(wildcard include/config/generic/bug.h) +    $(wildcard include/config/generic/bug/relative/pointers.h) +  include/asm-generic/percpu.h +    $(wildcard include/config/have/setup/per/cpu/area.h) +  include/linux/threads.h +    $(wildcard include/config/nr/cpus.h) +    $(wildcard include/config/base/small.h) +  include/linux/percpu-defs.h +    $(wildcard include/config/debug/force/weak/per/cpu.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/system.h +    $(wildcard include/config/ia32/emulation.h) +    $(wildcard include/config/x86/32/lazy/gs.h) +    $(wildcard include/config/x86/ppro/fence.h) +    $(wildcard include/config/x86/oostore.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/nops.h +    $(wildcard include/config/mk7.h) +  include/linux/irqflags.h +    $(wildcard include/config/trace/irqflags.h) +    $(wildcard include/config/irqsoff/tracer.h) +    $(wildcard include/config/trace/irqflags/support.h) +    $(wildcard include/config/x86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irqflags.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt.h +    $(wildcard include/config/highpte.h) +    $(wildcard include/config/paravirt/spinlocks.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_types.h +    $(wildcard include/config/compat/vdso.h) +    $(wildcard include/config/proc/fs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt_types.h +    $(wildcard include/config/x86/local/apic.h) +    $(wildcard include/config/paravirt/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/desc_defs.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/kmap_types.h +    $(wildcard include/config/debug/highmem.h) +  include/asm-generic/kmap_types.h +  include/linux/cpumask.h +    $(wildcard include/config/cpumask/offstack.h) +    $(wildcard include/config/hotplug/cpu.h) +    $(wildcard include/config/debug/per/cpu/maps.h) +    $(wildcard include/config/disable/obsolete/cpumask/functions.h) +  include/linux/bitmap.h +  include/linux/string.h +    $(wildcard include/config/binary/printf.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr-index.h +  include/linux/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ioctl.h +  include/asm-generic/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/errno.h +  include/asm-generic/errno.h +  include/asm-generic/errno-base.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpumask.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ds.h +    $(wildcard include/config/x86/ds.h) +  include/linux/err.h +  include/linux/personality.h +  include/linux/cache.h +    $(wildcard include/config/arch/has/cache/line/size.h) +  include/linux/math64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/div64.h +  include/asm-generic/div64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ftrace.h +    $(wildcard include/config/function/tracer.h) +    $(wildcard include/config/dynamic/ftrace.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic_64.h +  include/asm-generic/atomic-long.h +  include/linux/list.h +    $(wildcard include/config/debug/list.h) +  include/linux/poison.h +    $(wildcard include/config/illegal/pointer/value.h) +  include/linux/prefetch.h +  include/linux/bottom_half.h +  include/linux/spinlock_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock_types.h +  include/linux/lockdep.h +    $(wildcard include/config/lockdep.h) +    $(wildcard include/config/lock/stat.h) +    $(wildcard include/config/generic/hardirqs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwlock.h +  include/linux/spinlock_api_smp.h +  include/linux/wait.h +  include/linux/numa.h +    $(wildcard include/config/nodes/shift.h) +  include/linux/seqlock.h +  include/linux/nodemask.h +  include/linux/pageblock-flags.h +    $(wildcard include/config/hugetlb/page.h) +    $(wildcard include/config/hugetlb/page/size/variable.h) +  include/linux/bounds.h +  include/linux/memory_hotplug.h +    $(wildcard include/config/have/arch/nodedata/extension.h) +    $(wildcard include/config/memory/hotremove.h) +  include/linux/notifier.h +  include/linux/errno.h +  include/linux/mutex.h +    $(wildcard include/config/debug/mutexes.h) +  include/linux/rwsem.h +    $(wildcard include/config/rwsem/generic/spinlock.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwsem.h +  include/linux/srcu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone_64.h +    $(wildcard include/config/numa/emu.h) +  include/linux/mmdebug.h +    $(wildcard include/config/debug/virtual.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/smp.h +    $(wildcard include/config/x86/io/apic.h) +    $(wildcard include/config/x86/32/smp.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec.h +    $(wildcard include/config/x86/numaq.h) +    $(wildcard include/config/mca.h) +    $(wildcard include/config/eisa.h) +    $(wildcard include/config/x86/mpparse.h) +    $(wildcard include/config/acpi.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec_def.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/x86_init.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bootparam.h +  include/linux/screen_info.h +  include/linux/apm_bios.h +  include/linux/edd.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/e820.h +    $(wildcard include/config/efi.h) +    $(wildcard include/config/hibernation.h) +    $(wildcard include/config/memtest.h) +  include/linux/ioport.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ist.h +  include/video/edid.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apic.h +    $(wildcard include/config/x86/x2apic.h) +  include/linux/delay.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/delay.h +  include/linux/pm.h +    $(wildcard include/config/pm/sleep.h) +    $(wildcard include/config/pm/runtime.h) +  include/linux/workqueue.h +  include/linux/timer.h +    $(wildcard include/config/timer/stats.h) +    $(wildcard include/config/debug/objects/timers.h) +  include/linux/ktime.h +    $(wildcard include/config/ktime/scalar.h) +  include/linux/time.h +    $(wildcard include/config/arch/uses/gettimeoffset.h) +  include/linux/jiffies.h +  include/linux/timex.h +    $(wildcard include/config/no/hz.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/timex.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/tsc.h +    $(wildcard include/config/x86/tsc.h) +  include/linux/debugobjects.h +    $(wildcard include/config/debug/objects/free.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apicdef.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fixmap.h +    $(wildcard include/config/provide/ohci1394/dma/init.h) +    $(wildcard include/config/x86/visws/apic.h) +    $(wildcard include/config/x86/f00f/bug.h) +    $(wildcard include/config/x86/cyclone/timer.h) +    $(wildcard include/config/pci/mmconfig.h) +    $(wildcard include/config/intel/txt.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/acpi.h +    $(wildcard include/config/acpi/numa.h) +  include/acpi/pdc_intel.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vsyscall.h +    $(wildcard include/config/generic/time.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_apic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irq_vectors.h +    $(wildcard include/config/sparse/irq.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sparsemem.h +  include/linux/topology.h +    $(wildcard include/config/sched/smt.h) +    $(wildcard include/config/sched/mc.h) +  include/linux/smp.h +    $(wildcard include/config/use/generic/smp/helpers.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/topology.h +    $(wildcard include/config/x86/ht.h) +    $(wildcard include/config/x86/64/acpi/numa.h) +  include/asm-generic/topology.h +  include/linux/slub_def.h +    $(wildcard include/config/slub/stats.h) +    $(wildcard include/config/slub/debug.h) +    $(wildcard include/config/kmemtrace.h) +  include/linux/kobject.h +  include/linux/sysfs.h +    $(wildcard include/config/sysfs.h) +  include/linux/kref.h +  include/linux/kmemtrace.h +  include/trace/events/kmem.h +  include/linux/tracepoint.h +    $(wildcard include/config/tracepoints.h) +  include/linux/rcupdate.h +    $(wildcard include/config/tree/preempt/rcu.h) +    $(wildcard include/config/tree/rcu.h) +  include/linux/completion.h +  include/linux/rcutree.h +  include/trace/define_trace.h +    $(wildcard include/config/event/tracing.h) +  include/linux/kmemleak.h +    $(wildcard include/config/debug/kmemleak.h) +  include/linux/netfilter.h +    $(wildcard include/config/netfilter.h) +    $(wildcard include/config/sysctl.h) +    $(wildcard include/config/netfilter/debug.h) +    $(wildcard include/config/nf/nat/needed.h) +    $(wildcard include/config/nf/conntrack.h) +  include/linux/skbuff.h +    $(wildcard include/config/bridge/netfilter.h) +    $(wildcard include/config/has/dma.h) +    $(wildcard include/config/xfrm.h) +    $(wildcard include/config/net/sched.h) +    $(wildcard include/config/net/cls/act.h) +    $(wildcard include/config/ipv6/ndisc/nodetype.h) +    $(wildcard include/config/net/dma.h) +    $(wildcard include/config/network/secmark.h) +  include/linux/kmemcheck.h +  include/linux/mm_types.h +    $(wildcard include/config/split/ptlock/cpus.h) +    $(wildcard include/config/want/page/debug/flags.h) +    $(wildcard include/config/mmu.h) +    $(wildcard include/config/aio.h) +    $(wildcard include/config/mm/owner.h) +    $(wildcard include/config/mmu/notifier.h) +  include/linux/auxvec.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/auxvec.h +  include/linux/prio_tree.h +  include/linux/rbtree.h +  include/linux/page-debug-flags.h +    $(wildcard include/config/page/poisoning.h) +    $(wildcard include/config/page/debug/something/else.h) +  include/linux/net.h +  include/linux/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/socket.h +  include/asm-generic/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sockios.h +  include/asm-generic/sockios.h +  include/linux/sockios.h +  include/linux/uio.h +  include/linux/random.h +  include/linux/irqnr.h +  include/linux/fcntl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fcntl.h +  include/asm-generic/fcntl.h +  include/linux/sysctl.h +  include/linux/textsearch.h +  include/linux/module.h +    $(wildcard include/config/modversions.h) +    $(wildcard include/config/unused/symbols.h) +    $(wildcard include/config/kallsyms.h) +    $(wildcard include/config/module/unload.h) +    $(wildcard include/config/constructors.h) +  include/linux/stat.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/stat.h +  include/linux/kmod.h +  include/linux/elf.h +  include/linux/elf-em.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/elf.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vdso.h +  include/linux/moduleparam.h +    $(wildcard include/config/alpha.h) +    $(wildcard include/config/ia64.h) +    $(wildcard include/config/ppc64.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/local.h +  include/linux/percpu.h +    $(wildcard include/config/have/legacy/per/cpu/area.h) +    $(wildcard include/config/need/per/cpu/embed/first/chunk.h) +    $(wildcard include/config/need/per/cpu/page/first/chunk.h) +  include/linux/pfn.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/module.h +    $(wildcard include/config/m586.h) +    $(wildcard include/config/m586tsc.h) +    $(wildcard include/config/m586mmx.h) +    $(wildcard include/config/mcore2.h) +    $(wildcard include/config/matom.h) +    $(wildcard include/config/m686.h) +    $(wildcard include/config/mpentiumii.h) +    $(wildcard include/config/mpentiumiii.h) +    $(wildcard include/config/mpentiumm.h) +    $(wildcard include/config/mpentium4.h) +    $(wildcard include/config/mk6.h) +    $(wildcard include/config/mk8.h) +    $(wildcard include/config/x86/elan.h) +    $(wildcard include/config/mcrusoe.h) +    $(wildcard include/config/mefficeon.h) +    $(wildcard include/config/mwinchipc6.h) +    $(wildcard include/config/mwinchip3d.h) +    $(wildcard include/config/mcyrixiii.h) +    $(wildcard include/config/mviac3/2.h) +    $(wildcard include/config/mviac7.h) +    $(wildcard include/config/mgeodegx1.h) +    $(wildcard include/config/mgeode/lx.h) +    $(wildcard include/config/4kstacks.h) +  include/asm-generic/module.h +  include/trace/events/module.h +  include/net/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess.h +    $(wildcard include/config/x86/wp/works/ok.h) +    $(wildcard include/config/x86/intel/usercopy.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum_64.h +  include/linux/dmaengine.h +    $(wildcard include/config/dma/engine.h) +    $(wildcard include/config/async/tx/dma.h) +    $(wildcard include/config/async/tx/disable/channel/switch.h) +  include/linux/device.h +    $(wildcard include/config/debug/devres.h) +    $(wildcard include/config/devtmpfs.h) +  include/linux/klist.h +  include/linux/semaphore.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/device.h +    $(wildcard include/config/dmar.h) +  include/linux/pm_wakeup.h +    $(wildcard include/config/pm.h) +  include/linux/dma-mapping.h +    $(wildcard include/config/have/dma/attrs.h) +  include/linux/dma-attrs.h +  include/linux/bug.h +  include/linux/scatterlist.h +    $(wildcard include/config/debug/sg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/scatterlist.h +  include/asm-generic/scatterlist.h +  include/linux/mm.h +    $(wildcard include/config/stack/growsup.h) +    $(wildcard include/config/swap.h) +    $(wildcard include/config/debug/pagealloc.h) +  include/linux/debug_locks.h +    $(wildcard include/config/debug/locking/api/selftests.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  include/asm-generic/pgtable.h +  include/linux/page-flags.h +    $(wildcard include/config/pageflags/extended.h) +    $(wildcard include/config/have/mlocked/page/bit.h) +    $(wildcard include/config/arch/uses/pg/uncached.h) +    $(wildcard include/config/memory/failure.h) +    $(wildcard include/config/s390.h) +  include/linux/vmstat.h +    $(wildcard include/config/vm/event/counters.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_64.h +  include/linux/vmalloc.h +  include/asm-generic/iomap.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/dma-mapping.h +    $(wildcard include/config/isa.h) +  include/linux/dma-debug.h +    $(wildcard include/config/dma/api/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swiotlb.h +    $(wildcard include/config/swiotlb.h) +  include/linux/swiotlb.h +  include/asm-generic/dma-coherent.h +    $(wildcard include/config/have/generic/dma/coherent.h) +  include/asm-generic/dma-mapping-common.h +  include/linux/hrtimer.h +    $(wildcard include/config/high/res/timers.h) +  include/linux/if.h +  include/linux/hdlc/ioctl.h +  include/linux/in.h +  include/linux/in6.h +  include/net/flow.h +  include/linux/proc_fs.h +    $(wildcard include/config/proc/devicetree.h) +    $(wildcard include/config/proc/kcore.h) +  include/linux/fs.h +    $(wildcard include/config/dnotify.h) +    $(wildcard include/config/quota.h) +    $(wildcard include/config/fsnotify.h) +    $(wildcard include/config/inotify.h) +    $(wildcard include/config/security.h) +    $(wildcard include/config/fs/posix/acl.h) +    $(wildcard include/config/epoll.h) +    $(wildcard include/config/debug/writecount.h) +    $(wildcard include/config/file/locking.h) +    $(wildcard include/config/auditsyscall.h) +    $(wildcard include/config/block.h) +    $(wildcard include/config/fs/xip.h) +    $(wildcard include/config/migration.h) +  include/linux/limits.h +  include/linux/kdev_t.h +  include/linux/dcache.h +  include/linux/rculist.h +  include/linux/path.h +  include/linux/radix-tree.h +  include/linux/pid.h +  include/linux/capability.h +    $(wildcard include/config/security/file/capabilities.h) +  include/linux/fiemap.h +  include/linux/quota.h +  include/linux/dqblk_xfs.h +  include/linux/dqblk_v1.h +  include/linux/dqblk_v2.h +  include/linux/dqblk_qtree.h +  include/linux/nfs_fs_i.h +  include/linux/nfs.h +  include/linux/sunrpc/msg_prot.h +  include/linux/inet.h +  include/linux/magic.h +  include/linux/version.h +  include/linux/kmalloc_sizes.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/rlp.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.h +
+/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.o: $(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.o)
+
+$(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.o):
diff -uNr nf-hipac/kernel/global.c nfhipac/kernel/global.c
--- nf-hipac/kernel/global.c	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/global.c	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,964 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#include "global.h"
+#include "ihash.h"
+
+#define LEN(array) (sizeof(array) / sizeof(*(array)))
+
+
+__u64 mem_max = 0;
+__u64 mem_current_tight = 0;
+__u64 mem_current_real = 0;
+static struct ihash *memhash = NULL;
+
+
+void *
+hp_alloc(__u32 size, int do_add)
+{
+	__u32 sz_real;
+	void *p;
+
+	if (unlikely(size == 0 || size >= 0x80000000)) {
+		ARG_MSG;
+		return NULL;
+	}
+	if (unlikely(memhash == NULL)) {
+		memhash = ihash_new(INITIAL_MEMHASH_LEN, 1,
+				    MEMHASH_AVRG_ELEM_PER_BUCKET,
+				    ihash_func_val, eq_val);
+		if (memhash == NULL) {
+			ERR("unable to create memhash");
+			return NULL;
+		}
+	}
+	if (size <= PAGE_SIZE) {
+		sz_real = mini_alloc_size(size);
+		if (unlikely(do_add && mem_current_real + sz_real > mem_max)) {
+			goto mem_max_reached;
+		}
+		p = mini_alloc(size);
+	} else {
+		sz_real = big_alloc_size(size);
+		if (unlikely(do_add && mem_current_real + sz_real > mem_max)) {
+			goto mem_max_reached;
+		}
+		p = big_alloc(size);
+	}
+	if (p == NULL) {
+		return NULL;
+	}
+	if (ihash_insert(&memhash, p,
+			 val_to_ptr(((!!do_add) << 31) | size)) < 0) {
+		if (size <= PAGE_SIZE) {
+			mini_free(p);
+		} else {
+			big_free(p);
+		}
+		return NULL;
+	}
+	if (do_add) {
+		mem_current_tight += size;
+		mem_current_real += sz_real;
+	}
+	return p;
+	
+ mem_max_reached:
+	return NULL;
+}
+
+void
+hp_free(void *p)
+{
+	__u32 size, sz_real, do_add;
+	void *inf;
+
+	if (unlikely(p == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	if (unlikely(memhash == NULL)) {
+		ERR("hp_free called before hp_alloc");
+		return;
+	}
+	inf = ihash_lookup_val(memhash, p);
+	if (unlikely(inf == NULL)) {
+		ERR("pointer %p not in memhash", p);
+		return;
+	}
+	size = ptr_to_val(inf);
+	do_add = size & 0x80000000;
+	size &= 0x7FFFFFFF;
+	if (size <= PAGE_SIZE) {
+		mini_free(p);
+		if (unlikely(ihash_delete(memhash, p, NULL) < 0)) {
+			goto hashdel_failed;
+		}
+		if (!do_add) {
+			return;
+		}
+		sz_real = mini_alloc_size(size);
+	} else {
+		big_free(p);
+		if (unlikely(ihash_delete(memhash, p, NULL) < 0)) {
+			goto hashdel_failed;
+		}
+		if (!do_add) {
+			return;
+		}
+		sz_real = big_alloc_size(size);
+	}
+	mem_current_tight -= size;
+	mem_current_real -= sz_real;
+	return;
+
+ hashdel_failed:
+	ERR("memhash delete failed");
+	return;
+}
+
+void *
+hp_realloc(void *p, __u32 newsize)
+{
+	__u32 sz, sz_real, newsz_real, do_add;
+	void *inf, *newp;
+
+	if (unlikely(newsize == 0 || newsize >= 0x80000000 || p == NULL)) {
+		ARG_MSG;
+		return NULL;
+	}
+	if (unlikely(memhash == NULL)) {
+		ERR("hp_realloc called before hp_alloc");
+		return NULL;
+	}
+	inf = ihash_lookup_val(memhash, p);
+	if (unlikely(inf == NULL)) {
+		ERR("pointer %p not in memhash\n", p);
+		return NULL;
+	}
+	sz = ptr_to_val(inf);
+	do_add = sz & 0x80000000;
+	sz &= 0x7FFFFFFF;
+	sz_real = sz <= PAGE_SIZE ? mini_alloc_size(sz) : big_alloc_size(sz);
+	if (newsize <= PAGE_SIZE) {
+		newsz_real = mini_alloc_size(newsize);
+		if (sz_real == newsz_real) {
+			goto only_size_change;
+		}
+		if (unlikely(do_add && mem_current_real + newsz_real >
+			     mem_max + sz_real)) {
+			if (newsize <= sz) {
+				goto only_size_change;
+			}
+			goto mem_max_reached;
+		}
+		newp = mini_alloc(newsize);
+	} else {
+		newsz_real = big_alloc_size(newsize);
+		if (sz_real == newsz_real) {
+			goto only_size_change;
+		}
+		if (unlikely(do_add && mem_current_real + newsz_real >
+			     mem_max + sz_real)) {
+			if (newsize <= sz) {
+				goto only_size_change;
+			}
+			goto mem_max_reached;
+		}
+		newp = big_alloc(newsize);
+	}
+	if (newp == NULL) {
+		if (newsize <= sz) {
+			goto only_size_change;
+		}
+		return NULL;
+	}
+	if (unlikely(ihash_replace(&memhash, p, NULL, newp,
+				   val_to_ptr(((!!do_add) << 31) |
+					      newsize)) < 0)) {
+		if (newsize <= PAGE_SIZE) {
+			mini_free(newp);
+		} else {
+			big_free(newp);
+		}
+		if (newsize <= sz) {
+			goto only_size_change;
+		}
+		return NULL;
+	}
+	memcpy(newp, p, sz < newsize ? sz : newsize);
+	if (sz <= PAGE_SIZE) {
+		mini_free(p);
+	} else {
+		big_free(p);
+	}
+	if (do_add) {
+		mem_current_tight += newsize;
+		mem_current_tight -= sz;
+		mem_current_real += newsz_real;
+		mem_current_real -= sz_real;
+	}
+	return newp;
+
+ mem_max_reached:
+	return NULL;
+
+ only_size_change:
+	if (unlikely(ihash_replace(&memhash, p, NULL, p,
+				   val_to_ptr(((!!do_add) << 31) |
+					      newsize)) < 0)) {
+		ERR("unable to replace memhash entry");
+		return NULL;
+	}
+	if (do_add) {
+		mem_current_tight += newsize;
+		mem_current_tight -= sz;
+	} 
+	return p;
+}
+
+hipac_error
+hp_size(void *p, __u64 *size_real, __u64 *size_tight)
+{
+	void *inf;
+	__u32 size;
+	
+	if (unlikely(size_real == NULL || size_tight == NULL)) {
+		ARG_ERR;
+	}
+	if (unlikely(p == NULL)) {
+		return HE_OK;
+	}
+	inf = ihash_lookup_val(memhash, p);
+	if (unlikely(inf == NULL)) {
+		IMPOSSIBLE_CONDITION("size request for unkown pointer");
+	}
+	size = ((__u32) ptr_to_val(inf)) & 0x7FFFFFFF;
+	*size_tight += size;
+	*size_real += size <= PAGE_SIZE ? mini_alloc_size(size) :
+		big_alloc_size(size);
+	return HE_OK;
+}
+
+void
+hp_mem_exit(void)
+{
+	if (unlikely(memhash == NULL)) {
+		return;
+	}
+	if (unlikely(memhash->elem_ct != 0)) {
+		WARN_("memhash still contains unfreed pointers");
+	}
+	if (unlikely(mem_current_tight != 0)) {
+		WARN_("mem_current_tight is not 0");
+	}
+	if (unlikely(mem_current_real != 0)) {
+		WARN_("mem_current_real is not 0");
+	}
+	ihash_free(memhash);
+	memhash = NULL;
+}
+
+hipac_error
+hipac_get_mem_stat(struct hipac_mem_stat *stat)
+{
+	struct ihash_stat istat;
+
+	if (stat == NULL) {
+		ARG_ERR;
+	}
+	if (sizeof(istat.bucket_dist) != sizeof(stat->memhash_bucket_stat)) {
+		IMPOSSIBLE_CONDITION("struct ihash_stat and struct "
+				     "hipac_mem_stat incompatible");
+	}
+	if (ihash_stat(memhash, &istat) < 0) {
+		IMPOSSIBLE_CONDITION("ihash_stat failed");
+	}
+	
+	stat->total_mem_tight = mem_current_tight;
+	stat->total_mem_real = mem_current_real;
+	stat->memhash_elem_num = istat.elem_ct;
+	stat->memhash_len = istat.bucket_len;
+	stat->memhash_smallest_bucket_len = istat.small_bucket_len;
+	stat->memhash_biggest_bucket_len = istat.big_bucket_len;
+	memcpy(stat->memhash_bucket_stat, istat.bucket_dist,
+	       sizeof(istat.bucket_dist));
+	return HE_OK;
+}
+
+
+
+/*
+ * statistical distributions
+ */
+
+void
+stat_distribution_add(__u32 dist[], __u32 len, __u32 val)
+{
+	__u32 i;
+
+	if (unlikely(dist == NULL || len == 0)) {
+		ARG_MSG;
+		return;
+	}
+	
+	for (i = 0; i < len - 1; i++) {
+		if (val <= (1 << i) - 1) {
+			dist[i]++;
+			return;
+		}
+	}
+	dist[i]++;
+}
+
+
+
+/*
+ * pointer block
+ */
+
+struct ptrblock *
+ptrblock_new(void *p, int do_add)
+{
+	struct ptrblock *new;
+	
+	if (unlikely(p == NULL)) {
+		ARG_MSG;
+		return NULL;
+	}
+	new = hp_alloc(sizeof(*new) + sizeof(*new->p), do_add);
+	if (new == NULL) {
+		return NULL;
+	}
+	new->len = 1;
+	new->p[0] = p;
+	return new;
+}
+
+int
+ptrblock_eq(const struct ptrblock *b1, const struct ptrblock *b2)
+{
+	__u32 i;
+	
+	if (b1 == b2) {
+		return 1;
+	}
+	if (b1 == NULL || b2 == NULL || b1->len != b2->len) {
+		return 0;
+	}
+	/* b1->len == 0 is valid if b1 and b2 are embedded ptrblocks */
+	for (i = 0; i < b1->len; i++) {
+		if (b1->p[i] != b2->p[i]) {
+			return 0;
+		}
+	}
+	return 1;
+}
+
+hipac_error
+ptrblock_clone(struct ptrblock *b, struct ptrblock **clone)
+{
+	__u32 sz;
+
+	if (unlikely(clone == NULL)) {
+		ARG_ERR;
+	}
+
+	if (b == NULL) {
+		*clone = NULL;
+		return HE_OK;
+	}
+	sz = ptrblock_size(b);
+	*clone = hp_alloc(sz, 1);
+	if (*clone == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	memcpy(*clone, b, sz);
+	return HE_OK;
+}
+
+hipac_error
+ptrblock_insert(struct ptrblock **b, void *p, __u32 pos)
+{
+	struct ptrblock *new;
+
+	if (unlikely(p == NULL || b == NULL || (*b == NULL && pos > 0) ||
+		     (*b != NULL && pos > (*b)->len))) {
+		ARG_ERR;
+	}
+
+	if (*b == NULL) {
+		new = ptrblock_new(p, 1);
+		if (new == NULL) {
+			return HE_LOW_MEMORY;
+		}
+		*b = new;
+		return HE_OK;
+	}
+	new = hp_realloc(*b, sizeof(**b) + ((*b)->len + 1) * sizeof(*(*b)->p));
+	if (new == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	if (new->len > pos) {
+		memmove(&new->p[pos + 1], &new->p[pos], (new->len - pos) *
+			sizeof(*new->p));
+	}
+	new->len++;
+	new->p[pos] = p;
+	*b = new;
+	return HE_OK;
+}
+
+hipac_error
+ptrblock_insert_embed(void **o, __u32 ptrblock_offset, void *p, __u32 pos)
+{
+	struct ptrblock *b;
+	void *new;
+
+	if (unlikely(o == NULL || *o == NULL || p == NULL ||
+		     pos > ((struct ptrblock *)
+			    ((char *) *o + ptrblock_offset))->len)) {
+		ARG_ERR;
+	}
+	b = (struct ptrblock *) ((char *) *o + ptrblock_offset);
+	new = hp_realloc(*o, ptrblock_offset + sizeof(*b) +
+			 (b->len + 1) * sizeof(*b->p));
+	if (new == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	b = (struct ptrblock *) ((char *) new + ptrblock_offset);
+	if (b->len > pos) {
+		memmove(&b->p[pos + 1], &b->p[pos], (b->len - pos) *
+			sizeof(*b->p));
+	}
+	b->len++;
+	b->p[pos] = p;
+	*o = new;
+	return HE_OK;
+}
+
+hipac_error
+ptrblock_append(struct ptrblock **b, void *p)
+{
+	struct ptrblock *new;
+
+	if (unlikely(p == NULL || b == NULL)) {
+		ARG_ERR;
+	}
+
+	if (*b == NULL) {
+		new = ptrblock_new(p, 1);
+		if (new == NULL) {
+			return HE_LOW_MEMORY;
+		}
+		*b = new;
+		return HE_OK;
+	}
+	new = hp_realloc(*b, sizeof(**b) + ((*b)->len + 1) * sizeof(*(*b)->p));
+	if (new == NULL) {
+		return HE_LOW_MEMORY;
+	}
+#ifdef DEBUG
+	{
+		__u32 i;
+		for (i = 0; i < new->len; i++) {
+			if (new->p[i] == p) {
+				IMPOSSIBLE_CONDITION("ptrblock contains "
+						     "duplicated pointer");
+			}
+		}
+	}
+#endif
+	new->p[new->len++] = p;
+	*b = new;
+	return HE_OK;
+}
+
+hipac_error
+ptrblock_delete_pos(struct ptrblock **b, __u32 pos)
+{
+	struct ptrblock *new;
+
+	if (unlikely(b == NULL || *b == NULL || pos >= (*b)->len)) {
+		ARG_ERR;
+	}
+
+	if ((*b)->len == 1) {
+		ptrblock_free(*b);
+		*b = NULL;
+		return HE_OK;
+	}
+	(*b)->len--;
+	if ((*b)->len > pos) {
+		memmove(&(*b)->p[pos], &(*b)->p[pos + 1],
+			((*b)->len - pos) * sizeof(*(*b)->p));
+	}
+	new = hp_realloc(*b, sizeof(**b) + (*b)->len * sizeof(*(*b)->p));
+	if (new == NULL) {
+		WARN_("hp_realloc returns NULL although less memory was "
+		     "requested");
+	} else {
+		*b = new;
+	}
+	return HE_OK;
+}
+
+hipac_error
+ptrblock_delete_pos_embed(void **o, __u32 ptrblock_offset, __u32 pos)
+{
+	struct ptrblock *new;
+	struct ptrblock *b;
+
+	if (unlikely(o == NULL || *o == NULL ||
+		     pos >= ((struct ptrblock *)
+			     ((char *) *o + ptrblock_offset))->len)) {
+		ARG_ERR;
+	}
+	b = (struct ptrblock *) ((char *) *o + ptrblock_offset);
+	b->len--;
+	if (b->len > pos) {
+		memmove(&b->p[pos], &b->p[pos + 1],
+			(b->len - pos) * sizeof(*b->p));
+	}
+	new = hp_realloc(*o, ptrblock_offset + sizeof(*b) +
+			 b->len * sizeof(*b->p));
+	if (new == NULL) {
+		WARN_("hp_realloc returns NULL although less memory was "
+		     "requested");
+	} else {
+		*o = new;
+	}
+	return HE_OK;
+}
+
+hipac_error
+ptrblock_delete(struct ptrblock **b, void *p)
+{
+	__u32 i;
+
+	if (unlikely(b == NULL || *b == NULL)) {
+		ARG_ERR;
+	}
+	for (i = 0; i < (*b)->len; i++) {
+		if ((*b)->p[i] == p) {
+			return ptrblock_delete_pos(b, i);
+		}
+	}
+	IMPOSSIBLE_CONDITION("pointer %p not in ptrblock", p);
+}
+
+hipac_error
+ptrblock_delete_tail(struct ptrblock **b)
+{
+	struct ptrblock *new;
+
+	if (unlikely(b == NULL || *b == NULL)) {
+		ARG_ERR;
+	}
+
+	if ((*b)->len == 1) {
+		ptrblock_free(*b);
+		*b = NULL;
+		return HE_OK;
+	}
+	(*b)->len--;
+	new = hp_realloc(*b, sizeof(**b) + (*b)->len * sizeof(*(*b)->p));
+	if (new == NULL) {
+		WARN_("hp_realloc returns NULL although less memory was "
+		     "requested");
+	} else {
+		*b = new;
+	}
+	return HE_OK;
+}
+
+hipac_error
+ptrblock_delete_multi(struct ptrblock **b, const struct ptrblock *mark)
+{
+	struct ptrblock *new;
+	__u32 first, last, i;
+
+	if (unlikely(b == NULL || mark == NULL ||
+		     (*b != NULL && mark->len < (*b)->len))) {
+		ARG_ERR;
+	}
+
+	if (*b == NULL) {
+		return HE_OK;
+	}
+	for (first = 0; first < (*b)->len && mark->p[first] != NULL; first++);
+	if (first == (*b)->len) {
+		/* nothing to delete */
+		return HE_OK;
+	}
+	for (last = first + 1, i = 0; last < (*b)->len; last++) {
+		if (mark->p[last] != NULL) {
+			continue;
+		}
+		if (last > first + 1) {
+			memmove(&(*b)->p[first - i], &(*b)->p[first + 1],
+				(last - first - 1) * sizeof(*(*b)->p));
+		}
+		i++;
+		first = last;
+	}
+	if ((*b)->len > first + 1) {
+		memmove(&(*b)->p[first - i], &(*b)->p[first + 1],
+			((*b)->len - first - 1) * sizeof(*(*b)->p));
+	}
+	(*b)->len -= i + 1;
+	if ((*b)->len == 0) {
+		ptrblock_free(*b);
+		*b = NULL;
+		return HE_OK;
+	}
+	new = hp_realloc(*b, sizeof(**b) + (*b)->len * sizeof(*(*b)->p));
+	if (new == NULL) {
+		WARN_("hp_realloc returns NULL although less memory was "
+		     "requested");
+	} else {
+		*b = new;
+	}
+	return HE_OK;
+}
+
+hipac_error
+ptrblock_delete_null(struct ptrblock **b)
+{
+	struct ptrblock *new;
+	__u32 first, last, i;
+
+	if (unlikely(b == NULL)) {
+		ARG_ERR;
+	}
+
+	if (*b == NULL) {
+		return HE_OK;
+	}
+	for (first = 0; first < (*b)->len && (*b)->p[first] != NULL; first++);
+	if (first == (*b)->len) {
+		/* nothing to delete */
+		return HE_OK;
+	}
+	for (last = first + 1, i = 0; last < (*b)->len; last++) {
+		if ((*b)->p[last] != NULL) {
+			continue;
+		}
+		if (last > first + 1) {
+			memmove(&(*b)->p[first - i], &(*b)->p[first + 1],
+				(last - first - 1) * sizeof(*(*b)->p));
+		}
+		i++;
+		first = last;
+	}
+	if ((*b)->len > first + 1) {
+		memmove(&(*b)->p[first - i], &(*b)->p[first + 1],
+			((*b)->len - first - 1) * sizeof(*(*b)->p));
+	}
+	(*b)->len -= i + 1;
+	if ((*b)->len == 0) {
+		ptrblock_free(*b);
+		*b = NULL;
+		return HE_OK;
+	}
+	new = hp_realloc(*b, sizeof(**b) + (*b)->len * sizeof(*(*b)->p));
+	if (new == NULL) {
+		WARN_("hp_realloc returns NULL although less memory was "
+		     "requested");
+	} else {
+		*b = new;
+	}
+	return HE_OK;
+}
+
+
+
+/*
+ * block of structs
+ */
+struct strblock *
+strblock_new(const void *s, __u32 size, int do_add)
+{
+	struct strblock *new;
+	
+	if (unlikely(s == NULL || size == 0)) {
+		ARG_MSG;
+		return NULL;
+	}
+	new = hp_alloc(sizeof(*new) + size, do_add);
+	if (new == NULL) {
+		return NULL;
+	}
+	new->len = 1;
+	new->size = size;
+	memcpy(new->d, s, size);
+	return new;
+}
+
+int
+strblock_eq(const struct strblock *b1, const struct strblock *b2,
+	    int (* eq) (void *, void *))
+{
+	__u32 i;
+
+	if (b1 == b2) {
+		return 1;
+	}
+	if (b1 == NULL || b2 == NULL || b1->len != b2->len ||
+	    b1->size != b2->size) {
+		return 0;
+	}
+	assert(b1->len > 0);
+	for (i = 0; i < b1->len; i++) {
+		if (!eq(STRBLOCK_ITH(b1, i, void *),
+			STRBLOCK_ITH(b2, i, void *))) {
+			return 0;
+		}
+	}
+	return 1;
+}
+
+hipac_error
+strblock_clone(struct strblock *b, struct strblock **clone)
+{
+	__u32 sz;
+
+	if (unlikely(clone == NULL)) {
+		ARG_ERR;
+	}
+
+	if (b == NULL) {
+		*clone = NULL;
+		return HE_OK;
+	}
+	sz = strblock_size(b);
+	*clone = hp_alloc(sz, 1);
+	if (*clone == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	memcpy(*clone, b, sz);
+	return HE_OK;
+}
+
+hipac_error
+strblock_insert(struct strblock **b, const void *s, __u32 size, __u32 pos)
+{
+	struct strblock *new;
+
+	if (unlikely(s == NULL || b == NULL ||
+		     (*b == NULL && (pos > 0 || size == 0)) ||
+		     (*b != NULL && (pos > (*b)->len ||
+				     (*b)->size != size)))) {
+		ARG_ERR;
+	}
+
+	if (*b == NULL) {
+		new = strblock_new(s, size, 1);
+		if (new == NULL) {
+			return HE_LOW_MEMORY;
+		}
+		*b = new;
+		return HE_OK;
+	}
+	new = hp_realloc(*b, sizeof(**b) + ((*b)->len + 1) * size);
+	if (new == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	if (new->len > pos) {
+		memmove(STRBLOCK_ITH(new, pos + 1, void *),
+			STRBLOCK_ITH(new, pos, void *),
+			(new->len - pos) * size);
+	}
+	new->len++;
+	memcpy(STRBLOCK_ITH(new, pos, void *), s, size);
+	*b = new;
+	return HE_OK;
+}
+
+hipac_error
+strblock_append(struct strblock **b, const void *s, __u32 size)
+{
+	struct strblock *new;
+
+	if (unlikely(s == NULL || b == NULL || (*b == NULL && size == 0) ||
+		     (*b != NULL && (*b)->size != size))) {
+		ARG_ERR;
+	}
+
+	if (*b == NULL) {
+		new = strblock_new(s, size, 1);
+		if (new == NULL) {
+			return HE_LOW_MEMORY;
+		}
+		*b = new;
+		return HE_OK;
+	}
+	new = hp_realloc(*b, sizeof(**b) + ((*b)->len + 1) * size);
+	if (new == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	memcpy(STRBLOCK_ITH(new, new->len, void *), s, size);
+	new->len++;
+	*b = new;
+	return HE_OK;
+}
+
+hipac_error
+strblock_delete_pos(struct strblock **b, __u32 pos)
+{
+	struct strblock *new;
+
+	if (unlikely(b == NULL || *b == NULL || pos >= (*b)->len)) {
+		ARG_ERR;
+	}
+
+	if ((*b)->len == 1) {
+		strblock_free(*b);
+		*b = NULL;
+		return HE_OK;
+	}
+	(*b)->len--;
+	if ((*b)->len > pos) {
+		memmove(STRBLOCK_ITH(*b, pos, void *),
+			STRBLOCK_ITH(*b, pos + 1, void *),
+			((*b)->len - pos) * (*b)->size);
+	}
+	new = hp_realloc(*b, sizeof(**b) + (*b)->len * (*b)->size);
+	if (new == NULL) {
+		WARN_("hp_realloc returns NULL although less memory was "
+		     "requested");
+	} else {
+		*b = new;
+	}
+	return HE_OK;
+}
+
+hipac_error
+strblock_delete_tail(struct strblock **b)
+{
+	struct strblock *new;
+
+	if (unlikely(b == NULL || *b == NULL)) {
+		ARG_ERR;
+	}
+
+	if ((*b)->len == 1) {
+		strblock_free(*b);
+		*b = NULL;
+		return HE_OK;
+	}
+	(*b)->len--;
+	new = hp_realloc(*b, sizeof(**b) + (*b)->len * (*b)->size);
+	if (new == NULL) {
+		WARN_("hp_realloc returns NULL although less memory was "
+		     "requested");
+	} else {
+		*b = new;
+	}
+	return HE_OK;
+}
+
+
+
+/*
+ * pointer list
+ */
+
+struct ptrlist *
+ptrlist_new(void)
+{
+	struct ptrlist *new;
+
+	new = mini_alloc(sizeof(*new));
+	if (new == NULL) {
+		return NULL;
+	}
+	new->len = 0;
+	INIT_LIST_HEAD(&new->head);
+	return new;
+}
+
+struct ptrlist_entry *
+ptrlist_new_entry(void *p)
+{
+	struct ptrlist_entry *new;
+
+	new = mini_alloc(sizeof(*new));
+	if (new == NULL) {
+		return NULL;
+	}
+	new->p = p;
+	return new;
+}
+
+void
+ptrlist_flush(struct ptrlist *l)
+{
+	struct list_head *lh;
+
+	if (unlikely(l == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	for (lh = l->head.next; lh != &l->head;) {
+		lh = lh->next;
+		mini_free(list_entry(lh->prev, struct ptrlist_entry, head));
+	}
+	INIT_LIST_HEAD(&l->head);
+	l->len = 0;
+}
+
+void
+ptrlist_free(struct ptrlist *l)
+{
+	struct list_head *lh;
+
+	if (unlikely(l == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	for (lh = l->head.next; lh != &l->head;) {
+		lh = lh->next;
+		mini_free(list_entry(lh->prev, struct ptrlist_entry, head));
+	}
+	mini_free(l);
+}
+
+hipac_error
+ptrlist_add(struct ptrlist *l, void *p, int check_dup)
+{
+	struct list_head *lh;
+	struct ptrlist_entry* e;
+
+	if (unlikely(l == NULL || p == NULL)) {
+		ARG_ERR;
+	}
+	if (unlikely(check_dup)) {
+		list_for_each(lh, &l->head) {
+			e = list_entry(lh, struct ptrlist_entry, head);
+			if (e->p == p) {
+				IMPOSSIBLE_CONDITION("pointer %p already in "
+						     "ptrlist", p);
+			}
+		}
+	}
+	e = mini_alloc(sizeof(*e));
+	if (e == NULL) {
+		return HE_LOW_MEMORY;
+	}
+	e->p = p;
+	list_add_tail(&e->head, &l->head);
+	l->len++;
+	return HE_OK;
+}
diff -uNr nf-hipac/kernel/global.h nfhipac/kernel/global.h
--- nf-hipac/kernel/global.h	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/global.h	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,388 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#ifndef _GLOBAL_H
+#define _GLOBAL_H
+//#define DEBUG	1
+
+#include "mode.h"
+#include "hipac.h"  // hipac_error
+
+#define INITIAL_MEMHASH_LEN          64
+#define MEMHASH_AVRG_ELEM_PER_BUCKET 15
+#define INITIAL_NEWSPEC_LEN          1024
+#define NEWSPEC_AVRG_ELEM_PER_BUCKET 3
+
+#ifdef DEBUG
+#  define DPRINT(type, str, args...) if ((type) & hipac_debug)  +                                          printk(str , ## args)
+#else
+#  define DPRINT(type, str, args...) do {} while (0)
+#endif
+
+/* the single space before the last ‘,‘ is vital to make this macro work the
+   expected way because of some idiosyncrasy of gcc */
+#ifdef DEBUG
+#  define MSG(type, str, args...)                                           +   printk(type "%-15s : %-30s : %6d :   " str "\n", __FILE__, __FUNCTION__, +	  __LINE__ , ## args)
+#else
+#  define MSG(type, str, args...)                             +   printk("%s:%s:%d: " str "\n", __FILE__, __FUNCTION__, +	  __LINE__ , ## args)
+#endif
+
+#define ERR(str, args...)    MSG(KERN_ERR, str , ## args)
+#define WARN_(str, args...)   MSG(KERN_WARNING, str , ## args)
+#define NOTICE(str, args...) MSG(KERN_NOTICE, str , ## args)
+#define DBG(str, args...)    MSG(KERN_DEBUG, str , ## args)
+#define ARG_MSG              MSG(KERN_ERR, "function arguments invalid")
+
+#define ARG_ERR                                      +do {                                                 +	MSG(KERN_ERR, "function arguments invalid"); +	return HE_IMPOSSIBLE_CONDITION;              +} while (0)
+
+#define IMPOSSIBLE_CONDITION(str, args...) +do {                                       +	MSG(KERN_ERR, str , ## args);      +	return HE_IMPOSSIBLE_CONDITION;    +} while (0)
+
+
+
+/* generic header for dimtree rules, elementary intervals and rlps */
+struct gen_spec
+{
+	unsigned rlp : 1;
+};
+
+/* dimid to bittype array */
+extern __u8 *dim2btype;
+
+/* match executor function */
+extern hipac_match_exec_t match_fn;
+
+/* target executor function */
+extern hipac_target_exec_t target_fn;
+
+/* dimension extractor function */
+extern hipac_extract_t *extract_fn;
+
+
+
+/*
+ * memory management wrappers
+ */
+
+/* upper bound for memory consumption in bytes */
+extern __u64 mem_max;
+
+/* current memory consumption in bytes in terms of how much
+   has been requested */
+extern __u64 mem_current_tight;
+
+/* current memory consumption in bytes in terms of how much
+   has actually been allocated */
+extern __u64 mem_current_real;
+
+/* do_add indicates whether mem_current_tight and mem_current_real 
+   should be updated or not */
+void *
+hp_alloc(__u32 size, int do_add);
+
+void
+hp_free(void *p);
+
+void *
+hp_realloc(void *p, __u32 newsize);
+
+/* add the number of bytes requested for p to *size_tight and the number
+   of bytes allocated for p to *size_real; if p is NULL, size_tight and
+   size_real are not modified;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+hp_size(void *p, __u64 *size_real, __u64 *size_tight);
+
+/* internal memhash is freed; if it is not empty a warning is printed */
+void
+hp_mem_exit(void);
+
+
+
+/*
+ * statistical distributions
+ */
+
+/* initialize statistical distribution dist of length len, i.e. set it to 0 */
+static inline void
+stat_distribution_init(__u32 dist[], __u32 len)
+{
+	if (unlikely(dist == NULL || len == 0)) {
+		ARG_MSG;
+		return;
+	}
+	memset(dist, 0, len * sizeof(*dist));
+}
+
+/* dist is an array of length len representing a statistical distribution;
+   val is added to dist */
+void
+stat_distribution_add(__u32 dist[], __u32 len, __u32 val);
+
+
+
+/*
+ * pointer block
+ */
+struct ptrblock
+{
+	__u32 len;
+	void *p[0];
+};
+
+/* return new pointer block with p as the only element; do_add indicates
+   whether mem_current_tight and mem_current_real should be updated or not */
+struct ptrblock *
+ptrblock_new(void *p, int do_add);
+
+static inline void
+ptrblock_free(struct ptrblock *b)
+{
+	hp_free(b);
+}
+
+static inline __u32
+ptrblock_size(const struct ptrblock *b)
+{
+	if (unlikely(b == NULL)) {
+		ARG_MSG;
+		return 0;
+	}
+	return sizeof(*b) + b->len * sizeof(*b->p);
+}
+
+/* returns 1 if b1 and b2 are equal and 0 otherwise; b1->len or b2->len might
+   be 0 in order allow equality test on embedded ptrblocks */
+int
+ptrblock_eq(const struct ptrblock *b1, const struct ptrblock *b2);
+
+/* clone b and store the result in clone; the memory for clone is allocated
+   via hp_alloc if necessary and do_add is 1; b might be NULL;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_clone(struct ptrblock *b, struct ptrblock **clone);
+
+/* insert p into b at position pos; if *b is NULL and pos is 0
+   ptrblock_new(p, 1) is called and the result is assigned to b;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_insert(struct ptrblock **b, void *p, __u32 pos);
+
+/* insert p into (struct ptrblock *) ((char *) *o + ptrblock_offset)
+   at position pos; o is assumed to end after the embedded ptrblock;
+   hp_realloc is used to resize o;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_insert_embed(void **o, __u32 ptrblock_offset, void *p, __u32 pos);
+
+/* append p to b; if *b is NULL ptrblock_new(p, 1) is called and the result
+   is assigned to b;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_append(struct ptrblock **b, void *p);
+
+/* delete pointer at position pos in b; if b contains only one element and
+   pos is 0 then *b is freed and NULL is assigned to *b;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_delete_pos(struct ptrblock **b, __u32 pos);
+
+/* delete pointer at position pos in
+   (struct ptrblock *) ((char *) *o + ptrblock_offset); o is assumed to end
+   after the embedded ptrblock; hp_realloc is used to resize o;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_delete_pos_embed(void **o, __u32 ptrblock_offset, __u32 pos);
+
+/* delete p in b; if p is the only element in b then *b is freed and NULL
+   is assigned to *b;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_delete(struct ptrblock **b, void *p);
+
+/* delete trailing pointer in b; if b contains only one element then *b is
+   freed and NULL is assigned to *b;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_delete_tail(struct ptrblock **b);
+
+/* for all mark->p[i] == NULL: delete the pointer at the position i fom b;
+   if b is empty after the delete operation NULL is assigned to *b;
+   note that mark->len must be >= (*b)->len;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_delete_multi(struct ptrblock **b, const struct ptrblock *mark);
+
+/* similar to ptrblock_delete_multi: the pointers in b which are NULL are
+   deleted;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrblock_delete_null(struct ptrblock **b);
+
+
+
+/*
+ * block of structs
+ */
+struct strblock
+{
+	__u32 len, size;
+	char d[0];
+};
+
+#define STRBLOCK_ITH(b, i, cast) ((cast) ((b)->d + (i) * (b)->size))
+
+/* return new struct block with s as the only element; size is the size of 
+   the struct pointed to by s in bytes; do_add indicates whether
+   mem_current_tight and mem_current_real should be updated or not */
+struct strblock *
+strblock_new(const void *s, __u32 size, int do_add);
+
+static inline void
+strblock_free(struct strblock *b)
+{
+	hp_free(b);
+}
+
+static inline __u32
+strblock_size(const struct strblock *b)
+{
+	if (unlikely(b == NULL)) {
+		ARG_MSG;
+		return 0;
+	}
+	return sizeof(*b) + b->len * b->size;
+}
+
+/* returns 1 if b1 and b2 are equal and 0 otherwise; eq is an equality test
+   function for the embedded structs; eq(a, b) returns 1 if a equals to b
+   and 0 otherwise */
+int
+strblock_eq(const struct strblock *b1, const struct strblock *b2,
+	    int (* eq) (void *, void *));
+
+/* clone b and store the result in clone; the memory for clone is allocated
+   via hp_alloc if necessary and do_add is 1; b might be NULL;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+strblock_clone(struct strblock *b, struct strblock **clone);
+
+/* insert struct s into b at position pos; if *b is NULL and pos is 0
+   strblock_new(s, size, 1) is called and the result is assigned to b;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+strblock_insert(struct strblock **b, const void *s, __u32 size, __u32 pos);
+
+/* append struct s to b; if *b is NULL then strblock_new(s, size, 1) is
+   called and the result is assigned to b;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+strblock_append(struct strblock **b, const void *s, __u32 size);
+
+/* delete struct at position pos in b; if b contains only one element and
+   pos is 0 then *b is freed and NULL is assigned to *b;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+strblock_delete_pos(struct strblock **b, __u32 pos);
+
+/* delete trailing struct in b; if b contains only one element then *b is
+   freed and NULL is assigned to *b;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+strblock_delete_tail(struct strblock **b);
+
+
+
+/*
+ * pointer list
+ */
+struct ptrlist
+{
+	struct list_head head;
+	__u32 len;
+};
+
+struct ptrlist_entry
+{
+	struct list_head head;
+	void *p;
+};
+
+/* return new empty pointer list or NULL if allocation fails */
+struct ptrlist *
+ptrlist_new(void);
+
+/* return new pointer list entry containing p or NULL if allocation fails */
+struct ptrlist_entry *
+ptrlist_new_entry(void *p);
+
+/* free all entries from the pointer list l */
+void
+ptrlist_flush(struct ptrlist *l);
+
+/* free all entries from the pointer list l and l itself */
+void
+ptrlist_free(struct ptrlist *l);
+
+/* free ptrlist entry */
+static inline void
+ptrlist_free_entry(struct ptrlist_entry *e)
+{
+	if (unlikely(e == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	list_del(&e->head);
+	mini_free(e);
+}
+
+/* return 1 if l is empty and 0 otherwise */
+static inline int
+ptrlist_is_empty(const struct ptrlist *l)
+{
+	if (unlikely(l == NULL)) {
+		ARG_MSG;
+		return 0;
+	}
+	assert((l->len != 0 || l->head.next == &l->head) &&
+	       (l->head.next != &l->head || l->len == 0));
+	return l->len == 0;
+}
+
+/* add a new pointer list entry containing p to l; if check_dup is not 0 
+   the new entry is only added if p is not already contained in a list
+   entry;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ptrlist_add(struct ptrlist *l, void *p, int check_dup);
+
+#endif
Binary files nf-hipac/kernel/global.o and nfhipac/kernel/global.o differ
diff -uNr nf-hipac/kernel/.global.o.cmd nfhipac/kernel/.global.o.cmd
--- nf-hipac/kernel/.global.o.cmd	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/.global.o.cmd	2014-11-21 12:54:40.000000000 +0800
@@ -0,0 +1,587 @@
+cmd_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.o := gcc -Wp,-MD,/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.global.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include -Iinclude  -I/usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include -include include/linux/autoconf.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -Wframe-larger-than=2048 -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-dwarf2-cfi-asm -fconserve-stack -D SINGLE_PATH  -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(global)"  -D"KBUILD_MODNAME=KBUILD_STR(nf_hipac)"  -c -o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.tmp_global.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.c
+
+deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.o := +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.c +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/mode.h +    $(wildcard include/config/uml/net.h) +    $(wildcard include/config/host/2g/2g.h) +    $(wildcard include/config/nest/level.h) +    $(wildcard include/config/kernel/half/gigs.h) +  include/linux/stddef.h +  include/linux/compiler.h +    $(wildcard include/config/trace/branch/profiling.h) +    $(wildcard include/config/profile/all/branches.h) +    $(wildcard include/config/enable/must/check.h) +    $(wildcard include/config/enable/warn/deprecated.h) +  include/linux/compiler-gcc.h +    $(wildcard include/config/arch/supports/optimized/inlining.h) +    $(wildcard include/config/optimize/inlining.h) +  include/linux/compiler-gcc4.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page.h +    $(wildcard include/config/x86/64.h) +  include/linux/types.h +    $(wildcard include/config/uid16.h) +    $(wildcard include/config/lbdaf.h) +    $(wildcard include/config/phys/addr/t/64bit.h) +    $(wildcard include/config/64bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/types.h +    $(wildcard include/config/highmem64g.h) +  include/asm-generic/types.h +  include/asm-generic/int-ll64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitsperlong.h +  include/asm-generic/bitsperlong.h +  include/linux/posix_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types.h +    $(wildcard include/config/x86/32.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_types.h +  include/linux/const.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64_types.h +    $(wildcard include/config/physical/start.h) +    $(wildcard include/config/physical/align.h) +    $(wildcard include/config/flatmem.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64.h +  include/asm-generic/memory_model.h +    $(wildcard include/config/discontigmem.h) +    $(wildcard include/config/sparsemem/vmemmap.h) +    $(wildcard include/config/sparsemem.h) +  include/asm-generic/getorder.h +  include/linux/slab.h +    $(wildcard include/config/slab/debug.h) +    $(wildcard include/config/debug/objects.h) +    $(wildcard include/config/kmemcheck.h) +    $(wildcard include/config/slub.h) +    $(wildcard include/config/slob.h) +    $(wildcard include/config/numa.h) +    $(wildcard include/config/debug/slab.h) +  include/linux/gfp.h +    $(wildcard include/config/highmem.h) +    $(wildcard include/config/zone/dma.h) +    $(wildcard include/config/zone/dma32.h) +    $(wildcard include/config/debug/vm.h) +  include/linux/mmzone.h +    $(wildcard include/config/force/max/zoneorder.h) +    $(wildcard include/config/smp.h) +    $(wildcard include/config/memory/hotplug.h) +    $(wildcard include/config/arch/populates/node/map.h) +    $(wildcard include/config/flat/node/mem/map.h) +    $(wildcard include/config/cgroup/mem/res/ctlr.h) +    $(wildcard include/config/have/memory/present.h) +    $(wildcard include/config/need/node/memmap/size.h) +    $(wildcard include/config/need/multiple/nodes.h) +    $(wildcard include/config/have/arch/early/pfn/to/nid.h) +    $(wildcard include/config/sparsemem/extreme.h) +    $(wildcard include/config/nodes/span/other/nodes.h) +    $(wildcard include/config/holes/in/zone.h) +    $(wildcard include/config/arch/has/holes/memorymodel.h) +  include/linux/spinlock.h +    $(wildcard include/config/debug/spinlock.h) +    $(wildcard include/config/generic/lockbreak.h) +    $(wildcard include/config/preempt.h) +    $(wildcard include/config/debug/lock/alloc.h) +  include/linux/typecheck.h +  include/linux/preempt.h +    $(wildcard include/config/debug/preempt.h) +    $(wildcard include/config/preempt/tracer.h) +    $(wildcard include/config/preempt/notifiers.h) +  include/linux/thread_info.h +    $(wildcard include/config/compat.h) +  include/linux/bitops.h +    $(wildcard include/config/generic/find/first/bit.h) +    $(wildcard include/config/generic/find/last/bit.h) +    $(wildcard include/config/generic/find/next/bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitops.h +    $(wildcard include/config/x86/cmov.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/alternative.h +    $(wildcard include/config/paravirt.h) +  include/linux/stringify.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/asm.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpufeature.h +    $(wildcard include/config/x86/invlpg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/required-features.h +    $(wildcard include/config/x86/minimum/cpu/family.h) +    $(wildcard include/config/math/emulation.h) +    $(wildcard include/config/x86/pae.h) +    $(wildcard include/config/x86/cmpxchg64.h) +    $(wildcard include/config/x86/use/3dnow.h) +    $(wildcard include/config/x86/p6/nop.h) +  include/asm-generic/bitops/sched.h +  include/asm-generic/bitops/hweight.h +  include/asm-generic/bitops/fls64.h +  include/asm-generic/bitops/ext2-non-atomic.h +  include/asm-generic/bitops/le.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/byteorder.h +  include/linux/byteorder/little_endian.h +  include/linux/swab.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swab.h +    $(wildcard include/config/x86/bswap.h) +  include/linux/byteorder/generic.h +  include/asm-generic/bitops/minix.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/thread_info.h +    $(wildcard include/config/debug/stack/usage.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor.h +    $(wildcard include/config/x86/vsmp.h) +    $(wildcard include/config/cc/stackprotector.h) +    $(wildcard include/config/m386.h) +    $(wildcard include/config/m486.h) +    $(wildcard include/config/x86/debugctlmsr.h) +    $(wildcard include/config/cpu/sup/amd.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor-flags.h +    $(wildcard include/config/vm86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vm86.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace.h +    $(wildcard include/config/x86/ptrace/bts.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace-abi.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/segment.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cache.h +    $(wildcard include/config/x86/l1/cache/shift.h) +  include/linux/linkage.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/linkage.h +    $(wildcard include/config/x86/alignment/16.h) +  include/linux/init.h +    $(wildcard include/config/modules.h) +    $(wildcard include/config/hotplug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/math_emu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sigcontext.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/current.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/percpu.h +    $(wildcard include/config/x86/64/smp.h) +  include/linux/kernel.h +    $(wildcard include/config/preempt/voluntary.h) +    $(wildcard include/config/debug/spinlock/sleep.h) +    $(wildcard include/config/prove/locking.h) +    $(wildcard include/config/printk.h) +    $(wildcard include/config/dynamic/debug.h) +    $(wildcard include/config/ring/buffer.h) +    $(wildcard include/config/tracing.h) +    $(wildcard include/config/ftrace/mcount/record.h) +  /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h +  include/linux/log2.h +    $(wildcard include/config/arch/has/ilog2/u32.h) +    $(wildcard include/config/arch/has/ilog2/u64.h) +  include/linux/ratelimit.h +  include/linux/param.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/param.h +  include/asm-generic/param.h +    $(wildcard include/config/hz.h) +  include/linux/dynamic_debug.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bug.h +    $(wildcard include/config/bug.h) +    $(wildcard include/config/debug/bugverbose.h) +  include/asm-generic/bug.h +    $(wildcard include/config/generic/bug.h) +    $(wildcard include/config/generic/bug/relative/pointers.h) +  include/asm-generic/percpu.h +    $(wildcard include/config/have/setup/per/cpu/area.h) +  include/linux/threads.h +    $(wildcard include/config/nr/cpus.h) +    $(wildcard include/config/base/small.h) +  include/linux/percpu-defs.h +    $(wildcard include/config/debug/force/weak/per/cpu.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/system.h +    $(wildcard include/config/ia32/emulation.h) +    $(wildcard include/config/x86/32/lazy/gs.h) +    $(wildcard include/config/x86/ppro/fence.h) +    $(wildcard include/config/x86/oostore.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/nops.h +    $(wildcard include/config/mk7.h) +  include/linux/irqflags.h +    $(wildcard include/config/trace/irqflags.h) +    $(wildcard include/config/irqsoff/tracer.h) +    $(wildcard include/config/trace/irqflags/support.h) +    $(wildcard include/config/x86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irqflags.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt.h +    $(wildcard include/config/highpte.h) +    $(wildcard include/config/paravirt/spinlocks.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_types.h +    $(wildcard include/config/compat/vdso.h) +    $(wildcard include/config/proc/fs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt_types.h +    $(wildcard include/config/x86/local/apic.h) +    $(wildcard include/config/paravirt/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/desc_defs.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/kmap_types.h +    $(wildcard include/config/debug/highmem.h) +  include/asm-generic/kmap_types.h +  include/linux/cpumask.h +    $(wildcard include/config/cpumask/offstack.h) +    $(wildcard include/config/hotplug/cpu.h) +    $(wildcard include/config/debug/per/cpu/maps.h) +    $(wildcard include/config/disable/obsolete/cpumask/functions.h) +  include/linux/bitmap.h +  include/linux/string.h +    $(wildcard include/config/binary/printf.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr-index.h +  include/linux/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ioctl.h +  include/asm-generic/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/errno.h +  include/asm-generic/errno.h +  include/asm-generic/errno-base.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpumask.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ds.h +    $(wildcard include/config/x86/ds.h) +  include/linux/err.h +  include/linux/personality.h +  include/linux/cache.h +    $(wildcard include/config/arch/has/cache/line/size.h) +  include/linux/math64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/div64.h +  include/asm-generic/div64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ftrace.h +    $(wildcard include/config/function/tracer.h) +    $(wildcard include/config/dynamic/ftrace.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic_64.h +  include/asm-generic/atomic-long.h +  include/linux/list.h +    $(wildcard include/config/debug/list.h) +  include/linux/poison.h +    $(wildcard include/config/illegal/pointer/value.h) +  include/linux/prefetch.h +  include/linux/bottom_half.h +  include/linux/spinlock_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock_types.h +  include/linux/lockdep.h +    $(wildcard include/config/lockdep.h) +    $(wildcard include/config/lock/stat.h) +    $(wildcard include/config/generic/hardirqs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwlock.h +  include/linux/spinlock_api_smp.h +  include/linux/wait.h +  include/linux/numa.h +    $(wildcard include/config/nodes/shift.h) +  include/linux/seqlock.h +  include/linux/nodemask.h +  include/linux/pageblock-flags.h +    $(wildcard include/config/hugetlb/page.h) +    $(wildcard include/config/hugetlb/page/size/variable.h) +  include/linux/bounds.h +  include/linux/memory_hotplug.h +    $(wildcard include/config/have/arch/nodedata/extension.h) +    $(wildcard include/config/memory/hotremove.h) +  include/linux/notifier.h +  include/linux/errno.h +  include/linux/mutex.h +    $(wildcard include/config/debug/mutexes.h) +  include/linux/rwsem.h +    $(wildcard include/config/rwsem/generic/spinlock.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwsem.h +  include/linux/srcu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone_64.h +    $(wildcard include/config/numa/emu.h) +  include/linux/mmdebug.h +    $(wildcard include/config/debug/virtual.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/smp.h +    $(wildcard include/config/x86/io/apic.h) +    $(wildcard include/config/x86/32/smp.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec.h +    $(wildcard include/config/x86/numaq.h) +    $(wildcard include/config/mca.h) +    $(wildcard include/config/eisa.h) +    $(wildcard include/config/x86/mpparse.h) +    $(wildcard include/config/acpi.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec_def.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/x86_init.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bootparam.h +  include/linux/screen_info.h +  include/linux/apm_bios.h +  include/linux/edd.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/e820.h +    $(wildcard include/config/efi.h) +    $(wildcard include/config/hibernation.h) +    $(wildcard include/config/memtest.h) +  include/linux/ioport.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ist.h +  include/video/edid.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apic.h +    $(wildcard include/config/x86/x2apic.h) +  include/linux/delay.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/delay.h +  include/linux/pm.h +    $(wildcard include/config/pm/sleep.h) +    $(wildcard include/config/pm/runtime.h) +  include/linux/workqueue.h +  include/linux/timer.h +    $(wildcard include/config/timer/stats.h) +    $(wildcard include/config/debug/objects/timers.h) +  include/linux/ktime.h +    $(wildcard include/config/ktime/scalar.h) +  include/linux/time.h +    $(wildcard include/config/arch/uses/gettimeoffset.h) +  include/linux/jiffies.h +  include/linux/timex.h +    $(wildcard include/config/no/hz.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/timex.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/tsc.h +    $(wildcard include/config/x86/tsc.h) +  include/linux/debugobjects.h +    $(wildcard include/config/debug/objects/free.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apicdef.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fixmap.h +    $(wildcard include/config/provide/ohci1394/dma/init.h) +    $(wildcard include/config/x86/visws/apic.h) +    $(wildcard include/config/x86/f00f/bug.h) +    $(wildcard include/config/x86/cyclone/timer.h) +    $(wildcard include/config/pci/mmconfig.h) +    $(wildcard include/config/intel/txt.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/acpi.h +    $(wildcard include/config/acpi/numa.h) +  include/acpi/pdc_intel.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vsyscall.h +    $(wildcard include/config/generic/time.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_apic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irq_vectors.h +    $(wildcard include/config/sparse/irq.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sparsemem.h +  include/linux/topology.h +    $(wildcard include/config/sched/smt.h) +    $(wildcard include/config/sched/mc.h) +  include/linux/smp.h +    $(wildcard include/config/use/generic/smp/helpers.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/topology.h +    $(wildcard include/config/x86/ht.h) +    $(wildcard include/config/x86/64/acpi/numa.h) +  include/asm-generic/topology.h +  include/linux/slub_def.h +    $(wildcard include/config/slub/stats.h) +    $(wildcard include/config/slub/debug.h) +    $(wildcard include/config/kmemtrace.h) +  include/linux/kobject.h +  include/linux/sysfs.h +    $(wildcard include/config/sysfs.h) +  include/linux/kref.h +  include/linux/kmemtrace.h +  include/trace/events/kmem.h +  include/linux/tracepoint.h +    $(wildcard include/config/tracepoints.h) +  include/linux/rcupdate.h +    $(wildcard include/config/tree/preempt/rcu.h) +    $(wildcard include/config/tree/rcu.h) +  include/linux/completion.h +  include/linux/rcutree.h +  include/trace/define_trace.h +    $(wildcard include/config/event/tracing.h) +  include/linux/kmemleak.h +    $(wildcard include/config/debug/kmemleak.h) +  include/linux/netfilter.h +    $(wildcard include/config/netfilter.h) +    $(wildcard include/config/sysctl.h) +    $(wildcard include/config/netfilter/debug.h) +    $(wildcard include/config/nf/nat/needed.h) +    $(wildcard include/config/nf/conntrack.h) +  include/linux/skbuff.h +    $(wildcard include/config/bridge/netfilter.h) +    $(wildcard include/config/has/dma.h) +    $(wildcard include/config/xfrm.h) +    $(wildcard include/config/net/sched.h) +    $(wildcard include/config/net/cls/act.h) +    $(wildcard include/config/ipv6/ndisc/nodetype.h) +    $(wildcard include/config/net/dma.h) +    $(wildcard include/config/network/secmark.h) +  include/linux/kmemcheck.h +  include/linux/mm_types.h +    $(wildcard include/config/split/ptlock/cpus.h) +    $(wildcard include/config/want/page/debug/flags.h) +    $(wildcard include/config/mmu.h) +    $(wildcard include/config/aio.h) +    $(wildcard include/config/mm/owner.h) +    $(wildcard include/config/mmu/notifier.h) +  include/linux/auxvec.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/auxvec.h +  include/linux/prio_tree.h +  include/linux/rbtree.h +  include/linux/page-debug-flags.h +    $(wildcard include/config/page/poisoning.h) +    $(wildcard include/config/page/debug/something/else.h) +  include/linux/net.h +  include/linux/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/socket.h +  include/asm-generic/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sockios.h +  include/asm-generic/sockios.h +  include/linux/sockios.h +  include/linux/uio.h +  include/linux/random.h +  include/linux/irqnr.h +  include/linux/fcntl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fcntl.h +  include/asm-generic/fcntl.h +  include/linux/sysctl.h +  include/linux/textsearch.h +  include/linux/module.h +    $(wildcard include/config/modversions.h) +    $(wildcard include/config/unused/symbols.h) +    $(wildcard include/config/kallsyms.h) +    $(wildcard include/config/module/unload.h) +    $(wildcard include/config/constructors.h) +  include/linux/stat.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/stat.h +  include/linux/kmod.h +  include/linux/elf.h +  include/linux/elf-em.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/elf.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vdso.h +  include/linux/moduleparam.h +    $(wildcard include/config/alpha.h) +    $(wildcard include/config/ia64.h) +    $(wildcard include/config/ppc64.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/local.h +  include/linux/percpu.h +    $(wildcard include/config/have/legacy/per/cpu/area.h) +    $(wildcard include/config/need/per/cpu/embed/first/chunk.h) +    $(wildcard include/config/need/per/cpu/page/first/chunk.h) +  include/linux/pfn.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/module.h +    $(wildcard include/config/m586.h) +    $(wildcard include/config/m586tsc.h) +    $(wildcard include/config/m586mmx.h) +    $(wildcard include/config/mcore2.h) +    $(wildcard include/config/matom.h) +    $(wildcard include/config/m686.h) +    $(wildcard include/config/mpentiumii.h) +    $(wildcard include/config/mpentiumiii.h) +    $(wildcard include/config/mpentiumm.h) +    $(wildcard include/config/mpentium4.h) +    $(wildcard include/config/mk6.h) +    $(wildcard include/config/mk8.h) +    $(wildcard include/config/x86/elan.h) +    $(wildcard include/config/mcrusoe.h) +    $(wildcard include/config/mefficeon.h) +    $(wildcard include/config/mwinchipc6.h) +    $(wildcard include/config/mwinchip3d.h) +    $(wildcard include/config/mcyrixiii.h) +    $(wildcard include/config/mviac3/2.h) +    $(wildcard include/config/mviac7.h) +    $(wildcard include/config/mgeodegx1.h) +    $(wildcard include/config/mgeode/lx.h) +    $(wildcard include/config/4kstacks.h) +  include/asm-generic/module.h +  include/trace/events/module.h +  include/net/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess.h +    $(wildcard include/config/x86/wp/works/ok.h) +    $(wildcard include/config/x86/intel/usercopy.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum_64.h +  include/linux/dmaengine.h +    $(wildcard include/config/dma/engine.h) +    $(wildcard include/config/async/tx/dma.h) +    $(wildcard include/config/async/tx/disable/channel/switch.h) +  include/linux/device.h +    $(wildcard include/config/debug/devres.h) +    $(wildcard include/config/devtmpfs.h) +  include/linux/klist.h +  include/linux/semaphore.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/device.h +    $(wildcard include/config/dmar.h) +  include/linux/pm_wakeup.h +    $(wildcard include/config/pm.h) +  include/linux/dma-mapping.h +    $(wildcard include/config/have/dma/attrs.h) +  include/linux/dma-attrs.h +  include/linux/bug.h +  include/linux/scatterlist.h +    $(wildcard include/config/debug/sg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/scatterlist.h +  include/asm-generic/scatterlist.h +  include/linux/mm.h +    $(wildcard include/config/stack/growsup.h) +    $(wildcard include/config/swap.h) +    $(wildcard include/config/debug/pagealloc.h) +  include/linux/debug_locks.h +    $(wildcard include/config/debug/locking/api/selftests.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  include/asm-generic/pgtable.h +  include/linux/page-flags.h +    $(wildcard include/config/pageflags/extended.h) +    $(wildcard include/config/have/mlocked/page/bit.h) +    $(wildcard include/config/arch/uses/pg/uncached.h) +    $(wildcard include/config/memory/failure.h) +    $(wildcard include/config/s390.h) +  include/linux/vmstat.h +    $(wildcard include/config/vm/event/counters.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_64.h +  include/linux/vmalloc.h +  include/asm-generic/iomap.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/dma-mapping.h +    $(wildcard include/config/isa.h) +  include/linux/dma-debug.h +    $(wildcard include/config/dma/api/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swiotlb.h +    $(wildcard include/config/swiotlb.h) +  include/linux/swiotlb.h +  include/asm-generic/dma-coherent.h +    $(wildcard include/config/have/generic/dma/coherent.h) +  include/asm-generic/dma-mapping-common.h +  include/linux/hrtimer.h +    $(wildcard include/config/high/res/timers.h) +  include/linux/if.h +  include/linux/hdlc/ioctl.h +  include/linux/in.h +  include/linux/in6.h +  include/net/flow.h +  include/linux/proc_fs.h +    $(wildcard include/config/proc/devicetree.h) +    $(wildcard include/config/proc/kcore.h) +  include/linux/fs.h +    $(wildcard include/config/dnotify.h) +    $(wildcard include/config/quota.h) +    $(wildcard include/config/fsnotify.h) +    $(wildcard include/config/inotify.h) +    $(wildcard include/config/security.h) +    $(wildcard include/config/fs/posix/acl.h) +    $(wildcard include/config/epoll.h) +    $(wildcard include/config/debug/writecount.h) +    $(wildcard include/config/file/locking.h) +    $(wildcard include/config/auditsyscall.h) +    $(wildcard include/config/block.h) +    $(wildcard include/config/fs/xip.h) +    $(wildcard include/config/migration.h) +  include/linux/limits.h +  include/linux/kdev_t.h +  include/linux/dcache.h +  include/linux/rculist.h +  include/linux/path.h +  include/linux/radix-tree.h +  include/linux/pid.h +  include/linux/capability.h +    $(wildcard include/config/security/file/capabilities.h) +  include/linux/fiemap.h +  include/linux/quota.h +  include/linux/dqblk_xfs.h +  include/linux/dqblk_v1.h +  include/linux/dqblk_v2.h +  include/linux/dqblk_qtree.h +  include/linux/nfs_fs_i.h +  include/linux/nfs.h +  include/linux/sunrpc/msg_prot.h +  include/linux/inet.h +  include/linux/magic.h +  include/linux/version.h +  include/linux/kmalloc_sizes.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.h +
+/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.o: $(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.o)
+
+$(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.o):
diff -uNr nf-hipac/kernel/hipac.c nfhipac/kernel/hipac.c
--- nf-hipac/kernel/hipac.c	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/hipac.c	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,3750 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#include "hipac.h"
+#include "global.h"
+#include "ihash.h"
+#include "dimtree.h"
+
+
+static struct hipac_chain *current_chain = NULL;
+static struct ihash* chain_hash = NULL;
+static struct ptrblock* native_dts = NULL;
+
+__u8 *dim2btype;
+__u8 d2blen;
+hipac_extract_t *extract_fn;
+static hipac_copy_constructor_t copy_fn;
+static hipac_destroy_exec_t destroy_fn;
+hipac_match_exec_t match_fn;
+hipac_target_exec_t target_fn;
+static hipac_eq_exec_t eq_fn;
+
+
+
+/* 
+ * Some helpful defines in order to make code more readable
+ */
+
+#define DONT_COMMIT    0
+#define COMMIT         1
+#define DONT_INC       0
+#define INC            1
+#define DONT_ADD       0
+#define ADD            1
+#define ORIGIN_ALL     0xffff
+
+#define CHAIN_IS_REFERENCED(chain) ((chain)->ref_count != 0)
+#define CHAIN_NOT_CONNECTED(chain) ((chain)->start == NULL)
+#define IS_ROOT_CHAIN(chain)       ((chain)->dimtree != NULL)
+#define IS_NOT_JUMP_RULE(rule)     ((rule)->r.action != TARGET_CHAIN)
+#define IS_JUMP_RULE(rule)         ((rule)->r.action == TARGET_CHAIN)
+
+#define P_ELEM(x, i)         (STRBLOCK_ITH(x, i, struct path_ *))
+#define P_ELEM_DIMTREE(x, i) (STRBLOCK_ITH(x, i, struct path_ *)->dimtree)
+#define P_ELEM_PREV(x, i)    (STRBLOCK_ITH(x, i, struct path_ *)->prev)
+#define P_ELEM_RULE(x, i)    (STRBLOCK_ITH(x, i, struct path_ *)->rule)
+
+
+#define CHAIN_HASH_LEN         16
+#define CHAIN_HASH_AVR_BUCKET   3
+#define HIPAC_REC_LIMIT        10
+
+
+#ifdef DEBUG
+#       define LOW_MEM(args...) do { NOTICE(args); return HE_LOW_MEMORY; +                                   } while (0)
+#       define CHECK_ERROR(func) +                if (error == HE_LOW_MEMORY) { +	                NOTICE(func " returned LOW_MEMORY error!"); +        } else if (error == HE_IMPOSSIBLE_CONDITION) {  +	        ERR(func " returned IMPOSSIBLE_CONDITION error!"); +	}
+
+        static inline hipac_error
+	strblock_append_check(struct strblock **b, const void *s, __u32 size){
+		__u32 i;
+		if (*b)
+			for (i = 0; i < (*b)->len; i++){
+				if (!(memcmp(STRBLOCK_ITH(*b, i, void *), 
+					     s, size)))
+					IMPOSSIBLE_CONDITION(
+						"already in strblock");
+			}
+		return strblock_append(b, s, size);
+	}
+
+#else
+#       define LOW_MEM(args...) return HE_LOW_MEMORY
+#       define CHECK_ERROR(func) +                if (error == HE_IMPOSSIBLE_CONDITION) {  +                        ERR(func " returned IMPOSSIBLE_CONDITION error!"); +                }
+
+        static inline hipac_error
+	strblock_append_check(struct strblock **b, const void *s, __u32 size){
+		return strblock_append(b, s, size);
+	}
+#endif
+
+
+
+
+/* element in strblock next_chain in struct hipac_chain
+   means that current chain contains ‘count‘ >= 1 rules 
+   that jump to chain ‘chain‘                                         */
+struct next_chain_elem
+{
+	__u32 count;
+	struct hipac_chain *chain;
+};
+
+
+/* the combined rule of all the chain_rules on the path
+   from a ROOT_CHAIN to the current chain                             */
+struct prefix_rule
+{
+	__u32 origin;
+	struct ptrblock *exec_matches;
+	__u8  native_mct;
+	struct hipac_match first_match[0];
+};
+
+
+/* the path from a ROOT_CHAIN to the current chain;
+   dimtree:   the dimtree corresponding to the ROOT of that path
+   prev:      the previous chain_rule on that path
+   rule:      the combined rule of all the chain_rules on that path   */
+struct path_
+{
+	struct dimtree *dimtree;
+	struct chain_rule *prev;
+	struct prefix_rule *rule;
+};
+
+
+/* hipac_chain is the ‘head‘ of the doubly linked list of chain_rules;
+   name:           the name of the chain
+   ref_count:      the number of rules that jump to this chain
+   next_chains:    block of next_chain_elem structs; each chain that is
+                   jumped to from a rule in this chain has its own 
+		   next_chain_elem in this block with its ‘count‘ field set to
+		   the number of rules that jump to that chain
+   paths:          block of all the paths from any ROOT_CHAIN to this chain
+   start:          contains pointers to dt_rules that mark the beginning
+                   of this chain in the internal dt_chain
+   end:            the same for the ending of the chain
+   dimtree:        points to a dimtree if chain is a ROOT_CHAIN,
+                   otherwise it‘s NULL                                */
+struct hipac_chain
+{
+	struct list_head head;
+	char name[HIPAC_CHAIN_NAME_MAX_LEN];
+	__u32 list_pos;
+	__u32 ref_count;
+	struct strblock *next_chains; 
+	struct strblock *paths;
+	struct ptrblock *start;
+	struct ptrblock *end;   
+	struct dimtree *dimtree;
+};
+
+/* chain_rule is contained in a cyclic doubly linked list of rules where the
+   ‘head‘ of the list is of type struct hipac_chain;
+   dtr:  contains pointers to dt_rules in the internal dt_chain that correspond
+         to this chain_rule                                           */
+struct chain_rule
+{
+	struct list_head head;
+	struct ptrblock *dtr;
+	struct hipac_rule r;
+};
+
+
+
+
+
+/* 
+ * Several functions to free certain structs.
+ * The functions recursively free all other data structures that
+ * are pointed to from within the structs.  
+ */
+
+static inline void
+dt_rule_free(struct dt_rule *rule)
+{
+	if (rule->exec_match)
+		ptrblock_free(rule->exec_match);
+	hp_free(rule);
+}
+
+static inline void
+hipac_rule_free(struct hipac_rule *rule)
+{
+	destroy_fn(rule);
+	hp_free(rule);
+}
+
+static inline void
+chain_rule_free(struct chain_rule *rule)
+{
+	if (rule->dtr)
+		ptrblock_free(rule->dtr);
+	hp_free(rule);
+}
+
+static inline void
+chain_rule_destroy(struct chain_rule *rule)
+{
+	if (rule->dtr)
+		ptrblock_free(rule->dtr);
+	destroy_fn(&rule->r);
+	hp_free(rule);
+}
+
+static inline void
+prefix_rule_free(struct prefix_rule *p)
+{
+	if (p->exec_matches)
+		ptrblock_free(p->exec_matches);
+	hp_free(p);
+}
+
+static inline void
+path_free(struct path_ *p)
+{
+	if (p->rule)
+		prefix_rule_free(p->rule);
+	hp_free(p);
+}
+
+static inline void
+paths_free(struct strblock *paths)
+{
+	__u32 i;
+	for (i = 0; i < paths->len; i++)
+		prefix_rule_free(P_ELEM_RULE(paths, i));
+	strblock_free(paths);
+}
+
+/* End of free functions */
+
+
+
+
+
+
+
+
+/*
+ * chain_hash_* functions
+ */
+
+
+/* insert ‘chain‘ into the global hash of all chains (‘chain_hash‘) 
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+static inline hipac_error
+chain_hash_insert(struct hipac_chain* chain)
+{
+	return ihash_insert(&chain_hash, chain->name, chain);//IS_THIS_CORRECT?
+}
+
+
+
+/* remove ‘chain‘ from the global hash of all chains (‘chain_hash‘)
+   the removed chain is not freed                                     */
+static inline void
+chain_hash_remove(struct hipac_chain* chain)
+{
+	if (current_chain && current_chain == chain)
+		current_chain = NULL;
+	ihash_delete(chain_hash, chain->name, NULL);
+}
+
+
+
+/* replace ‘org‘ with ‘new‘ in global hash of all chains
+   the replaced chain is not freed                                    */
+static inline hipac_error
+chain_hash_replace(struct hipac_chain *org, struct hipac_chain *new)
+{
+	if (current_chain && current_chain == org)
+		current_chain = NULL;
+	return ihash_replace(&chain_hash, org->name, NULL, new->name, new);
+}
+
+
+
+/* lookup ‘chain‘ with name ‘name‘ in global ‘chain_hash‘,
+   the hash of all chains. 
+   possible errors: HE_CHAIN_NOT_EXISTENT, HE_IMPOSSIBLE_CONDITION    */
+static inline hipac_error
+chain_hash_lookup(const char* name, struct hipac_chain **chain)
+{
+	if (unlikely(!name || !chain))
+		ARG_ERR;
+	if ((current_chain) &&
+	    (!strcmp(name, current_chain->name))){
+		*chain = current_chain;
+		return HE_OK;
+	}
+	*chain = (struct hipac_chain*) ihash_lookup(chain_hash, name);
+	if (*chain != NULL) {
+		current_chain = *chain;
+		return HE_OK;
+	}
+	return HE_CHAIN_NOT_EXISTENT;
+}
+
+
+/* End of chain_hash_* functions */
+
+
+
+
+
+/* get previous dt_rules of the internal dt_rule representations of
+   chain_rule ‘rule‘.
+   if previous chain_rule ‘prev‘ is not a jump rule return pointer to 
+   ‘prev->dtr‘ and set ‘free_needed‘ to 0. otherwise a new ptrblock
+   with pointers to the previous dt_rules has to be computed from the
+   ‘chain->end‘ block of the chain ‘prev‘ is pointing to and 
+   ‘free_needed‘ is set to 1.
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+static inline hipac_error
+get_prev_dt_rules(const struct hipac_chain *chain, 
+		  const struct chain_rule *rule, 
+		  __u8 *free_needed, struct ptrblock **p)
+{			     
+	struct chain_rule *prev;
+	
+	if (unlikely(CHAIN_NOT_CONNECTED(chain)))
+		return HE_IMPOSSIBLE_CONDITION;
+	
+	if (unlikely(rule->head.prev == &chain->head)){
+		*p = chain->start;
+		*free_needed = 0;
+		return HE_OK;
+	}
+	
+	prev = list_entry(rule->head.prev, struct chain_rule, head);
+	*free_needed = IS_JUMP_RULE(prev);
+	if (!(*free_needed)){
+		*p = prev->dtr;
+	} else {
+		struct hipac_chain *c = NULL;
+		hipac_error error;
+		__u32 i;
+		chain_hash_lookup((void *) &prev->r 
+				  + prev->r.target_offset, &c);
+		*p = NULL;
+		for (i = 0; i < c->paths->len; i++){
+			if (prev == P_ELEM_PREV(c->paths, i)){
+				if ((error = 
+				     ptrblock_append(p, c->end->p[i]))){
+					CHECK_ERROR("ptrblock_append");
+					if (*p)
+						ptrblock_free(*p);
+					*p = NULL;
+					return error;
+				}
+			}
+		}
+	}
+	return HE_OK;
+}
+
+
+
+/* get next dt_rules of the internal dt_rule representations of 
+   chain_rule ‘rule‘.
+   if next chain_rule ‘next‘ is not a jump rule return pointer to
+   ‘next->dtr‘ and set ‘free_needed‘ to 0. otherwise a new ptrblock
+   with pointers to the next dt_rules has to be computed from the
+   ‘chain->start‘ block of the chain ‘next‘ is pointing to and 
+   ‘free_needed‘ is set to 1. 
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+static inline hipac_error
+get_next_dt_rules(const struct hipac_chain *chain, 
+		  const struct chain_rule *rule, 
+		  __u8 *free_needed, struct ptrblock **p)
+{			     
+	struct chain_rule *next;
+	
+	if (unlikely(CHAIN_NOT_CONNECTED(chain)))
+		return HE_IMPOSSIBLE_CONDITION;
+	
+	if (unlikely(rule->head.next == &chain->head)){
+		*p = chain->end;
+		*free_needed = 0;
+		return HE_OK;
+	}
+	
+	next = list_entry(rule->head.next, struct chain_rule, head);
+	*free_needed = IS_JUMP_RULE(next);
+	if (!(*free_needed)){
+		*p = next->dtr;
+	} else {
+		struct hipac_chain *c = NULL;
+		hipac_error error;
+		__u32 i;
+		chain_hash_lookup((void *) &next->r + 
+				  next->r.target_offset, &c);
+		*p = NULL;
+		for (i = 0; i < c->paths->len; i++){
+			if (next == P_ELEM_PREV(c->paths, i)){
+				if ((error = 
+				     ptrblock_append(p, c->start->p[i]))){
+					CHECK_ERROR("ptrblock_append");
+					if (*p)
+						ptrblock_free(*p);
+					*p = NULL;
+					return error;
+				}
+			}
+		}
+	}
+	return HE_OK;
+}
+
+
+
+
+
+/*
+ * chain_* functions
+ */
+
+
+/* create new hipac_chain with name ‘name‘ and initialize all fields 
+   in struct hipac_chain ‘result‘. ‘list_pos‘ is used to initialize
+   the list_pos member of ‘result‘
+   hipac_chain ‘result‘ is not inserted into ‘chain_hash‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_EXISTS,
+                    HE_IMPOSSIBLE_CONDITION                           */
+static inline hipac_error
+chain_new(const char *name, struct hipac_chain **result, __u32 list_pos)
+{	
+	struct hipac_chain *chain;
+	hipac_error error;
+
+	if (unlikely(!name || !result))
+		ARG_ERR;
+	
+	if (unlikely(!(error = chain_hash_lookup(name, &chain))))
+		return HE_CHAIN_EXISTS;
+		
+	*result = chain = hp_alloc(sizeof(*chain), ADD);
+	if (!chain)
+		LOW_MEM("chain alloc failed!");
+	INIT_LIST_HEAD(&chain->head);
+	strncpy(chain->name, name, HIPAC_CHAIN_NAME_MAX_LEN);
+	chain->name[HIPAC_CHAIN_NAME_MAX_LEN - 1] = ‘\0‘;
+	chain->list_pos = list_pos;
+	chain->ref_count = 0;
+	chain->next_chains = NULL;
+	chain->paths = NULL;
+	chain->start = NULL;
+	chain->end = NULL;
+	chain->dimtree = NULL;
+	return HE_OK;
+}
+
+
+
+/* free hipac_chain ‘chain‘ and recursively all other data 
+   structures that are pointed to from within this struct.
+   also free all rules in this chain.
+   attention: make sure ‘chain‘ is NOT in the global 
+              ‘chain_hash‘ anymore!                                   */
+static inline void
+chain_free(struct hipac_chain* chain)
+{
+	struct list_head *lh;
+	struct chain_rule *rule;
+	
+	if (unlikely(!chain)){
+		ARG_MSG;
+		return;
+	}
+	
+	lh = chain->head.next;
+	while (lh != &chain->head) {
+		rule = list_entry(lh, struct chain_rule, head);
+		lh = lh->next;
+		list_del(lh->prev);
+		chain_rule_destroy(rule);
+	} 
+	if (chain->next_chains)
+		strblock_free(chain->next_chains);
+	if (chain->paths)
+		paths_free(chain->paths);
+	if (chain->start)
+		ptrblock_free(chain->start);
+	if (chain->end)
+		ptrblock_free(chain->end);
+       	hp_free(chain);
+}
+
+
+
+/* flush hipac_chain ‘chain‘
+   free all rules in this chain and all other data structures
+   that are pointed to from within this struct.                       */
+static inline void
+chain_flush(struct hipac_chain* chain)
+{
+	struct list_head *lh;
+	struct chain_rule *rule;
+	
+	if (unlikely(!chain)){
+		ARG_MSG;
+		return;
+	}
+	
+	lh = chain->head.next;
+	while (lh != &chain->head) {
+		rule = list_entry(lh, struct chain_rule, head);
+		lh = lh->next;
+		list_del(lh->prev);
+		chain_rule_destroy(rule);
+	}
+	if (chain->next_chains){
+		strblock_free(chain->next_chains);
+		chain->next_chains = NULL;
+	}
+	if (chain->paths){
+		paths_free(chain->paths);
+		chain->paths = NULL;
+	}
+	if (chain->start){
+		ptrblock_free(chain->start);
+		chain->start = NULL;
+	}
+	if (chain->end){
+		ptrblock_free(chain->end);
+		chain->end = NULL;
+	}
+	chain->ref_count = 0;
+	
+}
+
+
+
+/* insert chain_rule ‘rule‘ into ‘chain‘ at position rule->r.pos;
+   if chain is empty, rule->r.pos is set to 1;
+   if rule->r.pos is larger than maxpos, rule->r.pos is set to maxpos;
+   ‘do_inc‘: when not 0 the pos field of all rules with 
+             pos >= rule->r.pos is incremented by 1                   */
+static inline void
+chain_insert(struct hipac_chain* chain, struct chain_rule *rule,
+	     const __u8 do_inc)
+{
+	struct list_head *lh;
+	__u32 rulepos;
+	struct chain_rule *curule;
+	
+	if (unlikely(!chain || !rule)){
+		ARG_MSG;
+		return;
+	}
+
+	if (list_empty(&chain->head)) {
+		list_add(&rule->head, &chain->head);
+		rule->r.pos = 1;
+		return;
+	}
+
+	if (rule->r.pos == 0)
+		rule->r.pos = 1;
+
+	lh = chain->head.prev;
+	rulepos = rule->r.pos;
+	curule = list_entry(lh, struct chain_rule, head);
+	
+	if (rulepos > curule->r.pos) {
+		list_add_tail(&rule->head, &chain->head);
+		rule->r.pos = curule->r.pos + 1;
+		return;
+	}
+
+	if (do_inc) {
+		do {
+			curule->r.pos++;
+			lh = lh->prev;
+			curule = list_entry(lh, struct chain_rule, head);
+		} while (lh != &chain->head && curule->r.pos >= rulepos);
+	} else {
+		do {
+			lh = lh->prev;
+			curule = list_entry(lh, struct chain_rule, head);
+		} while (lh != &chain->head && curule->r.pos >= rulepos);
+	}
+
+	if (lh == &chain->head) {
+		assert(rulepos == 1);
+		assert(!do_inc || 
+		       list_entry(chain->head.next,
+				  struct chain_rule, head)->r.pos == 2);
+		assert(do_inc ||
+		       list_entry(chain->head.next,
+				  struct chain_rule, head)->r.pos == 1);
+		
+		list_add(&rule->head, &chain->head);
+	} else {
+		assert(curule->r.pos < rulepos);
+		assert(!do_inc ||
+		       list_entry(curule->head.next,
+				  struct chain_rule,
+				  head)->r.pos == rulepos + 1);
+		assert(do_inc ||
+		       list_entry(curule->head.next,
+				  struct chain_rule,
+				  head)->r.pos == rulepos);
+		
+		list_add(&rule->head, &curule->head);
+	}
+}
+
+
+
+/* delete and all rules in ‘chain‘ with position == ‘rulepos‘;
+   attention: you must NOT call chain_delete with an empty chain!
+              does not free the rules!                                */
+static void
+chain_delete(const struct hipac_chain* chain, const __u32 rulepos)
+{
+       	struct chain_rule *current_rule;
+	
+	if (unlikely(!chain)){
+		ARG_MSG;
+		return;
+	}
+	current_rule = list_entry(chain->head.prev, struct chain_rule, head);
+	
+	while (current_rule->r.pos > rulepos) {
+		current_rule->r.pos--;
+		current_rule = list_entry(current_rule->head.prev, 
+					  struct chain_rule, head);
+	}	
+       	list_del(¤t_rule->head);
+}
+
+
+
+/* find rule in hipac_chain ‘chain‘ that equals hipac_rule ‘rule‘.
+   possible errors: HE_RULE_NOT_EXISTENT, HE_IMPOSSIBLE_CONDITION     */
+static inline hipac_error
+chain_find_rule(const struct hipac_chain *chain, const struct hipac_rule *rule,
+		struct chain_rule **result)
+{
+	struct list_head *lh;
+	struct chain_rule *currule;
+
+	if (!chain || !rule || !result)
+		ARG_ERR;
+			
+	list_for_each(lh, &chain->head) {
+		currule = list_entry(lh, struct chain_rule, head);
+		if (eq_fn(rule, &currule->r)){
+			*result = currule;
+			return HE_OK;
+		}
+	}
+	return HE_RULE_NOT_EXISTENT;
+}
+
+
+
+/* find rule in hipac_chain ‘chain‘ with position ‘pos‘
+   possible errors: HE_RULE_NOT_EXISTENT, HE_IMPOSSIBLE_CONDITION     */
+static inline hipac_error
+chain_find_rule_with_pos(const struct hipac_chain *chain, const __u32 pos,
+			 struct chain_rule **result)
+{
+	struct list_head *lh;
+	struct chain_rule *currule;
+
+	if (!chain || !result)
+		ARG_ERR;
+			
+	list_for_each(lh, &chain->head) {
+		currule = list_entry(lh, struct chain_rule, head);
+		if (currule->r.pos == pos){
+			*result = currule;
+			return HE_OK;
+		}
+	}
+	return HE_RULE_NOT_EXISTENT;
+}
+
+
+/* End of chain_* functions */
+
+
+
+
+
+
+/* build chain_rule ‘result‘ from hipac_rule ‘rule‘.        
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+hipac_error
+build_chain_rule_from_hipac_rule(const struct hipac_rule *rule, 
+				 struct chain_rule **result)
+{
+	if (unlikely(!rule || !result))
+		ARG_ERR;
+
+	*result = hp_alloc(sizeof(**result) - sizeof(struct hipac_rule)
+	                   + rule->size, ADD);
+	if (!(*result))
+		LOW_MEM("chain_rule alloc failed!");
+	
+	(*result)->dtr = NULL;
+	copy_fn(rule, &(*result)->r);
+       	return HE_OK;
+}
+
+
+
+/* build hipac_rule ‘result‘ from dt_rule ‘dt_rule‘.
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+hipac_error
+build_hipac_rule_from_dt_rule(const struct dt_rule *dt_rule,
+			      struct hipac_rule **result)
+{
+	__u32 size, exec_match_size = 0;
+	__u32 i;
+
+	if (unlikely(!dt_rule || !result))
+		ARG_ERR;
+
+	size = sizeof(**result) 
+		+ dt_rule->dt_match_len * sizeof(struct hipac_match)
+		+ dt_rule->exec_target_size;
+	
+	if (dt_rule->exec_match){
+		for (i = 0; i < dt_rule->exec_match->len; i += 2){ 
+			exec_match_size += (void *) 
+				dt_rule->exec_match->p[i + 1]
+				- dt_rule->exec_match->p[i];
+		}
+	}
+	size += exec_match_size;
+
+	*result = hp_alloc(size, ADD);
+	if (!(*result))
+		LOW_MEM("hipac_rule alloc failed!");
+	
+	(*result)->pos = dt_rule->spec.pos;
+	(*result)->size = size;
+	(*result)->origin = 0;
+	(*result)->action = dt_rule->spec.action;
+	(*result)->native_mct = dt_rule->dt_match_len;
+	if (dt_rule->exec_match)
+		(*result)->match_offset = sizeof(**result)
+			+ dt_rule->dt_match_len * sizeof(struct hipac_match);
+	else (*result)->match_offset = 0;
+	(*result)->target_offset = sizeof(**result)
+		+ dt_rule->dt_match_len * sizeof(struct hipac_match)
+		+ exec_match_size;
+	
+	for (i = 0; i < dt_rule->dt_match_len; i++){
+		(*result)->first_match[i].dimid =
+			dt_rule->first_dt_match[i].dimid;
+		(*result)->first_match[i].invert = 0;
+		(*result)->first_match[i].left =
+			dt_rule->first_dt_match[i].left;
+		(*result)->first_match[i].right =
+			dt_rule->first_dt_match[i].right;
+	}
+	if (dt_rule->exec_match){
+		void *pos = (void *) (*result) + (*result)->match_offset;
+		for (i = 0; i < dt_rule->exec_match->len; i += 2){ 
+			size = dt_rule->exec_match->p[i + 1]
+				- dt_rule->exec_match->p[i];
+			memcpy(pos, dt_rule->exec_match->p[i], size);
+			pos += size;
+		}
+	}
+	if (dt_rule->exec_target_size){
+		memcpy((void *) (*result) + (*result)->target_offset, 
+		       dt_rule->exec_target, dt_rule->exec_target_size);
+	}
+	return HE_OK;
+}
+
+
+
+/* if hipac_rule ‘r‘ contains exec_matches, add a pointer to the beginning
+   and a pointer to the end of that exec_matches to the ptrblock ‘*p‘  
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+static inline hipac_error
+add_exec_matches(struct ptrblock **p, const struct hipac_rule *r)
+{
+       	hipac_error error;
+
+	if (unlikely(!p || !r))
+		ARG_ERR;
+
+	if (r->match_offset == 0)
+		return HE_OK;
+	
+	if ((error = ptrblock_append(p, (void *) r + r->match_offset))){
+		CHECK_ERROR("ptrblock_append");
+		return error;
+	}
+	if ((error = ptrblock_append(p, (void *) r + r->target_offset))){
+		CHECK_ERROR("ptrblock_append");
+		ptrblock_delete_tail(p);
+		return error;
+	}
+	return HE_OK;
+}
+
+
+
+/* build new dt_rule from prefix_rule and/or hipac_rule.
+   prefix_rule and/or hipac_rule can be NULL.
+   pos:      the position of the new dt_rule; is written to result->spec.pos
+   action:   the action of the new dt_rule;   is written to result->spec.action
+   the exec_matches from prefix and hipac_rule are merged into
+   result->exec_match.
+   if the hipac_rule contains a exec_target it is written to 
+   result->exec_target.
+   attention: does NOT copy the native matches, this must be done externally!
+              allocs space for prefix->native_mct + rule->native_mct matches!
+              when merging the native matches externally, remember to do a
+              ‘hipac_realloc‘ when prefix and rule contain the same dimids!
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+static inline hipac_error
+build_dt_rule(struct prefix_rule *prefix, const struct hipac_rule *rule, 
+	      const __u32 pos, const __u32 action, struct dt_rule **result)
+{
+	hipac_error error;
+	struct dt_rule *new_dt_rule;
+	__u8 mct = 0;
+
+	if (unlikely(!result))
+		ARG_ERR;
+	
+	if (prefix)
+		mct += prefix->native_mct;
+	if (rule) 
+		mct += rule->native_mct;
+	
+	new_dt_rule = hp_alloc(dt_rule_size(mct), ADD);
+	if (!new_dt_rule)
+		LOW_MEM("dt_rule alloc failed!");
+	new_dt_rule->spec.rlp = 0;
+	new_dt_rule->spec.rtype = RT_RULE;
+	new_dt_rule->spec.action = action;
+	new_dt_rule->spec.pos = pos;
+	new_dt_rule->exec_match = NULL;
+	new_dt_rule->exec_target = NULL;
+	new_dt_rule->exec_target_size = 0;
+	new_dt_rule->deleted = 0;
+	
+	if (prefix){
+		if ((error = ptrblock_clone(prefix->exec_matches, 
+					    &new_dt_rule->exec_match))){
+			dt_rule_free(new_dt_rule);
+			CHECK_ERROR("ptrblock_clone");
+			return error;
+		}
+	}
+	if (rule){
+		if ((error = add_exec_matches(&new_dt_rule->exec_match,
+						  rule))){
+			dt_rule_free(new_dt_rule);
+			CHECK_ERROR("add_exec_matches");
+			return error;
+		}
+	}
+	if (action == TARGET_EXEC){
+		new_dt_rule->exec_target = (void *) rule + rule->target_offset;
+		new_dt_rule->exec_target_size = ((void *) rule + rule->size)
+			- ((void *) rule + rule->target_offset);
+	}
+	new_dt_rule->dt_match_len = mct;
+	*result = new_dt_rule;
+	return HE_OK;
+}
+
+
+
+/* Remove last element from strblock ‘paths‘ and also free the data
+   structures that are pointed to from within this element            */
+static inline void
+paths_delete_tail(struct strblock **paths)
+{
+	struct prefix_rule *p = P_ELEM_RULE(*paths, (*paths)->len - 1);
+	if (p)
+		prefix_rule_free(p);
+	strblock_delete_tail(paths);
+}
+
+
+
+/* Remove element with position ‘pos‘ from strblock ‘paths‘ and also free
+   the data structures that are pointed to from within this element.  */
+static inline void
+paths_delete_pos(struct strblock **paths, __u32 pos)
+{
+	struct prefix_rule *p = P_ELEM_RULE(*paths, pos);
+	if (p)
+		prefix_rule_free(p);
+	strblock_delete_pos(paths, pos);
+}
+
+
+/* count number of negations/inverted matches in hipac_match array    */
+static inline __u8
+count_inv_matches(const struct hipac_match *first_match, const __u8 match_cnt)
+{
+	__u8 i, result = 0;
+	for (i = 0; i < match_cnt; i++)
+		if (first_match[i].invert)
+			result++;
+	return result;
+}	 
+
+
+
+/* count number of negations/inverted matches in both rules, but
+   without counting matches in the same dimid twice                   */
+static inline __u8
+count_inv_matches_2(const struct hipac_rule *hipac_rule, 
+		    const struct prefix_rule *prefix_rule)
+{
+	__u8 i, j, result = 0;
+
+	for (i = 0, j = 0; i < prefix_rule->native_mct; i++){
+			while ((j < hipac_rule->native_mct)
+			       && (hipac_rule->first_match[j].dimid 
+				   < prefix_rule->first_match[i].dimid)){
+				if (hipac_rule->first_match[j].invert)
+					result++;
+				j++;
+			}
+			if ((j < hipac_rule->native_mct)
+			    && (hipac_rule->first_match[j].dimid 
+				== prefix_rule->first_match[i].dimid)){
+				if (hipac_rule->first_match[j].invert)
+					result++;
+				j++;
+				continue;
+			}
+			if (prefix_rule->first_match[i].invert)
+				result++;
+	}
+	while (j < hipac_rule->native_mct){
+		if (hipac_rule->first_match[j].invert)
+			result++;	
+		j++;
+	}	
+	return result;
+}	 
+
+
+
+/* merge hipac_match ‘s‘ into dt_match ‘new‘ while keeping negation
+   in mind.                                                           */
+static inline void
+merge_dimension(struct hipac_match *s, struct dt_match *new,
+		__u32 inv, __u16 *inv_match, __u8 *not_valid)
+{
+	if (!(s->invert)){
+		new->dimid = s->dimid;
+		new->left = s->left;
+		new->right = s->right;
+		return;
+	}
+	if (inv & (1 << *inv_match)){
+		if (s->right < 
+		    MAXKEY(dim2btype[s->dimid])){
+			new->dimid = s->dimid;
+			new->left = s->right + 1;
+			new->right = MAXKEY(dim2btype[s->dimid]);
+			(*inv_match)++;
+		} else {
+			*not_valid = 1;
+		}
+	} else {
+		if (s->left){	
+			new->dimid = s->dimid;
+			new->left = 0;
+			new->right = s->left - 1;
+			(*inv_match)++;
+		} else {
+			*not_valid = 1;
+		}
+	}
+}
+
+
+
+/* insert new dt_rule(s) at position ‘pos‘ into dimtree ‘path->dimtree‘.
+   the new dt_rule is created from information found in ‘path->rule‘
+   and ‘rule‘. if ‘path->rule‘ or ‘rule‘ contain negation solve this by
+   adding several new dt_rules to the dimtree. append the (first) new 
+   dt_rule to the ‘rule->dtr‘ pointer block.
+   if commit is not 0 commit the changes.
+   in case of an error undo all changes.
+   attention: in case of an error already inserted rules are not removed
+              from the internal dimtree chain. those rules have to be
+	      removed externally.  
+   possible errors: HE_LOW_MEMORY, HE_RULE_ORIGIN_MISMATCH,
+                    HE_RULE_PREFIX_MISMATCH, HE_IMPOSSIBLE_CONDITION  */
+hipac_error
+insert_into_dt(const struct path_ *path,
+	       struct chain_rule *rule,
+	       const __u32 pos, const __u8 commit)
+{
+	struct dt_rule *new_dt_rule;
+	hipac_error error;
+       	__u32 i, j, inv;
+	__u8 first = 1;
+	__u8 num;
+	struct dt_match *new;
+	__u32 mct = 0;
+	
+	if (unlikely(!path || !path->rule || !rule))
+		ARG_ERR;
+
+	num = count_inv_matches_2(&rule->r, path->rule);
+	
+	mct = rule->r.native_mct + path->rule->native_mct;
+	
+	if (!(num)){
+		__u32 new_mct = 0;
+		struct hipac_match *p = path->rule->first_match;
+		struct hipac_match *r = rule->r.first_match;
+		
+
+		if ((error = build_dt_rule(path->rule, &rule->r, pos, 
+					   rule->r.action, &new_dt_rule))){
+			CHECK_ERROR("build_dt_rule");
+			return error;
+		}
+
+		new = new_dt_rule->first_dt_match;
+
+		for (i = 0, j = 0; i < path->rule->native_mct; i++){
+			while ((j < rule->r.native_mct)
+			       && (r[j].dimid < p[i].dimid)){
+				new[new_mct].dimid = r[j].dimid;
+				new[new_mct].left = r[j].left;
+				new[new_mct].right = r[j].right;
+				j++;
+				new_mct++;
+				
+			}
+			if ((j < rule->r.native_mct)
+			    && (r[j].dimid == p[i].dimid)){
+				if (p[i].invert){
+					if (!(r[j].right < p[i].left
+					      || r[j].left > p[i].right)){
+						dt_rule_free(new_dt_rule);
+						return HE_RULE_PREFIX_MISMATCH;
+					}
+				} else if (r[j].left < p[i].left
+					   || r[j].right > p[i].right){
+					dt_rule_free(new_dt_rule);
+					return HE_RULE_PREFIX_MISMATCH;
+				}
+				new[new_mct].dimid = r[j].dimid;
+				new[new_mct].left = r[j].left;
+				new[new_mct].right = r[j].right;
+				j++;
+				new_mct++;
+				continue;
+			}
+			new[new_mct].dimid = p[i].dimid;
+			new[new_mct].left = p[i].left;
+			new[new_mct].right = p[i].right;
+			new_mct++;
+		}
+		
+		while (j < rule->r.native_mct){
+			new[new_mct].dimid = r[j].dimid;
+			new[new_mct].left = r[j].left;
+			new[new_mct].right = r[j].right;
+			j++;
+			new_mct++;
+		}
+  	
+		if (new_mct < mct){
+			new_dt_rule->dt_match_len = new_mct;
+			new_dt_rule = hp_realloc(new_dt_rule, 
+						 dt_rule_size(new_mct));
+			if (!new_dt_rule){
+				dt_rule_free(new_dt_rule);
+				IMPOSSIBLE_CONDITION("new_dt_rule is NULL");
+			}
+		}
+		
+		if ((error = ptrblock_append(&rule->dtr,
+					     (void *) new_dt_rule))){
+			CHECK_ERROR("ptrblock_append");
+			dt_rule_free(new_dt_rule);
+			return error;
+		}
+		if ((error = dimtree_insert(path->dimtree, new_dt_rule,
+					    rule->r.origin, INC, commit))){
+			CHECK_ERROR("dimtree_insert");
+			return error;
+		}
+		return HE_OK;
+	} 
+	//else we have a rule containing negation
+	
+       	for (inv = 0; inv < (1 << num); inv++){
+		__u16 j;
+		__u8 not_valid = 0;
+		__u16 inv_match = 0;
+		__u32 new_mct = 0;
+		struct hipac_match *p = path->rule->first_match;
+		struct hipac_match *r = rule->r.first_match;
+	
+		if ((error = build_dt_rule(path->rule, &rule->r, pos, 
+					   rule->r.action, &new_dt_rule))){
+			CHECK_ERROR("build_dt_rule");
+			if (!first)
+				dimtree_failed(native_dts);
+			return error;
+		}
+		
+		new = new_dt_rule->first_dt_match;
+
+		for (i = 0, j = 0; i < path->rule->native_mct; i++){
+			while ((j < rule->r.native_mct)
+			       && (r[j].dimid < p[i].dimid)){
+				merge_dimension(&r[j], &new[new_mct], inv, 
+						&inv_match, ?_valid);
+				if (not_valid)
+					break;
+				j++;
+				new_mct++;
+			}
+			if (not_valid)
+				break;
+			if ((j < rule->r.native_mct)
+			    && (r[j].dimid == p[i].dimid)){
+				if (!r[j].invert && !p[i].invert){
+					if (r[j].left < p[i].left
+					    || r[j].right > p[i].right){
+						dt_rule_free(new_dt_rule);
+						if (!first)
+							dimtree_failed(
+								native_dts);
+						return HE_RULE_PREFIX_MISMATCH;
+					}
+				} else if (r[j].invert && !p[i].invert){
+					dt_rule_free(new_dt_rule);
+					if (!first)
+						dimtree_failed(native_dts);
+					return HE_RULE_PREFIX_MISMATCH;
+				} else if (!r[j].invert && p[i].invert){
+					if (!(r[j].right < p[i].left
+					      || r[j].left > p[i].right)){
+						dt_rule_free(new_dt_rule);
+						if (!first)
+							dimtree_failed(
+								native_dts);
+						return HE_RULE_PREFIX_MISMATCH;
+					}
+				} else if(r[j].invert && p[i].invert){
+					if (r[j].left > p[i].left
+					    || r[j].right < p[i].right){
+						dt_rule_free(new_dt_rule);
+						if (!first)
+							dimtree_failed(
+								native_dts);
+						return HE_RULE_PREFIX_MISMATCH;
+					}
+				}
+
+				merge_dimension(&r[j], &new[new_mct], inv, 
+						&inv_match, ?_valid);
+				if (not_valid)
+					break;
+				j++;
+				new_mct++;
+				continue;
+				
+			}
+			merge_dimension(&p[i], &new[new_mct], inv, 
+					&inv_match, ?_valid);
+			if (not_valid)
+				break;
+			new_mct++;
+		}
+		if (not_valid){
+			dt_rule_free(new_dt_rule);
+			continue;
+		}
+		while (j < rule->r.native_mct){
+			merge_dimension(&r[j], &new[new_mct], inv, 
+					&inv_match, ?_valid);
+			if (not_valid)
+				break;
+			j++;
+			new_mct++;
+		}			
+		if (not_valid){
+			dt_rule_free(new_dt_rule);
+			continue;
+		}
+		
+		if (new_mct < mct){
+			new_dt_rule->dt_match_len = new_mct;
+			new_dt_rule = hp_realloc(new_dt_rule, 
+						 dt_rule_size(new_mct));
+			if (!new_dt_rule){
+				dt_rule_free(new_dt_rule);
+				IMPOSSIBLE_CONDITION("new_dt_rule is NULL");
+			}
+		}
+
+		if (first){
+			if ((error = ptrblock_append(&rule->dtr,
+						     (void *) new_dt_rule))){
+				CHECK_ERROR("ptrblock_append");
+				dt_rule_free(new_dt_rule);
+				return error;
+			}
+		}
+		if ((error = dimtree_insert(path->dimtree, new_dt_rule,
+					    rule->r.origin, first, 
+					    DONT_COMMIT))){
+			CHECK_ERROR("dimtree_insert");
+			return error;
+		}
+		if (first)
+			first = 0;
+	}	
+	if (commit)
+		dimtree_commit(native_dts);
+	return HE_OK;
+}	
+
+
+
+/* detect loop in hipac_chains.
+   if any rule in hipac_chain ‘chain‘ (or recursively in any other
+   hipac_chain any rule in ‘chain‘ jumps to) jumps to hipac_chain ‘org‘
+   a loop is detected.
+   possible errors: HE_LOOP_DETECTED, HE_REC_LIMIT                    */
+hipac_error
+detect_loop(const struct hipac_chain *chain, 
+	    const struct hipac_chain *org, __u32 depth)
+{
+	if (unlikely(!chain || !org))
+		ARG_ERR;
+	
+	if (depth > HIPAC_REC_LIMIT)
+		return HE_REC_LIMIT;
+
+	if (chain->next_chains){
+		__u32 i;
+		hipac_error error;
+		struct hipac_chain *next;
+		for (i = 0; i < chain->next_chains->len; i++){
+			next = STRBLOCK_ITH(chain->next_chains, i,
+					    struct next_chain_elem *)->chain;
+			if (next == org)
+				return HE_LOOP_DETECTED;
+			if ((error = detect_loop(next, org, depth + 1)))
+				return error;
+		}
+	}
+	return HE_OK;
+}
+
+
+
+/* add new path to the paths block of hipac_chain ‘chain‘.
+   the new path is computed from the path ‘path‘ and the chain_rule ‘rule‘.
+   possible errors: HE_LOW_MEMORY, HE_RULE_PREFIX_MISMATCH, 
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+add_path(struct hipac_chain *chain, const struct path_ *path,
+	 struct chain_rule *rule)
+{
+	hipac_error error;
+	struct path_ *new_path;
+	struct prefix_rule *new_prefix;
+	struct hipac_match *r, *p, *new;
+	__u8 mct, i, j = 0, new_mct = 0;
+
+	if (!chain || !path || !path->rule || !rule)
+		ARG_ERR;
+	
+	mct = rule->r.native_mct + path->rule->native_mct;
+	
+	new_prefix = hp_alloc(sizeof(*new_prefix) 
+			      + mct * sizeof(struct hipac_match), ADD);
+	if (!new_prefix){
+		LOW_MEM("new_prefix alloc failed!");
+	}
+	new_path = hp_alloc(sizeof(*new_path), ADD);
+	if (!new_path){
+		hp_free(new_prefix);
+		LOW_MEM("new_path alloc failed!");
+	}
+
+	new_path->dimtree = path->dimtree;
+	new_path->prev = rule;
+	new_path->rule = new_prefix;
+	
+	new_prefix->origin = path->rule->origin & rule->r.origin;
+	new_prefix->exec_matches = NULL;
+	if ((error = ptrblock_clone(path->rule->exec_matches, 
+				    &new_prefix->exec_matches))){
+		CHECK_ERROR("ptrblock_clone");
+		path_free(new_path);
+		return error;
+	}
+	if ((error = add_exec_matches(&new_prefix->exec_matches, 
+				      &rule->r))){
+		CHECK_ERROR("add_exec_matches");
+		path_free(new_path);
+		return error;
+	}
+	r = rule->r.first_match;
+	p = path->rule->first_match;
+	new = new_prefix->first_match;
+	
+	for (i = 0; i < path->rule->native_mct; i++){
+		while ((j < rule->r.native_mct)
+		       && (r[j].dimid < p[i].dimid)){
+			new[new_mct].dimid = r[j].dimid;
+			new[new_mct].invert = r[j].invert;
+			new[new_mct].left = r[j].left;
+			new[new_mct].right = r[j].right;
+			j++;
+			new_mct++;
+		}
+		if ((j < rule->r.native_mct)
+		    && (r[j].dimid == p[i].dimid)){
+			if (!r[j].invert && !p[i].invert){
+				if (r[j].left < p[i].left
+				    || r[j].right > p[i].right){
+					path_free(new_path);
+					return HE_RULE_PREFIX_MISMATCH;
+				}
+			} else if (r[j].invert && !p[i].invert){
+				path_free(new_path);
+				return HE_RULE_PREFIX_MISMATCH;
+			} else if (!r[j].invert && p[i].invert){
+				if (!(r[j].right < p[i].left
+				      || r[j].left > p[i].right)){
+					path_free(new_path);
+					return HE_RULE_PREFIX_MISMATCH;
+				}
+			} else if(r[j].invert && p[i].invert){
+				if (r[j].left > p[i].left
+				    || r[j].right < p[i].right){
+					path_free(new_path);
+					return HE_RULE_PREFIX_MISMATCH;
+				}
+			}
+			
+			new[new_mct].dimid = r[j].dimid;
+			new[new_mct].invert = r[j].invert;
+			new[new_mct].left = r[j].left;
+			new[new_mct].right = r[j].right;
+			j++;
+			new_mct++;
+			continue;
+		}
+		new[new_mct].dimid = p[i].dimid;
+		new[new_mct].invert = p[i].invert;
+		new[new_mct].left = p[i].left;
+		new[new_mct].right = p[i].right;
+		new_mct++;
+	}
+
+	while (j < rule->r.native_mct){
+		new[new_mct].dimid = r[j].dimid;
+		new[new_mct].invert = r[j].invert;
+		new[new_mct].left = r[j].left;
+		new[new_mct].right = r[j].right;
+		j++;
+		new_mct++;
+	}
+	
+	if (new_mct < mct){
+		new_prefix = hp_realloc(new_prefix, sizeof(*new_prefix)
+					+ new_mct
+					* sizeof(struct hipac_match));
+		if (!new_prefix){
+			path_free(new_path);
+			IMPOSSIBLE_CONDITION("new_prefix is NULL");
+		}
+		new_path->rule = new_prefix;
+	}
+
+	new_prefix->native_mct = new_mct;
+	
+	if ((error = strblock_append_check(&chain->paths, new_path, 
+					   sizeof(*new_path)))){
+		CHECK_ERROR("strblock_append");
+		path_free(new_path);
+		return error;
+	}
+	hp_free(new_path);
+	return HE_OK;
+
+}
+
+
+
+/* add a dt_rule marking the beginning of the hipac_chain ‘chain‘
+   in the internal dimtree chain to ‘path->dimtree‘ and add a pointer
+   to that new dt_rule to the ‘chain->start‘ ptrblock.
+   the dt_rule is added with TARGET_DUMMY, so that it is not inserted
+   into the internal dimtree only into the internal dimtree chain.
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+static inline hipac_error
+add_chain_start(struct hipac_chain *chain, const struct path_ *path,
+		const __u32 pos)
+{
+	hipac_error error;
+	struct dt_rule *start;
+
+	if ((error = build_dt_rule(NULL, NULL, pos, 
+				   TARGET_DUMMY, &start))){
+		CHECK_ERROR("build_dt_rule");
+		return error;
+	}
+	if ((error = ptrblock_append(&chain->start, start))){
+		CHECK_ERROR("ptrblock_append");
+		dt_rule_free(start);
+		return error;
+	}
+	if ((error = dimtree_insert(path->dimtree, start, 
+				    ORIGIN_ALL, INC, DONT_COMMIT))){
+		CHECK_ERROR("dimtree_insert");
+		ptrblock_delete_tail(&chain->start);
+		dt_rule_free(start);
+		return error;
+	}
+	return HE_OK;
+}
+
+
+
+/* add a dt_rule marking the end of the hipac_chain ‘chain‘
+   in the internal dimtree chain to ‘path->dimtree‘ and add a pointer
+   to that new dt_rule to the ‘chain->end‘ ptrblock.
+   the dt_rule added to the internal dimtree corresponds to ‘path->rule‘.
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+hipac_error
+add_chain_end(struct hipac_chain *chain, struct path_ *path,
+	      const __u32 pos)
+{
+	struct dt_rule *new_dt_rule;
+	hipac_error error;
+       	__u32 i;
+	__u8 first = 1;
+	__u8 num;
+     	struct hipac_match *old;
+	struct dt_match *new;
+		
+		
+	num = count_inv_matches((struct hipac_match *) path->rule->first_match,
+				path->rule->native_mct);
+
+	if (!(num)){
+		if ((error = build_dt_rule(path->rule, NULL, pos, 
+					   TARGET_NONE, &new_dt_rule))){
+			CHECK_ERROR("build_dt_rule");
+			return error;
+		}
+		for (i = 0; i < path->rule->native_mct; i++){
+			new_dt_rule->first_dt_match[i].dimid = 
+				path->rule->first_match[i].dimid;
+			new_dt_rule->first_dt_match[i].left = 
+				path->rule->first_match[i].left;
+			new_dt_rule->first_dt_match[i].right = 
+				path->rule->first_match[i].right;
+		}
+		if ((error = ptrblock_append(&chain->end,
+					     (void *) new_dt_rule))){
+			CHECK_ERROR("ptrblock_append");
+			dt_rule_free(new_dt_rule);
+			return error;
+		}
+		if ((error = dimtree_insert(path->dimtree, new_dt_rule, 
+					    ORIGIN_ALL, INC, DONT_COMMIT))){
+			CHECK_ERROR("dimtree_insert");
+			return error;
+		}
+		return HE_OK;
+	} 
+	//else we have a rule containing negation
+	
+       	for (i = 0; i < (1 << num); i++){
+		__u16 j;
+		__u8 not_valid = 0;
+		__u16 inv_match = 0;
+	
+	
+		if ((error = build_dt_rule(path->rule, NULL, pos, 
+					   TARGET_NONE, &new_dt_rule))){
+			CHECK_ERROR("build_dt_rule");
+			if (!first)
+				dimtree_failed(native_dts);
+			return error;
+		}
+		old = path->rule->first_match;
+		new = new_dt_rule->first_dt_match;
+		for (j = 0; j < path->rule->native_mct; j++){
+			if (!(old[j].invert)){
+				new[j].dimid = old[j].dimid;
+				new[j].left = old[j].left;
+				new[j].right = old[j].right;
+				continue;
+			}
+			if (i & (1 << inv_match)){
+				if (old[j].right < 
+				    MAXKEY(dim2btype[old[j].dimid])){
+					new[j].dimid = old[j].dimid;
+					new[j].left = old[j].right + 1;
+					new[j].right = 
+						MAXKEY(dim2btype[new[j].dimid]);
+				} else {
+					not_valid = 1;
+					break;
+				}
+			} else {
+				if (old[j].left){
+					new[j].dimid = old[j].dimid;
+					new[j].left = 0;
+					new[j].right = old[j].left - 1;
+				} else {
+					not_valid = 1;
+					break;
+				}
+			}
+			inv_match++;
+		}
+		if (not_valid){
+			dt_rule_free(new_dt_rule);
+			continue;
+		}	
+		if (first){
+			if ((error = ptrblock_append(&chain->end,
+						     (void *) new_dt_rule))){
+				CHECK_ERROR("ptrblock_append");
+				dt_rule_free(new_dt_rule);
+				return error;
+			}
+		}
+		if ((error = dimtree_insert(path->dimtree, new_dt_rule,
+					    ORIGIN_ALL, first, DONT_COMMIT))){
+			CHECK_ERROR("dimtree_insert");
+			return error;
+		}
+		if (first)
+			first = 0;
+	}
+	return HE_OK;
+}
+
+
+
+/* add hipac_chain ‘to‘ to the next_chain block of hipac_chain ‘from‘.
+   if ‘from‘ already contains a reference to hipac_chain ‘to‘ then the
+   corresponding count field is incremented by 1, otherwise a new
+   next_chain_elem with its count field set to 1 is added to the
+   next_chain block.
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+static inline hipac_error
+add_next_chain(struct hipac_chain *from, struct hipac_chain *to)
+{
+	hipac_error error;
+	struct next_chain_elem *nc;
+
+	if (from->next_chains){
+		__u32 i;
+		for (i = 0; i < from->next_chains->len; i++){
+			nc = STRBLOCK_ITH(from->next_chains, i,
+					  struct next_chain_elem *);
+			if (nc->chain == to){
+				nc->count++;
+				return HE_OK;
+			}
+		}
+	}
+
+	nc = hp_alloc(sizeof(*nc), ADD);
+	if (!nc)
+		LOW_MEM("next_chain alloc failed!");
+	nc->count = 1;
+	nc->chain = to;
+	error = strblock_append_check(&from->next_chains, nc, sizeof(*nc));
+	hp_free(nc);
+	CHECK_ERROR("strblock_append");
+     	return error;
+}
+
+
+
+/* remove one reference to hipac_chain ‘to‘ from the next_chain block
+   of hipac_chain ‘from‘.                                             */
+static inline void
+delete_next_chain(struct hipac_chain *from, const struct hipac_chain *to)
+{
+     	struct next_chain_elem *nc;
+	
+	if (from->next_chains){
+		__u32 i;
+		for (i = 0; i < from->next_chains->len; i++){
+			nc = STRBLOCK_ITH(from->next_chains, i,
+					  struct next_chain_elem *);
+			if (nc->chain == to){
+				if (nc->count > 1){
+					nc->count--;
+				} else {
+					strblock_delete_pos(&from->next_chains,
+							    i);
+				}
+				break;
+			}
+		}
+	}
+}
+
+
+
+/* recursively insert jump rule ‘rule‘ into hipac data structures
+   and dimtrees. in case of an error changes must be undone 
+   externally via delete_jump_from_hipac_layer(),
+   delete_dt_rules_from_dt_chains() and dimtree_chain_fix().
+   attention: in case of an success does NOT commit the changes.
+              don‘t forget to eventually commit the modifications
+	      externally via dimtree_commit().
+   possible errors: HE_LOW_MEMORY, HE_LOOP_DETECTED, HE_REC_LIMIT,
+                    HE_RULE_ORIGIN_MISMATCH, HE_RULE_RREFIX_MISMATCH,
+		    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+insert_jump_rec(const struct hipac_chain *org, const struct ptrblock *next,
+		const struct path_ *path, const __u32 ins_num,
+		struct chain_rule *rule, __u32 depth)
+{
+	hipac_error error;
+	struct list_head *lh;
+	struct chain_rule *currule;
+	struct path_ *new_path;
+	struct hipac_chain *chain = NULL;
+	__u32 i;
+       
+	if (depth > HIPAC_REC_LIMIT)
+		return HE_REC_LIMIT;
+
+	chain_hash_lookup((void *) &rule->r + rule->r.target_offset, &chain);
+		
+	if (org == chain)
+		return HE_LOOP_DETECTED;
+	
+	for (i = 0; i < ins_num; i++){
+		if ((error = add_path(chain, path + i, rule))){
+			CHECK_ERROR("add_path");
+			for (; i > 0; i--){
+				paths_delete_tail(&chain->paths);
+				ptrblock_delete_tail(&chain->start);
+			}
+			return error;
+		}
+		if ((error = add_chain_start(chain, 
+					     P_ELEM(chain->paths,
+						    chain->paths->len - 1),
+					     ((struct dt_rule *)
+					      next->p[i])->spec.pos))){
+			CHECK_ERROR("add_chain_start");
+			paths_delete_tail(&chain->paths);
+			for (; i > 0; i--){
+				paths_delete_tail(&chain->paths);
+				ptrblock_delete_tail(&chain->start);
+			}
+			return error;
+		}
+	}
+
+	new_path = P_ELEM(chain->paths, chain->paths->len - ins_num);
+		
+	list_for_each(lh, &chain->head){
+		currule = list_entry(lh, struct chain_rule, head);
+		if (IS_JUMP_RULE(currule)){
+			if ((error = insert_jump_rec(org, next,
+						     new_path, ins_num,
+						     currule, depth + 1))){
+				CHECK_ERROR("insert_jump_rec");
+				return error;
+			}
+		} else for (i = 0; i < ins_num; i++){
+				if ((error = insert_into_dt(new_path + i, currule,
+							    ((struct dt_rule *)
+							     next->p[i])->spec.pos, 
+							    DONT_COMMIT))){
+					CHECK_ERROR("insert_into_dt");
+					return error;
+				}
+		}
+	}   
+	for (i = 0; i < ins_num; i++){
+		if ((error = add_chain_end(chain, new_path + i, 
+					   ((struct dt_rule *) 
+					    next->p[i])->spec.pos))){
+			CHECK_ERROR("add_chain_end");
+			return error;
+		}
+	}
+		
+	return HE_OK;
+}	
+
+
+
+/* delete all entries in the hipac layer data structures corresponding to
+   jump rule ‘rule‘. all entries in hipac_chain path, start and end blocks
+   pointing to dt_rules with positions > prev and < next are deleted.
+   attention: be sure that those rules have been deleted from the dimtrees
+              before and that those changes have been commited. there must NOT
+	      be any intervall in any dimtree anymore pointing to one of those
+	      rules! BUT the corresponding dt_rules must NOT yet have been
+	      deleted from the internal dimtree chains!               */
+static void
+delete_jump_from_hipac_layer(const struct hipac_chain *org,
+			     const struct ptrblock *prev, 
+			     const struct ptrblock *next,
+			     const struct chain_rule *rule)
+{
+	struct list_head *lh;
+	struct hipac_chain *chain = NULL;
+	struct chain_rule *currule;
+	__u32 i, j , finished = 0, del_num = 0;
+	
+	chain_hash_lookup((void *) &rule->r + rule->r.target_offset, 
+			  &chain);
+	
+	if (!chain->start)
+		return;
+	
+	for (i = chain->start->len; i > 0; i--){
+		for (j = 0; j < prev->len; j++){
+			if (!chain->paths){
+				finished = 1;
+				break;
+			}
+			if ((P_ELEM_DIMTREE(chain->paths, i - 1)
+			     == P_ELEM_DIMTREE(org->paths, j))
+			    && (((struct dt_rule *)
+				 chain->start->p[i - 1])->spec.pos
+				> ((struct dt_rule *) prev->p[j])->spec.pos)
+			    && (((struct dt_rule *) 
+				 chain->start->p[i - 1])->spec.pos
+				< ((struct dt_rule *) next->p[j])->spec.pos)){
+				
+				chain->start->p[i - 1] = NULL;
+				paths_delete_pos(&chain->paths, i - 1);
+				del_num++;
+				break;
+			}
+		}
+		if (finished)
+			break;
+	}
+
+	if (!del_num)
+		return;
+	
+	ptrblock_delete_multi(&chain->end, chain->start);
+		
+	list_for_each(lh, &chain->head){
+		currule = list_entry(lh, 
+				     struct chain_rule, head);
+		if (IS_JUMP_RULE(currule)){
+			delete_jump_from_hipac_layer(org, prev, next, currule);
+		} else {
+			if (!currule->dtr)
+				break;
+			if (chain->end
+			    && chain->end->len == currule->dtr->len)
+				break;
+			ptrblock_delete_multi(&currule->dtr, chain->start);
+		}
+	}		
+	
+	for (i = chain->start->len; i > 0; i--){
+		if (!chain->start->p[i - 1])
+			ptrblock_delete_pos(&chain->start, i - 1);
+	}
+}							   
+							   
+
+      
+/* delete all dt_rules between prev and next from the internal dimtrees.
+   all rules with positions > prev and < next are deleted.
+   in case of an error undo all made changes.
+   attention: does NOT commit the changes. don‘t forget to eventually commit
+              the modifications externally via dimtree_commit().
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+static inline hipac_error
+delete_dt_rules_from_dimtrees(const struct hipac_chain *chain,
+			      const struct ptrblock *prev,
+			      const struct ptrblock *next)
+{
+	hipac_error error;
+	__u32 i;
+	struct dt_rule *rule;
+	
+	if (!chain || !prev || !next)
+		ARG_ERR;
+	
+	for (i = 0; i < prev->len; i++){
+		rule = list_entry(((struct dt_rule *) prev->p[i])->head.next, 
+				  struct dt_rule, head);
+		
+		while (rule->spec.pos == 
+		       ((struct dt_rule *) prev->p[i])->spec.pos){
+			rule = list_entry(rule->head.next, 
+					  struct dt_rule, head);
+		}
+		while (rule != ((struct dt_rule *) next->p[i])){
+			if ((error = dimtree_delete(P_ELEM_DIMTREE(chain->paths,
+								   i),
+						    rule, DONT_COMMIT))){
+				CHECK_ERROR("dimtree_delete");
+				return error;
+			}
+			rule = list_entry(rule->head.next,
+					  struct dt_rule, head);
+		}
+	}
+	return HE_OK;
+}
+
+
+
+/* delete all dt_rules between prev and next from the internal dimtree chains.
+   all rules with positions > prev and < next are deleted.
+   attention: be sure that those rules have been deleted from the dimtrees
+              before and that those changes have been commited. there must NOT
+	      be any intervall in any dimtree anymore pointing to one of those
+	      rules!                                                  */
+static inline void
+delete_dt_rules_from_dt_chains(const struct hipac_chain *chain,
+			       const struct ptrblock *prev,
+			       const struct ptrblock *next)
+{
+	__u32 i, end_pos;
+	struct dt_rule *start;
+	
+	if (!chain || !prev || !next)
+		ARG_MSG;
+	
+	for (i = 0; i < prev->len; i++){
+		end_pos = ((struct dt_rule *) next->p[i])->spec.pos - 1;
+		if (((struct dt_rule *) prev->p[i])->spec.pos == end_pos){
+			continue;
+		}
+		start = list_entry(((struct dt_rule *) prev->p[i])->head.next, 
+				   struct dt_rule, head);
+		while (start->spec.pos == 
+		       ((struct dt_rule *) prev->p[i])->spec.pos){
+			start = list_entry(start->head.next, 
+					   struct dt_rule, head);
+		}
+		dimtree_chain_delete(P_ELEM_DIMTREE(chain->paths, i), start, 
+				     end_pos);
+	}
+}
+
+
+
+/* insert chain_rule ‘rule‘ into hipac_chain ‘chain‘ and 
+   commit the changes. in case of an error undo all made changes.
+   possible errors: HE_LOW_MEMORY, HE_LOOP_DETECTED, HE_REC_LIMIT,
+                    HE_RULE_ORIGIN_MISMATCH, HE_RULE_PREFIX_MISMATCH,
+		    HE_TARGET_CHAIN_IS_NATIVE, 
+		    HE_TARGET_CHAIN_NOT_EXISTENT,
+		    HE_IMPOSSIBLE_CONDITION                           */
+static inline hipac_error
+insert(struct hipac_chain *chain, struct chain_rule *rule)
+{
+     	hipac_error error;
+	struct ptrblock *prev, *next;
+	__u8 prev_free, next_free;
+	
+	if (CHAIN_NOT_CONNECTED(chain)){
+		if (IS_JUMP_RULE(rule)){
+			struct hipac_chain *target_chain;
+			if ((error = chain_hash_lookup((void *) &rule->r 
+						       + rule->r.target_offset,
+						       &target_chain))){
+				chain_rule_free(rule);
+				return HE_TARGET_CHAIN_NOT_EXISTENT;
+			}
+			if (target_chain == chain){
+				chain_rule_free(rule);
+				return HE_LOOP_DETECTED;
+			}
+			if (IS_ROOT_CHAIN(target_chain)){
+				chain_rule_free(rule);
+				return HE_TARGET_CHAIN_IS_NATIVE;
+			}
+			if ((error = detect_loop(target_chain, chain, 1))){
+				chain_rule_free(rule);
+				return error;
+			}
+			if ((error = add_next_chain(chain, target_chain))){
+				chain_rule_free(rule);
+				return error;
+			}
+			target_chain->ref_count++;
+		}
+		chain_insert(chain, rule, INC);
+		return HE_OK;
+	}
+
+	chain_insert(chain, rule, INC);
+	if ((error = get_prev_dt_rules(chain, rule, &prev_free, &prev))){
+		CHECK_ERROR("get_prev_dt_rules");
+		chain_delete(chain, rule->r.pos);
+		chain_rule_free(rule);
+		return error;
+	}
+	if ((error = get_next_dt_rules(chain, rule, &next_free, &next))){
+		CHECK_ERROR("get_next_dt_rules");
+		chain_delete(chain, rule->r.pos);
+		chain_rule_free(rule);
+		if (prev_free)
+			ptrblock_free(prev);
+		return error;
+	}
+
+
+	if (likely(IS_NOT_JUMP_RULE(rule))){
+		__u32 i;
+		__u8 commit = DONT_COMMIT;
+		if (next->len == 1)
+			commit = COMMIT;
+		for (i = 0; i < next->len; i++){
+			if ((error = 
+			     insert_into_dt(P_ELEM(chain->paths, i), rule,
+					    ((struct dt_rule *) 
+					     next->p[i])->spec.pos, commit))){
+				CHECK_ERROR("insert_into_dt");
+				dimtree_failed(native_dts);
+				delete_dt_rules_from_dt_chains(chain, 
+							       prev, next);
+				dimtree_chain_fix(native_dts);
+				chain_delete(chain, rule->r.pos);
+				chain_rule_free(rule);
+				if (prev_free)
+					ptrblock_free(prev);
+				if (next_free)
+					ptrblock_free(next);
+				return error;
+			}
+		}
+		if (!commit)
+			dimtree_commit(native_dts);
+	} else {
+		struct hipac_chain *target_chain;
+		if ((error = chain_hash_lookup((void *) &rule->r 
+					       + rule->r.target_offset,
+					       &target_chain))){
+			CHECK_ERROR("chain_hash_lookup");
+			chain_delete(chain, rule->r.pos);
+			chain_rule_free(rule);
+			if (prev_free)
+				ptrblock_free(prev);
+			if (next_free)
+				ptrblock_free(next);
+			return HE_TARGET_CHAIN_NOT_EXISTENT;
+		}
+		if (target_chain == chain){
+			chain_delete(chain, rule->r.pos);
+			chain_rule_free(rule);
+			if (prev_free)
+				ptrblock_free(prev);
+			if (next_free)
+				ptrblock_free(next);
+			return HE_LOOP_DETECTED;
+		}
+		if (IS_ROOT_CHAIN(target_chain)){
+			chain_delete(chain, rule->r.pos);
+			chain_rule_free(rule);
+			if (prev_free)
+				ptrblock_free(prev);
+			if (next_free)
+				ptrblock_free(next);
+			return HE_TARGET_CHAIN_IS_NATIVE;
+		}
+		if ((error = add_next_chain(chain, target_chain))){
+			CHECK_ERROR("add_next_chain");
+			chain_delete(chain, rule->r.pos);
+			chain_rule_free(rule);
+			if (prev_free)
+				ptrblock_free(prev);
+			if (next_free)
+				ptrblock_free(next);
+			return error;
+		}
+		if ((error = insert_jump_rec(chain, next, 
+					     P_ELEM(chain->paths, 0),
+					     chain->paths->len, rule, 1))){
+			CHECK_ERROR("insert_jump_rec");
+			dimtree_failed(native_dts);
+			delete_jump_from_hipac_layer(chain, prev, next, rule);
+			delete_dt_rules_from_dt_chains(chain, prev, next);
+			dimtree_chain_fix(native_dts);
+			delete_next_chain(chain, target_chain);
+			chain_delete(chain, rule->r.pos);
+			chain_rule_free(rule);
+			if (prev_free)
+				ptrblock_free(prev);
+			if (next_free)
+				ptrblock_free(next);
+			return error;
+		}
+		dimtree_commit(native_dts);
+		target_chain->ref_count++;
+	}
+      	if (prev_free)
+		ptrblock_free(prev);
+	if (next_free)
+		ptrblock_free(next);
+	return HE_OK;
+}
+
+
+
+/* delete chain_rule ‘rule‘ from hipac_chain ‘chain‘ and commit
+   the changes. all representations of that rule in the internal 
+   dimtrees are removed. 
+   in case of an error undo all made changes.
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */
+static inline hipac_error
+delete(struct hipac_chain* chain, struct chain_rule* rule)
+{
+	hipac_error error;
+	__u8 inv;
+	
+	if (unlikely(CHAIN_NOT_CONNECTED(chain))){
+		if (unlikely(IS_JUMP_RULE(rule))){
+			struct hipac_chain *target_chain = NULL;
+			chain_hash_lookup((void *) &rule->r 
+					  + rule->r.target_offset,
+					  &target_chain);
+			delete_next_chain(chain, target_chain);
+			target_chain->ref_count--;
+		}
+		chain_delete(chain, rule->r.pos);
+		chain_rule_destroy(rule);
+		return HE_OK;
+	}
+	
+	inv = count_inv_matches(rule->r.first_match, 
+				rule->r.native_mct);
+	
+	if (likely(!inv && IS_NOT_JUMP_RULE(rule))){
+      		__u32 i;
+		__u8 commit = 0;
+		if (rule->dtr->len == 1){
+			commit = 1;
+		}
+		for (i = 0; i < rule->dtr->len; i++){
+			if ((error = 
+			     dimtree_delete(P_ELEM_DIMTREE(chain->paths, i),
+					    (struct dt_rule *) rule->dtr->p[i],
+					    commit))){
+				CHECK_ERROR("dimtree_delete");
+				if (!commit)
+					dimtree_failed(native_dts);
+				return error;
+			}
+		}
+		if (!commit)
+			dimtree_commit(native_dts);
+		for (i = 0; i < rule->dtr->len; i++){
+			dimtree_chain_delete(P_ELEM_DIMTREE(chain->paths, i),
+					     (struct dt_rule *) rule->dtr->p[i],
+					     ((struct dt_rule *) 
+					      rule->dtr->p[i])->spec.pos);
+		}
+	} else {
+		struct ptrblock *prev, *next;
+		__u8 prev_free, next_free;
+		
+		if ((error = get_prev_dt_rules(chain, rule, 
+					       &prev_free, &prev))){
+			CHECK_ERROR("get_prev_dt_rules");
+			return error;
+		}
+		if ((error = get_next_dt_rules(chain, rule, 
+					       &next_free, &next))){
+			CHECK_ERROR("get_next_dt_rules");
+			if (prev_free)
+				ptrblock_free(prev);
+			return error;
+		}
+		if ((error = delete_dt_rules_from_dimtrees(chain, 
+							   prev, next))){
+			CHECK_ERROR("delete_dt_rules_from_dimtrees");
+			dimtree_failed(native_dts);
+			if (prev_free)
+				ptrblock_free(prev);
+			if (next_free)
+				ptrblock_free(next);
+			return error;
+		}
+		dimtree_commit(native_dts);
+		if (unlikely(IS_JUMP_RULE(rule))){
+			struct hipac_chain *target_chain = NULL;
+			chain_hash_lookup((void *) &rule->r + rule->r.target_offset,
+					  &target_chain);
+			delete_next_chain(chain, target_chain);
+			target_chain->ref_count--;
+			delete_jump_from_hipac_layer(chain, prev, next, rule);
+		}
+		delete_dt_rules_from_dt_chains(chain, prev, next);
+		if (prev_free)
+			ptrblock_free(prev);
+		if (next_free)
+			ptrblock_free(next);
+	}
+	dimtree_chain_fix(native_dts);
+	chain_delete(chain, rule->r.pos);
+	chain_rule_destroy(rule);
+	return HE_OK;
+}
+
+
+
+/* replace chain_rule ‘old_rule‘ in hipac_chain ‘chain‘ with 
+   chain_rule ‘new_rule‘ and commit the changes.
+   in case of an error undo all made changes.
+   possible errors: HE_LOW_MEMORY, HE_LOOP_DETECTED, HE_REC_LIMIT,
+                    HE_RULE_ORIGIN_MISMATCH, HE_RULE_PREFIX_MISMATCH,
+		    HE_TARGET_CHAIN_IS_NATIVE,
+                    HE_TARGET_CHAIN_NOT_EXISTENT,
+		    HE_IMPOSSIBLE_CONDITION                           */
+static inline hipac_error
+replace(struct hipac_chain *chain, struct chain_rule *old_rule,
+	struct chain_rule *new_rule)
+{
+     	hipac_error error;
+	struct ptrblock *prev_old, *prev_new, *next_old, *next_new;
+	__u8 prev_free_old, prev_free_new, next_free_old, next_free_new;
+	struct hipac_chain *target_chain = NULL;
+	
+	if (CHAIN_NOT_CONNECTED(chain)){
+		if (IS_JUMP_RULE(new_rule)){
+			if ((error = 
+			     chain_hash_lookup((void *) &new_rule->r 
+					       + new_rule->r.target_offset,
+					       &target_chain))){
+				chain_rule_free(new_rule);
+				return HE_TARGET_CHAIN_NOT_EXISTENT;
+			}
+			if (target_chain == chain){
+				chain_rule_free(new_rule);
+				return HE_LOOP_DETECTED;
+			}
+			if (IS_ROOT_CHAIN(target_chain)){
+				chain_rule_free(new_rule);
+				return HE_TARGET_CHAIN_IS_NATIVE;
+			}
+			if ((error = detect_loop(target_chain, chain, 1))){
+				chain_rule_free(new_rule);
+				return error;
+			}
+			if ((error = add_next_chain(chain, target_chain))){
+				chain_rule_free(new_rule);
+				return error;
+			}
+			target_chain->ref_count++;
+		}
+		if (IS_JUMP_RULE(old_rule)){
+			chain_hash_lookup((void *) &old_rule->r 
+					  + old_rule->r.target_offset,
+					  &target_chain);
+			delete_next_chain(chain, target_chain);
+			target_chain->ref_count--;
+		}
+		chain_delete(chain, old_rule->r.pos);
+		chain_rule_destroy(old_rule);
+		chain_insert(chain, new_rule, INC);
+		return HE_OK;
+	}
+
+	if ((error = get_prev_dt_rules(chain, old_rule, 
+				       &prev_free_new, &prev_new))){
+		CHECK_ERROR("get_prev_dt_rules");
+		chain_rule_free(new_rule);
+		return error;
+	}
+	if ((error = get_next_dt_rules(chain, old_rule, 
+				       &next_free_old, &next_old))){
+		CHECK_ERROR("get_next_dt_rules");
+		chain_rule_free(new_rule);
+		if (prev_free_new)
+			ptrblock_free(prev_new);
+		return error;
+	}
+	if ((error = delete_dt_rules_from_dimtrees(chain, 
+						   prev_new, next_old))){
+		CHECK_ERROR("delete_dt_rules_from_dimtrees");
+		dimtree_failed(native_dts);
+		chain_rule_free(new_rule);
+		if (prev_free_new)
+			ptrblock_free(prev_new);
+		if (next_free_old)
+			ptrblock_free(next_old);
+		return error;
+	}
+	
+	chain_insert(chain, new_rule, INC);
+	
+	if ((error = get_next_dt_rules(chain, new_rule, 
+				       &next_free_new, &next_new))){
+		CHECK_ERROR("get_next_dt_rules");
+		chain_delete(chain, new_rule->r.pos);
+		chain_rule_free(new_rule);
+		dimtree_failed(native_dts);
+		if (prev_free_new)
+			ptrblock_free(prev_new);
+		if (next_free_old)
+			ptrblock_free(next_old);
+		return error;
+	}	
+
+	if (likely(IS_NOT_JUMP_RULE(new_rule))){
+		__u32 i;
+		for (i = 0; i < next_new->len; i++){
+			if ((error = insert_into_dt(P_ELEM(chain->paths, i),
+						    new_rule, 
+						    ((struct dt_rule *)
+						     next_new->p[i])->spec.pos, 
+						    DONT_COMMIT))){
+				CHECK_ERROR("insert_into_dt");
+				dimtree_failed(native_dts);
+				delete_dt_rules_from_dt_chains(chain, 
+							       prev_new, 
+							       next_new);
+				dimtree_chain_fix(native_dts);
+				chain_delete(chain, new_rule->r.pos);
+				chain_rule_free(new_rule);
+				if (prev_free_new)
+					ptrblock_free(prev_new);
+				if (next_free_old)
+					ptrblock_free(next_old);
+				if (next_free_new)
+					ptrblock_free(next_new);
+				return error;
+			}
+		}
+		if ((error = get_prev_dt_rules(chain, old_rule, 
+				       &prev_free_old, &prev_old))){
+			CHECK_ERROR("get_prev_dt_rules");
+			dimtree_failed(native_dts);
+			delete_dt_rules_from_dt_chains(chain, prev_new, 
+						       next_new);
+			dimtree_chain_fix(native_dts);
+			chain_delete(chain, new_rule->r.pos);
+			chain_rule_free(new_rule);
+			if (prev_free_new)
+				ptrblock_free(prev_new);
+			if (next_free_old)
+				ptrblock_free(next_old);
+			if (next_free_new)
+				ptrblock_free(next_new);
+			return error;
+		}
+	} else {
+		if ((error = chain_hash_lookup((void *) &new_rule->r 
+					       + new_rule->r.target_offset,
+					       &target_chain))){
+			CHECK_ERROR("chain_hash_lookup");
+			chain_delete(chain, new_rule->r.pos);
+			chain_rule_free(new_rule);
+			dimtree_failed(native_dts);
+			if (prev_free_new)
+				ptrblock_free(prev_new);
+			if (next_free_old)
+				ptrblock_free(next_old);
+			if (next_free_new)
+				ptrblock_free(next_new);
+			return HE_TARGET_CHAIN_NOT_EXISTENT;
+		}
+		if (target_chain == chain){
+			chain_delete(chain, new_rule->r.pos);
+			chain_rule_free(new_rule);
+			dimtree_failed(native_dts);
+			if (prev_free_new)
+				ptrblock_free(prev_new);
+			if (next_free_old)
+				ptrblock_free(next_old);
+			if (next_free_new)
+				ptrblock_free(next_new);
+			return HE_LOOP_DETECTED;
+		}
+		if (IS_ROOT_CHAIN(target_chain)){
+			chain_delete(chain, new_rule->r.pos);
+			chain_rule_free(new_rule);
+			dimtree_failed(native_dts);
+			if (prev_free_new)
+				ptrblock_free(prev_new);
+			if (next_free_old)
+				ptrblock_free(next_old);
+			if (next_free_new)
+				ptrblock_free(next_new);
+			return HE_TARGET_CHAIN_IS_NATIVE;
+		}
+		if ((error = add_next_chain(chain, target_chain))){
+			CHECK_ERROR("add_next_chain");
+			chain_delete(chain, new_rule->r.pos);
+			chain_rule_free(new_rule);
+			dimtree_failed(native_dts);
+			if (prev_free_new)
+				ptrblock_free(prev_new);
+			if (next_free_old)
+				ptrblock_free(next_old);
+			if (next_free_new)
+				ptrblock_free(next_new);
+			return error;
+		}
+		if ((error = insert_jump_rec(chain, next_new, 
+					     P_ELEM(chain->paths, 0),
+					     chain->paths->len, new_rule, 1))){
+			CHECK_ERROR("insert_jump_rec");
+			dimtree_failed(native_dts);
+			delete_jump_from_hipac_layer(chain, prev_new, 
+						     next_new, new_rule);
+			delete_dt_rules_from_dt_chains(chain, prev_new, 
+						       next_new);
+			dimtree_chain_fix(native_dts);
+			delete_next_chain(chain, target_chain);
+			chain_delete(chain, new_rule->r.pos);
+			chain_rule_free(new_rule);
+			if (prev_free_new)
+				ptrblock_free(prev_new);
+			if (next_free_old)
+				ptrblock_free(next_old);
+			if (next_free_new)
+				ptrblock_free(next_new);
+			return error;
+		}
+		if ((error = get_prev_dt_rules(chain, old_rule, 
+					       &prev_free_old, &prev_old))){
+			CHECK_ERROR("get_prev_dt_rules");
+			dimtree_failed(native_dts);
+			delete_jump_from_hipac_layer(chain, prev_new, 
+						     next_new, new_rule);
+			delete_dt_rules_from_dt_chains(chain, prev_new, 
+						       next_new);
+			dimtree_chain_fix(native_dts);
+			delete_next_chain(chain, target_chain);
+			chain_delete(chain, new_rule->r.pos);
+			chain_rule_free(new_rule);
+			if (prev_free_new)
+				ptrblock_free(prev_new);
+			if (next_free_old)
+				ptrblock_free(next_old);
+			if (next_free_new)
+				ptrblock_free(next_new);
+			return error;
+		}
+		target_chain->ref_count++;
+	}
+	dimtree_commit(native_dts);
+	
+	if (likely(IS_JUMP_RULE(old_rule))){
+		chain_hash_lookup((void *) &old_rule->r 
+				  + old_rule->r.target_offset,
+				  &target_chain);
+		delete_next_chain(chain, target_chain);
+		target_chain->ref_count--;
+		delete_jump_from_hipac_layer(chain, prev_old, next_old, 
+					     old_rule);
+	}
+	delete_dt_rules_from_dt_chains(chain, prev_old, next_old);
+	dimtree_chain_fix(native_dts);
+	chain_delete(chain, old_rule->r.pos);
+	chain_rule_destroy(old_rule);
+	if (prev_free_old)
+		ptrblock_free(prev_old);
+	if (prev_free_new)
+		ptrblock_free(prev_new);
+	if (next_free_old)
+		ptrblock_free(next_old);
+	if (next_free_new)
+		ptrblock_free(next_new);
+	return HE_OK;
+}
+
+
+
+
+
+/*
+ * hipac_* functions
+ */
+
+
+/* init hipac data structures;
+   MUST be called once at the beginning in order to let the other
+   operations work properly!
+   dimid_to_bittype: assigns dimids to bit types.
+                     i-th element of the array contains the bit type
+		     of dimension id i
+   extract:          functions to extract certain fields from a packet. 
+                     the function at position i of the array returns
+		     the entry in a packet that corresponds to 
+		     dimension id i (i.e. the source ip of the packet)
+   len:              length of the dim2btype and extract array
+   copycon:          constructor function
+   destroy:          destructor function
+   match:            match executor function
+   target:           target executor function
+   eq:               equality function to compare rules
+   maxmem:           maximum allowed memory consumption  
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */  
+hipac_error
+hipac_init(const __u8 dimid_to_bittype[], const hipac_extract_t extract[],
+	   const __u8 len, hipac_copy_constructor_t copycon,
+	   hipac_destroy_exec_t destroy, hipac_match_exec_t match,
+	   hipac_target_exec_t target, hipac_eq_exec_t eq, 
+	   const __u64 maxmem)
+{
+        
+	if (unlikely(!dimid_to_bittype || !extract || !copycon || !destroy ||
+		     !match || !target || !eq ))
+	ARG_ERR;
+	
+	mem_max = maxmem;
+	d2blen = len;
+	current_chain = NULL;
+	chain_hash = NULL;
+	native_dts = NULL;
+	dim2btype = hp_alloc(len, ADD);
+	if (!dim2btype)
+		LOW_MEM("dim2btype alloc failed!");
+	extract_fn = hp_alloc(len * sizeof(void *), ADD);
+	if (!extract_fn){
+		hp_free(dim2btype);
+		LOW_MEM("extract_fn alloc failed!");
+	}
+	chain_hash = ihash_new(CHAIN_HASH_LEN, ADD, CHAIN_HASH_AVR_BUCKET,
+			       ihash_func_str, eq_str);
+	if (!chain_hash){
+		hp_free(dim2btype);
+		hp_free(extract_fn);
+		LOW_MEM("ihash_new failed!");
+	}
+	memcpy(dim2btype, dimid_to_bittype, len);
+	memcpy(extract_fn, extract, len * sizeof(void *));
+	copy_fn = copycon;
+	destroy_fn = destroy;
+	match_fn = match;
+	target_fn = target;
+	eq_fn = eq;
+	return HE_OK;
+}
+
+
+
+/* free all hipac data structures;
+   MUST be called once in the end
+   attention: make sure there are no external accesses to hipac
+              data structures taking place anymore!                   */
+void
+hipac_exit(void)
+{
+	if (native_dts){
+		__u8 i;
+		for(i = 0; i < native_dts->len; i++){
+			dimtree_free((struct dimtree*) native_dts->p[i]);
+		}
+		ptrblock_free(native_dts);
+	} 
+	hp_free(dim2btype);
+	hp_free(extract_fn);
+	IHASH_VAL_ITERATE(chain_hash, struct hipac_chain *, chain_free);
+	ihash_free(chain_hash);
+	hp_mem_exit();
+}
+
+
+
+/* return new hipac data structure
+   name:        name of the public chain
+   name_intern: name of the internal dimtree chain
+   policy:      initial policy
+   origin:      bitvector uniq to this data structure
+   hipac:       pointer to a pointer to the resulting hipac data
+                structure. use as first argument to hipac_match()
+   possible errors: HE_LOW_MEMORY, HE_NATIVE_CHAIN_EXISTS,
+                    HE_CHAIN_EXISTS, HE_IMPOSSIBLE_CONDITION          */
+hipac_error
+hipac_new(const char *name, const char* name_intern, const __u8 policy, 
+	  const __u32 origin, void **hipac)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	struct dt_rule *start, *end;
+	struct prefix_rule *prefix_rule;
+	struct path_ *new_path;
+	__u32 i, j, list_pos = 0;
+
+	if (unlikely(!name || !name_intern || !hipac))
+		ARG_ERR;
+
+	for (i = 0; i < chain_hash->len; i++) {
+		if (chain_hash->bucket[i] == NULL) {
+			continue;
+		}
+		for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+			struct hipac_chain *c;
+			c = chain_hash->bucket[i]->kv[j].val;
+			if (c->dimtree && list_pos <= c->list_pos) {
+				list_pos = c->list_pos + 1;
+			}
+		}
+	}
+	
+	if (native_dts){
+		__u32 i = 0;
+		for (i = 0; i < native_dts->len; i++)
+			if (!strcmp(((struct dimtree *)native_dts->p[i])
+				    ->chain->name, name_intern))
+				return HE_NATIVE_CHAIN_EXISTS;
+	}
+
+	if ((error = chain_new(name, &chain, list_pos))){
+		CHECK_ERROR("chain_new");
+		return error;
+	}
+
+	if ((error = build_dt_rule(NULL, NULL, 0, TARGET_DUMMY, &start))){
+		CHECK_ERROR("build_dt_rule");
+		chain_free(chain);
+		return error;
+	}
+
+	if ((error = ptrblock_append(&chain->start, start))){
+		CHECK_ERROR("ptrblock_append");
+		chain_free(chain);
+		dt_rule_free(start);
+		return error;
+	}
+	if ((error = build_dt_rule(NULL, NULL, 1, policy, &end))){
+		CHECK_ERROR("build_dt_rule");
+		chain_free(chain);
+		dt_rule_free(start);
+		return error;
+	}
+	
+        if ((error = ptrblock_append(&chain->end, end))){
+		CHECK_ERROR("ptrblock_append");
+		chain_free(chain);
+		dt_rule_free(start);
+		dt_rule_free(end);
+		return error;
+	}
+	if ((error = dimtree_new((struct dimtree **)hipac, 
+				 origin, name_intern,
+				 start, end))){
+		CHECK_ERROR("dimtree_new");
+		chain_free(chain);
+		dt_rule_free(start);
+		dt_rule_free(end);
+		return error;
+	}
+
+	if ((error = ptrblock_append(&native_dts, 
+				     *(struct dimtree**) hipac))){
+		CHECK_ERROR("ptrblock_append");
+		dimtree_free(*(struct dimtree**) hipac);
+		chain_free(chain);
+		return error;
+	}
+
+	prefix_rule = hp_alloc(sizeof(*prefix_rule), ADD);
+	if (!prefix_rule){
+		dimtree_free(*(struct dimtree**) hipac);
+		chain_free(chain);
+		ptrblock_delete_tail(&native_dts);
+		LOW_MEM("prefix rule alloc failed");
+	}
+	new_path = hp_alloc(sizeof(*new_path), ADD);
+	if (!new_path){
+		hp_free(prefix_rule);
+		dimtree_free(*(struct dimtree**) hipac);
+		chain_free(chain);
+		ptrblock_delete_tail(&native_dts);
+		LOW_MEM("new_path alloc failed");
+	}
+	new_path->dimtree = *(struct dimtree**) hipac;
+	new_path->prev = NULL;
+	new_path->rule = prefix_rule;
+	prefix_rule->origin = ORIGIN_ALL;
+	prefix_rule->exec_matches = NULL;
+	prefix_rule->native_mct = 0;
+	if ((error = strblock_append_check(&chain->paths, new_path, 
+					   sizeof(*new_path)))){
+		CHECK_ERROR("strblock_append");
+		path_free(new_path);
+		dimtree_free(*(struct dimtree**) hipac);
+		chain_free(chain);
+		ptrblock_delete_tail(&native_dts);
+		return error;
+	}
+	hp_free(new_path);
+
+	if ((error = chain_hash_insert(chain))){
+		CHECK_ERROR("chain_hash_insert");
+		chain_free(chain);
+		dimtree_free(*(struct dimtree**) hipac);
+		ptrblock_delete_tail(&native_dts);
+		return error;
+	}
+	chain->dimtree = *(struct dimtree**) hipac;
+	return HE_OK;
+}
+
+
+
+/* set maximum amount of memory the hipac data structures are 
+   allowed to occupy. return LOW_MEMORY if ‘mem‘ is lower than
+   currently allocated memory
+   possible errors: HE_LOW_MEMORY                                     */  
+hipac_error
+hipac_set_maxmem(const __u64 mem)
+{
+	if (mem_current_real > mem){
+		LOW_MEM();
+	}
+	mem_max = mem;
+	return HE_OK;
+}
+
+
+
+/* get maximum amount of memory the hipac data structures are 
+   allowed to occupy.                                                 */  
+__u64
+hipac_get_maxmem(void)
+{
+	return mem_max;
+}
+
+
+
+/* set policy of chain with name ‘name‘ to ‘policy‘.
+   possible errors: HE_CHAIN_NOT_EXISTENT, HE_CHAIN_IS_USERDEFINED,
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_set_policy(const char *name, const __u8 policy)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	
+        if (unlikely(!name))
+		ARG_ERR;
+	if ((error = chain_hash_lookup(name, &chain))){
+		CHECK_ERROR("chain_hash_lookup");
+		return error;
+	}
+	if (!chain->dimtree)
+		return HE_CHAIN_IS_USERDEFINED;
+	((struct dt_rule *)(chain->end->p[0]))->spec.action = policy;
+	return HE_OK;
+}
+
+
+
+/* get policy of chain with name ‘name‘ and write it to ‘result‘.
+   possible errors: HE_CHAIN_NOT_EXISTENT, HE_CHAIN_IS_USERDEFINED,
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_policy(const char *name, __u8 *result)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	
+	if (unlikely(!name || !result))
+		ARG_ERR;
+	if ((error = chain_hash_lookup(name, &chain))){
+		CHECK_ERROR("chain_hash_lookup");
+		return error;
+	}
+	if (!chain->dimtree)
+		return HE_CHAIN_IS_USERDEFINED;
+	*result = ((struct dt_rule *)(chain->end->p[0]))->spec.action;
+	return HE_OK;
+}
+
+
+
+/* create new user-defined chain with name ‘name‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_EXISTS, 
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_new_chain(const char* name)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	__u32 i, j, list_pos;
+
+	if (unlikely(!name))
+		ARG_ERR;
+	
+	list_pos = chain_hash->elem_ct - (native_dts ? native_dts->len : 0);
+	if ((error = chain_new(name, &chain, list_pos))){
+		CHECK_ERROR("chain_new");
+		return error;
+	}
+	if ((error = chain_hash_insert(chain))){
+		CHECK_ERROR("chain_hash_insert");
+		chain_free(chain);
+		return error;
+	}
+	for (i = 0; i < chain_hash->len; i++) {
+		if (chain_hash->bucket[i] == NULL) {
+			continue;
+		}
+		for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+			struct hipac_chain *c;
+			c = chain_hash->bucket[i]->kv[j].val;
+			if (c->dimtree) {
+				continue;
+			}
+			if (strcmp(c->name, name) > 0) {
+				if (c->list_pos < list_pos) {
+					list_pos = c->list_pos;
+				}
+				c->list_pos++;
+			}
+		}
+	}
+	chain->list_pos = list_pos;
+
+	return HE_OK;
+}
+
+
+
+/* delete all rules in chain with name ‘name‘.
+   if ‘name‘ is NULL all rules in all chains are deleted.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT,
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error 
+hipac_flush_chain(const char *name)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	struct list_head *lh;
+	struct chain_rule *rule;
+	struct next_chain_elem *n_elem;
+	__u32 i, j;
+	
+	if (!name){
+		//flushing all chains	
+		for (i = 0; i < chain_hash->len; i++) {
+			if (chain_hash->bucket[i] == NULL) {
+				continue;
+			}
+			for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+				chain = chain_hash->bucket[i]->kv[j].val;
+				if (chain->dimtree){
+					dimtree_flush(chain->dimtree);
+					lh = chain->head.next;
+					while (lh != &chain->head) {
+						rule = list_entry(
+							lh, struct chain_rule,
+							head);
+						lh = lh->next;
+						list_del(lh->prev);
+						chain_rule_destroy(rule);
+					}
+					if (chain->next_chains){
+						strblock_free(
+							chain->next_chains);
+						chain->next_chains = NULL;
+					}
+				} else {
+					chain_flush(chain);
+				}
+			}                                                         
+		}
+		return HE_OK;
+	}
+
+	if ((error = chain_hash_lookup(name, &chain)))
+		return error;
+
+
+	if (unlikely(CHAIN_NOT_CONNECTED(chain))){			
+		if (chain->next_chains){
+			for (i = 0; i < chain->next_chains->len; i++){
+				n_elem = STRBLOCK_ITH(chain->next_chains, i,
+						      struct next_chain_elem *);
+				n_elem->chain->ref_count -= n_elem->count;
+			}
+			strblock_free(chain->next_chains);
+			chain->next_chains = NULL;
+		}
+		lh = chain->head.next;
+		while (lh != &chain->head) {
+			rule = list_entry(lh, struct chain_rule, head);
+			lh = lh->next;
+			list_del(lh->prev);
+			chain_rule_destroy(rule);
+		}
+		return HE_OK;
+	}
+
+	
+	if (!chain->dimtree){
+		if ((error = delete_dt_rules_from_dimtrees(chain, 
+							   chain->start,
+							   chain->end))){
+			CHECK_ERROR("delete_dt_rules_from_dimtrees");
+			dimtree_failed(native_dts);
+			return error;
+		}
+		dimtree_commit(native_dts);
+	}
+	
+	if (chain->next_chains){
+		for (i = 0; i < chain->next_chains->len; i++){
+			n_elem = STRBLOCK_ITH(chain->next_chains, i,
+					      struct next_chain_elem *);
+			n_elem->chain->ref_count -= n_elem->count;
+		}
+		strblock_free(chain->next_chains);
+		chain->next_chains = NULL;
+	}
+
+	lh = chain->head.next;
+	while (lh != &chain->head) {
+		rule = list_entry(lh, struct chain_rule, head);
+		lh = lh->next;
+		list_del(lh->prev);
+		if (IS_JUMP_RULE(rule)){
+			delete_jump_from_hipac_layer(chain, chain->start,
+						     chain->end, rule);
+		}
+		chain_rule_destroy(rule);
+	}
+	
+	if (chain->dimtree){
+		dimtree_flush(chain->dimtree);
+	} else {
+		delete_dt_rules_from_dt_chains(chain, 
+					       chain->start, chain->end);
+		dimtree_chain_fix(native_dts);
+	}
+	return HE_OK;
+}
+
+
+
+/* delete user-defined chain with name ‘name‘.
+   if ‘name‘ is NULL delete all chains that are empty 
+   and not referenced from other chains.
+   possible errors: HE_CHAIN_NOT_EXISTENT, HE_CHAIN_IS_NATIVE,
+                    HE_CHAIN_NOT_EMPTY, HE_CHAIN_IS_REFERENCED        */   
+hipac_error
+hipac_delete_chain(const char *name)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	__u32 i, j;
+	
+	if (!name){
+		//delete all empty and not referenced user-defined chains
+		for (i = 0; i < chain_hash->len; i++) {
+			if (chain_hash->bucket[i] == NULL) {
+				continue;
+			}
+			for (j = 0; j < chain_hash->bucket[i]->len;) {
+				__u32 k, l;
+				chain = chain_hash->bucket[i]->kv[j].val;
+				if (chain->dimtree
+				    || !list_empty(&chain->head)
+				    || CHAIN_IS_REFERENCED(chain)) {
+					j++;
+					continue;
+				}
+				chain_hash_remove(chain);
+				for (k = 0; k < chain_hash->len; k++) {
+					if (!chain_hash->bucket[k]) {
+						continue;
+					}
+					for (l = 0; l < chain_hash->
+						     bucket[k]->len; l++) {
+						struct hipac_chain *c;
+						c = chain_hash->bucket[k]->
+							kv[l].val;
+						if (!c->dimtree &&
+						    c->list_pos >
+						    chain->list_pos) {
+							c->list_pos--;
+						}
+					}
+				}
+				chain_free(chain);
+			}                                                         
+		}
+		return HE_OK;
+	}
+
+	if ((error = chain_hash_lookup(name, &chain)))
+		return HE_CHAIN_NOT_EXISTENT;
+
+	if (chain->dimtree)
+		return HE_CHAIN_IS_NATIVE;
+	
+	if (!list_empty(&chain->head))
+		return HE_CHAIN_NOT_EMPTY;
+
+	if (CHAIN_IS_REFERENCED(chain))
+		return HE_CHAIN_IS_REFERENCED;
+	
+	chain_hash_remove(chain);
+	for (i = 0; i < chain_hash->len; i++) {
+		struct hipac_chain *c;
+		if (chain_hash->bucket[i] == NULL) {
+			continue;
+		}
+		for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+			c = chain_hash->bucket[i]->kv[j].val;
+			if (!c->dimtree && c->list_pos > chain->list_pos) {
+				c->list_pos--;
+			}
+		}                                                         
+	}
+	chain_free(chain);
+	return HE_OK;
+}
+
+
+
+/* rename chain with name ‘name‘ to ‘new_name‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_EXISTS, 
+                    HE_CHAIN_NOT_EXISTENT, HE_CHAIN_IS_NATIVE,
+		    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_rename_chain(const char *name, const char *new_name)
+{
+	hipac_error error;
+	struct hipac_chain *old_chain, *new_chain;
+	struct list_head *lh;
+	struct chain_rule *rule;
+	int new_is_larger;
+	char *old;
+	__u32 i, j, k, list_pos;
+
+	if (unlikely(!name || !new_name))
+		ARG_ERR;
+	
+	if ((!(error = chain_hash_lookup(new_name, &old_chain))))
+		return HE_CHAIN_EXISTS;
+
+	if ((error = chain_hash_lookup(name, &old_chain)))
+		return error;
+	
+	if (old_chain->dimtree)
+		return HE_CHAIN_IS_NATIVE;
+
+	new_chain = hp_alloc(sizeof(*new_chain), ADD);
+	if (!new_chain)
+		return HE_LOW_MEMORY;
+
+	memcpy(new_chain, old_chain, sizeof(*new_chain));
+
+	strncpy(new_chain->name, new_name, HIPAC_CHAIN_NAME_MAX_LEN);
+	new_chain->name[HIPAC_CHAIN_NAME_MAX_LEN - 1] = ‘\0‘;
+
+	if ((error = chain_hash_replace(old_chain, new_chain))) {
+		CHECK_ERROR("chain_hash_replace");
+		hp_free(new_chain);
+		return error;
+	}
+	current_chain = NULL;
+	
+	if (list_empty(&old_chain->head)) {
+		INIT_LIST_HEAD(&new_chain->head);
+	} else {
+		lh = old_chain->head.next;
+		list_del(&old_chain->head);
+		list_add_tail(&new_chain->head, lh);
+	}
+	
+	new_is_larger = (strcmp(new_name, name) > 0);
+	list_pos = old_chain->list_pos;
+	if (!CHAIN_IS_REFERENCED(old_chain)) {
+		for (i = 0; i < chain_hash->len; i++) {
+			struct hipac_chain *chain;
+			if (chain_hash->bucket[i] == NULL) {
+				continue;
+			}
+			for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+				chain = chain_hash->bucket[i]->kv[j].val;
+				if (chain->dimtree)
+					continue;
+				if (new_is_larger) {
+					if (chain->list_pos >
+					    old_chain->list_pos &&
+					    strcmp(chain->name,
+						   new_name) < 0) {
+						if (list_pos <
+						    chain->list_pos) {
+							list_pos = chain->
+								list_pos;
+						}
+						chain->list_pos--;
+					}
+				} else {
+					if (chain->list_pos <
+					    old_chain->list_pos &&
+					    strcmp(chain->name,
+						   new_name) > 0) {
+						if (list_pos >
+						    chain->list_pos) {
+							list_pos = chain->
+								list_pos;
+						}
+						chain->list_pos++;
+					}
+				}
+			}
+		}
+		new_chain->list_pos = list_pos;
+		hp_free(old_chain);
+		return HE_OK;
+	}
+	
+	for (i = 0; i < chain_hash->len; i++) {
+		struct hipac_chain *chain, **next;
+		if (chain_hash->bucket[i] == NULL) {
+			continue;
+		}
+		for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+			chain = chain_hash->bucket[i]->kv[j].val;
+
+			if (chain->next_chains){
+				for (k = 0; k < chain->next_chains->len; k++){
+					next = &STRBLOCK_ITH(
+						chain->next_chains, k,
+						struct next_chain_elem *)
+						->chain;
+					if (*next == old_chain)
+						*next = new_chain;
+				}
+			}
+
+			list_for_each(lh, &chain->head) {
+				rule = list_entry(lh, struct chain_rule, head);
+				if (IS_JUMP_RULE(rule)){
+					old = (void *) &rule->r 
+						+ rule->r.target_offset;
+					if (!strcmp(old, name)){
+						strncpy(old, new_name,
+						    HIPAC_CHAIN_NAME_MAX_LEN);
+						old[HIPAC_CHAIN_NAME_MAX_LEN
+						    - 1] = ‘\0‘;
+					}
+				}
+			}	
+
+			if (chain->dimtree)
+				continue;
+				
+			if (new_is_larger) {
+				if (chain->list_pos > old_chain->list_pos &&
+				    strcmp(chain->name, new_name) < 0) {
+					if (list_pos < chain->list_pos) {
+						list_pos = chain->list_pos;
+					}
+					chain->list_pos--;
+				}
+			} else {
+				if (chain->list_pos < old_chain->list_pos &&
+				    strcmp(chain->name, new_name) > 0) {
+					if (list_pos > chain->list_pos) {
+						list_pos = chain->list_pos;
+					}
+					chain->list_pos++;
+				}
+			}
+		}
+	}
+	new_chain->list_pos = list_pos;
+	hp_free(old_chain);
+	return HE_OK;
+}
+
+
+
+/* get an array of hipac_chain_info structs containing required infos
+   for a rule listing of chain with name ‘name‘. if ‘name‘ is NULL
+   return infos for all chains. ‘len‘ specifies the length of the
+   returned struct hipac_chain_info array.
+   attention: don‘t forget to free the struct hipac_chain_info array
+              after the rule listing via hipac_free_chain_infos()!
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT,
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_chain_infos(const char *name, struct hipac_chain_info **inf,
+		      __u32 *len)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+
+	if (unlikely(!inf || !len))
+		ARG_ERR;
+	
+	if (!name){
+		__u32 i, j, e;
+		*len = chain_hash->elem_ct;
+		*inf = hp_alloc(*len * sizeof(**inf), ADD);
+		if (!(*inf)){
+			LOW_MEM("hipac_chain_info alloc failed!");
+		}
+		for (i = 0; i < chain_hash->len; i++) {
+		        if (!chain_hash->bucket[i])
+				continue;
+			for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+				chain = chain_hash->bucket[i]->kv[j].val;
+				if (chain->dimtree) {
+					e = chain->list_pos;
+					(*inf)[e].policy = ((struct dt_rule *)
+							    (chain->end->p[0]))
+						->spec.action;
+				} else {
+					e = chain->list_pos +
+						(native_dts ?
+						 native_dts->len : 0);
+					(*inf)[e].policy = 0;
+				}
+				(*inf)[e].label = chain->name;
+				(*inf)[e].is_internal_chain = 0;
+				if (list_empty(&chain->head)){
+					(*inf)[e].rule_num = 0;
+				} else {
+					(*inf)[e].rule_num =
+						list_entry(chain->head.prev,
+							   struct chain_rule, 
+							   head)->r.pos;
+				}
+				(*inf)[e].chain_head = &chain->head;
+			}                                                       
+		}
+		return HE_OK;
+	}
+		
+
+	if ((error = chain_hash_lookup(name, &chain))){
+		// it‘s not a user-defined chain
+		// check if it‘s a internal dimtree chain
+		__u32 i;
+		struct dimtree *dt;
+		if (!native_dts) 
+			return  HE_CHAIN_NOT_EXISTENT;
+		for (i = 0; i < native_dts->len; i++){
+			dt = (struct dimtree *) native_dts->p[i];
+			if (!strcmp(name, dt->chain->name)){
+				*len = 1;
+				*inf = hp_alloc(sizeof(**inf), ADD);
+				if (!(*inf))
+					LOW_MEM();
+				(*inf)[0].label = dt->chain->name;
+				(*inf)[0].policy = 
+					list_entry(dt->chain->head.prev,
+						   struct dt_rule, 
+						   head)->spec.action;
+				(*inf)[0].is_internal_chain = 1;
+				(*inf)[0].rule_num = dt->chain->len;
+				(*inf)[0].chain_head = &dt->chain->head;
+				return HE_OK;
+			}
+		}
+		return HE_CHAIN_NOT_EXISTENT;
+	}
+	
+	*len = 1;
+	*inf = hp_alloc(sizeof(**inf), ADD);
+	if (!(*inf))
+		LOW_MEM("hipac_chain_info alloc failed!");
+	(*inf)[0].label = chain->name;
+	if (chain->dimtree)
+		(*inf)[0].policy = ((struct dt_rule *)
+				    (chain->end->p[0]))->spec.action;
+	else (*inf)[0].policy = 0;
+	(*inf)[0].is_internal_chain = 0;
+	if (list_empty(&chain->head)){
+		(*inf)[0].rule_num = 0;
+	} else {
+		(*inf)[0].rule_num = list_entry(
+			chain->head.prev,
+			struct chain_rule, head)->r.pos;
+	} 
+	(*inf)[0].chain_head = &chain->head;
+	return HE_OK;
+}
+
+
+
+/* free array of hipac_chain_info structs that has been allocated
+   before via hipac_get_chain_infos(). 
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_free_chain_infos(struct hipac_chain_info *inf)
+{
+	if (unlikely(!inf))
+		ARG_ERR;
+	hp_free(inf);
+	return HE_OK;
+}
+
+
+
+/* get next hipac_rule ‘next‘ of previous hipac_rule ‘prev‘.
+   with this function you can walk over the chain during rule listing.
+   to get the first hipac_rule of a chain, set ‘prev_rule‘ to NULL.
+   when the end of the chain is reached or the chain is empty the
+   hipac_error HE_RULE_NOT_EXISTENT is returned.
+   attention: during rule listing of a chain hipac_get_next_rule() 
+              must always be called until finally HE_RULE_NOT_EXISTENT 
+	      is returned!
+   possible errors: HE_LOW_MEMORY, HE_RULE_NOT_EXISTENT,
+                    IMPOSSIBLE_CONDITION                              */
+hipac_error
+hipac_get_next_rule(const struct hipac_chain_info *inf,
+		    struct hipac_rule *prev, 
+		    struct hipac_rule **next)
+{
+	hipac_error error;
+	static struct dt_rule *dt_rule = NULL;
+
+	if (unlikely(!inf || !next))
+		ARG_ERR;
+
+	if (unlikely(!prev)){
+		if (!inf->is_internal_chain){
+			if (unlikely(list_empty(inf->chain_head))){
+				*next = NULL;
+				return HE_RULE_NOT_EXISTENT;
+			} else {
+				*next = &list_entry(inf->chain_head->next,
+						    struct chain_rule, 
+						    head)->r;
+			}
+		} else {
+			if (dt_rule)
+				IMPOSSIBLE_CONDITION("dt_rule is defined!");
+			dt_rule = list_entry(inf->chain_head->next,
+					     struct dt_rule, head);
+			if ((error = build_hipac_rule_from_dt_rule(dt_rule, 
+								   next))){
+				CHECK_ERROR("build_hipac_rule_from_dt_rule");
+				dt_rule = NULL;
+				*next = NULL;
+				return error;
+			}
+		}
+		return HE_OK;
+	}
+       
+	if (!inf->is_internal_chain){
+		struct chain_rule *prev_chain_rule;
+		prev_chain_rule = list_entry(prev, 
+					     struct chain_rule, r);
+		if (prev_chain_rule->head.next == inf->chain_head){
+			*next = NULL;
+			return HE_RULE_NOT_EXISTENT;
+		}
+		*next = &list_entry(prev_chain_rule->head.next,
+				    struct chain_rule, head)->r;
+	} else {
+		hp_free(prev);
+		if (!dt_rule)
+			IMPOSSIBLE_CONDITION("dt_rule not defined!");
+		if (dt_rule->head.next == inf->chain_head){
+			dt_rule = NULL;
+			*next = NULL;
+			return HE_RULE_NOT_EXISTENT;
+		}
+		dt_rule = list_entry(dt_rule->head.next,
+				     struct dt_rule, head);
+		if ((error = build_hipac_rule_from_dt_rule(dt_rule, 
+							   next))){
+			CHECK_ERROR("build_hipac_rule_from_dt_rule");
+			dt_rule = NULL;
+			*next = NULL;
+			return error;
+		}
+	}
+	return HE_OK;
+}
+
+
+/* append hipac_rule ‘rule‘ to chain with name ‘name‘.
+   ‘rule->pos‘ is set to the position of the last rule
+   in the chain + 1.  
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT, 
+                    HE_LOOP_DETECTED, HE_REC_LIMIT,
+		    HE_RULE_ORIGIN_MISMATCH, HE_RULE_PREFIX_MISMATCH,
+		    HE_TARGET_CHAIN_NOT_EXISTENT,
+		    HE_TARGET_CHAIN_IS_NATIVE, 
+		    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_append(const char *name, const struct hipac_rule *rule)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	struct chain_rule *new_rule;
+	
+	if (unlikely(!name || !rule))
+		ARG_ERR;
+	
+	if ((error = chain_hash_lookup(name, &chain)))
+		return error;
+
+	if (unlikely(error = build_chain_rule_from_hipac_rule(rule, &new_rule)))
+		return error;
+
+	new_rule->r.pos = (list_empty(&chain->head)) ?
+		1 : (list_entry(chain->head.prev,
+				struct chain_rule, head)->r.pos + 1);
+	return insert(chain, new_rule);
+}	
+
+
+
+/* insert hipac_rule ‘rule‘ at position ‘rule->pos‘ into chain
+   with name ‘name‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT,
+                    HE_LOOP_DETECTED, HE_REC_LIMIT,
+		    HE_RULE_ORIGIN_MISMATCH, HE_RULE_PREFIX_MISMATCH,
+		    HE_TARGET_CHAIN_NOT_EXISTENT,
+		    HE_TARGET_CHAIN_IS_NATIVE, 
+		    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_insert(const char *name, const struct hipac_rule *rule)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	struct chain_rule *new_rule;
+
+	if (unlikely(!name || !rule))
+		ARG_ERR;
+
+	if ((error = chain_hash_lookup(name, &chain)))
+		return error;
+
+	if (unlikely(error = build_chain_rule_from_hipac_rule(rule, &new_rule)))
+		return error;
+
+	return insert(chain, new_rule);
+}
+
+
+
+/* delete hipac_rule with position ‘pos‘ from chain with name ‘name‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT, 
+                    HE_RULE_NOT_EXISTENT, HE_IMPOSSIBLE_CONDITION     */
+hipac_error
+hipac_delete_pos(const char *name, const __u32 pos)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	struct chain_rule *del_rule;
+	
+	if (unlikely(!name))
+		ARG_ERR;
+	
+	if ((error = chain_hash_lookup(name, &chain)))
+		return error;
+	
+	if ((error = chain_find_rule_with_pos(chain, pos, &del_rule)))
+		return error;
+
+	return delete(chain, del_rule);
+}
+
+
+
+/* find the first rule in chain with name ‘name‘ that equals to
+   hipac_rule ‘rule‘ and delete it.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT, 
+                    HE_RULE_NOT_EXISTENT, HE_IMPOSSIBLE_CONDITION     */
+hipac_error
+hipac_delete(const char *name, const struct hipac_rule *rule)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	struct chain_rule *del_rule;
+
+	if (unlikely(!name || !rule))
+		ARG_ERR;
+	
+	if ((error = chain_hash_lookup(name, &chain)))
+		return error;
+	
+	if ((error = chain_find_rule(chain, rule, &del_rule)))
+		return error;
+	
+	return delete(chain, del_rule);
+}
+
+
+
+/* replace rule with position ‘rule->pos‘ in chain with name ‘name‘
+   with hipac_rule ‘rule‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT,
+                    HE_RULE_NOT_EXISTENT, HE_LOOP_DETECTED,
+		    HE_REC_LIMIT, HE_RULE_ORIGIN_MISMATCH,
+		    HE_RULE_PREFIX_MISMATCH,
+		    HE_TARGET_CHAIN_NOT_EXISTENT,
+		    HE_TARGET_CHAIN_IS_NATIVE, 
+		    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_replace(const char *name, const struct hipac_rule *rule)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	struct chain_rule *del_rule, *new_rule;
+		
+	if (unlikely(!name || !rule))
+		ARG_ERR;
+	
+	if ((error = chain_hash_lookup(name, &chain)))
+		return error;
+	
+	if ((error = chain_find_rule_with_pos(chain, rule->pos, 
+						      &del_rule)))
+		return error;
+	
+	if (unlikely(error = build_chain_rule_from_hipac_rule(rule, &new_rule)))
+		return error;
+	
+	return replace(chain, del_rule, new_rule);
+}
+
+
+
+
+
+/*
+ * hipac statistic functions
+ */
+
+
+
+/* get hipac chain statistics
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_chain_stat(struct hipac_chain_stat *stat)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	struct prefix_rule *prefix;
+	struct list_head *lh;
+	struct chain_rule *rule;
+	__u32 i, j, k;
+	
+	if (unlikely(!stat))
+		ARG_ERR;
+	
+	stat->mem_tight = 0;
+	stat->mem_real = 0;
+	stat->chain_num = chain_hash->elem_ct;
+	stat->rule_num = 0;
+	stat_distribution_init(stat->prefix_stat, 16);
+	stat_distribution_init(stat->incoming_stat, 16);
+	stat_distribution_init(stat->outgoing_stat, 16);
+	
+	for (i = 0; i < chain_hash->len; i++) {
+		if (chain_hash->bucket[i] == NULL) {
+			continue;
+		}
+		for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+			chain = chain_hash->bucket[i]->kv[j].val;
+			if ((error = hp_size(chain, 
+					     &stat->mem_real,
+					     &stat->mem_tight)))
+				return error;
+			if ((error = hp_size(chain->next_chains, 
+					     &stat->mem_real,
+					     &stat->mem_tight)))
+				return error;
+			if ((error = hp_size(chain->paths, 
+					     &stat->mem_real,
+					     &stat->mem_tight)))
+				return error;
+			if (chain->paths){
+				for (k = 0; k < chain->paths->len; k++){
+					prefix = P_ELEM_RULE(chain->paths, k);
+					if ((error = 
+					     hp_size(prefix, 
+						     &stat->mem_real,
+						     &stat->mem_tight)))
+					       	return error;
+					if (prefix
+					    && (error = 
+						hp_size(prefix->exec_matches, 
+							&stat->mem_real,
+							&stat->mem_tight)))
+						return error;
+				}
+			}
+			if ((error = hp_size(chain->start, 
+					     &stat->mem_real,
+					     &stat->mem_tight)))
+				return error;
+			if ((error = hp_size(chain->end, 
+					     &stat->mem_real,
+					     &stat->mem_tight)))
+				return error;
+
+			if (!list_empty(&chain->head)){
+				stat->rule_num += 
+					list_entry(chain->head.prev,
+						   struct chain_rule, 
+						   head)->r.pos;
+			}   
+			
+			if (chain->paths)
+				stat_distribution_add(stat->prefix_stat, 16, 
+						      chain->paths->len);
+			else stat_distribution_add(stat->prefix_stat, 16, 0);
+			stat_distribution_add(stat->incoming_stat, 16,
+					      chain->ref_count);
+			if (chain->next_chains)
+				stat_distribution_add(stat->outgoing_stat, 16,
+						      chain->next_chains->len);
+			else stat_distribution_add(stat->outgoing_stat, 16, 0);
+			
+			list_for_each(lh, &chain->head) {
+				rule = list_entry(lh, struct chain_rule, head);
+				if ((error = hp_size(rule, 
+						     &stat->mem_real,
+						     &stat->mem_tight)))
+					return error;
+				if ((error = hp_size(rule->dtr, 
+						     &stat->mem_real,
+						     &stat->mem_tight)))
+					return error;
+			}
+		}
+	}
+	return HE_OK;
+}
+
+
+
+/* get hipac rule statistics
+   returned statistic constains all rules of those chains that are
+   reachable from the root chain represented by the ‘hipac‘ pointer.
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_rule_stat(void *hipac, struct hipac_rule_stat *stat)
+{
+	struct hipac_chain *chain;
+	struct list_head *lh;
+	struct chain_rule *rule;
+	__u32 i, j, k, inv;
+	__u8 found;
+	
+	if (unlikely(!hipac || !stat))
+		ARG_ERR;
+	
+	stat->rule_num = 0;
+	stat->exec_match_num = 0;
+	stat->exec_target_num = 0;
+	stat->jump_target_num = 0;
+	stat->return_target_num = 0;
+	stat_distribution_init(stat->hipac_match_stat, 16);
+	stat_distribution_init(stat->inv_rules_stat, 16);
+	
+	for (i = 0; i < chain_hash->len; i++) {
+		if (chain_hash->bucket[i] == NULL) {
+			continue;
+		}
+		for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+			chain = chain_hash->bucket[i]->kv[j].val;
+			found = 0;
+			if (chain->paths){
+				for (k = 0; k < chain->paths->len; k++){
+					if (hipac ==
+					    P_ELEM_DIMTREE(chain->paths, k)){
+						found = 1;
+						break;
+					}
+				}
+			}
+			if (!found)
+				continue;
+			if (!list_empty(&chain->head)){
+				stat->rule_num += 
+					list_entry(chain->head.prev,
+						   struct chain_rule, 
+						   head)->r.pos;
+			}   
+			
+			list_for_each(lh, &chain->head) {
+				rule = list_entry(lh, struct chain_rule, head);
+				if (rule->r.match_offset)
+					stat->exec_match_num++;
+				if (rule->r.action == TARGET_EXEC)
+					stat->exec_target_num++;
+				if (rule->r.action == TARGET_CHAIN)
+					stat->jump_target_num++;
+				if (rule->r.action == TARGET_RETURN)
+					stat->return_target_num++;
+				stat->hipac_match_stat[rule->r.native_mct]++;
+				inv = count_inv_matches(rule->r.first_match, 
+							rule->r.native_mct);
+				stat->inv_rules_stat[inv]++;
+			}
+		}
+	}
+	return HE_OK;
+}
+	
+
+
+/* get hipac user statistics
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_user_stat(struct hipac_user_stat *stat)
+{
+	struct hipac_chain *chain;
+	__u32 i, j;
+	
+	if (unlikely(!stat))
+		ARG_ERR;
+
+	stat->total_mem_tight = mem_current_tight;
+	stat->total_mem_real = mem_current_real;
+	stat->chain_num = chain_hash->elem_ct;
+	stat->rule_num = 0;
+	
+	for (i = 0; i < chain_hash->len; i++) {
+		if (chain_hash->bucket[i] == NULL) {
+			continue;
+		}
+		for (j = 0; j < chain_hash->bucket[i]->len; j++) {
+			chain = chain_hash->bucket[i]->kv[j].val;
+			if (!list_empty(&chain->head)){
+				stat->rule_num += 
+					list_entry(chain->head.prev,
+						   struct chain_rule, 
+						   head)->r.pos;
+			}                 
+		}
+	}
+	return HE_OK;
+}
+
+
+
+#ifdef DEBUG
+hipac_error
+hipac_get_dt_rule_ptrs(const char *name, const __u32 pos, 
+		       void **res)
+{
+	hipac_error error;
+	struct hipac_chain *chain;
+	struct chain_rule *rule;
+	
+	if (unlikely(!name || !res))
+		ARG_ERR;
+	
+	if ((error = chain_hash_lookup(name, &chain)))
+		return error;
+       
+	if (list_empty(&chain->head)){
+		*res = chain->end;
+		return HE_OK;
+	}
+	rule = list_entry(chain->head.prev, struct chain_rule, head);
+	if (pos > rule->r.pos){
+		if (pos == rule->r.pos + 1){
+			*res = chain->end;
+			return HE_OK;
+		} else {
+			return HE_RULE_NOT_EXISTENT;
+		}
+	}
+
+	if (unlikely(error = chain_find_rule_with_pos(chain, pos, &rule)))
+		return error;
+
+	*res = rule->dtr;
+	return HE_OK;
+}
+
+
+
+__u8
+dt_rules_have_same_position(void *hipac, void *dt_start, void *dt_rule)
+{
+	struct dt_rule *rule = (struct dt_rule *) dt_start;
+	
+	if (!hipac || !dt_start || !dt_rule){
+		 ARG_MSG;
+		 return 0;
+	}
+	if (rule->head.prev != &((struct dimtree *) hipac)->chain->head) {
+	        if (rule->spec.pos ==
+		    list_entry(rule->head.prev, struct dt_rule, head)
+		    ->spec.pos){
+			ERR("previous rule with same position found");
+			return 0;
+		}
+	}
+	while (rule->spec.pos == ((struct dt_rule *) dt_rule)->spec.pos) {
+		if (rule == dt_rule)
+			return 1;
+		if (rule->head.next == 
+		    &((struct dimtree *) hipac)->chain->head)
+			return 0;
+		rule = list_entry(rule->head.next, struct dt_rule, head);
+	}
+	return 0;
+}
+
+
+#endif
+
+
+
+/* End of hipac_* functions */
diff -uNr nf-hipac/kernel/hipac.h nfhipac/kernel/hipac.h
--- nf-hipac/kernel/hipac.h	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/hipac.h	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,623 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#ifndef _HIPAC_H
+#define _HIPAC_H
+
+#include "mode.h"
+
+/* values of bittype in specification header */
+#define BIT_U16  0
+#define BIT_U32  1
+
+/* maximum length of a hipac chain name (including terminating ‘\0‘) */
+#define HIPAC_CHAIN_NAME_MAX_LEN 32
+
+/* representation of the match [left, right] associated with a dimension id;
+   [left, right] must not be a wildcard match */
+struct hipac_match
+{
+        unsigned dimid  : 5;
+	unsigned invert : 1;
+        __u32 left;
+        __u32 right;
+	char next_match[0];
+};
+
+struct hipac_rule
+{
+	__u32 pos;
+	char  cmp_start[0];
+	__u32 size;
+	__u32 origin;
+	__u8  action;
+	__u8  native_mct;
+	__u16 match_offset;
+	__u32 target_offset;
+	struct hipac_match first_match[0];
+};
+
+struct hipac_chain_info
+{
+	char *label;
+	__u8 policy;
+	__u8 is_internal_chain;
+	__u32 rule_num;
+	struct list_head *chain_head;
+};
+
+
+
+/* return values of function based match executor */
+typedef enum
+{
+	MATCH_YES,
+	MATCH_NO,
+	MATCH_HOTDROP
+} hipac_match_t;
+
+
+/* hipac_rule action value; TARGET_DUMMY is reserved for internal usage only;
+   the function based target exectutor may return TARGET_ACCEPT, TARGET_DROP
+   or TARGET_NONE */
+typedef enum
+{
+	TARGET_DROP = NF_DROP,
+	TARGET_ACCEPT = NF_ACCEPT,
+	TARGET_NONE = (NF_ACCEPT > NF_DROP ? NF_ACCEPT + 1 : NF_DROP + 1),
+	TARGET_RETURN,
+	TARGET_DUMMY,
+	TARGET_EXEC,
+	TARGET_CHAIN
+} hipac_target_t;
+
+
+/* function based match and target executor function types */
+typedef hipac_match_t (* hipac_match_exec_t) (const void *packet,
+					      void *first_match, void *end);
+typedef hipac_target_t (* hipac_target_exec_t) (const void *packet,
+						void *target);
+
+
+/* dimension extractor function type */
+typedef __u32 (* hipac_extract_t) (const void *packet, int *hotdrop);
+
+
+/* equality function type */
+typedef int (* hipac_eq_exec_t) (const struct hipac_rule *r1,
+				 const struct hipac_rule *r2);
+
+
+/* constructor/destructor function type */
+typedef void (* hipac_copy_constructor_t) (const struct hipac_rule *r_org,
+					   struct hipac_rule *r_new);
+typedef void (* hipac_destroy_exec_t) (struct hipac_rule *r);
+
+
+/* hipac error codes */
+typedef enum
+{
+	HE_OK                        =  0,
+	HE_IMPOSSIBLE_CONDITION      = -1,
+	HE_LOW_MEMORY                = -2,
+	HE_CHAIN_EXISTS              = -3,
+    	HE_CHAIN_NOT_EXISTENT        = -4,
+	HE_CHAIN_IS_EMPTY            = -5,
+	HE_CHAIN_NOT_EMPTY           = -6,
+	HE_CHAIN_IS_USERDEFINED      = -7,
+	HE_CHAIN_IS_CONNECTED        = -8,
+	HE_CHAIN_IS_REFERENCED       = -9,
+	HE_CHAIN_NOT_NATIVE          = -10,
+	HE_CHAIN_IS_NATIVE           = -11,
+	HE_RULE_NOT_EXISTENT         = -12,
+	HE_RULE_ORIGIN_MISMATCH      = -13,
+	HE_RULE_PREFIX_MISMATCH      = -14,
+	HE_LOOP_DETECTED             = -15,
+	HE_REC_LIMIT                 = -16,
+	HE_TARGET_CHAIN_NOT_EXISTENT = -17,
+	HE_TARGET_CHAIN_IS_NATIVE    = -18,
+	HE_NATIVE_CHAIN_EXISTS       = -19,
+	HE_NEXT_ERROR                = -100  // shouldn‘t be changed
+} hipac_error;
+
+
+
+/* return maximum key of a dimension with the given bittype */
+static inline __u32
+hipac_maxkey(__u8 bittype)
+{
+	if (bittype == BIT_U16)
+		return 0xffff;
+	return 0xffffffff;
+}
+
+
+/* init hipac data structures;
+   MUST be called once at the beginning in order to let the other
+   operations work properly!
+   dimid_to_bittype: assigns dimids to bit types. 
+                     i-th element of the array contains the bit type
+		     of dimension id i
+   extract:          functions to extract certain fields from a packet. 
+                     the function at position i of the array returns
+		     the entry in a packet that corresponds to 
+		     dimension id i (i.e. the source ip of the packet)
+   len:              length of the dim2btype and extract array
+   copycon:          constructor function
+   destroy:          destructor function
+   match:            match executor function
+   target:           target executor function
+   eq:               equality function to compare rules
+   maxmem:           maximum allowed memory consumption  
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION            */  
+hipac_error
+hipac_init(const __u8 dimid_to_bittype[], const hipac_extract_t extract[],
+	   const __u8 len, hipac_copy_constructor_t copycon,
+	   hipac_destroy_exec_t destroy, hipac_match_exec_t match,
+	   hipac_target_exec_t target, hipac_eq_exec_t eq, 
+	   const __u64 maxmem);
+
+
+/* free all hipac data structures;
+   MUST be called once in the end
+   attention: make sure there are no external accesses to hipac 
+              data structures taking place anymore!                   */
+void
+hipac_exit(void);
+
+
+/* return new hipac data structure
+   name:        name of the public chain
+   name_intern: name of the internal dimtree chain
+   policy:      initial policy
+   origin:      bitvector uniq to this data structure
+   hipac:       pointer to a pointer to the resulting hipac data
+                structure. use as first argument to hipac_match()
+   possible errors: HE_LOW_MEMORY, HE_NATIVE_CHAIN_EXISTS,
+                    HE_CHAIN_EXISTS, HE_IMPOSSIBLE_CONDITION          */
+hipac_error
+hipac_new(const char *name, const char* name_intern, const __u8 policy, 
+	  const __u32 origin, void **hipac);  
+
+
+/* set maximum amount of memory the hipac data structures are 
+   allowed to occupy. return LOW_MEMORY if ‘mem‘ is lower than
+   currently allocated memory
+   possible errors: HE_LOW_MEMORY                                     */  
+hipac_error
+hipac_set_maxmem(const __u64 mem);
+
+
+/* get maximum amount of memory the hipac data structures are 
+   allowed to occupy.                                                 */  
+__u64
+hipac_get_maxmem(void);
+
+
+/* set policy of chain with name ‘name‘ to ‘policy‘.
+   possible errors: HE_CHAIN_NOT_EXISTENT, HE_CHAIN_IS_USERDEFINED,
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error 
+hipac_set_policy(const char *name, const __u8 policy);
+
+
+/* get policy of chain with name ‘name‘ and write it to ‘result‘.
+   possible errors: HE_CHAIN_NOT_EXISTENT, HE_CHAIN_IS_USERDEFINED,
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_policy(const char *name, __u8 *result);
+
+
+/* create new user-defined chain with name ‘name‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_EXISTS, 
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_new_chain(const char* name);
+
+
+/* delete all rules in chain with name ‘name‘.
+   if ‘name‘ is NULL all rules in all chains are deleted
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT,
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_flush_chain(const char *name);
+
+
+/* delete user-defined chain with name ‘name‘.
+   if ‘name‘ is NULL delete all chains that are empty 
+   and not referenced from other chains.
+   possible errors: HE_CHAIN_NOT_EXISTENT, HE_CHAIN_IS_NATIVE,
+                    HE_CHAIN_NOT_EMPTY, HE_CHAIN_IS_REFERENCED        */   
+hipac_error
+hipac_delete_chain(const char *name);
+
+
+/* rename chain with name ‘name‘ to ‘new_name‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_EXISTS, 
+                    HE_CHAIN_NOT_EXISTENT, HE_CHAIN_IS_NATIVE,
+		    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_rename_chain(const char *name, const char *new_name);
+
+
+/* get an array of hipac_chain_info structs containing required infos
+   for a rule listing of chain with name ‘name‘. if ‘name‘ is NULL
+   return infos for all chains. ‘len‘ specifies the length of the
+   returned struct hipac_chain_info array.
+   attention: don‘t forget to free the struct hipac_chain_info array
+              after the rule listing via hipac_free_chain_infos()!
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT,
+                    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_chain_infos(const char *name, struct hipac_chain_info **inf,
+		      __u32 *len);
+
+
+/* free array of hipac_chain_info structs that has been allocated
+   before via hipac_get_chain_infos(). 
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_free_chain_infos(struct hipac_chain_info *inf);
+
+
+/* get next hipac_rule ‘next‘ of previous hipac_rule ‘prev‘.
+   with this function you can walk over the chain during rule listing.
+   to get the first hipac_rule of a chain, set ‘prev‘ to NULL.
+   when the end of the chain is reached or the chain is empty the
+   hipac_error HE_RULE_NOT_EXISTENT is returned.
+   attention: during rule listing of a chain hipac_get_next_rule() 
+              must always be called until finally HE_RULE_NOT_EXISTENT 
+	      is returned!
+   possible errors: HE_LOW_MEMORY, HE_RULE_NOT_EXISTENT,
+                    IMPOSSIBLE_CONDITION                              */
+hipac_error
+hipac_get_next_rule(const struct hipac_chain_info *inf,
+		    struct hipac_rule *prev,
+		    struct hipac_rule **next);
+
+
+/* append hipac_rule ‘rule‘ to chain with name ‘name‘.
+   ‘rule->pos‘ is set to the position of the last rule
+   in the chain + 1.  
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT, 
+                    HE_LOOP_DETECTED, HE_REC_LIMIT,
+		    HE_RULE_ORIGIN_MISMATCH, HE_RULE_PREFIX_MISMATCH,
+		    HE_TARGET_CHAIN_NOT_EXISTENT,
+		    HE_TARGET_CHAIN_IS_NATIVE, 
+		    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_append(const char *name, const struct hipac_rule *rule);
+
+
+/* insert hipac_rule ‘rule‘ at position ‘rule->pos‘ into chain
+   with name ‘name‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT,
+                    HE_LOOP_DETECTED, HE_REC_LIMIT,
+		    HE_RULE_ORIGIN_MISMATCH, HE_RULE_PREFIX_MISMATCH,
+		    HE_TARGET_CHAIN_NOT_EXISTENT,
+		    HE_TARGET_CHAIN_IS_NATIVE, 
+		    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_insert(const char *name, const struct hipac_rule *rule);
+
+
+/* delete hipac_rule with position ‘pos‘ from chain with name ‘name‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT, 
+                    HE_RULE_NOT_EXISTENT, HE_IMPOSSIBLE_CONDITION     */
+hipac_error
+hipac_delete_pos(const char *name, const __u32 pos);
+
+
+/* find the first rule in chain with name ‘name‘ that equals to
+   hipac_rule ‘rule‘ and delete it.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT, 
+                    HE_RULE_NOT_EXISTENT, HE_IMPOSSIBLE_CONDITION     */
+hipac_error
+hipac_delete(const char *name, const struct hipac_rule *rule);
+
+
+/* replace rule with position ‘rule->pos‘ in chain with name ‘name‘
+   with hipac_rule ‘rule‘.
+   possible errors: HE_LOW_MEMORY, HE_CHAIN_NOT_EXISTENT,
+                    HE_RULE_NOT_EXISTENT, HE_LOOP_DETECTED,
+		    HE_REC_LIMIT, HE_RULE_ORIGIN_MISMATCH,
+		    HE_RULE_PREFIX_MISMATCH,
+		    HE_TARGET_CHAIN_NOT_EXISTENT,
+		    HE_TARGET_CHAIN_IS_NATIVE, 
+		    HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_replace(const char *name, const struct hipac_rule *rule);
+
+
+/* match packet and return the terminal packet action which is either
+   TARGET_ACCEPT or TARGET_DROP; note that this is the only function
+   that may be used in parallel with other functions of the hipac API */
+hipac_target_t
+hipac_match(void *hipac, const void *packet);
+
+
+
+/*
+ * hipac statistics: data structures
+ */
+
+/* rlp statistics
+   total_mem_tight:       current overall memory consumption in bytes
+                          in terms of how much has been requested
+   total_mem_real:        current overall memory consumption in bytes
+                          in terms of how much has actually been
+                          allocated
+   rlp_mem_tight:         current memory consumption in bytes of all
+                          rlps (not including termrule blocks) in
+                          terms of how much has been requested
+   rlp_mem_real:          current memory consumption in bytes of all
+                          rlps (not including termrule blocks) in
+                          terms of how much has actually been
+			  allocated
+   termrule_mem_tight:    current memory consumption in bytes of all
+                          termrule blocks in terms of how much has
+			  been requested
+   termrule_mem_real:     current memory consumption in bytes of all
+                          termrule blocks in terms of how much has
+			  actually been allocated
+   rlp_num:               number of rlps
+   rlp_dimid_num:         mapping with [i] containing the number of
+                          rlps in dimension i
+   rlp_depth_num:         mapping with [i] containing the number of
+                          rlps in depth i
+   termrule_num:          number of termrule blocks
+   termrule_ptr_num:      number of entries in all termrule blocks
+   keys_num:              number of keys in all rlps
+   rlp_dimid_keys_stat:   array of distributions with [i][j]
+                          containing the number of rlps in
+			  dimension i with 2^(i - 1) <= keys < 2^i
+   termptr_num:           number of terminal pointers (of all rlps)
+   termptr_dimid_num:     mapping with [i] containing the number of
+                          terminal pointers in dimension i
+   termptr_depth_num:     mapping with [i] containing the number of
+                          terminal pointers in depth i
+   nontermptr_num:        number of non-terminal pointers (of all
+                          rlps)
+   nontermptr_dimid_num:  mapping with [i] containing the number of
+                          non-terminal pointers in dimension i
+   nontermptr_depth_num:  mapping with [i] containing the number of
+                          non-terminal pointers in depth i
+   dt_elem_num:           number of elementary interval structures
+   dt_elem_ptr_num:       number of rules in all elementary interval
+                          structures
+   dt_elem_stat:          distribution with [i] containing the number
+                          of elementary interval structures with
+			  2^(i - 1) <= rules < 2^i                    */
+struct hipac_rlp_stat
+{
+	__u64 total_mem_tight;
+	__u64 total_mem_real;
+	__u64 rlp_mem_tight;
+	__u64 rlp_mem_real;
+	__u64 termrule_mem_tight;
+	__u64 termrule_mem_real;
+	__u32 rlp_num;
+	__u32 rlp_dimid_num[16];
+	__u32 rlp_depth_num[16];
+	__u32 termrule_num;
+	__u32 termrule_ptr_num;
+	__u32 keys_num;
+	__u32 rlp_dimid_keys_stat[16][18];
+	__u32 termptr_num;
+	__u32 termptr_dimid_num[16];
+	__u32 termptr_depth_num[16];
+	__u32 nontermptr_num;
+	__u32 nontermptr_dimid_num[16];
+	__u32 nontermptr_depth_num[16];
+	__u32 dt_elem_num;
+	__u32 dt_elem_ptr_num;
+	__u32 dt_elem_stat[16];
+};
+
+/* dimtree statistics
+   chain_mem_tight:         current memory consumption in bytes of
+                            a dimtree chain including the rules in
+                            terms of how much has been requested
+   chain_mem_real:          current memory consumption in bytes of
+                            a dimtree chain including the rules in
+                            terms of how much has actually been
+                            allocated
+   rule_num:                number of dimtree rules
+   rules_with_exec_matches: number of dimtree rules containing at
+                            least one function based match
+   rules_with_exec_target:  number of dimtree rules containing
+                            a function based target
+   rules_same_pos_stat:     distribution with [i] containing number
+                            of dimtree rule series of length
+                            >= 2^(i - 1) and < 2^i where all rules
+                            share the same position 
+   dt_match_stat:           mapping with [i] containing the number
+                            of dimtree rules having i non-wildcard
+                            matches                                   */
+struct hipac_dimtree_stat
+{
+	__u64 chain_mem_tight;
+	__u64 chain_mem_real;
+	__u32 rule_num;
+	__u32 rules_with_exec_matches;
+	__u32 rules_with_exec_target;
+	__u32 rules_same_pos_stat[16];
+	__u32 dt_match_stat[16];
+};
+
+/* hipac memory statistics
+   total_mem_tight:             current overall memory consumption in
+                                bytes in terms of how much has been
+                                requested
+   total_mem_real:              current overall memory consumption in
+                                bytes in terms of how much has
+                                actually been allocated
+   memhash_elem_num:            number of objects for which memory
+                                has been requested
+   memhash_len:                 number of buckets in the memory hash
+   memhash_smallest_bucket_len: number of objects in the smallest
+                                bucket of the memory hash
+   memhash_biggest_bucket_len:  number of objects in the biggest
+                                bucket of the memory hash
+   memhash_bucket_stat:         distribution with [i] containing the
+                                number of buckets with
+                                2^(i - 1) <= objects < 2^i            */
+struct hipac_mem_stat
+{
+	__u64 total_mem_tight;
+	__u64 total_mem_real;
+	__u32 memhash_elem_num;
+	__u32 memhash_len;
+	__u32 memhash_smallest_bucket_len;
+	__u32 memhash_biggest_bucket_len;
+	__u32 memhash_bucket_stat[16];
+	
+};
+
+
+/* hipac chain statistics
+   mem_tight:     current memory consumption in bytes of all
+                  hipac chains including the rules in terms of 
+		  how much has been requested
+   mem_real:      current memory consumption in bytes of all
+                  hipac chains including the rules in terms of
+		  how much has actually been allocated
+   chain_num:     number of chains
+   rule_num:      number of rules in all chains
+   paths_stat:    distribution with [i] containing the number of 
+                  chains with 2^(i - 1) <= paths < 2^i
+   incoming_stat: distribution with [i] containing the number of
+                  chains with 2^(i - 1) <= incoming edges < 2^i
+   outgoing_stat: distribution with [i] containing the number of
+                  chains with 2^(i - 1) <= outgoing edges < 2^i       */
+struct hipac_chain_stat
+{	
+	__u64 mem_tight;
+	__u64 mem_real;
+	__u32 chain_num;
+	__u32 rule_num;
+	__u32 prefix_stat[16];
+	__u32 incoming_stat[16];
+	__u32 outgoing_stat[16];
+};
+
+
+/* hipac rule statistics
+   rule_num:          number of rules 
+   exec_match_num:    number of rules with exec_matches
+   exec_target_num:   number of rules with exec_target
+   jump_target_num:   number of rules with jump target
+   return_target_num: number of rules with return target
+   hipac_match_stat:  mapping with [i] containing the number
+                      of rules with i hipac_matches
+   inv_rules_stat:    mapping with [i] containing the number
+                      of rules with i inversion flags                 */
+struct hipac_rule_stat
+{
+	__u32 rule_num;
+	__u32 exec_match_num;
+	__u32 exec_target_num;
+	__u32 jump_target_num;
+	__u32 return_target_num;
+	__u32 hipac_match_stat[16];
+	__u32 inv_rules_stat[16];
+};
+
+
+/* hipac user statistics
+   total_mem_tight: current memory consumption in bytes in terms 
+                    of how much has been requested
+   total_mem_real:  current memory consumption in bytes in terms
+                    of how much has actually been allocated
+   chain_num:       number of chains
+   rule_num:        number of rules in all chains                     */
+struct hipac_user_stat
+{
+	__u64 total_mem_tight;
+	__u64 total_mem_real;	
+	__u32 chain_num;
+	__u32 rule_num;
+};
+
+
+
+/*
+ * hipac statistics: functions
+ */
+
+/* get rlp statistics, i.e. the statistics of the internal
+   rlp representation of all rules reachable from the root chain
+   represented by the ‘hipac‘ pointer
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_rlp_stat(void *hipac, struct hipac_rlp_stat *stat);
+
+
+/* get dimtree statistics, i.e. the statistics of the internal
+   chain representation of all rules reachable from the root chain
+   represented by the ‘hipac‘ pointer
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_dimtree_stat(void *hipac, struct hipac_dimtree_stat *stat);
+
+
+/* get hipac memory statistics
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_mem_stat(struct hipac_mem_stat *stat);
+
+
+/* get hipac chain statistics
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_chain_stat(struct hipac_chain_stat *stat);
+
+
+/* get hipac rule statistics
+   returned statistics constains all rules of those chains that are
+   reachable from the root chain represented by the ‘hipac‘ pointer
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_rule_stat(void *hipac, struct hipac_rule_stat *stat);
+
+
+/* get hipac user statistics
+   possible errors: HE_IMPOSSIBLE_CONDITION                           */
+hipac_error
+hipac_get_user_stat(struct hipac_user_stat *stat);
+
+#ifdef DEBUG
+/* per object debugging: selection is done by an externally defined variable
+   hipac_debug which is a bit vector of DEBUG_* */
+#  define DEBUG_HIPAC   0x01
+#  define DEBUG_DIMTREE 0x02
+#  define DEBUG_RLP     0x04
+#  define DEBUG_IHASH   0x08
+#  define DEBUG_GLOBAL  0x10
+   extern unsigned hipac_debug;
+
+hipac_error
+hipac_get_dt_rule_ptrs(const char *name, const __u32 pos, void **res);
+
+__u8
+dt_rules_have_same_position(void *hipac, void *dt_start, void *dt_rule);
+#endif
+
+#endif
Binary files nf-hipac/kernel/hipac.o and nfhipac/kernel/hipac.o differ
diff -uNr nf-hipac/kernel/.hipac.o.cmd nfhipac/kernel/.hipac.o.cmd
--- nf-hipac/kernel/.hipac.o.cmd	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/.hipac.o.cmd	2014-11-21 12:54:43.000000000 +0800
@@ -0,0 +1,589 @@
+cmd_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.o := gcc -Wp,-MD,/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.hipac.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include -Iinclude  -I/usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include -include include/linux/autoconf.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -Wframe-larger-than=2048 -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-dwarf2-cfi-asm -fconserve-stack -D SINGLE_PATH  -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(hipac)"  -D"KBUILD_MODNAME=KBUILD_STR(nf_hipac)"  -c -o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.tmp_hipac.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.c
+
+deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.o := +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.c +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/mode.h +    $(wildcard include/config/uml/net.h) +    $(wildcard include/config/host/2g/2g.h) +    $(wildcard include/config/nest/level.h) +    $(wildcard include/config/kernel/half/gigs.h) +  include/linux/stddef.h +  include/linux/compiler.h +    $(wildcard include/config/trace/branch/profiling.h) +    $(wildcard include/config/profile/all/branches.h) +    $(wildcard include/config/enable/must/check.h) +    $(wildcard include/config/enable/warn/deprecated.h) +  include/linux/compiler-gcc.h +    $(wildcard include/config/arch/supports/optimized/inlining.h) +    $(wildcard include/config/optimize/inlining.h) +  include/linux/compiler-gcc4.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page.h +    $(wildcard include/config/x86/64.h) +  include/linux/types.h +    $(wildcard include/config/uid16.h) +    $(wildcard include/config/lbdaf.h) +    $(wildcard include/config/phys/addr/t/64bit.h) +    $(wildcard include/config/64bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/types.h +    $(wildcard include/config/highmem64g.h) +  include/asm-generic/types.h +  include/asm-generic/int-ll64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitsperlong.h +  include/asm-generic/bitsperlong.h +  include/linux/posix_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types.h +    $(wildcard include/config/x86/32.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_types.h +  include/linux/const.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64_types.h +    $(wildcard include/config/physical/start.h) +    $(wildcard include/config/physical/align.h) +    $(wildcard include/config/flatmem.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64.h +  include/asm-generic/memory_model.h +    $(wildcard include/config/discontigmem.h) +    $(wildcard include/config/sparsemem/vmemmap.h) +    $(wildcard include/config/sparsemem.h) +  include/asm-generic/getorder.h +  include/linux/slab.h +    $(wildcard include/config/slab/debug.h) +    $(wildcard include/config/debug/objects.h) +    $(wildcard include/config/kmemcheck.h) +    $(wildcard include/config/slub.h) +    $(wildcard include/config/slob.h) +    $(wildcard include/config/numa.h) +    $(wildcard include/config/debug/slab.h) +  include/linux/gfp.h +    $(wildcard include/config/highmem.h) +    $(wildcard include/config/zone/dma.h) +    $(wildcard include/config/zone/dma32.h) +    $(wildcard include/config/debug/vm.h) +  include/linux/mmzone.h +    $(wildcard include/config/force/max/zoneorder.h) +    $(wildcard include/config/smp.h) +    $(wildcard include/config/memory/hotplug.h) +    $(wildcard include/config/arch/populates/node/map.h) +    $(wildcard include/config/flat/node/mem/map.h) +    $(wildcard include/config/cgroup/mem/res/ctlr.h) +    $(wildcard include/config/have/memory/present.h) +    $(wildcard include/config/need/node/memmap/size.h) +    $(wildcard include/config/need/multiple/nodes.h) +    $(wildcard include/config/have/arch/early/pfn/to/nid.h) +    $(wildcard include/config/sparsemem/extreme.h) +    $(wildcard include/config/nodes/span/other/nodes.h) +    $(wildcard include/config/holes/in/zone.h) +    $(wildcard include/config/arch/has/holes/memorymodel.h) +  include/linux/spinlock.h +    $(wildcard include/config/debug/spinlock.h) +    $(wildcard include/config/generic/lockbreak.h) +    $(wildcard include/config/preempt.h) +    $(wildcard include/config/debug/lock/alloc.h) +  include/linux/typecheck.h +  include/linux/preempt.h +    $(wildcard include/config/debug/preempt.h) +    $(wildcard include/config/preempt/tracer.h) +    $(wildcard include/config/preempt/notifiers.h) +  include/linux/thread_info.h +    $(wildcard include/config/compat.h) +  include/linux/bitops.h +    $(wildcard include/config/generic/find/first/bit.h) +    $(wildcard include/config/generic/find/last/bit.h) +    $(wildcard include/config/generic/find/next/bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitops.h +    $(wildcard include/config/x86/cmov.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/alternative.h +    $(wildcard include/config/paravirt.h) +  include/linux/stringify.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/asm.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpufeature.h +    $(wildcard include/config/x86/invlpg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/required-features.h +    $(wildcard include/config/x86/minimum/cpu/family.h) +    $(wildcard include/config/math/emulation.h) +    $(wildcard include/config/x86/pae.h) +    $(wildcard include/config/x86/cmpxchg64.h) +    $(wildcard include/config/x86/use/3dnow.h) +    $(wildcard include/config/x86/p6/nop.h) +  include/asm-generic/bitops/sched.h +  include/asm-generic/bitops/hweight.h +  include/asm-generic/bitops/fls64.h +  include/asm-generic/bitops/ext2-non-atomic.h +  include/asm-generic/bitops/le.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/byteorder.h +  include/linux/byteorder/little_endian.h +  include/linux/swab.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swab.h +    $(wildcard include/config/x86/bswap.h) +  include/linux/byteorder/generic.h +  include/asm-generic/bitops/minix.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/thread_info.h +    $(wildcard include/config/debug/stack/usage.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor.h +    $(wildcard include/config/x86/vsmp.h) +    $(wildcard include/config/cc/stackprotector.h) +    $(wildcard include/config/m386.h) +    $(wildcard include/config/m486.h) +    $(wildcard include/config/x86/debugctlmsr.h) +    $(wildcard include/config/cpu/sup/amd.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor-flags.h +    $(wildcard include/config/vm86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vm86.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace.h +    $(wildcard include/config/x86/ptrace/bts.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace-abi.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/segment.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cache.h +    $(wildcard include/config/x86/l1/cache/shift.h) +  include/linux/linkage.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/linkage.h +    $(wildcard include/config/x86/alignment/16.h) +  include/linux/init.h +    $(wildcard include/config/modules.h) +    $(wildcard include/config/hotplug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/math_emu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sigcontext.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/current.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/percpu.h +    $(wildcard include/config/x86/64/smp.h) +  include/linux/kernel.h +    $(wildcard include/config/preempt/voluntary.h) +    $(wildcard include/config/debug/spinlock/sleep.h) +    $(wildcard include/config/prove/locking.h) +    $(wildcard include/config/printk.h) +    $(wildcard include/config/dynamic/debug.h) +    $(wildcard include/config/ring/buffer.h) +    $(wildcard include/config/tracing.h) +    $(wildcard include/config/ftrace/mcount/record.h) +  /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h +  include/linux/log2.h +    $(wildcard include/config/arch/has/ilog2/u32.h) +    $(wildcard include/config/arch/has/ilog2/u64.h) +  include/linux/ratelimit.h +  include/linux/param.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/param.h +  include/asm-generic/param.h +    $(wildcard include/config/hz.h) +  include/linux/dynamic_debug.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bug.h +    $(wildcard include/config/bug.h) +    $(wildcard include/config/debug/bugverbose.h) +  include/asm-generic/bug.h +    $(wildcard include/config/generic/bug.h) +    $(wildcard include/config/generic/bug/relative/pointers.h) +  include/asm-generic/percpu.h +    $(wildcard include/config/have/setup/per/cpu/area.h) +  include/linux/threads.h +    $(wildcard include/config/nr/cpus.h) +    $(wildcard include/config/base/small.h) +  include/linux/percpu-defs.h +    $(wildcard include/config/debug/force/weak/per/cpu.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/system.h +    $(wildcard include/config/ia32/emulation.h) +    $(wildcard include/config/x86/32/lazy/gs.h) +    $(wildcard include/config/x86/ppro/fence.h) +    $(wildcard include/config/x86/oostore.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/nops.h +    $(wildcard include/config/mk7.h) +  include/linux/irqflags.h +    $(wildcard include/config/trace/irqflags.h) +    $(wildcard include/config/irqsoff/tracer.h) +    $(wildcard include/config/trace/irqflags/support.h) +    $(wildcard include/config/x86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irqflags.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt.h +    $(wildcard include/config/highpte.h) +    $(wildcard include/config/paravirt/spinlocks.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_types.h +    $(wildcard include/config/compat/vdso.h) +    $(wildcard include/config/proc/fs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt_types.h +    $(wildcard include/config/x86/local/apic.h) +    $(wildcard include/config/paravirt/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/desc_defs.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/kmap_types.h +    $(wildcard include/config/debug/highmem.h) +  include/asm-generic/kmap_types.h +  include/linux/cpumask.h +    $(wildcard include/config/cpumask/offstack.h) +    $(wildcard include/config/hotplug/cpu.h) +    $(wildcard include/config/debug/per/cpu/maps.h) +    $(wildcard include/config/disable/obsolete/cpumask/functions.h) +  include/linux/bitmap.h +  include/linux/string.h +    $(wildcard include/config/binary/printf.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr-index.h +  include/linux/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ioctl.h +  include/asm-generic/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/errno.h +  include/asm-generic/errno.h +  include/asm-generic/errno-base.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpumask.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ds.h +    $(wildcard include/config/x86/ds.h) +  include/linux/err.h +  include/linux/personality.h +  include/linux/cache.h +    $(wildcard include/config/arch/has/cache/line/size.h) +  include/linux/math64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/div64.h +  include/asm-generic/div64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ftrace.h +    $(wildcard include/config/function/tracer.h) +    $(wildcard include/config/dynamic/ftrace.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic_64.h +  include/asm-generic/atomic-long.h +  include/linux/list.h +    $(wildcard include/config/debug/list.h) +  include/linux/poison.h +    $(wildcard include/config/illegal/pointer/value.h) +  include/linux/prefetch.h +  include/linux/bottom_half.h +  include/linux/spinlock_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock_types.h +  include/linux/lockdep.h +    $(wildcard include/config/lockdep.h) +    $(wildcard include/config/lock/stat.h) +    $(wildcard include/config/generic/hardirqs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwlock.h +  include/linux/spinlock_api_smp.h +  include/linux/wait.h +  include/linux/numa.h +    $(wildcard include/config/nodes/shift.h) +  include/linux/seqlock.h +  include/linux/nodemask.h +  include/linux/pageblock-flags.h +    $(wildcard include/config/hugetlb/page.h) +    $(wildcard include/config/hugetlb/page/size/variable.h) +  include/linux/bounds.h +  include/linux/memory_hotplug.h +    $(wildcard include/config/have/arch/nodedata/extension.h) +    $(wildcard include/config/memory/hotremove.h) +  include/linux/notifier.h +  include/linux/errno.h +  include/linux/mutex.h +    $(wildcard include/config/debug/mutexes.h) +  include/linux/rwsem.h +    $(wildcard include/config/rwsem/generic/spinlock.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwsem.h +  include/linux/srcu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone_64.h +    $(wildcard include/config/numa/emu.h) +  include/linux/mmdebug.h +    $(wildcard include/config/debug/virtual.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/smp.h +    $(wildcard include/config/x86/io/apic.h) +    $(wildcard include/config/x86/32/smp.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec.h +    $(wildcard include/config/x86/numaq.h) +    $(wildcard include/config/mca.h) +    $(wildcard include/config/eisa.h) +    $(wildcard include/config/x86/mpparse.h) +    $(wildcard include/config/acpi.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec_def.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/x86_init.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bootparam.h +  include/linux/screen_info.h +  include/linux/apm_bios.h +  include/linux/edd.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/e820.h +    $(wildcard include/config/efi.h) +    $(wildcard include/config/hibernation.h) +    $(wildcard include/config/memtest.h) +  include/linux/ioport.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ist.h +  include/video/edid.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apic.h +    $(wildcard include/config/x86/x2apic.h) +  include/linux/delay.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/delay.h +  include/linux/pm.h +    $(wildcard include/config/pm/sleep.h) +    $(wildcard include/config/pm/runtime.h) +  include/linux/workqueue.h +  include/linux/timer.h +    $(wildcard include/config/timer/stats.h) +    $(wildcard include/config/debug/objects/timers.h) +  include/linux/ktime.h +    $(wildcard include/config/ktime/scalar.h) +  include/linux/time.h +    $(wildcard include/config/arch/uses/gettimeoffset.h) +  include/linux/jiffies.h +  include/linux/timex.h +    $(wildcard include/config/no/hz.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/timex.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/tsc.h +    $(wildcard include/config/x86/tsc.h) +  include/linux/debugobjects.h +    $(wildcard include/config/debug/objects/free.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apicdef.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fixmap.h +    $(wildcard include/config/provide/ohci1394/dma/init.h) +    $(wildcard include/config/x86/visws/apic.h) +    $(wildcard include/config/x86/f00f/bug.h) +    $(wildcard include/config/x86/cyclone/timer.h) +    $(wildcard include/config/pci/mmconfig.h) +    $(wildcard include/config/intel/txt.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/acpi.h +    $(wildcard include/config/acpi/numa.h) +  include/acpi/pdc_intel.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vsyscall.h +    $(wildcard include/config/generic/time.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_apic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irq_vectors.h +    $(wildcard include/config/sparse/irq.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sparsemem.h +  include/linux/topology.h +    $(wildcard include/config/sched/smt.h) +    $(wildcard include/config/sched/mc.h) +  include/linux/smp.h +    $(wildcard include/config/use/generic/smp/helpers.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/topology.h +    $(wildcard include/config/x86/ht.h) +    $(wildcard include/config/x86/64/acpi/numa.h) +  include/asm-generic/topology.h +  include/linux/slub_def.h +    $(wildcard include/config/slub/stats.h) +    $(wildcard include/config/slub/debug.h) +    $(wildcard include/config/kmemtrace.h) +  include/linux/kobject.h +  include/linux/sysfs.h +    $(wildcard include/config/sysfs.h) +  include/linux/kref.h +  include/linux/kmemtrace.h +  include/trace/events/kmem.h +  include/linux/tracepoint.h +    $(wildcard include/config/tracepoints.h) +  include/linux/rcupdate.h +    $(wildcard include/config/tree/preempt/rcu.h) +    $(wildcard include/config/tree/rcu.h) +  include/linux/completion.h +  include/linux/rcutree.h +  include/trace/define_trace.h +    $(wildcard include/config/event/tracing.h) +  include/linux/kmemleak.h +    $(wildcard include/config/debug/kmemleak.h) +  include/linux/netfilter.h +    $(wildcard include/config/netfilter.h) +    $(wildcard include/config/sysctl.h) +    $(wildcard include/config/netfilter/debug.h) +    $(wildcard include/config/nf/nat/needed.h) +    $(wildcard include/config/nf/conntrack.h) +  include/linux/skbuff.h +    $(wildcard include/config/bridge/netfilter.h) +    $(wildcard include/config/has/dma.h) +    $(wildcard include/config/xfrm.h) +    $(wildcard include/config/net/sched.h) +    $(wildcard include/config/net/cls/act.h) +    $(wildcard include/config/ipv6/ndisc/nodetype.h) +    $(wildcard include/config/net/dma.h) +    $(wildcard include/config/network/secmark.h) +  include/linux/kmemcheck.h +  include/linux/mm_types.h +    $(wildcard include/config/split/ptlock/cpus.h) +    $(wildcard include/config/want/page/debug/flags.h) +    $(wildcard include/config/mmu.h) +    $(wildcard include/config/aio.h) +    $(wildcard include/config/mm/owner.h) +    $(wildcard include/config/mmu/notifier.h) +  include/linux/auxvec.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/auxvec.h +  include/linux/prio_tree.h +  include/linux/rbtree.h +  include/linux/page-debug-flags.h +    $(wildcard include/config/page/poisoning.h) +    $(wildcard include/config/page/debug/something/else.h) +  include/linux/net.h +  include/linux/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/socket.h +  include/asm-generic/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sockios.h +  include/asm-generic/sockios.h +  include/linux/sockios.h +  include/linux/uio.h +  include/linux/random.h +  include/linux/irqnr.h +  include/linux/fcntl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fcntl.h +  include/asm-generic/fcntl.h +  include/linux/sysctl.h +  include/linux/textsearch.h +  include/linux/module.h +    $(wildcard include/config/modversions.h) +    $(wildcard include/config/unused/symbols.h) +    $(wildcard include/config/kallsyms.h) +    $(wildcard include/config/module/unload.h) +    $(wildcard include/config/constructors.h) +  include/linux/stat.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/stat.h +  include/linux/kmod.h +  include/linux/elf.h +  include/linux/elf-em.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/elf.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vdso.h +  include/linux/moduleparam.h +    $(wildcard include/config/alpha.h) +    $(wildcard include/config/ia64.h) +    $(wildcard include/config/ppc64.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/local.h +  include/linux/percpu.h +    $(wildcard include/config/have/legacy/per/cpu/area.h) +    $(wildcard include/config/need/per/cpu/embed/first/chunk.h) +    $(wildcard include/config/need/per/cpu/page/first/chunk.h) +  include/linux/pfn.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/module.h +    $(wildcard include/config/m586.h) +    $(wildcard include/config/m586tsc.h) +    $(wildcard include/config/m586mmx.h) +    $(wildcard include/config/mcore2.h) +    $(wildcard include/config/matom.h) +    $(wildcard include/config/m686.h) +    $(wildcard include/config/mpentiumii.h) +    $(wildcard include/config/mpentiumiii.h) +    $(wildcard include/config/mpentiumm.h) +    $(wildcard include/config/mpentium4.h) +    $(wildcard include/config/mk6.h) +    $(wildcard include/config/mk8.h) +    $(wildcard include/config/x86/elan.h) +    $(wildcard include/config/mcrusoe.h) +    $(wildcard include/config/mefficeon.h) +    $(wildcard include/config/mwinchipc6.h) +    $(wildcard include/config/mwinchip3d.h) +    $(wildcard include/config/mcyrixiii.h) +    $(wildcard include/config/mviac3/2.h) +    $(wildcard include/config/mviac7.h) +    $(wildcard include/config/mgeodegx1.h) +    $(wildcard include/config/mgeode/lx.h) +    $(wildcard include/config/4kstacks.h) +  include/asm-generic/module.h +  include/trace/events/module.h +  include/net/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess.h +    $(wildcard include/config/x86/wp/works/ok.h) +    $(wildcard include/config/x86/intel/usercopy.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum_64.h +  include/linux/dmaengine.h +    $(wildcard include/config/dma/engine.h) +    $(wildcard include/config/async/tx/dma.h) +    $(wildcard include/config/async/tx/disable/channel/switch.h) +  include/linux/device.h +    $(wildcard include/config/debug/devres.h) +    $(wildcard include/config/devtmpfs.h) +  include/linux/klist.h +  include/linux/semaphore.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/device.h +    $(wildcard include/config/dmar.h) +  include/linux/pm_wakeup.h +    $(wildcard include/config/pm.h) +  include/linux/dma-mapping.h +    $(wildcard include/config/have/dma/attrs.h) +  include/linux/dma-attrs.h +  include/linux/bug.h +  include/linux/scatterlist.h +    $(wildcard include/config/debug/sg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/scatterlist.h +  include/asm-generic/scatterlist.h +  include/linux/mm.h +    $(wildcard include/config/stack/growsup.h) +    $(wildcard include/config/swap.h) +    $(wildcard include/config/debug/pagealloc.h) +  include/linux/debug_locks.h +    $(wildcard include/config/debug/locking/api/selftests.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  include/asm-generic/pgtable.h +  include/linux/page-flags.h +    $(wildcard include/config/pageflags/extended.h) +    $(wildcard include/config/have/mlocked/page/bit.h) +    $(wildcard include/config/arch/uses/pg/uncached.h) +    $(wildcard include/config/memory/failure.h) +    $(wildcard include/config/s390.h) +  include/linux/vmstat.h +    $(wildcard include/config/vm/event/counters.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_64.h +  include/linux/vmalloc.h +  include/asm-generic/iomap.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/dma-mapping.h +    $(wildcard include/config/isa.h) +  include/linux/dma-debug.h +    $(wildcard include/config/dma/api/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swiotlb.h +    $(wildcard include/config/swiotlb.h) +  include/linux/swiotlb.h +  include/asm-generic/dma-coherent.h +    $(wildcard include/config/have/generic/dma/coherent.h) +  include/asm-generic/dma-mapping-common.h +  include/linux/hrtimer.h +    $(wildcard include/config/high/res/timers.h) +  include/linux/if.h +  include/linux/hdlc/ioctl.h +  include/linux/in.h +  include/linux/in6.h +  include/net/flow.h +  include/linux/proc_fs.h +    $(wildcard include/config/proc/devicetree.h) +    $(wildcard include/config/proc/kcore.h) +  include/linux/fs.h +    $(wildcard include/config/dnotify.h) +    $(wildcard include/config/quota.h) +    $(wildcard include/config/fsnotify.h) +    $(wildcard include/config/inotify.h) +    $(wildcard include/config/security.h) +    $(wildcard include/config/fs/posix/acl.h) +    $(wildcard include/config/epoll.h) +    $(wildcard include/config/debug/writecount.h) +    $(wildcard include/config/file/locking.h) +    $(wildcard include/config/auditsyscall.h) +    $(wildcard include/config/block.h) +    $(wildcard include/config/fs/xip.h) +    $(wildcard include/config/migration.h) +  include/linux/limits.h +  include/linux/kdev_t.h +  include/linux/dcache.h +  include/linux/rculist.h +  include/linux/path.h +  include/linux/radix-tree.h +  include/linux/pid.h +  include/linux/capability.h +    $(wildcard include/config/security/file/capabilities.h) +  include/linux/fiemap.h +  include/linux/quota.h +  include/linux/dqblk_xfs.h +  include/linux/dqblk_v1.h +  include/linux/dqblk_v2.h +  include/linux/dqblk_qtree.h +  include/linux/nfs_fs_i.h +  include/linux/nfs.h +  include/linux/sunrpc/msg_prot.h +  include/linux/inet.h +  include/linux/magic.h +  include/linux/version.h +  include/linux/kmalloc_sizes.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/rlp.h +
+/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.o: $(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.o)
+
+$(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.o):
diff -uNr nf-hipac/kernel/ihash.c nfhipac/kernel/ihash.c
--- nf-hipac/kernel/ihash.c	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/ihash.c	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,463 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#include "global.h"
+#include "ihash.h"
+
+#define MAX_BUCKETS_MINI_ALLOC    (MINI_ALLOC_MAX / sizeof(void *))
+#define INC_POSSIBLE(ihash, len)  (!(ihash)->use_mini_alloc ||     +				   (len) <= MAX_BUCKETS_MINI_ALLOC)
+#define BUCKET_SIZE(len)          (sizeof(struct ihash_bucket) + (len) * +				   sizeof(struct ihash_keyval))
+#define LEN(array)                (sizeof(array) / sizeof(*(array)))
+
+
+int
+eq_val(const void *key1, const void *key2)
+{
+	return key1 == key2;
+}
+
+__u32
+ihash_func_val(const void *key)
+{
+#ifdef BIT32_ARCH
+	/* 32 bit mix function */
+	__u32 h = (__u32) key;
+	
+	h += ~(h << 15);
+	h ^=  (h >> 10);
+	h +=  (h << 3);
+	h ^=  (h >> 6);
+	h += ~(h << 11);
+	h ^=  (h >> 16);
+#else
+	/* 64 bit mix function */
+	__u64 h = (__u64) key;
+
+	h += ~(h << 32);
+	h ^=  (h >> 22);
+	h += ~(h << 13);
+	h ^=  (h >> 8);
+	h +=  (h << 3);
+	h ^=  (h >> 15);
+	h += ~(h << 27);
+	h ^=  (h >> 31);
+#endif
+	return h;
+}
+
+int
+eq_str(const void *key1, const void *key2)
+{
+	return !strcmp(key1, key2);
+}
+
+__u32
+ihash_func_str(const void *key)
+{
+	__u32 high, h = 0;
+	const char *c = key;
+
+	if (unlikely(key == NULL)) {
+		ERR("key is NULL");
+		return 0;
+	}
+	for (; *c != ‘\0‘; c++) {
+		/* CRC variant */
+		high = h & 0xf8000000;
+		h <<= 5;
+		h ^= high >> 27;
+		h ^= *c;
+	}
+	return h;
+}
+
+static inline __u32
+near_pow2(__u32 n)
+{
+	if (n == 0 || n > 0x80000000) {
+		return 1;
+	}
+	n--;
+	n |= n >> 1;
+	n |= n >> 2;
+	n |= n >> 4;
+	n |= n >> 8;
+	n |= n >> 16;
+	return ++n;
+}
+
+struct ihash *
+ihash_new(__u32 len, int use_mini_alloc, __u32 avrg_elem_per_bucket,
+	  ihash_func_t hash_fn, eq_t eq_fn)
+{
+	struct ihash *h;
+	struct ihash_bucket **b;
+	__u32 i;
+
+	if (unlikely(hash_fn == NULL || eq_fn == NULL)) {
+		ARG_MSG;
+		return NULL;
+	}
+	h = mini_alloc(sizeof(*h));
+	if (h == NULL) {
+		return NULL;
+	}
+	if (use_mini_alloc && len > MAX_BUCKETS_MINI_ALLOC) {
+		len = MAX_BUCKETS_MINI_ALLOC;
+	} else {
+		len = near_pow2(len);
+	}
+	b = use_mini_alloc ? mini_alloc(len * sizeof(*b)) :
+		hp_alloc(len * sizeof(*b), 1);
+	if (b == NULL) {
+		mini_free(h);
+		return NULL;
+	}
+	h->hash_fn = hash_fn;
+	h->eq_fn = eq_fn;
+	h->use_mini_alloc = use_mini_alloc;
+	h->avrg_elem_per_bucket = avrg_elem_per_bucket;
+	h->len = len;
+	h->elem_ct = 0;
+	h->bucket = b;
+	/* strictly speaking memset(b, 0, len * sizeof(*b)) would be wrong
+	   here because there are architectures where the machine
+	   representation of the NULL pointer is not 0x0 */
+	for (i = 0; i < len; i++) {
+		b[i] = NULL;
+	}
+	return h;
+}
+
+void
+ihash_free(struct ihash *h)
+{
+	__u32 i;
+
+	if (unlikely(h == NULL)) {
+		ARG_MSG;
+		return;
+	}
+	for (i = 0; i < h->len; i++) {
+		if (h->bucket[i] != NULL) {
+			mini_free(h->bucket[i]);
+		}
+	}
+	if (h->use_mini_alloc) {
+		mini_free(h->bucket);
+	} else {
+		hp_free(h->bucket);
+	}
+	mini_free(h);
+}
+
+/* return values:  0 : ok
+                  -1 : low memory
+                  -2 : bucket cannot be enlarged further */
+static inline int
+insert(struct ihash *h, void *key, void *val)
+{
+	struct ihash_bucket *b;
+	__u32 i;
+
+	i = HASH(h->hash_fn, key, h->len);
+	if (h->bucket[i] == NULL) {
+		/* first element in bucket */
+		b = mini_alloc(BUCKET_SIZE(1));
+		if (b == NULL) {
+			return -1;
+		}
+		b->len = 1;
+		b->kv[0].key = key;
+		b->kv[0].val = val;
+		h->elem_ct++;
+		h->bucket[i] = b;
+		return 0;
+	}
+	if (unlikely(BUCKET_SIZE(h->bucket[i]->len + 1) > MINI_ALLOC_MAX)) {
+		/* bucket cannot be enlarged further */
+		return -2;
+	}
+	if (unlikely(mini_alloc_size(BUCKET_SIZE(h->bucket[i]->len)) !=
+		     mini_alloc_size(BUCKET_SIZE(h->bucket[i]->len + 1)))) {
+		/* bucket must be enlarged */
+		b = mini_alloc(BUCKET_SIZE(h->bucket[i]->len + 1));
+		if (b == NULL) {
+			return -1;
+		}
+		b->len = h->bucket[i]->len + 1;
+		b->kv[0].key = key;
+		b->kv[0].val = val;
+		memcpy(&b->kv[1], &h->bucket[i]->kv[0],
+		       h->bucket[i]->len * sizeof(*b->kv));
+		h->elem_ct++;
+		mini_free(h->bucket[i]);
+		h->bucket[i] = b;
+		return 0;
+	}
+
+	h->bucket[i]->kv[h->bucket[i]->len].key = key;
+	h->bucket[i]->kv[h->bucket[i]->len].val = val;
+	h->bucket[i]->len++;
+	h->elem_ct++;
+	return 0;
+}
+
+/* return values like insert */
+static inline int
+rehash(struct ihash *h_old, struct ihash *h_new)
+{
+	__u32 i, j;
+	int stat;
+
+	for (i = 0; i < h_old->len; i++) {
+		if (h_old->bucket[i] == NULL) {
+			continue;
+		}
+		for (j = 0; j < h_old->bucket[i]->len; j++) {
+			stat = insert(
+				h_new, h_old->bucket[i]->kv[j].key,
+				h_old->bucket[i]->kv[j].val);
+			if (stat < 0) {
+				return stat;
+			}
+		}
+	}
+	return 0;
+}
+
+hipac_error
+ihash_insert(struct ihash **h, void *key, void *val)
+{
+	int shift = 1;
+	int do_inc = 0;
+	int stat;
+	__u32 len;
+	
+	if (unlikely(h == NULL || *h == NULL || key == NULL)) {
+		ARG_ERR;
+	}
+	len = (*h)->len;
+	while (1) {
+		if (unlikely((do_inc || (*h)->elem_ct >=
+			      len * (*h)->avrg_elem_per_bucket) &&
+			     INC_POSSIBLE(*h, len << shift))) {
+			/* increase hash table */
+			struct ihash *new;
+			
+			new = ihash_new(len << shift, (*h)->use_mini_alloc,
+					(*h)->avrg_elem_per_bucket,
+					(*h)->hash_fn, (*h)->eq_fn);
+			if (new == NULL) {
+				return HE_LOW_MEMORY;
+			}
+			stat = rehash(*h, new);
+			if (stat < 0) {
+				ihash_free(new);
+				if (stat == -2 &&
+				    INC_POSSIBLE(*h, len << ++shift)) {
+					WARN_("ihash bucket full after rehash "
+					     "-> try again with more buckets");
+					continue;
+				}
+				return HE_LOW_MEMORY;
+			}
+			ihash_free(*h);
+			*h = new;
+			do_inc = 0;
+		}
+		stat = insert(*h, key, val);
+		if (stat < 0) {
+			if (stat == -2 &&
+			    (((*h)->elem_ct <
+			      len * (*h)->avrg_elem_per_bucket &&
+			      INC_POSSIBLE(*h, len << shift)) ||
+			     INC_POSSIBLE(*h, len << ++shift))) {
+				WARN_("ihash bucket full after rehash -> try "
+				     "again with more buckets");
+				do_inc = 1;
+				continue;
+			}
+			return HE_LOW_MEMORY;
+		}
+		return HE_OK;
+	}
+}
+
+static inline void
+delete(struct ihash *h, int i, int j, void **val)
+{
+	struct ihash_bucket *b;
+	
+	if (unlikely(mini_alloc_size(BUCKET_SIZE(h->bucket[i]->len)) !=
+		     mini_alloc_size(BUCKET_SIZE(h->bucket[i]->len - 1)))) {
+		/* shrink bucket */
+		b = mini_alloc(BUCKET_SIZE(h->bucket[i]->len - 1));
+		if (b != NULL) {
+			b->len = h->bucket[i]->len - 1;
+			if (j > 0) {
+				memcpy(b->kv, h->bucket[i]->kv,
+				       j * sizeof(*b->kv));
+			}
+			if (h->bucket[i]->len > j + 1) {
+				memcpy(&b->kv[j], &h->bucket[i]->kv[j+1],
+				       (h->bucket[i]->len - j - 1) *
+				       sizeof(*b->kv));
+			}
+			if (val != NULL) {
+				*val = h->bucket[i]->kv[j].val;
+			}
+			mini_free(h->bucket[i]);
+			h->bucket[i] = b;
+			h->elem_ct--;
+			return;
+		} else {
+			WARN_("unable to shrink ihash bucket");
+		}
+	}
+	
+ 	if (val != NULL) {
+		*val = h->bucket[i]->kv[j].val;
+	}
+	if (h->bucket[i]->len > j + 1) {
+		memmove(&h->bucket[i]->kv[j], &h->bucket[i]->kv[j + 1],
+			(h->bucket[i]->len - j - 1) * sizeof(*b->kv));
+	}
+	h->bucket[i]->len--;
+	h->elem_ct--;
+}
+
+hipac_error
+ihash_delete(struct ihash *h, const void *key, void **val)
+{
+	int i, j;
+
+	if (unlikely(h == NULL || key == NULL)) {
+		ARG_ERR;
+	}
+	i = HASH(h->hash_fn, key, h->len);
+	if (unlikely(h->bucket[i] == NULL)) {
+		goto not_contained;
+	}
+	for (j = h->bucket[i]->len - 1; j >= 0; j--) {
+		if (h->eq_fn(h->bucket[i]->kv[j].key, key)) {
+			delete(h, i, j, val);
+			return HE_OK;
+		}
+	}
+	
+ not_contained:
+	IMPOSSIBLE_CONDITION("key not contained in ihash");
+}
+
+hipac_error
+ihash_replace(struct ihash **h, const void *oldkey, void **oldval,
+	      void *newkey, void *newval)
+{
+	int i, j, stat;
+	
+	if (unlikely(h == NULL || *h == NULL || oldkey == NULL ||
+		     newkey == NULL)) {
+		ARG_ERR;
+	}
+	i = HASH((*h)->hash_fn, oldkey, (*h)->len);
+	if (unlikely((*h)->bucket[i] == NULL)) {
+		goto not_contained;
+	}
+	if (i != HASH((*h)->hash_fn, newkey, (*h)->len)) {
+		stat = ihash_insert(h, newkey, newval);
+		if (unlikely(stat < 0)) {
+			if (stat != HE_LOW_MEMORY) {
+				IMPOSSIBLE_CONDITION("ihash insert failed for"
+						     " another reason than "
+						     "low memory");
+			}
+			return stat;
+		}
+		/* a rehash might have occured so i must be recomputed */
+		i = HASH((*h)->hash_fn, oldkey, (*h)->len);
+		for (j = (*h)->bucket[i]->len - 1; j >= 0; j--) {
+			if ((*h)->eq_fn((*h)->bucket[i]->kv[j].key, oldkey)) {
+				delete(*h, i, j, oldval);
+				return HE_OK;
+			}
+		}
+		/* oldkey is not contained in h */
+		i = HASH((*h)->hash_fn, newkey, (*h)->len);
+		for (j = (*h)->bucket[i]->len - 1; j >= 0; j--) {
+			if ((*h)->eq_fn((*h)->bucket[i]->kv[j].key, newkey)) {
+				delete(*h, i, j, NULL);
+				goto not_contained;
+			}
+		}
+		IMPOSSIBLE_CONDITION("newkey not contained in ihash although "
+				     "it has been inserted");
+	}
+	for (j = (*h)->bucket[i]->len - 1; j >= 0; j--) {
+		if ((*h)->eq_fn((*h)->bucket[i]->kv[j].key, oldkey)) {
+			if (oldval != NULL) {
+				*oldval = (*h)->bucket[i]->kv[j].val;
+			}
+			(*h)->bucket[i]->kv[j].key = newkey;
+			(*h)->bucket[i]->kv[j].val = newval;
+			return HE_OK;
+		}
+	}
+
+ not_contained:
+	IMPOSSIBLE_CONDITION("oldkey not contained in ihash");
+}
+
+hipac_error
+ihash_stat(struct ihash *h, struct ihash_stat *stat)
+{
+	__u32 i;
+
+	if (unlikely(h == NULL || stat == NULL)) {
+		ARG_ERR;
+	}
+
+	stat->elem_ct = h->elem_ct;
+	stat->bucket_len = h->len;
+	stat->small_bucket_len = 0xffffffff;
+	stat->big_bucket_len = 0;
+	stat_distribution_init(stat->bucket_dist, LEN(stat->bucket_dist));
+
+	for (i = 0; i < h->len; i++) {
+		if (h->bucket[i] == NULL) {
+			stat->small_bucket_len = 0;
+			stat_distribution_add(stat->bucket_dist,
+					      LEN(stat->bucket_dist), 0);
+			continue;
+		}
+		if (h->bucket[i]->len < stat->small_bucket_len) {
+			stat->small_bucket_len = h->bucket[i]->len;
+		}
+		if (h->bucket[i]->len > stat->big_bucket_len) {
+			stat->big_bucket_len = h->bucket[i]->len;
+		}
+		stat_distribution_add(stat->bucket_dist,
+				      LEN(stat->bucket_dist),
+				      h->bucket[i]->len);
+	}
+	return HE_OK;
+}
diff -uNr nf-hipac/kernel/ihash.h nfhipac/kernel/ihash.h
--- nf-hipac/kernel/ihash.h	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/ihash.h	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,285 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#ifndef _IHASH_H
+#define _IHASH_H
+
+#include "mode.h"
+#include "global.h"  // hipac_error and error message macros
+
+#define HASH(fn, key, len) (fn(key) & ((len) - 1))
+
+typedef __u32 (*ihash_func_t) (const void *key);
+typedef int (*eq_t) (const void *key1, const void *key2);
+
+struct ihash_keyval
+{
+	void *key, *val;
+};
+
+struct ihash_bucket
+{
+	__u32 len;
+	struct ihash_keyval kv[0];
+};
+
+struct ihash
+{
+	ihash_func_t hash_fn;
+	eq_t eq_fn;
+	int use_mini_alloc;
+	__u32 len, elem_ct, avrg_elem_per_bucket;
+	struct ihash_bucket **bucket;
+};
+
+struct ihash_stat
+{
+	__u32 elem_ct;
+	__u32 bucket_len, small_bucket_len, big_bucket_len;
+	/* bucket_dist[i] (0 <= i <= 14) contains the number of buckets
+	   with <= 2^i - 1 (and >= 2^(i-1) if i > 0) elements; 
+	   bucket_dist[15] contains the number of buckets with >= 2^14
+	   elements */
+	__u32 bucket_dist[16];
+};
+
+
+/* equality and hash function for strings as keys */
+int
+eq_str(const void *key1, const void *key2);
+
+__u32
+ihash_func_str(const void *key);
+
+
+/* equality and hash function for values as keys */
+int
+eq_val(const void *key1, const void *key2);
+
+__u32
+ihash_func_val(const void *key);
+
+/* if the value of the (key, val) pair is not a pointer but a value ptr_to_val
+   and val_to_ptr serve as a conversion functions */
+static inline __u64
+ptr_to_val(const void *p)
+{
+#ifdef BIT32_ARCH
+	return (__u32) p;
+#else
+	return (__u64) p;
+#endif
+}
+
+static inline void *
+val_to_ptr(__u64 v)
+{
+#ifdef BIT32_ARCH
+	return (void *) (__u32) v;
+#else
+	return (void *) v;
+#endif
+}
+
+
+/* create new hash table with len‘ buckets whereby len‘ is the nearest power
+   of two >= len; if use_mini_alloc is not 0 then mini_alloc is used to
+   allcate the bucket pointer array, otherwise hp_alloc is used;
+   avrg_elem_per_bucket indicates how many elements per bucket are allowed
+   at maximum assuming that they are equally distributed; in the case
+   use_mini_alloc is not 0 and the bucket pointer array cannot be further
+   enlarged the average number of elements per bucket may be larger */
+struct ihash *
+ihash_new(__u32 len, int use_mini_alloc, __u32 avrg_elem_per_bucket,
+	  ihash_func_t hash_fn, eq_t eq_fn);
+
+void
+ihash_free(struct ihash *h);
+
+/* key must not be contained in h (this is not checked);
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ihash_insert(struct ihash **h, void *key, void *val);
+
+/* delete key and the corresponding value v from h; v stored in *val if val
+   is not NULL; key must be contained in h;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ihash_delete(struct ihash *h, const void *key, void **val);
+
+/* replace oldkey and the corresponding value v by newkey and newval; v is
+   stored in *oldval if oldval is not NULL; oldkey must be contained in h;
+   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ihash_replace(struct ihash **h, const void *oldkey, void **oldval,
+	      void *newkey, void *newval);
+
+/* compute statistical info about h;
+   possible errors: HE_IMPOSSIBLE_CONDITION */
+hipac_error
+ihash_stat(struct ihash *h, struct ihash_stat *stat);
+
+/* generic lookup function */
+static inline void *
+ihash_lookup(const struct ihash *h, const void *key)
+{
+	__u32 i;
+	struct ihash_keyval *kv, *end;
+
+	if (unlikely(h == NULL || key == NULL)) {
+		ARG_MSG;
+		return NULL;
+	}
+	i = HASH(h->hash_fn, key, h->len);
+	if (h->bucket[i] == NULL) {
+		return NULL;
+	}
+	end = h->bucket[i]->kv + h->bucket[i]->len;
+	for (kv = h->bucket[i]->kv; kv < end; kv++) {
+		if (h->eq_fn(kv->key, key)) {
+			return kv->val;
+		}
+	}
+	return NULL;
+}
+
+/* optimized lookup function if keys are values */
+static inline void *
+ihash_lookup_val(const struct ihash *h, const void *key)
+{
+	__u32 i;
+	struct ihash_keyval *kv, *end;
+
+	if (unlikely(h == NULL || key == NULL)) {
+		ARG_MSG;
+		return NULL;
+	}
+	i = HASH(ihash_func_val, key, h->len);
+	if (h->bucket[i] == NULL) {
+		return NULL;
+	}
+	end = h->bucket[i]->kv + h->bucket[i]->len;
+	for (kv = h->bucket[i]->kv; kv < end; kv++) {
+		if (kv->key == key) {
+			return kv->val;
+		}
+	}
+	return NULL;
+}
+
+/* optimized lookup function if keys are strings */
+static inline void *
+ihash_lookup_str(const struct ihash *h, const void *key)
+{
+	__u32 i;
+	struct ihash_keyval *kv, *end;
+
+	if (unlikely(h == NULL || key == NULL)) {
+		ARG_MSG;
+		return NULL;
+	}
+	i = HASH(ihash_func_str, key, h->len);
+	if (i < 0 || i >= h->len || h->bucket[i] == NULL) {
+		return NULL;
+	}
+	end = h->bucket[i]->kv + h->bucket[i]->len;
+	for (kv = h->bucket[i]->kv; kv < end; kv++) {
+		if (!strcmp(kv->key, key)) {
+			return kv->val;
+		}
+	}
+	return NULL;
+}
+
+/* call fn(key) for all keys of h */
+#define IHASH_KEY_ITERATE(h, cast, fn, args...)                           +do {                                                                      +	__u32 i, j;                                                       +                                                                          +	if (unlikely((h) == NULL)) {                                      +		ARG_MSG;                                                  +		break;                                                    +	}                                                                 +	for (i = 0; i < (h)->len; i++) {                                  +                if ((h)->bucket[i] == NULL) {                             +                        continue;                                         +                }                                                         +		for (j = 0; j < (h)->bucket[i]->len; j++) {               +			(fn)((cast) (h)->bucket[i]->kv[j].key , ## args); +		}                                                         +	}                                                                 +} while (0)
+
+/* call fn(val) for all values of h */
+#define IHASH_VAL_ITERATE(h, cast, fn, args...)                           +do {                                                                      +	__u32 i, j;                                                       +                                                                          +	if (unlikely((h) == NULL)) {                                      +		ARG_MSG;                                                  +		break;                                                    +	}                                                                 +	for (i = 0; i < (h)->len; i++) {                                  +                if ((h)->bucket[i] == NULL) {                             +                        continue;                                         +                }                                                         +		for (j = 0; j < (h)->bucket[i]->len; j++) {               +			(fn)((cast) (h)->bucket[i]->kv[j].val , ## args); +		}                                                         +	}                                                                 +} while (0)
+
+/* use the following macros to iterate over all (key, val) pairs in hash:
+   IHASH_FOR_EACH(hash, key, val) {
+           // do something with key, val
+           IHASH_FOR_EACH_END;
+   }
+   IHASH_FOR_EACH_KEY and IHASH_FOR_EACH_VAL are used similarly */
+#define IHASH_FOR_EACH(h, hkey, hval)                                     +{                                                                         +	__u32 _ihash_i, _ihash_j;                                         +	for (_ihash_i = 0; _ihash_i < (h)->len; _ihash_i++) {             +		if ((h)->bucket[_ihash_i] == NULL) {                      +			continue;                                         +		}                                                         +		for (_ihash_j = 0; _ihash_j < (h)->bucket[_ihash_i]->len; +		     _ihash_j++) {                                        +			(hkey) = (h)->bucket[_ihash_i]->kv[_ihash_j].key; +			(hval) = (h)->bucket[_ihash_i]->kv[_ihash_j].val;
+
+#define IHASH_FOR_EACH_KEY(h, hkey)                                       +{                                                                         +	__u32 _ihash_i, _ihash_j;                                         +	for (_ihash_i = 0; _ihash_i < (h)->len; _ihash_i++) {             +		if ((h)->bucket[_ihash_i] == NULL) {                      +			continue;                                         +		}                                                         +		for (_ihash_j = 0; _ihash_j < (h)->bucket[_ihash_i]->len; +		     _ihash_j++) {                                        +			(hkey) = (h)->bucket[_ihash_i]->kv[_ihash_j].key;
+
+#define IHASH_FOR_EACH_VAL(h, hval)                                       +{                                                                         +	__u32 _ihash_i, _ihash_j;                                         +	for (_ihash_i = 0; _ihash_i < (h)->len; _ihash_i++) {             +		if ((h)->bucket[_ihash_i] == NULL) {                      +			continue;                                         +		}                                                         +		for (_ihash_j = 0; _ihash_j < (h)->bucket[_ihash_i]->len; +		     _ihash_j++) {                                        +			(hval) = (h)->bucket[_ihash_i]->kv[_ihash_j].val;
+
+#define IHASH_FOR_EACH_END }}} do {} while (0)
+
+#endif
Binary files nf-hipac/kernel/ihash.o and nfhipac/kernel/ihash.o differ
diff -uNr nf-hipac/kernel/.ihash.o.cmd nfhipac/kernel/.ihash.o.cmd
--- nf-hipac/kernel/.ihash.o.cmd	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/.ihash.o.cmd	2014-11-21 12:54:40.000000000 +0800
@@ -0,0 +1,587 @@
+cmd_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.o := gcc -Wp,-MD,/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.ihash.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include -Iinclude  -I/usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include -include include/linux/autoconf.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -Wframe-larger-than=2048 -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-dwarf2-cfi-asm -fconserve-stack -D SINGLE_PATH  -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(ihash)"  -D"KBUILD_MODNAME=KBUILD_STR(nf_hipac)"  -c -o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.tmp_ihash.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.c
+
+deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.o := +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.c +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/mode.h +    $(wildcard include/config/uml/net.h) +    $(wildcard include/config/host/2g/2g.h) +    $(wildcard include/config/nest/level.h) +    $(wildcard include/config/kernel/half/gigs.h) +  include/linux/stddef.h +  include/linux/compiler.h +    $(wildcard include/config/trace/branch/profiling.h) +    $(wildcard include/config/profile/all/branches.h) +    $(wildcard include/config/enable/must/check.h) +    $(wildcard include/config/enable/warn/deprecated.h) +  include/linux/compiler-gcc.h +    $(wildcard include/config/arch/supports/optimized/inlining.h) +    $(wildcard include/config/optimize/inlining.h) +  include/linux/compiler-gcc4.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page.h +    $(wildcard include/config/x86/64.h) +  include/linux/types.h +    $(wildcard include/config/uid16.h) +    $(wildcard include/config/lbdaf.h) +    $(wildcard include/config/phys/addr/t/64bit.h) +    $(wildcard include/config/64bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/types.h +    $(wildcard include/config/highmem64g.h) +  include/asm-generic/types.h +  include/asm-generic/int-ll64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitsperlong.h +  include/asm-generic/bitsperlong.h +  include/linux/posix_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types.h +    $(wildcard include/config/x86/32.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_types.h +  include/linux/const.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64_types.h +    $(wildcard include/config/physical/start.h) +    $(wildcard include/config/physical/align.h) +    $(wildcard include/config/flatmem.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64.h +  include/asm-generic/memory_model.h +    $(wildcard include/config/discontigmem.h) +    $(wildcard include/config/sparsemem/vmemmap.h) +    $(wildcard include/config/sparsemem.h) +  include/asm-generic/getorder.h +  include/linux/slab.h +    $(wildcard include/config/slab/debug.h) +    $(wildcard include/config/debug/objects.h) +    $(wildcard include/config/kmemcheck.h) +    $(wildcard include/config/slub.h) +    $(wildcard include/config/slob.h) +    $(wildcard include/config/numa.h) +    $(wildcard include/config/debug/slab.h) +  include/linux/gfp.h +    $(wildcard include/config/highmem.h) +    $(wildcard include/config/zone/dma.h) +    $(wildcard include/config/zone/dma32.h) +    $(wildcard include/config/debug/vm.h) +  include/linux/mmzone.h +    $(wildcard include/config/force/max/zoneorder.h) +    $(wildcard include/config/smp.h) +    $(wildcard include/config/memory/hotplug.h) +    $(wildcard include/config/arch/populates/node/map.h) +    $(wildcard include/config/flat/node/mem/map.h) +    $(wildcard include/config/cgroup/mem/res/ctlr.h) +    $(wildcard include/config/have/memory/present.h) +    $(wildcard include/config/need/node/memmap/size.h) +    $(wildcard include/config/need/multiple/nodes.h) +    $(wildcard include/config/have/arch/early/pfn/to/nid.h) +    $(wildcard include/config/sparsemem/extreme.h) +    $(wildcard include/config/nodes/span/other/nodes.h) +    $(wildcard include/config/holes/in/zone.h) +    $(wildcard include/config/arch/has/holes/memorymodel.h) +  include/linux/spinlock.h +    $(wildcard include/config/debug/spinlock.h) +    $(wildcard include/config/generic/lockbreak.h) +    $(wildcard include/config/preempt.h) +    $(wildcard include/config/debug/lock/alloc.h) +  include/linux/typecheck.h +  include/linux/preempt.h +    $(wildcard include/config/debug/preempt.h) +    $(wildcard include/config/preempt/tracer.h) +    $(wildcard include/config/preempt/notifiers.h) +  include/linux/thread_info.h +    $(wildcard include/config/compat.h) +  include/linux/bitops.h +    $(wildcard include/config/generic/find/first/bit.h) +    $(wildcard include/config/generic/find/last/bit.h) +    $(wildcard include/config/generic/find/next/bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitops.h +    $(wildcard include/config/x86/cmov.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/alternative.h +    $(wildcard include/config/paravirt.h) +  include/linux/stringify.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/asm.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpufeature.h +    $(wildcard include/config/x86/invlpg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/required-features.h +    $(wildcard include/config/x86/minimum/cpu/family.h) +    $(wildcard include/config/math/emulation.h) +    $(wildcard include/config/x86/pae.h) +    $(wildcard include/config/x86/cmpxchg64.h) +    $(wildcard include/config/x86/use/3dnow.h) +    $(wildcard include/config/x86/p6/nop.h) +  include/asm-generic/bitops/sched.h +  include/asm-generic/bitops/hweight.h +  include/asm-generic/bitops/fls64.h +  include/asm-generic/bitops/ext2-non-atomic.h +  include/asm-generic/bitops/le.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/byteorder.h +  include/linux/byteorder/little_endian.h +  include/linux/swab.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swab.h +    $(wildcard include/config/x86/bswap.h) +  include/linux/byteorder/generic.h +  include/asm-generic/bitops/minix.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/thread_info.h +    $(wildcard include/config/debug/stack/usage.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor.h +    $(wildcard include/config/x86/vsmp.h) +    $(wildcard include/config/cc/stackprotector.h) +    $(wildcard include/config/m386.h) +    $(wildcard include/config/m486.h) +    $(wildcard include/config/x86/debugctlmsr.h) +    $(wildcard include/config/cpu/sup/amd.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor-flags.h +    $(wildcard include/config/vm86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vm86.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace.h +    $(wildcard include/config/x86/ptrace/bts.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace-abi.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/segment.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cache.h +    $(wildcard include/config/x86/l1/cache/shift.h) +  include/linux/linkage.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/linkage.h +    $(wildcard include/config/x86/alignment/16.h) +  include/linux/init.h +    $(wildcard include/config/modules.h) +    $(wildcard include/config/hotplug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/math_emu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sigcontext.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/current.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/percpu.h +    $(wildcard include/config/x86/64/smp.h) +  include/linux/kernel.h +    $(wildcard include/config/preempt/voluntary.h) +    $(wildcard include/config/debug/spinlock/sleep.h) +    $(wildcard include/config/prove/locking.h) +    $(wildcard include/config/printk.h) +    $(wildcard include/config/dynamic/debug.h) +    $(wildcard include/config/ring/buffer.h) +    $(wildcard include/config/tracing.h) +    $(wildcard include/config/ftrace/mcount/record.h) +  /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h +  include/linux/log2.h +    $(wildcard include/config/arch/has/ilog2/u32.h) +    $(wildcard include/config/arch/has/ilog2/u64.h) +  include/linux/ratelimit.h +  include/linux/param.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/param.h +  include/asm-generic/param.h +    $(wildcard include/config/hz.h) +  include/linux/dynamic_debug.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bug.h +    $(wildcard include/config/bug.h) +    $(wildcard include/config/debug/bugverbose.h) +  include/asm-generic/bug.h +    $(wildcard include/config/generic/bug.h) +    $(wildcard include/config/generic/bug/relative/pointers.h) +  include/asm-generic/percpu.h +    $(wildcard include/config/have/setup/per/cpu/area.h) +  include/linux/threads.h +    $(wildcard include/config/nr/cpus.h) +    $(wildcard include/config/base/small.h) +  include/linux/percpu-defs.h +    $(wildcard include/config/debug/force/weak/per/cpu.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/system.h +    $(wildcard include/config/ia32/emulation.h) +    $(wildcard include/config/x86/32/lazy/gs.h) +    $(wildcard include/config/x86/ppro/fence.h) +    $(wildcard include/config/x86/oostore.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/nops.h +    $(wildcard include/config/mk7.h) +  include/linux/irqflags.h +    $(wildcard include/config/trace/irqflags.h) +    $(wildcard include/config/irqsoff/tracer.h) +    $(wildcard include/config/trace/irqflags/support.h) +    $(wildcard include/config/x86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irqflags.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt.h +    $(wildcard include/config/highpte.h) +    $(wildcard include/config/paravirt/spinlocks.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_types.h +    $(wildcard include/config/compat/vdso.h) +    $(wildcard include/config/proc/fs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt_types.h +    $(wildcard include/config/x86/local/apic.h) +    $(wildcard include/config/paravirt/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/desc_defs.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/kmap_types.h +    $(wildcard include/config/debug/highmem.h) +  include/asm-generic/kmap_types.h +  include/linux/cpumask.h +    $(wildcard include/config/cpumask/offstack.h) +    $(wildcard include/config/hotplug/cpu.h) +    $(wildcard include/config/debug/per/cpu/maps.h) +    $(wildcard include/config/disable/obsolete/cpumask/functions.h) +  include/linux/bitmap.h +  include/linux/string.h +    $(wildcard include/config/binary/printf.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr-index.h +  include/linux/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ioctl.h +  include/asm-generic/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/errno.h +  include/asm-generic/errno.h +  include/asm-generic/errno-base.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpumask.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ds.h +    $(wildcard include/config/x86/ds.h) +  include/linux/err.h +  include/linux/personality.h +  include/linux/cache.h +    $(wildcard include/config/arch/has/cache/line/size.h) +  include/linux/math64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/div64.h +  include/asm-generic/div64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ftrace.h +    $(wildcard include/config/function/tracer.h) +    $(wildcard include/config/dynamic/ftrace.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic_64.h +  include/asm-generic/atomic-long.h +  include/linux/list.h +    $(wildcard include/config/debug/list.h) +  include/linux/poison.h +    $(wildcard include/config/illegal/pointer/value.h) +  include/linux/prefetch.h +  include/linux/bottom_half.h +  include/linux/spinlock_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock_types.h +  include/linux/lockdep.h +    $(wildcard include/config/lockdep.h) +    $(wildcard include/config/lock/stat.h) +    $(wildcard include/config/generic/hardirqs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwlock.h +  include/linux/spinlock_api_smp.h +  include/linux/wait.h +  include/linux/numa.h +    $(wildcard include/config/nodes/shift.h) +  include/linux/seqlock.h +  include/linux/nodemask.h +  include/linux/pageblock-flags.h +    $(wildcard include/config/hugetlb/page.h) +    $(wildcard include/config/hugetlb/page/size/variable.h) +  include/linux/bounds.h +  include/linux/memory_hotplug.h +    $(wildcard include/config/have/arch/nodedata/extension.h) +    $(wildcard include/config/memory/hotremove.h) +  include/linux/notifier.h +  include/linux/errno.h +  include/linux/mutex.h +    $(wildcard include/config/debug/mutexes.h) +  include/linux/rwsem.h +    $(wildcard include/config/rwsem/generic/spinlock.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwsem.h +  include/linux/srcu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone_64.h +    $(wildcard include/config/numa/emu.h) +  include/linux/mmdebug.h +    $(wildcard include/config/debug/virtual.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/smp.h +    $(wildcard include/config/x86/io/apic.h) +    $(wildcard include/config/x86/32/smp.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec.h +    $(wildcard include/config/x86/numaq.h) +    $(wildcard include/config/mca.h) +    $(wildcard include/config/eisa.h) +    $(wildcard include/config/x86/mpparse.h) +    $(wildcard include/config/acpi.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec_def.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/x86_init.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bootparam.h +  include/linux/screen_info.h +  include/linux/apm_bios.h +  include/linux/edd.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/e820.h +    $(wildcard include/config/efi.h) +    $(wildcard include/config/hibernation.h) +    $(wildcard include/config/memtest.h) +  include/linux/ioport.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ist.h +  include/video/edid.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apic.h +    $(wildcard include/config/x86/x2apic.h) +  include/linux/delay.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/delay.h +  include/linux/pm.h +    $(wildcard include/config/pm/sleep.h) +    $(wildcard include/config/pm/runtime.h) +  include/linux/workqueue.h +  include/linux/timer.h +    $(wildcard include/config/timer/stats.h) +    $(wildcard include/config/debug/objects/timers.h) +  include/linux/ktime.h +    $(wildcard include/config/ktime/scalar.h) +  include/linux/time.h +    $(wildcard include/config/arch/uses/gettimeoffset.h) +  include/linux/jiffies.h +  include/linux/timex.h +    $(wildcard include/config/no/hz.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/timex.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/tsc.h +    $(wildcard include/config/x86/tsc.h) +  include/linux/debugobjects.h +    $(wildcard include/config/debug/objects/free.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apicdef.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fixmap.h +    $(wildcard include/config/provide/ohci1394/dma/init.h) +    $(wildcard include/config/x86/visws/apic.h) +    $(wildcard include/config/x86/f00f/bug.h) +    $(wildcard include/config/x86/cyclone/timer.h) +    $(wildcard include/config/pci/mmconfig.h) +    $(wildcard include/config/intel/txt.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/acpi.h +    $(wildcard include/config/acpi/numa.h) +  include/acpi/pdc_intel.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vsyscall.h +    $(wildcard include/config/generic/time.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_apic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irq_vectors.h +    $(wildcard include/config/sparse/irq.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sparsemem.h +  include/linux/topology.h +    $(wildcard include/config/sched/smt.h) +    $(wildcard include/config/sched/mc.h) +  include/linux/smp.h +    $(wildcard include/config/use/generic/smp/helpers.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/topology.h +    $(wildcard include/config/x86/ht.h) +    $(wildcard include/config/x86/64/acpi/numa.h) +  include/asm-generic/topology.h +  include/linux/slub_def.h +    $(wildcard include/config/slub/stats.h) +    $(wildcard include/config/slub/debug.h) +    $(wildcard include/config/kmemtrace.h) +  include/linux/kobject.h +  include/linux/sysfs.h +    $(wildcard include/config/sysfs.h) +  include/linux/kref.h +  include/linux/kmemtrace.h +  include/trace/events/kmem.h +  include/linux/tracepoint.h +    $(wildcard include/config/tracepoints.h) +  include/linux/rcupdate.h +    $(wildcard include/config/tree/preempt/rcu.h) +    $(wildcard include/config/tree/rcu.h) +  include/linux/completion.h +  include/linux/rcutree.h +  include/trace/define_trace.h +    $(wildcard include/config/event/tracing.h) +  include/linux/kmemleak.h +    $(wildcard include/config/debug/kmemleak.h) +  include/linux/netfilter.h +    $(wildcard include/config/netfilter.h) +    $(wildcard include/config/sysctl.h) +    $(wildcard include/config/netfilter/debug.h) +    $(wildcard include/config/nf/nat/needed.h) +    $(wildcard include/config/nf/conntrack.h) +  include/linux/skbuff.h +    $(wildcard include/config/bridge/netfilter.h) +    $(wildcard include/config/has/dma.h) +    $(wildcard include/config/xfrm.h) +    $(wildcard include/config/net/sched.h) +    $(wildcard include/config/net/cls/act.h) +    $(wildcard include/config/ipv6/ndisc/nodetype.h) +    $(wildcard include/config/net/dma.h) +    $(wildcard include/config/network/secmark.h) +  include/linux/kmemcheck.h +  include/linux/mm_types.h +    $(wildcard include/config/split/ptlock/cpus.h) +    $(wildcard include/config/want/page/debug/flags.h) +    $(wildcard include/config/mmu.h) +    $(wildcard include/config/aio.h) +    $(wildcard include/config/mm/owner.h) +    $(wildcard include/config/mmu/notifier.h) +  include/linux/auxvec.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/auxvec.h +  include/linux/prio_tree.h +  include/linux/rbtree.h +  include/linux/page-debug-flags.h +    $(wildcard include/config/page/poisoning.h) +    $(wildcard include/config/page/debug/something/else.h) +  include/linux/net.h +  include/linux/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/socket.h +  include/asm-generic/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sockios.h +  include/asm-generic/sockios.h +  include/linux/sockios.h +  include/linux/uio.h +  include/linux/random.h +  include/linux/irqnr.h +  include/linux/fcntl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fcntl.h +  include/asm-generic/fcntl.h +  include/linux/sysctl.h +  include/linux/textsearch.h +  include/linux/module.h +    $(wildcard include/config/modversions.h) +    $(wildcard include/config/unused/symbols.h) +    $(wildcard include/config/kallsyms.h) +    $(wildcard include/config/module/unload.h) +    $(wildcard include/config/constructors.h) +  include/linux/stat.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/stat.h +  include/linux/kmod.h +  include/linux/elf.h +  include/linux/elf-em.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/elf.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vdso.h +  include/linux/moduleparam.h +    $(wildcard include/config/alpha.h) +    $(wildcard include/config/ia64.h) +    $(wildcard include/config/ppc64.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/local.h +  include/linux/percpu.h +    $(wildcard include/config/have/legacy/per/cpu/area.h) +    $(wildcard include/config/need/per/cpu/embed/first/chunk.h) +    $(wildcard include/config/need/per/cpu/page/first/chunk.h) +  include/linux/pfn.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/module.h +    $(wildcard include/config/m586.h) +    $(wildcard include/config/m586tsc.h) +    $(wildcard include/config/m586mmx.h) +    $(wildcard include/config/mcore2.h) +    $(wildcard include/config/matom.h) +    $(wildcard include/config/m686.h) +    $(wildcard include/config/mpentiumii.h) +    $(wildcard include/config/mpentiumiii.h) +    $(wildcard include/config/mpentiumm.h) +    $(wildcard include/config/mpentium4.h) +    $(wildcard include/config/mk6.h) +    $(wildcard include/config/mk8.h) +    $(wildcard include/config/x86/elan.h) +    $(wildcard include/config/mcrusoe.h) +    $(wildcard include/config/mefficeon.h) +    $(wildcard include/config/mwinchipc6.h) +    $(wildcard include/config/mwinchip3d.h) +    $(wildcard include/config/mcyrixiii.h) +    $(wildcard include/config/mviac3/2.h) +    $(wildcard include/config/mviac7.h) +    $(wildcard include/config/mgeodegx1.h) +    $(wildcard include/config/mgeode/lx.h) +    $(wildcard include/config/4kstacks.h) +  include/asm-generic/module.h +  include/trace/events/module.h +  include/net/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess.h +    $(wildcard include/config/x86/wp/works/ok.h) +    $(wildcard include/config/x86/intel/usercopy.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum_64.h +  include/linux/dmaengine.h +    $(wildcard include/config/dma/engine.h) +    $(wildcard include/config/async/tx/dma.h) +    $(wildcard include/config/async/tx/disable/channel/switch.h) +  include/linux/device.h +    $(wildcard include/config/debug/devres.h) +    $(wildcard include/config/devtmpfs.h) +  include/linux/klist.h +  include/linux/semaphore.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/device.h +    $(wildcard include/config/dmar.h) +  include/linux/pm_wakeup.h +    $(wildcard include/config/pm.h) +  include/linux/dma-mapping.h +    $(wildcard include/config/have/dma/attrs.h) +  include/linux/dma-attrs.h +  include/linux/bug.h +  include/linux/scatterlist.h +    $(wildcard include/config/debug/sg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/scatterlist.h +  include/asm-generic/scatterlist.h +  include/linux/mm.h +    $(wildcard include/config/stack/growsup.h) +    $(wildcard include/config/swap.h) +    $(wildcard include/config/debug/pagealloc.h) +  include/linux/debug_locks.h +    $(wildcard include/config/debug/locking/api/selftests.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  include/asm-generic/pgtable.h +  include/linux/page-flags.h +    $(wildcard include/config/pageflags/extended.h) +    $(wildcard include/config/have/mlocked/page/bit.h) +    $(wildcard include/config/arch/uses/pg/uncached.h) +    $(wildcard include/config/memory/failure.h) +    $(wildcard include/config/s390.h) +  include/linux/vmstat.h +    $(wildcard include/config/vm/event/counters.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_64.h +  include/linux/vmalloc.h +  include/asm-generic/iomap.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/dma-mapping.h +    $(wildcard include/config/isa.h) +  include/linux/dma-debug.h +    $(wildcard include/config/dma/api/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swiotlb.h +    $(wildcard include/config/swiotlb.h) +  include/linux/swiotlb.h +  include/asm-generic/dma-coherent.h +    $(wildcard include/config/have/generic/dma/coherent.h) +  include/asm-generic/dma-mapping-common.h +  include/linux/hrtimer.h +    $(wildcard include/config/high/res/timers.h) +  include/linux/if.h +  include/linux/hdlc/ioctl.h +  include/linux/in.h +  include/linux/in6.h +  include/net/flow.h +  include/linux/proc_fs.h +    $(wildcard include/config/proc/devicetree.h) +    $(wildcard include/config/proc/kcore.h) +  include/linux/fs.h +    $(wildcard include/config/dnotify.h) +    $(wildcard include/config/quota.h) +    $(wildcard include/config/fsnotify.h) +    $(wildcard include/config/inotify.h) +    $(wildcard include/config/security.h) +    $(wildcard include/config/fs/posix/acl.h) +    $(wildcard include/config/epoll.h) +    $(wildcard include/config/debug/writecount.h) +    $(wildcard include/config/file/locking.h) +    $(wildcard include/config/auditsyscall.h) +    $(wildcard include/config/block.h) +    $(wildcard include/config/fs/xip.h) +    $(wildcard include/config/migration.h) +  include/linux/limits.h +  include/linux/kdev_t.h +  include/linux/dcache.h +  include/linux/rculist.h +  include/linux/path.h +  include/linux/radix-tree.h +  include/linux/pid.h +  include/linux/capability.h +    $(wildcard include/config/security/file/capabilities.h) +  include/linux/fiemap.h +  include/linux/quota.h +  include/linux/dqblk_xfs.h +  include/linux/dqblk_v1.h +  include/linux/dqblk_v2.h +  include/linux/dqblk_qtree.h +  include/linux/nfs_fs_i.h +  include/linux/nfs.h +  include/linux/sunrpc/msg_prot.h +  include/linux/inet.h +  include/linux/magic.h +  include/linux/version.h +  include/linux/kmalloc_sizes.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.h +
+/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.o: $(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.o)
+
+$(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.o):
diff -uNr nf-hipac/kernel/Makefile nfhipac/kernel/Makefile
--- nf-hipac/kernel/Makefile	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/Makefile	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,24 @@
+#
+# Makefile for nf-hipac on top of IPv4.
+#
+LINUXPATH = /lib/modules/`uname -r`/build
+CURDIR = $(shell pwd)
+
+obj-m += nf_hipac.o
+nf_hipac-objs := ihash.o global.o rlp.o dimtree.o hipac.o nfhp_dev.o nfhp_proc.o nfhp_mod.o
+
+EXTRA_CFLAGS += -D SINGLE_PATH
+
+ifneq ($(ARCH), ia64)
+ifneq ($(ARCH), x86_64)
+EXTRA_CFLAGS += -D BIT32_ARCH
+endif
+endif
+
+all: mod
+
+mod:
+	$(MAKE) -C $(LINUXPATH) M=$(CURDIR) modules
+
+clean:
+	rm -rf *.o *.ko *.mod.c *.symvers *.mod.o .*.cmd .tmp_versions modules.order
diff -uNr nf-hipac/kernel/mode.h nfhipac/kernel/mode.h
--- nf-hipac/kernel/mode.h	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/mode.h	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,236 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#ifndef _MODE_H
+#define _MODE_H
+
+#include <linux/stddef.h> // offsetof
+
+/* maximal number of bytes allocatable by mini_alloc */
+#define MINI_ALLOC_MAX 131072
+
+
+/*
+ * NEVER use big_alloc and big_free. Use hp_alloc and hp_free instead.
+ * The only exceptions to this rule is the implementation of hp_alloc,
+ * hp_realloc and hp_free.
+ *
+ * mini_alloc and mini_free can be used for small (<= MINI_ALLOC_MAX bytes)
+ * data structures if one wants to avoid the overhead of hp_alloc and hp_free
+ */
+#ifdef __KERNEL__
+#include <asm/page.h>
+#else
+#include <sys/user.h>
+#endif
+
+static inline unsigned
+big_alloc_size(unsigned size)
+{
+	return size == 0 ? 0 : (((size - 1) + PAGE_SIZE) & ~(PAGE_SIZE - 1));
+}
+
+
+#ifdef __KERNEL__
+/*
+ * Kernel space
+ */
+#include <linux/slab.h>
+#include <linux/kernel.h>    // ULONG_MAX
+#include <linux/smp.h>       // smp_num_cpus, cpu_number_map, smp_processor_id
+#include <linux/rcupdate.h>  // Read Copy Update: sychronize_rcu
+#include <linux/cache.h>     // __cacheline_aligned
+#include <linux/netfilter.h> // NF_ACCEPT, NF_DROP
+#include <linux/vmalloc.h>
+#include <linux/list.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+#define IPT_ALIGN(s) XT_ALIGN(s)
+#endif
+
+#define assert(as)           do {} while (0)
+#define printf(str, args...) printk(str , ## args)
+
+static inline unsigned
+mini_alloc_size(unsigned size)
+{
+	unsigned int s;
+#define CACHE(x) if (size <= x) { s = x; goto found;}
+#include <linux/kmalloc_sizes.h>
+	return 0;
+found:
+	return s;
+}
+
+/* for small amounts of memory only (up to 128 KB) */
+static inline void *
+mini_alloc(unsigned size)
+{
+	return vmalloc(size);
+}
+
+static inline void
+mini_free(void *p)
+{
+	vfree(p);
+}
+
+/* memory is allocated in amounts of multiples of PAGE_SIZE */
+static inline void *
+big_alloc(unsigned size)
+{
+	return vmalloc(size);
+}
+
+static inline void
+big_free(void *p)
+{
+	vfree(p);
+}
+
+/* dirty hack to make stuff work with uml (otherwise high_physmem and end_vm
+   are not defined) */
+#ifdef  CONFIG_UML_NET
+#  undef  TOP
+#  ifdef  CONFIG_HOST_2G_2G
+#    define TOP 0x80000000
+#  else
+#    define TOP 0xc0000000
+#  endif
+#  undef  SIZE
+#  define SIZE  ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
+#  undef  START
+#  define START (TOP - SIZE)
+#  undef  VMALLOC_OFFSET
+#  define VMALLOC_OFFSET (8 * 1024 * 1024)
+#  undef  VMALLOC_START
+#  define VMALLOC_START (((unsigned long) (START + 32 * 1024 * 1024) + + 	VMALLOC_OFFSET) & ~(VMALLOC_OFFSET - 1))
+static unsigned long high_physmem = START + 32 * 1024 * 1024;
+static unsigned long end_vm       = VMALLOC_START + 32 * 1024 * 1024;
+#endif  /* CONFIG_UML_NET */
+
+
+
+
+#else /* __KERNEL__ */
+/*
+ * User space
+ */
+#include <features.h>
+#if defined(__GLIBC__) && __GLIBC__ == 2
+#  include <asm/types.h>
+#else /* libc5 */
+#  include <linux/types.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>  // ULONG_MAX
+#include <assert.h>
+#include <malloc.h>
+
+/* no assertions if not debugging */
+#ifndef DEBUG
+#  undef  assert
+#  define assert(as) do {} while (0)
+#endif
+
+/* locking unnecessary in user space */
+#define synchronize_rcu(x)    do {} while (0)
+
+/* printk compatibility */
+#define KERN_EMERG    "KERN_EMERG: "
+#define KERN_ALERT    "KERN_ALERT: "
+#define KERN_CRIT     "KERN_CRIT: "
+#define KERN_ERR      "KERN_ERR: "
+#define KERN_WARNING  "KERN_WARNING: "
+#define KERN_NOTICE   "KERN_NOTICE: "
+#define KERN_INFO     "KERN_INFO: "
+#define KERN_DEBUG    "KERN_DEBUG: "
+#define printk(str, args...) printf(str , ## args)
+
+/* netfilter verdict compatibility */
+#define NF_DROP   0
+#define NF_ACCEPT 1
+
+/* macro to annotate likely branch directions which results in the
+   blocks being reordered appropriately */
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
+#  define __builtin_expect(x, expected_value) (x)
+#  define likely(x)   __builtin_expect((x), 1)
+#  define unlikely(x) __builtin_expect((x), 0)
+#endif
+
+static inline unsigned
+mini_alloc_size(unsigned size)
+{
+	unsigned int s;
+#define CACHE(x) if (size <= x) { s = x; goto found;}
+	CACHE(32);
+	CACHE(64);
+	CACHE(96);
+	CACHE(128);
+	CACHE(192);
+	CACHE(256);
+	CACHE(512);
+	CACHE(1024);
+	CACHE(2048);
+	CACHE(4096);
+	CACHE(8192);
+	CACHE(16384);
+	CACHE(32768);
+	CACHE(65536);
+	CACHE(131072);
+	return 0;
+found:
+	return s;
+}
+
+/* for small amounts of memory only (up to 128 KB) */
+static inline void *
+mini_alloc(unsigned size)
+{
+	return malloc(mini_alloc_size(size));
+}
+
+static inline void
+mini_free(void *p)
+{
+	free(p);
+}
+
+/* memory is allocated in amounts of multiples of PAGE_SIZE */
+static inline void *
+big_alloc(unsigned size)
+{
+	return malloc(big_alloc_size(size));
+}
+
+static inline void
+big_free(void *p)
+{
+	free(p);
+}
+
+#endif /* __KERNEL__ */
+
+#endif
diff -uNr nf-hipac/kernel/modules.order nfhipac/kernel/modules.order
--- nf-hipac/kernel/modules.order	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/modules.order	2014-11-21 12:54:45.000000000 +0800
@@ -0,0 +1 @@
+kernel//usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.ko
diff -uNr nf-hipac/kernel/Module.symvers nfhipac/kernel/Module.symvers
--- nf-hipac/kernel/Module.symvers	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/Module.symvers	2014-11-21 12:54:45.000000000 +0800
@@ -0,0 +1,2 @@
+0xcef73171	nfhp_unregister_cthelp	/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac	EXPORT_SYMBOL
+0x61534606	nfhp_register_cthelp	/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac	EXPORT_SYMBOL
Binary files nf-hipac/kernel/nf_hipac.ko and nfhipac/kernel/nf_hipac.ko differ
diff -uNr nf-hipac/kernel/.nf_hipac.ko.cmd nfhipac/kernel/.nf_hipac.ko.cmd
--- nf-hipac/kernel/.nf_hipac.ko.cmd	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/.nf_hipac.ko.cmd	2014-11-21 12:54:45.000000000 +0800
@@ -0,0 +1 @@
+cmd_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.ko := ld -r -m elf_x86_64 -T /usr/src/linux-headers-2.6.32-5-amd64-hz1000/scripts/module-common.lds --build-id -o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.ko /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.mod.o
diff -uNr nf-hipac/kernel/nf_hipac.mod.c nfhipac/kernel/nf_hipac.mod.c
--- nf-hipac/kernel/nf_hipac.mod.c	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/nf_hipac.mod.c	2014-11-21 12:54:45.000000000 +0800
@@ -0,0 +1,74 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+ .arch = MODULE_ARCH_INIT,
+};
+
+static const struct modversion_info ____versions[]
+__used
+__attribute__((section("__versions"))) = {
+	{ 0xef0eea15, "module_layout" },
+	{ 0x6a52c3b3, "kmalloc_caches" },
+	{ 0x5a34a45c, "__kmalloc" },
+	{ 0xd6ee688f, "vmalloc" },
+	{ 0x1a75caa3, "_read_lock" },
+	{ 0x979b3cc3, "sock_release" },
+	{ 0x23a0cd75, "dev_get_by_name" },
+	{ 0x20000329, "simple_strtoul" },
+	{ 0x105e2727, "__tracepoint_kmalloc" },
+	{ 0x63ecad53, "register_netdevice_notifier" },
+	{ 0x12bd491d, "remove_proc_entry" },
+	{ 0xb0529411, "mutex_unlock" },
+	{ 0x4d20b80, "nf_register_hook" },
+	{ 0x999e8297, "vfree" },
+	{ 0x3c2c5af5, "sprintf" },
+	{ 0xb3a307c6, "si_meminfo" },
+	{ 0xfe769456, "unregister_netdevice_notifier" },
+	{ 0x716de2c2, "skb_trim" },
+	{ 0xe2d5255a, "strcmp" },
+	{ 0x15f6a9ac, "netlink_kernel_create" },
+	{ 0x4c2dae38, "proc_mkdir" },
+	{ 0xea147363, "printk" },
+	{ 0x2fa5a500, "memcmp" },
+	{ 0x7ec9bfbc, "strncpy" },
+	{ 0x85abc85f, "strncmp" },
+	{ 0x672144bd, "strlcpy" },
+	{ 0x7c229376, "mutex_lock" },
+	{ 0x748caf40, "down" },
+	{ 0xc2cdbf1, "synchronize_sched" },
+	{ 0x8b080c79, "netlink_unicast" },
+	{ 0x8875a1c0, "init_net" },
+	{ 0x9d258f, "_write_lock" },
+	{ 0x7a795a78, "kmem_cache_alloc" },
+	{ 0x92b0b65e, "__alloc_skb" },
+	{ 0x3abb9c47, "create_proc_entry" },
+	{ 0x5a86d09, "nf_unregister_hook" },
+	{ 0x3a2204c6, "security_netlink_recv" },
+	{ 0x3aa1dbcf, "_spin_unlock_bh" },
+	{ 0x3484d476, "netlink_dump_start" },
+	{ 0x37a0cba, "kfree" },
+	{ 0x3f1899f1, "up" },
+	{ 0x9edbecae, "snprintf" },
+	{ 0xa3a5be95, "memmove" },
+	{ 0x93cbd1ec, "_spin_lock_bh" },
+	{ 0x8af80239, "skb_put" },
+	{ 0x405480cf, "skb_copy_bits" },
+	{ 0x3302b500, "copy_from_user" },
+	{ 0xe914e41e, "strcpy" },
+};
+
+static const char __module_depends[]
+__used
+__attribute__((section(".modinfo"))) =
+"depends=";
+
Binary files nf-hipac/kernel/nf_hipac.mod.o and nfhipac/kernel/nf_hipac.mod.o differ
diff -uNr nf-hipac/kernel/.nf_hipac.mod.o.cmd nfhipac/kernel/.nf_hipac.mod.o.cmd
--- nf-hipac/kernel/.nf_hipac.mod.o.cmd	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/.nf_hipac.mod.o.cmd	2014-11-21 12:54:45.000000000 +0800
@@ -0,0 +1,431 @@
+cmd_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.mod.o := gcc -Wp,-MD,/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.nf_hipac.mod.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include -Iinclude  -I/usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include -include include/linux/autoconf.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -Wframe-larger-than=2048 -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-dwarf2-cfi-asm -fconserve-stack -D SINGLE_PATH  -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(nf_hipac.mod)"  -D"KBUILD_MODNAME=KBUILD_STR(nf_hipac)"  -DMODULE -c -o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.mod.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.mod.c
+
+deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.mod.o := +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.mod.c +    $(wildcard include/config/module/unload.h) +  include/linux/module.h +    $(wildcard include/config/modules.h) +    $(wildcard include/config/modversions.h) +    $(wildcard include/config/unused/symbols.h) +    $(wildcard include/config/generic/bug.h) +    $(wildcard include/config/kallsyms.h) +    $(wildcard include/config/tracepoints.h) +    $(wildcard include/config/tracing.h) +    $(wildcard include/config/event/tracing.h) +    $(wildcard include/config/ftrace/mcount/record.h) +    $(wildcard include/config/smp.h) +    $(wildcard include/config/constructors.h) +    $(wildcard include/config/sysfs.h) +  include/linux/list.h +    $(wildcard include/config/debug/list.h) +  include/linux/stddef.h +  include/linux/compiler.h +    $(wildcard include/config/trace/branch/profiling.h) +    $(wildcard include/config/profile/all/branches.h) +    $(wildcard include/config/enable/must/check.h) +    $(wildcard include/config/enable/warn/deprecated.h) +  include/linux/compiler-gcc.h +    $(wildcard include/config/arch/supports/optimized/inlining.h) +    $(wildcard include/config/optimize/inlining.h) +  include/linux/compiler-gcc4.h +  include/linux/poison.h +    $(wildcard include/config/illegal/pointer/value.h) +  include/linux/prefetch.h +  include/linux/types.h +    $(wildcard include/config/uid16.h) +    $(wildcard include/config/lbdaf.h) +    $(wildcard include/config/phys/addr/t/64bit.h) +    $(wildcard include/config/64bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/types.h +    $(wildcard include/config/x86/64.h) +    $(wildcard include/config/highmem64g.h) +  include/asm-generic/types.h +  include/asm-generic/int-ll64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitsperlong.h +  include/asm-generic/bitsperlong.h +  include/linux/posix_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types.h +    $(wildcard include/config/x86/32.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor.h +    $(wildcard include/config/x86/vsmp.h) +    $(wildcard include/config/cc/stackprotector.h) +    $(wildcard include/config/paravirt.h) +    $(wildcard include/config/m386.h) +    $(wildcard include/config/m486.h) +    $(wildcard include/config/x86/debugctlmsr.h) +    $(wildcard include/config/cpu/sup/amd.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor-flags.h +    $(wildcard include/config/vm86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vm86.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace.h +    $(wildcard include/config/x86/ptrace/bts.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace-abi.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/segment.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cache.h +    $(wildcard include/config/x86/l1/cache/shift.h) +  include/linux/linkage.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/linkage.h +    $(wildcard include/config/x86/alignment/16.h) +  include/linux/stringify.h +  include/linux/init.h +    $(wildcard include/config/hotplug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/math_emu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sigcontext.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/current.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/percpu.h +    $(wildcard include/config/x86/64/smp.h) +  include/linux/kernel.h +    $(wildcard include/config/preempt/voluntary.h) +    $(wildcard include/config/debug/spinlock/sleep.h) +    $(wildcard include/config/prove/locking.h) +    $(wildcard include/config/printk.h) +    $(wildcard include/config/dynamic/debug.h) +    $(wildcard include/config/ring/buffer.h) +    $(wildcard include/config/numa.h) +  /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h +  include/linux/bitops.h +    $(wildcard include/config/generic/find/first/bit.h) +    $(wildcard include/config/generic/find/last/bit.h) +    $(wildcard include/config/generic/find/next/bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitops.h +    $(wildcard include/config/x86/cmov.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/alternative.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/asm.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpufeature.h +    $(wildcard include/config/x86/invlpg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/required-features.h +    $(wildcard include/config/x86/minimum/cpu/family.h) +    $(wildcard include/config/math/emulation.h) +    $(wildcard include/config/x86/pae.h) +    $(wildcard include/config/x86/cmpxchg64.h) +    $(wildcard include/config/x86/use/3dnow.h) +    $(wildcard include/config/x86/p6/nop.h) +  include/asm-generic/bitops/sched.h +  include/asm-generic/bitops/hweight.h +  include/asm-generic/bitops/fls64.h +  include/asm-generic/bitops/ext2-non-atomic.h +  include/asm-generic/bitops/le.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/byteorder.h +  include/linux/byteorder/little_endian.h +  include/linux/swab.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swab.h +    $(wildcard include/config/x86/bswap.h) +  include/linux/byteorder/generic.h +  include/asm-generic/bitops/minix.h +  include/linux/log2.h +    $(wildcard include/config/arch/has/ilog2/u32.h) +    $(wildcard include/config/arch/has/ilog2/u64.h) +  include/linux/typecheck.h +  include/linux/ratelimit.h +  include/linux/param.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/param.h +  include/asm-generic/param.h +    $(wildcard include/config/hz.h) +  include/linux/dynamic_debug.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bug.h +    $(wildcard include/config/bug.h) +    $(wildcard include/config/debug/bugverbose.h) +  include/asm-generic/bug.h +    $(wildcard include/config/generic/bug/relative/pointers.h) +  include/asm-generic/percpu.h +    $(wildcard include/config/debug/preempt.h) +    $(wildcard include/config/have/setup/per/cpu/area.h) +  include/linux/threads.h +    $(wildcard include/config/nr/cpus.h) +    $(wildcard include/config/base/small.h) +  include/linux/percpu-defs.h +    $(wildcard include/config/debug/force/weak/per/cpu.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/system.h +    $(wildcard include/config/ia32/emulation.h) +    $(wildcard include/config/x86/32/lazy/gs.h) +    $(wildcard include/config/x86/ppro/fence.h) +    $(wildcard include/config/x86/oostore.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/nops.h +    $(wildcard include/config/mk7.h) +  include/linux/irqflags.h +    $(wildcard include/config/trace/irqflags.h) +    $(wildcard include/config/irqsoff/tracer.h) +    $(wildcard include/config/preempt/tracer.h) +    $(wildcard include/config/trace/irqflags/support.h) +    $(wildcard include/config/x86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irqflags.h +    $(wildcard include/config/debug/lock/alloc.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt.h +    $(wildcard include/config/highpte.h) +    $(wildcard include/config/paravirt/spinlocks.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_types.h +    $(wildcard include/config/kmemcheck.h) +    $(wildcard include/config/compat/vdso.h) +    $(wildcard include/config/proc/fs.h) +  include/linux/const.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64_types.h +    $(wildcard include/config/physical/start.h) +    $(wildcard include/config/physical/align.h) +    $(wildcard include/config/flatmem.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt_types.h +    $(wildcard include/config/x86/local/apic.h) +    $(wildcard include/config/paravirt/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/desc_defs.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/kmap_types.h +    $(wildcard include/config/debug/highmem.h) +  include/asm-generic/kmap_types.h +  include/linux/cpumask.h +    $(wildcard include/config/cpumask/offstack.h) +    $(wildcard include/config/hotplug/cpu.h) +    $(wildcard include/config/debug/per/cpu/maps.h) +    $(wildcard include/config/disable/obsolete/cpumask/functions.h) +  include/linux/bitmap.h +  include/linux/string.h +    $(wildcard include/config/binary/printf.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64.h +  include/asm-generic/memory_model.h +    $(wildcard include/config/discontigmem.h) +    $(wildcard include/config/sparsemem/vmemmap.h) +    $(wildcard include/config/sparsemem.h) +  include/asm-generic/getorder.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr-index.h +  include/linux/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ioctl.h +  include/asm-generic/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/errno.h +  include/asm-generic/errno.h +  include/asm-generic/errno-base.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpumask.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ds.h +    $(wildcard include/config/x86/ds.h) +  include/linux/err.h +  include/linux/personality.h +  include/linux/cache.h +    $(wildcard include/config/arch/has/cache/line/size.h) +  include/linux/math64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/div64.h +  include/asm-generic/div64.h +  include/linux/stat.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/stat.h +  include/linux/time.h +    $(wildcard include/config/arch/uses/gettimeoffset.h) +  include/linux/seqlock.h +  include/linux/spinlock.h +    $(wildcard include/config/debug/spinlock.h) +    $(wildcard include/config/generic/lockbreak.h) +    $(wildcard include/config/preempt.h) +  include/linux/preempt.h +    $(wildcard include/config/preempt/notifiers.h) +  include/linux/thread_info.h +    $(wildcard include/config/compat.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/thread_info.h +    $(wildcard include/config/debug/stack/usage.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ftrace.h +    $(wildcard include/config/function/tracer.h) +    $(wildcard include/config/dynamic/ftrace.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic_64.h +  include/asm-generic/atomic-long.h +  include/linux/bottom_half.h +  include/linux/spinlock_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock_types.h +  include/linux/lockdep.h +    $(wildcard include/config/lockdep.h) +    $(wildcard include/config/lock/stat.h) +    $(wildcard include/config/generic/hardirqs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwlock.h +  include/linux/spinlock_api_smp.h +  include/linux/kmod.h +    $(wildcard include/config/pm/sleep.h) +  include/linux/gfp.h +    $(wildcard include/config/highmem.h) +    $(wildcard include/config/zone/dma.h) +    $(wildcard include/config/zone/dma32.h) +    $(wildcard include/config/debug/vm.h) +  include/linux/mmzone.h +    $(wildcard include/config/force/max/zoneorder.h) +    $(wildcard include/config/memory/hotplug.h) +    $(wildcard include/config/arch/populates/node/map.h) +    $(wildcard include/config/flat/node/mem/map.h) +    $(wildcard include/config/cgroup/mem/res/ctlr.h) +    $(wildcard include/config/have/memory/present.h) +    $(wildcard include/config/need/node/memmap/size.h) +    $(wildcard include/config/need/multiple/nodes.h) +    $(wildcard include/config/have/arch/early/pfn/to/nid.h) +    $(wildcard include/config/sparsemem/extreme.h) +    $(wildcard include/config/nodes/span/other/nodes.h) +    $(wildcard include/config/holes/in/zone.h) +    $(wildcard include/config/arch/has/holes/memorymodel.h) +  include/linux/wait.h +  include/linux/numa.h +    $(wildcard include/config/nodes/shift.h) +  include/linux/nodemask.h +  include/linux/pageblock-flags.h +    $(wildcard include/config/hugetlb/page.h) +    $(wildcard include/config/hugetlb/page/size/variable.h) +  include/linux/bounds.h +  include/linux/memory_hotplug.h +    $(wildcard include/config/have/arch/nodedata/extension.h) +    $(wildcard include/config/memory/hotremove.h) +  include/linux/notifier.h +  include/linux/errno.h +  include/linux/mutex.h +    $(wildcard include/config/debug/mutexes.h) +  include/linux/rwsem.h +    $(wildcard include/config/rwsem/generic/spinlock.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwsem.h +  include/linux/srcu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone_64.h +    $(wildcard include/config/numa/emu.h) +  include/linux/mmdebug.h +    $(wildcard include/config/debug/virtual.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/smp.h +    $(wildcard include/config/x86/io/apic.h) +    $(wildcard include/config/x86/32/smp.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec.h +    $(wildcard include/config/x86/numaq.h) +    $(wildcard include/config/mca.h) +    $(wildcard include/config/eisa.h) +    $(wildcard include/config/x86/mpparse.h) +    $(wildcard include/config/acpi.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec_def.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/x86_init.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bootparam.h +  include/linux/screen_info.h +  include/linux/apm_bios.h +  include/linux/edd.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/e820.h +    $(wildcard include/config/efi.h) +    $(wildcard include/config/hibernation.h) +    $(wildcard include/config/memtest.h) +  include/linux/ioport.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ist.h +  include/video/edid.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apic.h +    $(wildcard include/config/x86/x2apic.h) +  include/linux/delay.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/delay.h +  include/linux/pm.h +    $(wildcard include/config/pm/runtime.h) +  include/linux/workqueue.h +  include/linux/timer.h +    $(wildcard include/config/timer/stats.h) +    $(wildcard include/config/debug/objects/timers.h) +  include/linux/ktime.h +    $(wildcard include/config/ktime/scalar.h) +  include/linux/jiffies.h +  include/linux/timex.h +    $(wildcard include/config/no/hz.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/timex.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/tsc.h +    $(wildcard include/config/x86/tsc.h) +  include/linux/debugobjects.h +    $(wildcard include/config/debug/objects.h) +    $(wildcard include/config/debug/objects/free.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apicdef.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fixmap.h +    $(wildcard include/config/provide/ohci1394/dma/init.h) +    $(wildcard include/config/x86/visws/apic.h) +    $(wildcard include/config/x86/f00f/bug.h) +    $(wildcard include/config/x86/cyclone/timer.h) +    $(wildcard include/config/pci/mmconfig.h) +    $(wildcard include/config/intel/txt.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/acpi.h +    $(wildcard include/config/acpi/numa.h) +  include/acpi/pdc_intel.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vsyscall.h +    $(wildcard include/config/generic/time.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_apic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irq_vectors.h +    $(wildcard include/config/sparse/irq.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sparsemem.h +  include/linux/topology.h +    $(wildcard include/config/sched/smt.h) +    $(wildcard include/config/sched/mc.h) +  include/linux/smp.h +    $(wildcard include/config/use/generic/smp/helpers.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/topology.h +    $(wildcard include/config/x86/ht.h) +    $(wildcard include/config/x86/64/acpi/numa.h) +  include/asm-generic/topology.h +  include/linux/elf.h +  include/linux/elf-em.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/elf.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/auxvec.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vdso.h +  include/linux/kobject.h +  include/linux/sysfs.h +  include/linux/kref.h +  include/linux/moduleparam.h +    $(wildcard include/config/alpha.h) +    $(wildcard include/config/ia64.h) +    $(wildcard include/config/ppc64.h) +  include/linux/tracepoint.h +  include/linux/rcupdate.h +    $(wildcard include/config/tree/preempt/rcu.h) +    $(wildcard include/config/tree/rcu.h) +  include/linux/completion.h +  include/linux/rcutree.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/local.h +  include/linux/percpu.h +    $(wildcard include/config/have/legacy/per/cpu/area.h) +    $(wildcard include/config/need/per/cpu/embed/first/chunk.h) +    $(wildcard include/config/need/per/cpu/page/first/chunk.h) +    $(wildcard include/config/debug/kmemleak.h) +  include/linux/slab.h +    $(wildcard include/config/slab/debug.h) +    $(wildcard include/config/slub.h) +    $(wildcard include/config/slob.h) +    $(wildcard include/config/debug/slab.h) +  include/linux/slub_def.h +    $(wildcard include/config/slub/stats.h) +    $(wildcard include/config/slub/debug.h) +    $(wildcard include/config/kmemtrace.h) +  include/linux/kmemtrace.h +  include/trace/events/kmem.h +  include/trace/define_trace.h +  include/linux/kmemleak.h +  include/linux/pfn.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/module.h +    $(wildcard include/config/m586.h) +    $(wildcard include/config/m586tsc.h) +    $(wildcard include/config/m586mmx.h) +    $(wildcard include/config/mcore2.h) +    $(wildcard include/config/matom.h) +    $(wildcard include/config/m686.h) +    $(wildcard include/config/mpentiumii.h) +    $(wildcard include/config/mpentiumiii.h) +    $(wildcard include/config/mpentiumm.h) +    $(wildcard include/config/mpentium4.h) +    $(wildcard include/config/mk6.h) +    $(wildcard include/config/mk8.h) +    $(wildcard include/config/x86/elan.h) +    $(wildcard include/config/mcrusoe.h) +    $(wildcard include/config/mefficeon.h) +    $(wildcard include/config/mwinchipc6.h) +    $(wildcard include/config/mwinchip3d.h) +    $(wildcard include/config/mcyrixiii.h) +    $(wildcard include/config/mviac3/2.h) +    $(wildcard include/config/mviac7.h) +    $(wildcard include/config/mgeodegx1.h) +    $(wildcard include/config/mgeode/lx.h) +    $(wildcard include/config/4kstacks.h) +  include/asm-generic/module.h +  include/trace/events/module.h +  include/linux/vermagic.h +  include/linux/utsrelease.h +
+/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.mod.o: $(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.mod.o)
+
+$(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.mod.o):
Binary files nf-hipac/kernel/nf_hipac.o and nfhipac/kernel/nf_hipac.o differ
diff -uNr nf-hipac/kernel/.nf_hipac.o.cmd nfhipac/kernel/.nf_hipac.o.cmd
--- nf-hipac/kernel/.nf_hipac.o.cmd	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/.nf_hipac.o.cmd	2014-11-21 12:54:45.000000000 +0800
@@ -0,0 +1 @@
+cmd_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.o := ld -m elf_x86_64   -r -o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nf_hipac.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/ihash.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/global.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/rlp.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/dimtree.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_dev.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_proc.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_mod.o 
diff -uNr nf-hipac/kernel/nfhp_com.h nfhipac/kernel/nfhp_com.h
--- nf-hipac/kernel/nfhp_com.h	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/nfhp_com.h	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,294 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#ifndef _NFHP_COM_H
+#define _NFHP_COM_H
+
+#ifdef __KERNEL__
+#  include <linux/if.h>
+#  include <linux/in.h>
+#  include <linux/types.h>
+#endif
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netlink.h>
+#include "hipac.h"
+
+
+/* a similar line will hopefully make its way into netlink.h */
+#define NETLINK_NFHIPAC	    26
+#define NLHP_PROTO          NETLINK_NFHIPAC
+#define NLHP_TYPE           0xFADE
+
+/* dimension id‘s */
+enum {
+	DIMID_STATE,
+	DIMID_SRC_IP,
+	DIMID_DEST_IP,
+	DIMID_INIFACE,
+	DIMID_OUTIFACE,
+	DIMID_PROTO,
+	DIMID_FRAGMENT,
+	DIMID_DPORT,
+	DIMID_SPORT,
+	DIMID_SYN,
+	DIMID_ICMP_TYPE,
+	DIMID_TTL,
+	NUMBER_OF_DIM
+};
+
+/* bit types */
+#define BIT_STATE       BIT_U16
+#define BIT_SRC_IP      BIT_U32
+#define BIT_DEST_IP     BIT_U32
+#define BIT_INIFACE     BIT_U16
+#define BIT_OUTIFACE    BIT_U16
+#define BIT_PROTO       BIT_U16
+#define BIT_FRAGMENT    BIT_U16
+#define BIT_DPORT       BIT_U16
+#define BIT_SPORT       BIT_U16
+#define BIT_SYN         BIT_U16
+#define BIT_ICMP_TYPE   BIT_U16
+#define BIT_TTL         BIT_U16
+
+/* origin bits */
+#define NFHP_ORIGIN_INPUT   0x1
+#define NFHP_ORIGIN_FORWARD 0x2
+#define NFHP_ORIGIN_OUTPUT  0x4
+
+/* hipac_error and nfhipac_error together form the netlink error messages */
+typedef enum
+{
+	NFHE_INDEX   = HE_NEXT_ERROR,      // Unable to retrieve unused ifindex
+	NFHE_NOMSG   = HE_NEXT_ERROR - 1,  // Incorrect message format
+	NFHE_CMD     = HE_NEXT_ERROR - 2,  // Invalid command
+	NFHE_LABEL   = HE_NEXT_ERROR - 3,  // Empty chain label
+	NFHE_NLABEL  = HE_NEXT_ERROR - 4,  // Empty new chain label
+	NFHE_POLICY  = HE_NEXT_ERROR - 5,  // Invalid policy
+	NFHE_ACTION  = HE_NEXT_ERROR - 6,  // Invalid action
+	NFHE_NMCT    = HE_NEXT_ERROR - 7,  // Invalid native match count
+	NFHE_IEOFF   = HE_NEXT_ERROR - 8,  // Invalid target_offset/next_offset
+	                                   // in ipt_entry
+	NFHE_SORT    = HE_NEXT_ERROR - 9,  // Native matches not sorted or 
+	                                   // dimid duplicate
+        NFHE_MINT    = HE_NEXT_ERROR - 10, // Invalid interval in native match
+	NFHE_DEVA    = HE_NEXT_ERROR - 11, // Native interface match but no 
+                                           // corresponding interface name
+	NFHE_DEVB    = HE_NEXT_ERROR - 12, // Interface name but no corres-
+	                                   // ponding native interface match
+	NFHE_FRAG    = HE_NEXT_ERROR - 13, // Invalid fragment match
+	NFHE_PROTO   = HE_NEXT_ERROR - 14, // Invalid protocol match
+        NFHE_SYN     = HE_NEXT_ERROR - 15, // Invalid syn match
+	NFHE_STATE   = HE_NEXT_ERROR - 16, // Invalid state match
+	NFHE_TCP     = HE_NEXT_ERROR - 17, // tcp match dependency failure
+	NFHE_TCPUDP  = HE_NEXT_ERROR - 18, // tcp or udp match dependency failure
+	NFHE_ICMP    = HE_NEXT_ERROR - 19, // icmp match dependency failure
+	NFHE_CMPMIS  = HE_NEXT_ERROR - 20, // Missing cmp_len array
+	NFHE_CMPSH   = HE_NEXT_ERROR - 21, // cmp_len array too short
+	NFHE_CMPLA   = HE_NEXT_ERROR - 22, // cmp_len array contains a value
+	                                   // larger than the corresponding
+	                                   // ipt match/target size
+	NFHE_ORIGIN  = HE_NEXT_ERROR - 23, // Illegal combination of matches
+                                           // (no valid origin)
+	NFHE_TOFF    = HE_NEXT_ERROR - 29, // Invalid target_offset
+	NFHE_CHAINE  = HE_NEXT_ERROR - 30, // Empty chain name
+	NFHE_CHAINL  = HE_NEXT_ERROR - 31, // Chain name too long
+	NFHE_CT      = HE_NEXT_ERROR - 32, // Kernel does not have support for 
+	                                   // connection tracking, please recompile
+	NFHE_CTHELP  = HE_NEXT_ERROR - 33, // Unable to load connection tracking
+	                                   // helper module (nf_hipac_cthelp.o)
+	NFHE_ILL     = HE_NEXT_ERROR - 34, // Illegal condition
+	NFHE_IMPL    = HE_NEXT_ERROR - 35, // Feature not yet implemented
+	NFHE_SYSOFF  = HE_NEXT_ERROR - 36  // - offset for system errno‘s -
+} nfhipac_error;
+
+/* errno is positive */
+#define ERRNO_TO_NFHE(e) (NFHE_SYSOFF - e)
+#define NFHE_TO_ERRNO(e) (NFHE_SYSOFF - e)
+
+/* connection tracking states */
+typedef enum
+{
+	NFHP_STATE_ESTABLISHED,
+	NFHP_STATE_RELATED,
+	NFHP_STATE_NEW,
+	NFHP_STATE_INVALID,
+	NFHP_STATE_UNTRACKED,
+	NFHP_STATE_NUM_VALID = NFHP_STATE_INVALID
+} nfhp_state;
+
+/* netlink commands */
+#define CMD_NONE           0
+#define CMD_MIN            1
+#define CMD_APPEND         1
+#define CMD_INSERT         2
+#define CMD_DELETE_RULE    3
+#define CMD_DELETE_POS     4 
+#define CMD_REPLACE        5
+#define CMD_FLUSH          6
+#define CMD_NEW_CHAIN      7
+#define CMD_DELETE_CHAIN   8
+#define CMD_RENAME_CHAIN   9
+#define CMD_SET_POLICY    10
+#define CMD_LIST          11
+#define CMD_MAX           11
+
+struct nfhp_rule
+{
+	char indev[IFNAMSIZ];
+	char outdev[IFNAMSIZ];
+	struct hipac_rule r;
+	struct hipac_match m[NUMBER_OF_DIM];  // == r.first_match
+	/* we cannot use aligned(__alignof__(u_int64_t)) instead of
+	   aligned(8) because of incompatibilities in gcc versions */
+	struct ipt_entry e[0] __attribute__((aligned(8)));
+};
+
+struct nfhp_chain
+{
+	char label[HIPAC_CHAIN_NAME_MAX_LEN];
+	char newlabel[HIPAC_CHAIN_NAME_MAX_LEN];
+	u_int8_t policy;
+};
+
+/* universal macros which can be used for USER <-> KERNEL (both directions) */
+#define HAS_CHAIN_TARGET(r)   ((r)->action == TARGET_CHAIN)
+
+/*
+ * netlink communication: USER -> KERNEL
+ */
+
+/* command sent to kernel; only the necessary parts (depending on the command
+   type) must be filled in;
+
+  this is how a nfhp_cmd really looks like:
+  --------------------------------------------
+  |              nfhp_cmd struct             |
+  |------------------------------------------|
+  |                ipt_entry                 |
+  |------------------------------------------|
+  |             ipt_entry_match 1            |
+  |------------------------------------------|
+  |                  . . .                   |
+  |------------------------------------------|
+  |             ipt_entry_match m            |
+  |------------------------------------------|
+  |             ipt_entry_target             |
+  |                    or                    |
+  |                chain label               |
+  |------------------------------------------|
+  |          cmp_len array of size m         |
+  |  or m + 1 if ipt_entry_target available  |
+  --------------------------------------------
+
+  ipt_entry, ipt_entry_matches, ipt_entry_target / chain label and cmp_len are
+  optional; here are the rules defining their presence:
+  1) if the rule action is TARGET_EXEC there is an ipt_entry_target
+  2) if the rule action is TARGET_CHAIN there is a chain label
+  3) if there is an ipt_entry_match or ipt_entry_target or chain label there
+     is an ipt_entry
+  4) if there is an ipt_entry and cmd is CMD_DELETE_RULE there is cmp_len
+
+  => the smallest command simply consists of the nfhp_cmd struct
+
+  struct nfhp_cmd contains an embedded struct hipac_rule; set its member
+  match_offset to a value > 0 if there is at least one ipt_entry_match;
+  otherwise it must be 0; you don‘t have to specify the following members:
+                           size, origin, target_offset
+
+
+*/
+struct nfhp_cmd
+{
+	u_int32_t cmd;
+	struct nfhp_chain chain;
+	struct nfhp_rule rule;
+};
+
+/* macros to access nfhp_cmd; hr is a pointer to the embedded hipac_rule */
+#define NFHP_RULE(hr)          ((struct nfhp_rule *)              +			        ((char *) (hr) - (unsigned long)  +			 	 (&((struct nfhp_rule *) 0)->r)))
+
+
+
+/*
+ * netlink communication: KERNEL -> USER
+ */
+
+/*
+  in reply to a CMD_LIST command the kernel sends a series of packets to
+  the userspace; each packet is filled as much as possible so that the
+  number of packets being transfered is reduced to a minimum;
+  in case of an error which can happen sometime during the
+  transmission a packet containing the error number is sent (int32_t);
+  the data sent to the userspace is organized in the following way:
+  |struct nfhp_list_chain (chain 1)|rule 1|padding|...|rule n_1|padding|
+  |                   .   .   .   .                                    |
+  |struct nfhp_list_chain (chain k)|rule 1|padding|...|rule n_k|padding|
+  the rules are of the type struct nfhp_rule;
+  
+  this is how a nfhp_list_rule really looks like:
+  --------------------------------------------
+  |           nfhp_list_rule struct          |
+  |------------------------------------------|
+  |               hipac_match 1              |
+  |------------------------------------------|
+  |                  . . .                   |
+  |------------------------------------------|
+  |               hipac_match n              |
+  |------------------------------------------|
+  |             ipt_entry_match 1            |
+  |------------------------------------------|
+  |                  . . .                   |
+  |------------------------------------------|
+  |             ipt_entry_match m            |
+  |------------------------------------------|
+  |             ipt_entry_target             |
+  |                    or                    |
+  |                chain label               |
+  --------------------------------------------
+
+  the number of hipac_matches depends on native_mct (member of hipac_rule);
+  there is neither ipt_entry nor cmp_len;
+
+  IMPORTANT: - there might be a padding between two consecutive rules
+               in order to meet the alignment requirements for rules which
+	       contain 64 bit members; so you have to use the IPT_ALIGN
+               macro to jump to the next rule; note that there is no padding
+               after a chain because it contains 64 bit members which
+	       enforce the strictest alignment on the system
+*/
+struct nfhp_list_chain
+{
+	char label[HIPAC_CHAIN_NAME_MAX_LEN];
+	u_int8_t policy;
+	u_int32_t rule_num;
+};
+
+struct nfhp_list_rule
+{
+        char indev[IFNAMSIZ];
+        char outdev[IFNAMSIZ];
+        struct hipac_rule r;
+};
+
+/* these macros together with the universal macros can be used to access
+   nfhp_list_rule */
+#endif
diff -uNr nf-hipac/kernel/nfhp_dev.c nfhipac/kernel/nfhp_dev.c
--- nf-hipac/kernel/nfhp_dev.c	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/nfhp_dev.c	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,313 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/notifier.h>
+#include "nfhp_com.h"
+#include "nfhp_dev.h"
+
+
+#define IFNAME_MAP_INIT_LEN 31
+
+struct ifname_map_t
+{
+	u32 len;
+	u32 size;
+	struct
+	{
+		char *ifname;
+		u16 vindex;
+	} map[0];
+};
+
+static struct ifname_map_t *ifname_map;
+static char (*ifnames)[IFNAMSIZ];
+struct nf_hipac_dev_ifindex_map_t nf_hipac_dev_ifindex_map
+__attribute__((aligned(SMP_CACHE_BYTES)));
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
+static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;
+#else
+static spinlock_t dev_lock = __ARCH_SPIN_LOCK_UNLOCKED;
+#endif
+
+static int
+init_data(void)
+{
+	ifname_map = kmalloc(sizeof(ifname_map) + IFNAME_MAP_INIT_LEN *
+			     sizeof(*ifname_map->map), GFP_KERNEL);
+	if (ifname_map == NULL) {
+		return -ENOMEM;
+	}
+
+	ifnames = kmalloc(IFNAME_MAP_INIT_LEN * sizeof(*ifnames), GFP_KERNEL);
+	if (ifnames == NULL) {
+		kfree(ifname_map);
+		return -ENOMEM;
+	}
+	memset(&nf_hipac_dev_ifindex_map, 0, sizeof(nf_hipac_dev_ifindex_map));
+	memset(ifname_map, 0, sizeof(ifname_map) + IFNAME_MAP_INIT_LEN *
+	       sizeof(*ifname_map->map));
+	memset(ifnames, 0, IFNAME_MAP_INIT_LEN * sizeof(*ifnames));
+	ifname_map->size = IFNAME_MAP_INIT_LEN;
+	return 0;
+}
+
+static void
+free_data(void)
+{
+	if (ifname_map != NULL) {
+		kfree(ifname_map);
+		ifname_map = NULL;
+	}
+
+	if (ifnames != NULL) {
+		kfree(ifnames);
+		ifnames = NULL;
+	}
+}
+
+static void
+ifindex_map_add_replace(u16 ifindex, u16 vindex)
+{
+	u16 i;
+	for (i = 0; i < nf_hipac_dev_ifindex_map.len; i++) {
+		if (nf_hipac_dev_ifindex_map.map[i].ifindex == ifindex) {
+			nf_hipac_dev_ifindex_map.map[i].vindex = vindex;
+			return;
+		}
+	}
+	for (i = 0; i < nf_hipac_dev_ifindex_map.len; i++) {
+		if (nf_hipac_dev_ifindex_map.map[i].ifindex == 0) {
+			nf_hipac_dev_ifindex_map.map[i].ifindex = ifindex;
+			nf_hipac_dev_ifindex_map.map[i].vindex = vindex;
+			return;
+		}
+	}
+	if (nf_hipac_dev_ifindex_map.len < NF_HIPAC_MAX_UP_INTERFACES) {
+		nf_hipac_dev_ifindex_map.map[nf_hipac_dev_ifindex_map.len]
+			.ifindex = ifindex;
+		nf_hipac_dev_ifindex_map.map[nf_hipac_dev_ifindex_map.len]
+			.vindex = vindex;
+		nf_hipac_dev_ifindex_map.len++;
+	} else {
+		printk(KERN_ERR "NF_HiPAC: too much interfaces UP at the "
+		       "same time. Please increase NF_HIPAC_MAX_UP_INTERFACES "
+		       "in nf_hipac_dev.h and recompile!");
+	}
+	return;
+}
+
+static void
+ifindex_map_del(u16 ifindex)
+{
+	u16 i;
+	for (i = 0; i < nf_hipac_dev_ifindex_map.len; i++) {
+		if (nf_hipac_dev_ifindex_map.map[i].ifindex == ifindex) {
+			nf_hipac_dev_ifindex_map.map[i].ifindex = 0;
+			nf_hipac_dev_ifindex_map.map[i].vindex = 0;
+			return;
+		}
+	}
+	return;
+}
+
+int
+ifname_map_lookup_vindex(const char *ifname)
+{
+	u16 pos;
+	int cmp;
+	u32 start = 1;
+	u32 stop = ifname_map->len;
+
+	while (stop >= start) {
+		pos = ((start + stop) >> 1) - 1;
+		cmp = strcmp(ifname_map->map[pos].ifname, ifname);
+		if (cmp < 0) {
+			start = pos + 2;
+		} else if (cmp > 0) {
+			stop = pos;
+		} else {
+			return ifname_map->map[pos].vindex;
+		}
+	}
+	return -1;
+}
+
+int
+nf_hipac_dev_lookup_ifname(int vindex, char ifname[])
+{
+	if (vindex < 1 || vindex > ifname_map->len)
+		return -1;
+	strlcpy(ifname, ifnames[vindex - 1], IFNAMSIZ);
+	return 0;
+}
+
+int
+nf_hipac_dev_get_vindex(const char *ifname)
+{
+	u32 max = 0;
+	u32 start = 1;
+	u16 pos;
+	u32 stop;
+	int cmp;
+	struct net_device *dev;
+
+	if (unlikely(ifname_map->len == 0)) {
+		strlcpy(ifnames[0], ifname, sizeof(*ifnames));
+		dev = dev_get_by_name(&init_net, ifname);
+		spin_lock_bh(&dev_lock);
+		ifname_map->len = 1;
+		ifname_map->map[0].ifname = ifnames[0];
+		ifname_map->map[0].vindex = 1;
+		if (dev) {
+			if (dev->flags & IFF_UP)
+				ifindex_map_add_replace(dev->ifindex, 1);
+			dev_put(dev);
+		}
+		spin_unlock_bh(&dev_lock);
+		return 1;
+	}
+
+	stop = ifname_map->len;
+	while (stop >= start) {
+		pos = ((start + stop) >> 1) - 1;
+		cmp = strcmp(ifname_map->map[pos].ifname, ifname);
+		if (cmp < 0) {
+			start = pos + 2;
+		} else if (cmp > 0) {
+			stop = pos;
+			max = pos + 1;
+		} else {
+			return ifname_map->map[pos].vindex;
+		}
+	}
+	if (max == 0) {
+		/* max has not been touched (otherwise it must be >= 1)
+		   => new ifname is "maximal" */
+		pos = ifname_map->len;
+	} else {
+		pos = max - 1;
+	}
+
+	if (ifname_map->len == 65535) {
+		return NFHE_INDEX;
+	}
+
+	/* new vindex required -> do reallocations first if necessary */
+	if (unlikely(ifname_map->len == ifname_map->size)) {
+		u32 newsize = ((ifname_map->size + 1) << 1) - 1;
+		struct ifname_map_t *new_ifname_map;
+		char (*new_ifnames)[IFNAMSIZ];
+		new_ifname_map = kmalloc(sizeof(new_ifname_map) + newsize *
+					 sizeof(*new_ifname_map->map),
+					 GFP_KERNEL);
+		if (new_ifname_map == NULL) {
+			return HE_LOW_MEMORY;
+		}
+		new_ifnames = kmalloc(newsize * sizeof(*new_ifnames),
+				      GFP_KERNEL);
+		if (new_ifnames == NULL) {
+			kfree(new_ifname_map);
+			return HE_LOW_MEMORY;
+		}
+		memcpy(new_ifname_map, ifname_map, sizeof(new_ifname_map) +
+		       ifname_map->size * sizeof(*new_ifname_map->map));
+		new_ifname_map->size = newsize;
+		memcpy(new_ifnames, ifnames,
+		       ifname_map->size * sizeof(*new_ifnames));
+		strlcpy(new_ifnames[ifname_map->len], ifname,
+			sizeof(*new_ifnames));
+		dev = dev_get_by_name(&init_net, ifname);
+		spin_lock_bh(&dev_lock);
+		kfree(ifname_map);
+		kfree(ifnames);
+		ifname_map = new_ifname_map;
+		ifnames = new_ifnames;
+	} else {
+		strlcpy(ifnames[ifname_map->len], ifname, sizeof(*ifnames));
+		dev = dev_get_by_name(&init_net, ifname);
+		spin_lock_bh(&dev_lock);
+	}
+	
+	if (pos < ifname_map->len) {
+		memmove(&ifname_map->map[pos + 1], &ifname_map->map[pos],
+			(ifname_map->len - pos) * sizeof(*ifname_map->map));
+	}
+	ifname_map->map[pos].ifname = ifnames[ifname_map->len];
+	ifname_map->map[pos].vindex = ++ifname_map->len;
+	if (dev) {
+		if (dev->flags & IFF_UP)
+			ifindex_map_add_replace(dev->ifindex, ifname_map->len);
+		dev_put(dev);
+	}
+	spin_unlock_bh(&dev_lock);
+	return ifname_map->len;
+}
+
+static int
+nf_hipac_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	int vindex;
+	struct net_device *dev = ptr;
+	switch (event) {
+	case NETDEV_UP:
+		spin_lock_bh(&dev_lock);
+		vindex = ifname_map_lookup_vindex(dev->name);
+		if (vindex > 0) {
+			// interface is in ruleset => add to ifindex_map
+			ifindex_map_add_replace(dev->ifindex, vindex);
+		}
+		spin_unlock_bh(&dev_lock);
+		break;
+		
+	case NETDEV_DOWN:
+		spin_lock_bh(&dev_lock);
+		ifindex_map_del(dev->ifindex);
+		spin_unlock_bh(&dev_lock);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block nf_hipac_dev_notifier = {
+        .notifier_call  = nf_hipac_dev_event,
+};
+
+int
+nf_hipac_dev_init(void)
+{
+	int stat;
+
+	stat = init_data();
+	if (stat < 0) {
+		return stat;
+	}
+	stat = register_netdevice_notifier(&nf_hipac_dev_notifier);
+	if (stat < 0) {
+		free_data();
+		return stat;
+	}
+	return 0;
+}
+
+void
+nf_hipac_dev_exit(void)
+{
+	unregister_netdevice_notifier(&nf_hipac_dev_notifier);
+	free_data();
+}
diff -uNr nf-hipac/kernel/nfhp_dev.h nfhipac/kernel/nfhp_dev.h
--- nf-hipac/kernel/nfhp_dev.h	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/nfhp_dev.h	2014-11-21 12:36:09.000000000 +0800
@@ -0,0 +1,66 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#ifndef _NF_HIPAC_DEV_H
+#define _NF_HIPAC_DEV_H
+
+#define NF_HIPAC_MAX_UP_INTERFACES 255
+
+struct nf_hipac_dev_ifindex_map_t
+{
+	u16 len;
+	struct
+	{
+		u16 ifindex;
+		u16 vindex;
+	} map[NF_HIPAC_MAX_UP_INTERFACES];
+};
+
+/* mapping from interface index to virtual interface index */
+extern struct nf_hipac_dev_ifindex_map_t nf_hipac_dev_ifindex_map;
+
+/* call init during module initialization; if something fails a negative 
+   errno is returned, otherwise 0 is returned */
+int
+nf_hipac_dev_init(void);
+
+/* call exit during module finalization */
+void
+nf_hipac_dev_exit(void);
+
+/* copies the device name corresponding to vindex to ifname which should
+   be at least IFNAMSIZ bytes large and return 0;
+   if vindex cannot be found a value < 0 is returned */
+int
+nf_hipac_dev_lookup_ifname(int vindex, char ifname[]);
+
+/* return the corresponding virtual interface index if the interface is
+   already known; otherwise the interface is added to the list of known
+   non-existing interfaces and a new virtual interface index is returned;
+   if something fails a nfhipac_error is returned */
+int
+nf_hipac_dev_get_vindex(const char *ifname);
+
+/* return virtual interface index corresponding to ifindex */
+static inline u16
+nf_hipac_dev_ifindex_to_vindex(u16 ifindex)
+{
+	u16 i;
+	for (i = 0; i < nf_hipac_dev_ifindex_map.len; i++) 
+		if (nf_hipac_dev_ifindex_map.map[i].ifindex == ifindex)
+			return nf_hipac_dev_ifindex_map.map[i].vindex;
+	return 0;
+}
+
+#endif
Binary files nf-hipac/kernel/nfhp_dev.o and nfhipac/kernel/nfhp_dev.o differ
diff -uNr nf-hipac/kernel/.nfhp_dev.o.cmd nfhipac/kernel/.nfhp_dev.o.cmd
--- nf-hipac/kernel/.nfhp_dev.o.cmd	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/.nfhp_dev.o.cmd	2014-11-21 12:54:43.000000000 +0800
@@ -0,0 +1,747 @@
+cmd_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_dev.o := gcc -Wp,-MD,/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.nfhp_dev.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include -Iinclude  -I/usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include -include include/linux/autoconf.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -Wframe-larger-than=2048 -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-dwarf2-cfi-asm -fconserve-stack -D SINGLE_PATH  -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(nfhp_dev)"  -D"KBUILD_MODNAME=KBUILD_STR(nf_hipac)"  -c -o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/.tmp_nfhp_dev.o /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_dev.c
+
+deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_dev.o := +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_dev.c +  include/linux/kernel.h +    $(wildcard include/config/lbdaf.h) +    $(wildcard include/config/preempt/voluntary.h) +    $(wildcard include/config/debug/spinlock/sleep.h) +    $(wildcard include/config/prove/locking.h) +    $(wildcard include/config/printk.h) +    $(wildcard include/config/dynamic/debug.h) +    $(wildcard include/config/ring/buffer.h) +    $(wildcard include/config/tracing.h) +    $(wildcard include/config/numa.h) +    $(wildcard include/config/ftrace/mcount/record.h) +  /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h +  include/linux/linkage.h +  include/linux/compiler.h +    $(wildcard include/config/trace/branch/profiling.h) +    $(wildcard include/config/profile/all/branches.h) +    $(wildcard include/config/enable/must/check.h) +    $(wildcard include/config/enable/warn/deprecated.h) +  include/linux/compiler-gcc.h +    $(wildcard include/config/arch/supports/optimized/inlining.h) +    $(wildcard include/config/optimize/inlining.h) +  include/linux/compiler-gcc4.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/linkage.h +    $(wildcard include/config/x86/32.h) +    $(wildcard include/config/x86/64.h) +    $(wildcard include/config/x86/alignment/16.h) +  include/linux/stringify.h +  include/linux/stddef.h +  include/linux/types.h +    $(wildcard include/config/uid16.h) +    $(wildcard include/config/phys/addr/t/64bit.h) +    $(wildcard include/config/64bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/types.h +    $(wildcard include/config/highmem64g.h) +  include/asm-generic/types.h +  include/asm-generic/int-ll64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitsperlong.h +  include/asm-generic/bitsperlong.h +  include/linux/posix_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/posix_types_64.h +  include/linux/bitops.h +    $(wildcard include/config/generic/find/first/bit.h) +    $(wildcard include/config/generic/find/last/bit.h) +    $(wildcard include/config/generic/find/next/bit.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bitops.h +    $(wildcard include/config/x86/cmov.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/alternative.h +    $(wildcard include/config/smp.h) +    $(wildcard include/config/paravirt.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/asm.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpufeature.h +    $(wildcard include/config/x86/invlpg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/required-features.h +    $(wildcard include/config/x86/minimum/cpu/family.h) +    $(wildcard include/config/math/emulation.h) +    $(wildcard include/config/x86/pae.h) +    $(wildcard include/config/x86/cmpxchg64.h) +    $(wildcard include/config/x86/use/3dnow.h) +    $(wildcard include/config/x86/p6/nop.h) +  include/asm-generic/bitops/sched.h +  include/asm-generic/bitops/hweight.h +  include/asm-generic/bitops/fls64.h +  include/asm-generic/bitops/ext2-non-atomic.h +  include/asm-generic/bitops/le.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/byteorder.h +  include/linux/byteorder/little_endian.h +  include/linux/swab.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swab.h +    $(wildcard include/config/x86/bswap.h) +  include/linux/byteorder/generic.h +  include/asm-generic/bitops/minix.h +  include/linux/log2.h +    $(wildcard include/config/arch/has/ilog2/u32.h) +    $(wildcard include/config/arch/has/ilog2/u64.h) +  include/linux/typecheck.h +  include/linux/ratelimit.h +  include/linux/param.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/param.h +  include/asm-generic/param.h +    $(wildcard include/config/hz.h) +  include/linux/dynamic_debug.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bug.h +    $(wildcard include/config/bug.h) +    $(wildcard include/config/debug/bugverbose.h) +  include/asm-generic/bug.h +    $(wildcard include/config/generic/bug.h) +    $(wildcard include/config/generic/bug/relative/pointers.h) +  include/linux/spinlock.h +    $(wildcard include/config/debug/spinlock.h) +    $(wildcard include/config/generic/lockbreak.h) +    $(wildcard include/config/preempt.h) +    $(wildcard include/config/debug/lock/alloc.h) +  include/linux/preempt.h +    $(wildcard include/config/debug/preempt.h) +    $(wildcard include/config/preempt/tracer.h) +    $(wildcard include/config/preempt/notifiers.h) +  include/linux/thread_info.h +    $(wildcard include/config/compat.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/thread_info.h +    $(wildcard include/config/debug/stack/usage.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_types.h +  include/linux/const.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64_types.h +    $(wildcard include/config/physical/start.h) +    $(wildcard include/config/physical/align.h) +    $(wildcard include/config/flatmem.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/page_64.h +  include/asm-generic/memory_model.h +    $(wildcard include/config/discontigmem.h) +    $(wildcard include/config/sparsemem/vmemmap.h) +    $(wildcard include/config/sparsemem.h) +  include/asm-generic/getorder.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor.h +    $(wildcard include/config/x86/vsmp.h) +    $(wildcard include/config/cc/stackprotector.h) +    $(wildcard include/config/m386.h) +    $(wildcard include/config/m486.h) +    $(wildcard include/config/x86/debugctlmsr.h) +    $(wildcard include/config/cpu/sup/amd.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/processor-flags.h +    $(wildcard include/config/vm86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vm86.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace.h +    $(wildcard include/config/x86/ptrace/bts.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ptrace-abi.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/segment.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cache.h +    $(wildcard include/config/x86/l1/cache/shift.h) +  include/linux/init.h +    $(wildcard include/config/modules.h) +    $(wildcard include/config/hotplug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/math_emu.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sigcontext.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/current.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/percpu.h +    $(wildcard include/config/x86/64/smp.h) +  include/asm-generic/percpu.h +    $(wildcard include/config/have/setup/per/cpu/area.h) +  include/linux/threads.h +    $(wildcard include/config/nr/cpus.h) +    $(wildcard include/config/base/small.h) +  include/linux/percpu-defs.h +    $(wildcard include/config/debug/force/weak/per/cpu.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/system.h +    $(wildcard include/config/ia32/emulation.h) +    $(wildcard include/config/x86/32/lazy/gs.h) +    $(wildcard include/config/x86/ppro/fence.h) +    $(wildcard include/config/x86/oostore.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cmpxchg_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/nops.h +    $(wildcard include/config/mk7.h) +  include/linux/irqflags.h +    $(wildcard include/config/trace/irqflags.h) +    $(wildcard include/config/irqsoff/tracer.h) +    $(wildcard include/config/trace/irqflags/support.h) +    $(wildcard include/config/x86.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irqflags.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt.h +    $(wildcard include/config/highpte.h) +    $(wildcard include/config/paravirt/spinlocks.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_types.h +    $(wildcard include/config/kmemcheck.h) +    $(wildcard include/config/compat/vdso.h) +    $(wildcard include/config/proc/fs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/paravirt_types.h +    $(wildcard include/config/x86/local/apic.h) +    $(wildcard include/config/paravirt/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/desc_defs.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/kmap_types.h +    $(wildcard include/config/debug/highmem.h) +  include/asm-generic/kmap_types.h +  include/linux/cpumask.h +    $(wildcard include/config/cpumask/offstack.h) +    $(wildcard include/config/hotplug/cpu.h) +    $(wildcard include/config/debug/per/cpu/maps.h) +    $(wildcard include/config/disable/obsolete/cpumask/functions.h) +  include/linux/bitmap.h +  include/linux/string.h +    $(wildcard include/config/binary/printf.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/string_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/msr-index.h +  include/linux/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ioctl.h +  include/asm-generic/ioctl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/errno.h +  include/asm-generic/errno.h +  include/asm-generic/errno-base.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cpumask.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ds.h +    $(wildcard include/config/x86/ds.h) +  include/linux/err.h +  include/linux/personality.h +  include/linux/cache.h +    $(wildcard include/config/arch/has/cache/line/size.h) +  include/linux/math64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/div64.h +  include/asm-generic/div64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ftrace.h +    $(wildcard include/config/function/tracer.h) +    $(wildcard include/config/dynamic/ftrace.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/atomic_64.h +  include/asm-generic/atomic-long.h +  include/linux/list.h +    $(wildcard include/config/debug/list.h) +  include/linux/poison.h +    $(wildcard include/config/illegal/pointer/value.h) +  include/linux/prefetch.h +  include/linux/bottom_half.h +  include/linux/spinlock_types.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock_types.h +  include/linux/lockdep.h +    $(wildcard include/config/lockdep.h) +    $(wildcard include/config/lock/stat.h) +    $(wildcard include/config/generic/hardirqs.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/spinlock.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwlock.h +  include/linux/spinlock_api_smp.h +  include/linux/notifier.h +  include/linux/errno.h +  include/linux/mutex.h +    $(wildcard include/config/debug/mutexes.h) +  include/linux/rwsem.h +    $(wildcard include/config/rwsem/generic/spinlock.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/rwsem.h +  include/linux/srcu.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_com.h +  include/linux/if.h +  include/linux/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/socket.h +  include/asm-generic/socket.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sockios.h +  include/asm-generic/sockios.h +  include/linux/sockios.h +  include/linux/uio.h +  include/linux/hdlc/ioctl.h +  include/linux/in.h +  include/linux/netfilter_ipv4/ip_tables.h +  include/linux/ip.h +  include/linux/skbuff.h +    $(wildcard include/config/nf/conntrack.h) +    $(wildcard include/config/bridge/netfilter.h) +    $(wildcard include/config/has/dma.h) +    $(wildcard include/config/xfrm.h) +    $(wildcard include/config/net/sched.h) +    $(wildcard include/config/net/cls/act.h) +    $(wildcard include/config/ipv6/ndisc/nodetype.h) +    $(wildcard include/config/net/dma.h) +    $(wildcard include/config/network/secmark.h) +  include/linux/kmemcheck.h +  include/linux/mm_types.h +    $(wildcard include/config/split/ptlock/cpus.h) +    $(wildcard include/config/want/page/debug/flags.h) +    $(wildcard include/config/mmu.h) +    $(wildcard include/config/aio.h) +    $(wildcard include/config/mm/owner.h) +    $(wildcard include/config/mmu/notifier.h) +  include/linux/auxvec.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/auxvec.h +  include/linux/prio_tree.h +  include/linux/rbtree.h +  include/linux/completion.h +  include/linux/wait.h +  include/linux/page-debug-flags.h +    $(wildcard include/config/page/poisoning.h) +    $(wildcard include/config/page/debug/something/else.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmu.h +  include/linux/time.h +    $(wildcard include/config/arch/uses/gettimeoffset.h) +  include/linux/seqlock.h +  include/linux/net.h +    $(wildcard include/config/sysctl.h) +  include/linux/random.h +  include/linux/irqnr.h +  include/linux/fcntl.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fcntl.h +  include/asm-generic/fcntl.h +  include/linux/sysctl.h +  include/linux/textsearch.h +  include/linux/module.h +    $(wildcard include/config/modversions.h) +    $(wildcard include/config/unused/symbols.h) +    $(wildcard include/config/kallsyms.h) +    $(wildcard include/config/tracepoints.h) +    $(wildcard include/config/event/tracing.h) +    $(wildcard include/config/module/unload.h) +    $(wildcard include/config/constructors.h) +    $(wildcard include/config/sysfs.h) +  include/linux/stat.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/stat.h +  include/linux/kmod.h +    $(wildcard include/config/pm/sleep.h) +  include/linux/gfp.h +    $(wildcard include/config/highmem.h) +    $(wildcard include/config/zone/dma.h) +    $(wildcard include/config/zone/dma32.h) +    $(wildcard include/config/debug/vm.h) +  include/linux/mmzone.h +    $(wildcard include/config/force/max/zoneorder.h) +    $(wildcard include/config/memory/hotplug.h) +    $(wildcard include/config/arch/populates/node/map.h) +    $(wildcard include/config/flat/node/mem/map.h) +    $(wildcard include/config/cgroup/mem/res/ctlr.h) +    $(wildcard include/config/have/memory/present.h) +    $(wildcard include/config/need/node/memmap/size.h) +    $(wildcard include/config/need/multiple/nodes.h) +    $(wildcard include/config/have/arch/early/pfn/to/nid.h) +    $(wildcard include/config/sparsemem/extreme.h) +    $(wildcard include/config/nodes/span/other/nodes.h) +    $(wildcard include/config/holes/in/zone.h) +    $(wildcard include/config/arch/has/holes/memorymodel.h) +  include/linux/numa.h +    $(wildcard include/config/nodes/shift.h) +  include/linux/nodemask.h +  include/linux/pageblock-flags.h +    $(wildcard include/config/hugetlb/page.h) +    $(wildcard include/config/hugetlb/page/size/variable.h) +  include/linux/bounds.h +  include/linux/memory_hotplug.h +    $(wildcard include/config/have/arch/nodedata/extension.h) +    $(wildcard include/config/memory/hotremove.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mmzone_64.h +    $(wildcard include/config/numa/emu.h) +  include/linux/mmdebug.h +    $(wildcard include/config/debug/virtual.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/smp.h +    $(wildcard include/config/x86/io/apic.h) +    $(wildcard include/config/x86/32/smp.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec.h +    $(wildcard include/config/x86/numaq.h) +    $(wildcard include/config/mca.h) +    $(wildcard include/config/eisa.h) +    $(wildcard include/config/x86/mpparse.h) +    $(wildcard include/config/acpi.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/mpspec_def.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/x86_init.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/bootparam.h +  include/linux/screen_info.h +  include/linux/apm_bios.h +  include/linux/edd.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/e820.h +    $(wildcard include/config/efi.h) +    $(wildcard include/config/hibernation.h) +    $(wildcard include/config/memtest.h) +  include/linux/ioport.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ist.h +  include/video/edid.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apic.h +    $(wildcard include/config/x86/x2apic.h) +  include/linux/delay.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/delay.h +  include/linux/pm.h +    $(wildcard include/config/pm/runtime.h) +  include/linux/workqueue.h +  include/linux/timer.h +    $(wildcard include/config/timer/stats.h) +    $(wildcard include/config/debug/objects/timers.h) +  include/linux/ktime.h +    $(wildcard include/config/ktime/scalar.h) +  include/linux/jiffies.h +  include/linux/timex.h +    $(wildcard include/config/no/hz.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/timex.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/tsc.h +    $(wildcard include/config/x86/tsc.h) +  include/linux/debugobjects.h +    $(wildcard include/config/debug/objects.h) +    $(wildcard include/config/debug/objects/free.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/apicdef.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/fixmap.h +    $(wildcard include/config/provide/ohci1394/dma/init.h) +    $(wildcard include/config/x86/visws/apic.h) +    $(wildcard include/config/x86/f00f/bug.h) +    $(wildcard include/config/x86/cyclone/timer.h) +    $(wildcard include/config/pci/mmconfig.h) +    $(wildcard include/config/intel/txt.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/acpi.h +    $(wildcard include/config/acpi/numa.h) +  include/acpi/pdc_intel.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/numa_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vsyscall.h +    $(wildcard include/config/generic/time.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_apic.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irq_vectors.h +    $(wildcard include/config/sparse/irq.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sparsemem.h +  include/linux/topology.h +    $(wildcard include/config/sched/smt.h) +    $(wildcard include/config/sched/mc.h) +  include/linux/smp.h +    $(wildcard include/config/use/generic/smp/helpers.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/topology.h +    $(wildcard include/config/x86/ht.h) +    $(wildcard include/config/x86/64/acpi/numa.h) +  include/asm-generic/topology.h +  include/linux/elf.h +  include/linux/elf-em.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/elf.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/vdso.h +  include/linux/kobject.h +  include/linux/sysfs.h +  include/linux/kref.h +  include/linux/moduleparam.h +    $(wildcard include/config/alpha.h) +    $(wildcard include/config/ia64.h) +    $(wildcard include/config/ppc64.h) +  include/linux/tracepoint.h +  include/linux/rcupdate.h +    $(wildcard include/config/tree/preempt/rcu.h) +    $(wildcard include/config/tree/rcu.h) +  include/linux/rcutree.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/local.h +  include/linux/percpu.h +    $(wildcard include/config/have/legacy/per/cpu/area.h) +    $(wildcard include/config/need/per/cpu/embed/first/chunk.h) +    $(wildcard include/config/need/per/cpu/page/first/chunk.h) +    $(wildcard include/config/debug/kmemleak.h) +  include/linux/slab.h +    $(wildcard include/config/slab/debug.h) +    $(wildcard include/config/slub.h) +    $(wildcard include/config/slob.h) +    $(wildcard include/config/debug/slab.h) +  include/linux/slub_def.h +    $(wildcard include/config/slub/stats.h) +    $(wildcard include/config/slub/debug.h) +    $(wildcard include/config/kmemtrace.h) +  include/linux/kmemtrace.h +  include/trace/events/kmem.h +  include/trace/define_trace.h +  include/linux/kmemleak.h +  include/linux/pfn.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/module.h +    $(wildcard include/config/m586.h) +    $(wildcard include/config/m586tsc.h) +    $(wildcard include/config/m586mmx.h) +    $(wildcard include/config/mcore2.h) +    $(wildcard include/config/matom.h) +    $(wildcard include/config/m686.h) +    $(wildcard include/config/mpentiumii.h) +    $(wildcard include/config/mpentiumiii.h) +    $(wildcard include/config/mpentiumm.h) +    $(wildcard include/config/mpentium4.h) +    $(wildcard include/config/mk6.h) +    $(wildcard include/config/mk8.h) +    $(wildcard include/config/x86/elan.h) +    $(wildcard include/config/mcrusoe.h) +    $(wildcard include/config/mefficeon.h) +    $(wildcard include/config/mwinchipc6.h) +    $(wildcard include/config/mwinchip3d.h) +    $(wildcard include/config/mcyrixiii.h) +    $(wildcard include/config/mviac3/2.h) +    $(wildcard include/config/mviac7.h) +    $(wildcard include/config/mgeodegx1.h) +    $(wildcard include/config/mgeode/lx.h) +    $(wildcard include/config/4kstacks.h) +  include/asm-generic/module.h +  include/trace/events/module.h +  include/net/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess.h +    $(wildcard include/config/x86/wp/works/ok.h) +    $(wildcard include/config/x86/intel/usercopy.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/uaccess_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/checksum_64.h +  include/linux/dmaengine.h +    $(wildcard include/config/dma/engine.h) +    $(wildcard include/config/async/tx/dma.h) +    $(wildcard include/config/async/tx/disable/channel/switch.h) +  include/linux/device.h +    $(wildcard include/config/debug/devres.h) +    $(wildcard include/config/devtmpfs.h) +  include/linux/klist.h +  include/linux/semaphore.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/device.h +    $(wildcard include/config/dmar.h) +  include/linux/pm_wakeup.h +    $(wildcard include/config/pm.h) +  include/linux/dma-mapping.h +    $(wildcard include/config/have/dma/attrs.h) +  include/linux/dma-attrs.h +  include/linux/bug.h +  include/linux/scatterlist.h +    $(wildcard include/config/debug/sg.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/scatterlist.h +  include/asm-generic/scatterlist.h +  include/linux/mm.h +    $(wildcard include/config/stack/growsup.h) +    $(wildcard include/config/swap.h) +    $(wildcard include/config/debug/pagealloc.h) +  include/linux/debug_locks.h +    $(wildcard include/config/debug/locking/api/selftests.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/pgtable_64_types.h +  include/asm-generic/pgtable.h +  include/linux/page-flags.h +    $(wildcard include/config/pageflags/extended.h) +    $(wildcard include/config/have/mlocked/page/bit.h) +    $(wildcard include/config/arch/uses/pg/uncached.h) +    $(wildcard include/config/memory/failure.h) +    $(wildcard include/config/s390.h) +  include/linux/vmstat.h +    $(wildcard include/config/vm/event/counters.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/io_64.h +  include/linux/vmalloc.h +  include/asm-generic/iomap.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/dma-mapping.h +    $(wildcard include/config/isa.h) +  include/linux/dma-debug.h +    $(wildcard include/config/dma/api/debug.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/swiotlb.h +    $(wildcard include/config/swiotlb.h) +  include/linux/swiotlb.h +  include/asm-generic/dma-coherent.h +    $(wildcard include/config/have/generic/dma/coherent.h) +  include/asm-generic/dma-mapping-common.h +  include/linux/hrtimer.h +    $(wildcard include/config/high/res/timers.h) +  include/linux/netfilter_ipv4.h +  include/linux/netfilter.h +    $(wildcard include/config/netfilter.h) +    $(wildcard include/config/netfilter/debug.h) +    $(wildcard include/config/nf/nat/needed.h) +  include/linux/in6.h +  include/net/flow.h +  include/linux/proc_fs.h +    $(wildcard include/config/proc/devicetree.h) +    $(wildcard include/config/proc/kcore.h) +  include/linux/fs.h +    $(wildcard include/config/dnotify.h) +    $(wildcard include/config/quota.h) +    $(wildcard include/config/fsnotify.h) +    $(wildcard include/config/inotify.h) +    $(wildcard include/config/security.h) +    $(wildcard include/config/fs/posix/acl.h) +    $(wildcard include/config/epoll.h) +    $(wildcard include/config/debug/writecount.h) +    $(wildcard include/config/file/locking.h) +    $(wildcard include/config/auditsyscall.h) +    $(wildcard include/config/block.h) +    $(wildcard include/config/fs/xip.h) +    $(wildcard include/config/migration.h) +  include/linux/limits.h +  include/linux/kdev_t.h +  include/linux/dcache.h +  include/linux/rculist.h +  include/linux/path.h +  include/linux/radix-tree.h +  include/linux/pid.h +  include/linux/capability.h +    $(wildcard include/config/security/file/capabilities.h) +  include/linux/fiemap.h +  include/linux/quota.h +  include/linux/dqblk_xfs.h +  include/linux/dqblk_v1.h +  include/linux/dqblk_v2.h +  include/linux/dqblk_qtree.h +  include/linux/nfs_fs_i.h +  include/linux/nfs.h +  include/linux/sunrpc/msg_prot.h +  include/linux/inet.h +  include/linux/magic.h +  include/linux/netfilter/x_tables.h +  include/linux/netdevice.h +    $(wildcard include/config/dcb.h) +    $(wildcard include/config/wlan/80211.h) +    $(wildcard include/config/ax25.h) +    $(wildcard include/config/mac80211/mesh.h) +    $(wildcard include/config/tr.h) +    $(wildcard include/config/net/ipip.h) +    $(wildcard include/config/net/ipgre.h) +    $(wildcard include/config/ipv6/sit.h) +    $(wildcard include/config/ipv6/tunnel.h) +    $(wildcard include/config/netpoll.h) +    $(wildcard include/config/net/poll/controller.h) +    $(wildcard include/config/fcoe.h) +    $(wildcard include/config/wireless/ext.h) +    $(wildcard include/config/net/dsa.h) +    $(wildcard include/config/net/ns.h) +    $(wildcard include/config/net/dsa/tag/dsa.h) +    $(wildcard include/config/net/dsa/tag/trailer.h) +    $(wildcard include/config/netpoll/trap.h) +  include/linux/if_ether.h +  include/linux/if_packet.h +  include/linux/ethtool.h +  include/net/net_namespace.h +    $(wildcard include/config/ipv6.h) +    $(wildcard include/config/ip/dccp.h) +    $(wildcard include/config/net.h) +  include/net/netns/core.h +  include/net/netns/mib.h +    $(wildcard include/config/xfrm/statistics.h) +  include/net/snmp.h +  include/linux/snmp.h +  include/net/netns/unix.h +  include/net/netns/packet.h +  include/net/netns/ipv4.h +    $(wildcard include/config/ip/multiple/tables.h) +    $(wildcard include/config/ip/mroute.h) +    $(wildcard include/config/ip/pimsm/v1.h) +    $(wildcard include/config/ip/pimsm/v2.h) +  include/net/inet_frag.h +  include/net/netns/ipv6.h +    $(wildcard include/config/ipv6/multiple/tables.h) +    $(wildcard include/config/ipv6/mroute.h) +    $(wildcard include/config/ipv6/pimsm/v2.h) +  include/net/dst_ops.h +  include/net/netns/dccp.h +  include/net/netns/x_tables.h +    $(wildcard include/config/bridge/nf/ebtables.h) +  include/net/netns/conntrack.h +  include/linux/list_nulls.h +  include/net/netns/xfrm.h +  include/linux/xfrm.h +  include/linux/seq_file_net.h +  include/linux/seq_file.h +  include/net/dsa.h +  include/net/dcbnl.h +  include/linux/interrupt.h +    $(wildcard include/config/generic/irq/probe.h) +    $(wildcard include/config/debug/shirq.h) +  include/linux/irqreturn.h +  include/linux/hardirq.h +    $(wildcard include/config/virt/cpu/accounting.h) +    $(wildcard include/config/irq/time/accounting.h) +  include/linux/ftrace_irq.h +    $(wildcard include/config/ftrace/nmi/enter.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/hardirq.h +    $(wildcard include/config/x86/mce.h) +    $(wildcard include/config/x86/mce/threshold.h) +  include/linux/irq.h +    $(wildcard include/config/irq/per/cpu.h) +    $(wildcard include/config/irq/release/method.h) +    $(wildcard include/config/intr/remap.h) +    $(wildcard include/config/generic/pending/irq.h) +    $(wildcard include/config/numa/irq/desc.h) +    $(wildcard include/config/generic/hardirqs/no//do/irq.h) +    $(wildcard include/config/cpumasks/offstack.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irq.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/irq_regs.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/hw_irq.h +  include/linux/profile.h +    $(wildcard include/config/profiling.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sections.h +  include/asm-generic/sections.h +  include/net/compat.h +  include/linux/compat.h +  include/linux/sem.h +    $(wildcard include/config/sysvipc.h) +  include/linux/ipc.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ipcbuf.h +  include/asm-generic/ipcbuf.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/sembuf.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/compat.h +  include/linux/sched.h +    $(wildcard include/config/sched/debug.h) +    $(wildcard include/config/detect/softlockup.h) +    $(wildcard include/config/detect/hung/task.h) +    $(wildcard include/config/core/dump/default/elf/headers.h) +    $(wildcard include/config/bsd/process/acct.h) +    $(wildcard include/config/taskstats.h) +    $(wildcard include/config/audit.h) +    $(wildcard include/config/inotify/user.h) +    $(wildcard include/config/posix/mqueue.h) +    $(wildcard include/config/keys.h) +    $(wildcard include/config/perf/events.h) +    $(wildcard include/config/schedstats.h) +    $(wildcard include/config/task/delay/acct.h) +    $(wildcard include/config/fair/group/sched.h) +    $(wildcard include/config/rt/group/sched.h) +    $(wildcard include/config/blk/dev/io/trace.h) +    $(wildcard include/config/rt/mutexes.h) +    $(wildcard include/config/task/xacct.h) +    $(wildcard include/config/cpusets.h) +    $(wildcard include/config/cgroups.h) +    $(wildcard include/config/futex.h) +    $(wildcard include/config/fault/injection.h) +    $(wildcard include/config/latencytop.h) +    $(wildcard include/config/function/graph/tracer.h) +    $(wildcard include/config/have/unstable/sched/clock.h) +    $(wildcard include/config/cgroup/sched.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/cputime.h +  include/asm-generic/cputime.h +  include/linux/signal.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/signal.h +  include/asm-generic/signal-defs.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/siginfo.h +  include/asm-generic/siginfo.h +  include/linux/proportions.h +  include/linux/percpu_counter.h +  include/linux/seccomp.h +    $(wildcard include/config/seccomp.h) +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/seccomp.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/seccomp_64.h +  include/linux/unistd.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/unistd.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/unistd_64.h +  include/asm/asm-offsets.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/ia32_unistd.h +  include/linux/rtmutex.h +    $(wildcard include/config/debug/rt/mutexes.h) +  include/linux/plist.h +    $(wildcard include/config/debug/pi/list.h) +  include/linux/resource.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/resource.h +  include/asm-generic/resource.h +  include/linux/task_io_accounting.h +    $(wildcard include/config/task/io/accounting.h) +  include/linux/latencytop.h +  include/linux/cred.h +    $(wildcard include/config/debug/credentials.h) +  include/linux/key.h +  include/linux/selinux.h +    $(wildcard include/config/security/selinux.h) +  include/linux/aio.h +  include/linux/aio_abi.h +  /usr/src/linux-headers-2.6.32-5-amd64-hz1000/arch/x86/include/asm/user32.h +  include/linux/netfilter/xt_tcpudp.h +  include/linux/netlink.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/hipac.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/mode.h +    $(wildcard include/config/uml/net.h) +    $(wildcard include/config/host/2g/2g.h) +    $(wildcard include/config/nest/level.h) +    $(wildcard include/config/kernel/half/gigs.h) +  include/linux/version.h +  include/linux/kmalloc_sizes.h +  /usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_dev.h +
+/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_dev.o: $(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_dev.o)
+
+$(deps_/usr/src/linux-source-2.6.32/net/ipv4/netfilter/nf-hipac/kernel/nfhp_dev.o):
diff -uNr nf-hipac/kernel/nfhp_mod.c nfhipac/kernel/nfhp_mod.c
--- nf-hipac/kernel/nfhp_mod.c	1970-01-01 08:00:00.000000000 +0800
+++ nfhipac/kernel/nfhp_mod.c	2014-11-21 12:51:25.000000000 +0800
@@ -0,0 +1,1181 @@
+/*
+ *             High performance packet classification 
+ *                     <http://www.hipac.org>
+ *
+ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
+ *                 +-----------------------------+
+ *                 |       Michael Bellion       |
+ *                 |  <michael@marasystems.com>  |
+ *                 +-----------------------------+
+ *
+ * (c) 2002-2003   hipac core team <nf@hipac.org>:
+ *     +---------------------------+--------------------------+
+ *     |      Michael Bellion      |       Thomas Heinz       |
+ *     |   <mbellion@hipac.org>    |   <creatix@hipac.org>    |
+ *     +---------------------------+--------------------------+
+ *
+ * Licenced under the GNU General Public Licence, version 2.
+ */
+
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/netlink.h>
+#include <linux/netfilter_ipv4.h>
+#include <net/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/icmp.h>
+#include <linux/netdevice.h>
+#include "nfhp_mod.h"
+#include "nfhp_com.h"
+#include "nfhp_dev.h"
+#include "nfhp_proc.h"
+#include "hipac.h"
+
+/* hook match functions */
+static nf_hookfn input_match;
+static nf_hookfn forward_match;
+static nf_hookfn output_match;
+
+/* hipac data structures for INPUT, FORWARD and OUPUT hook plus
+   their corresponding netfilter ops */
+void *hipac_input   = NULL;
+void *hipac_forward = NULL;
+void *hipac_output  = NULL;
+struct nf_hook_ops input_op =
+{
+	.hook           = input_match,
+	.owner          = THIS_MODULE,
+	.pf             = PF_INET,
+	.hooknum        = NF_INET_LOCAL_IN,
+	.priority       = NF_IP_PRI_FILTER - 1,
+};
+struct nf_hook_ops forward_op =
+{
+	.hook           = forward_match,
+	.owner          = THIS_MODULE,
+	.pf             = PF_INET,
+	.hooknum        = NF_INET_FORWARD,
+	.priority       = NF_IP_PRI_FILTER - 1,
+};
+struct nf_hook_ops output_op  =
+{
+	.hook           = output_match,
+	.owner          = THIS_MODULE,
+	.pf             = PF_INET,
+	.hooknum        = NF_INET_LOCAL_OUT,
+	.priority       = NF_IP_PRI_FILTER - 1,
+};
+
+/* used to serialize hipac modifications caused by netlink commands and
+   the interface handling module */
+static DEFINE_MUTEX(nfhp_mutex);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
+DECLARE_MUTEX(nlhp_lock);
+#else
+DEFINE_SEMAPHORE(nlhp_lock);
+#endif
+
+static struct sock *nfhp_sock = NULL;
+
+/* latest hipac_get_chain_info snapshot */
+struct list_info
+{
+	struct hipac_chain_info *inf;
+	u32 len;
+};
+static struct list_info linfo = {NULL, 0};
+
+struct packet
+{
+	int hook;
+	struct sk_buff **skbuff;
+	const struct net_device *indev, *outdev;
+};
+
+/*
+ * dimension extractor functions
+ */
+
+static u32
+get_state(const void *pkt, int *hotdrop)
+{
+	return 0;
+}
+
+static u32
+get_src_ip(const void *pkt, int *hotdrop)
+{
+	const struct sk_buff *skb = *((struct packet *) pkt)->skbuff;
+	struct iphdr *iph = ip_hdr(skb);
+	return ntohl(iph->saddr);
+}
+
+static u32
+get_dst_ip(const void *pkt, int *hotdrop)
+{
+	const struct sk_buff *skb = *((struct packet *) pkt)->skbuff;
+	struct iphdr *iph = ip_hdr(skb);
+	return ntohl(iph->daddr);
+}
+
+static u32
+get_iniface(const void *pkt, int *hotdrop)
+{
+	return nf_hipac_dev_ifindex_to_vindex(((struct packet*) pkt)
+					      ->indev->ifindex);
+}
+
+static u32
+get_outiface(const void *pkt, int *hotdrop)
+{
+	return nf_hipac_dev_ifindex_to_vindex(((struct packet*)	pkt)
+					      ->outdev->ifindex);
+}
+
+static u32
+get_proto(const void *pkt, int *hotdrop)
+{
+	const struct sk_buff *skb = *((struct packet *) pkt)->skbuff;
+	struct iphdr *iph = ip_hdr(skb);
+	return iph->protocol;
+}
+
+static u32
+get_fragment(const void *pkt, int *hotdrop)
+{
+	const struct sk_buff *skb = *((struct packet *) pkt)->skbuff;
+	struct iphdr *iph = ip_hdr(skb);
+	int offset = ntohs(iph->frag_off) & IP_OFFSET;
+	if (unlikely(offset)) {
+		if (unlikely(offset == 1 &&
+			     iph->protocol == IPPROTO_TCP)) {
+			printk(KERN_NOTICE "Dropping evil TCP offset=1 "
+			       "fragment.\n");
+			*hotdrop = 1;
+		}
+		return 1;
+	}
+	return 0;
+}
+
+static u32
+get_dport(const void *pkt, int *hotdrop)
+{
+	struct udphdr _udph, *uh;
+	const struct sk_buff *skb = *((struct packet *) pkt)->skbuff;
+	struct iphdr *iph = ip_hdr(skb);
+	uh = skb_header_pointer(skb, iph->ihl*4, 
+				sizeof(_udph), &_udph);
+	if (unlikely(uh == NULL)) {
+		/* We‘ve been asked to examine this packet, and we
+		   can‘t.  Hence, no choice but to drop. */
+		*hotdrop = 1;
+		return 0;
+	}
+	return ntohs(uh->dest);
+}
+
+static u32
+get_sport(const void *pkt, int *hotdrop)
+{
+	struct udphdr _udph, *uh;
+	const struct sk_buff *skb = *((struct packet *) pkt)->skbuff;
+	struct iphdr *iph = ip_hdr(skb);
+	uh = skb_header_pointer(skb, iph->ihl*4, 
+				sizeof(_udph), &_udph);
+	if (unlikely(uh == NULL)) {
+		*hotdrop = 1;
+		return 0;
+	}
+	return ntohs(uh->source);
+}
+
+static u32
+get_syn(const void *pkt, int *hotdrop)
+{
+	struct tcphdr _tcph, *th;
+	const struct sk_buff *skb = *((struct packet *) pkt)->skbuff;
+	struct iphdr *iph = ip_hdr(skb);
+	th = skb_header_pointer(skb, iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (unlikely(th == NULL)) {
+		*hotdrop = 1;
+		return 0;
+	}
+	return !(th->syn && !th->ack && !th->fin && !th->rst);
+}
+
+static u32
+get_icmptypes(const void *pkt, int *hotdrop)
+{
+	struct icmphdr _icmph, *ic;
+	const struct sk_buff *skb = *((struct packet *) pkt)->skbuff;
+	struct iphdr *iph = ip_hdr(skb);
+	ic = skb_header_pointer(skb, iph->ihl*4,
+				sizeof(_icmph), &_icmph);
+	if (unlikely(ic == NULL)) {
+		*hotdrop = 1;
+		return 0;
+	}
+	return (ic->type << 8) + ic->code;
+}
+
+static u32
+get_ttl(const void *pkt, int *hotdrop)
+{
+	const struct sk_buff *skb = *((struct packet *) pkt)->skbuff;
+	struct iphdr *iph = ip_hdr(skb);
+	return iph->ttl;
+}
+
+
+/*
+ * conntrack dependency management
+ */
+
+int
+nfhp_register_cthelp(struct module *cthelp)
+{
+	return 0;
+}
+
+void
+nfhp_unregister_cthelp(struct module *cthelp)
+{
+}
+
+static inline int
+cthelp_use(void)
+{
+	return NFHE_CT;
+}
+
+static inline void
+cthelp_unuse(void)
+{
+}
+
+/*
+ * functions and data structures necessary for hipac initialization
+ */
+
+/* dimension id to bit type mapping */
+static const u8 dim2btype[] =
+{
+	[DIMID_STATE]      = BIT_STATE,
+	[DIMID_SRC_IP]     = BIT_SRC_IP,
+	[DIMID_DEST_IP]    = BIT_DEST_IP,
+	[DIMID_INIFACE]    = BIT_INIFACE,
+	[DIMID_OUTIFACE]   = BIT_OUTIFACE,
+	[DIMID_PROTO]      = BIT_PROTO,
+	[DIMID_FRAGMENT]   = BIT_FRAGMENT,
+	[DIMID_DPORT]      = BIT_DPORT,
+	[DIMID_SPORT]      = BIT_SPORT,
+	[DIMID_SYN]        = BIT_SYN,
+	[DIMID_ICMP_TYPE]  = BIT_ICMP_TYPE,
+	[DIMID_TTL]        = BIT_TTL
+};
+
+/* dimension extractor functions */
+static const hipac_extract_t extract[] =
+{
+	[DIMID_STATE]      = get_state,
+	[DIMID_SRC_IP]     = get_src_ip,
+	[DIMID_DEST_IP]    = get_dst_ip,
+	[DIMID_INIFACE]    = get_iniface,
+	[DIMID_OUTIFACE]   = get_outiface,
+	[DIMID_PROTO]      = get_proto,
+	[DIMID_FRAGMENT]   = get_fragment,
+	[DIMID_DPORT]      = get_dport,
+	[DIMID_SPORT]      = get_sport,
+	[DIMID_SYN]        = get_syn,
+	[DIMID_ICMP_TYPE]  = get_icmptypes,
+	[DIMID_TTL]        = get_ttl,
+};
+
+/* iptables_match executor */
+static hipac_match_t
+hipac_match_exec(const void *packet, void *first_match, void *end)
+{
+	return MATCH_NO;
+}
+
+/* iptables_target executor */
+static hipac_target_t
+hipac_target_exec(const void *packet, void *target)
+{
+	return TARGET_NONE;
+}
+
+/* equality test - rnl is the hipac_rule in netlink format which implies
+   that it contains ipt_entry and cmp_len if the rule has an ipt_entry_match
+   or ipt_entry_target or chain label; rhp is in hipac format which means
+   that it does not contain ipt_entry and cmp_len */
+static int
+hipac_eq_exec(const struct hipac_rule *rnl, const struct hipac_rule *rhp)
+{
+
+	if (rnl == rhp) {
+		printk(KERN_ERR "%s: rnl == rhp error\n", __FUNCTION__);
+		return 0;
+	}
+	if (rnl == NULL || rhp == NULL || rnl->size != rhp->size ||
+	    rnl->native_mct != rhp->native_mct ||
+	    memcmp(rnl->cmp_start, rhp->cmp_start,
+		   sizeof(*rnl) - offsetof(struct hipac_rule, cmp_start) +
+		   rnl->native_mct * sizeof(*rnl->first_match))) {
+		return 0;
+	}
+	return 1;
+}
+
+/* r is constructed by copying rnl to the exclusion of ipt_entry and
+   cmp_len (if present); rnl->size already states the size of r _but_
+   rnl may be smaller than rnl->size if it has a chain target */
+static void
+hipac_copy_constructor(const struct hipac_rule *rnl, struct hipac_rule *r)
+{
+	memcpy(r, rnl, rnl->size);
+}
+
+/* destructor for iptables matches/target */
+static void
+hipac_destroy_exec(struct hipac_rule *r)
+{
+	int i;
+
+	if (r == NULL) {
+		return;
+	}
+	for (i = 0; i < r->native_mct &&
+		     r->first_match[i].dimid < DIMID_STATE; i++);
+	if (i < r->native_mct && r->first_match[i].dimid == DIMID_STATE) {
+		cthelp_unuse();
+	}
+}
+
+/* destructor for iptables matches/target (rnl is the hipac_rule in
+   netlink format) */
+static void
+hipac_destroy_exec_nl(struct hipac_rule *rnl)
+{
+	int i;
+
+	if (rnl == NULL) {
+		return;
+	}
+	for (i = 0; i < rnl->native_mct &&
+		     rnl->first_match[i].dimid < DIMID_STATE; i++);
+	if (i < rnl->native_mct && rnl->first_match[i].dimid == DIMID_STATE) {
+		cthelp_unuse();
+	}
+}
+
+static unsigned int
+input_match(unsigned int hooknum,
+	    struct sk_buff *skb,
+	    const struct net_device *in,
+	    const struct net_device *out,
+	    int (*okfn) (struct sk_buff *))
+{
+	const struct packet pkt = {hooknum, &skb, in, out};
+	return hipac_match(hipac_input, &pkt);
+}
+
+static unsigned int
+forward_match(unsigned int hooknum,
+	      struct sk_buff *skb,
+	      const struct net_device *in,
+	      const struct net_device *out,
+	      int (*okfn) (struct sk_buff *))
+{
+	const struct packet pkt = {hooknum, &skb, in, out};
+	return hipac_match(hipac_forward, &pkt);
+}
+
+static unsigned int
+output_match(unsigned int hooknum,
+	     struct sk_buff *skb,
+	     const struct net_device *in,
+	     const struct net_device *out,
+	     int (*okfn) (struct sk_buff *))
+{
+	const struct packet pkt = {hooknum, &skb, in, out};
+	struct iphdr *iph = ip_hdr(skb);
+
+	/* root is playing with raw sockets. */
+	if (unlikely(skb->len < sizeof(struct iphdr) ||
+		     (iph->ihl << 2) < sizeof(struct iphdr))) {
+		return NF_ACCEPT;
+	}
+	return hipac_match(hipac_output, &pkt);
+}
+
+
+/*
+ * kernel-user netlink communication
+ */
+
+static inline void *
+nlhp_list_rule(struct nfhp_list_rule *r, struct hipac_rule *rule, int *len)
+{
+	int size = IPT_ALIGN(offsetof(struct nfhp_list_rule, r) + rule->size);
+	u32 i;
+
+	if (*len < size) {
+		return NULL;
+	}
+	r->indev[0] = ‘\0‘;
+	r->outdev[0] = ‘\0‘;
+	memcpy(&r->r, rule, rule->size);
+	
+	/* fill in interface names if necessary */
+	for (i = 0; i < r->r.native_mct; i++) {
+		switch (r->r.first_match[i].dimid) {
+		case DIMID_INIFACE:
+			if (nf_hipac_dev_lookup_ifname(
+				    r->r.first_match[i].left,
+				    r->indev) < 0) {
+				printk(KERN_ERR "%s: interface name look"
+				       "up failed\n", __FUNCTION__);
+			}
+			break;
+		case DIMID_OUTIFACE:
+			if (nf_hipac_dev_lookup_ifname(
+				    r->r.first_match[i].left,
+				    r->outdev) < 0) {
+				printk(KERN_ERR "%s: interface name look"
+				       "up failed\n", __FUNCTION__);
+			}
+			break;
+		}
+	}
+
+	*len -= size;
+	return (char *) r + size;
+}
+
+static inline void *
+nlhp_list_chain(struct nfhp_list_chain *c, int pos, int *len)
+{
+	if (*len < sizeof(*c)) {
+		return NULL;
+	}
+	strncpy(c->label, linfo.inf[pos].label, sizeof(c->label));
+	c->label[sizeof(c->label) - 1] = ‘\0‘;
+	c->policy = linfo.inf[pos].policy;
+	c->rule_num = linfo.inf[pos].rule_num;
+	*len -= sizeof(*c);
+	return c + 1;
+}
+
+static inline int
+nlhp_list_next_rule(struct hipac_rule *prev, struct hipac_rule **rule, int pos)
+{
+	int stat;
+
+	stat = hipac_get_next_rule(&linfo.inf[pos], prev, rule);
+	switch (stat) {
+	case HE_OK:
+		return 0;
+	case HE_RULE_NOT_EXISTENT:
+		*rule = NULL;
+		return 0;
+	default:
+		if (unlikely(stat > 0)) {
+			/* this should never happen */
+			printk(KERN_ERR "%s: hipac_get_next_rule returned "
+			       "status > 0\n", __FUNCTION__);
+			stat = -stat;
+		}
+		return stat;
+	}
+}
+
+/* callback function for CMD_LIST command */
+static int
+nlhp_list(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	static u32 pos;
+	static struct hipac_rule *rule;
+	struct nlmsghdr *nlh;
+	int len, total, stat;
+	void *data;
+
+	total = skb_tailroom(skb) - NLMSG_SPACE(0);
+	switch (cb->args[0]) {
+	    case 0:
+		    /* first callback in the series */
+		    pos = 0;
+		    rule = NULL;
+		    data = http://www.mamicode.com/NLMSG_DATA(skb->data);>

可编译易用的模块化nf-HiPAC移植成功