Module Name:    src
Committed By:   christos
Date:           Wed Jan  9 13:23:21 UTC 2013

Modified Files:
        src/sys/external/bsd/ipf/netinet: fil.c ip_compat.h ip_nat.c ip_nat.h
            ip_nat6.c ip_state.c ipf_rb.h

Log Message:
Back out my last change, which was a partial fix for hash code computation 
problems.
Apply Darren's more complete reworking of hash code computation.
Ensure that the struct containing the red-black tree head is properly 
initialized.
>From Geoff Adams


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/external/bsd/ipf/netinet/fil.c
cvs rdiff -u -r1.5 -r1.6 src/sys/external/bsd/ipf/netinet/ip_compat.h \
    src/sys/external/bsd/ipf/netinet/ip_nat.h
cvs rdiff -u -r1.8 -r1.9 src/sys/external/bsd/ipf/netinet/ip_nat.c
cvs rdiff -u -r1.3 -r1.4 src/sys/external/bsd/ipf/netinet/ip_nat6.c
cvs rdiff -u -r1.4 -r1.5 src/sys/external/bsd/ipf/netinet/ip_state.c \
    src/sys/external/bsd/ipf/netinet/ipf_rb.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/ipf/netinet/fil.c
diff -u src/sys/external/bsd/ipf/netinet/fil.c:1.7 src/sys/external/bsd/ipf/netinet/fil.c:1.8
--- src/sys/external/bsd/ipf/netinet/fil.c:1.7	Thu Dec 20 16:42:27 2012
+++ src/sys/external/bsd/ipf/netinet/fil.c	Wed Jan  9 08:23:20 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: fil.c,v 1.7 2012/12/20 21:42:27 christos Exp $	*/
+/*	$NetBSD: fil.c,v 1.8 2013/01/09 13:23:20 christos Exp $	*/
 
 /*
  * Copyright (C) 2012 by Darren Reed.
@@ -138,7 +138,7 @@ extern struct timeout ipf_slowtimer_ch;
 #if !defined(lint)
 #if defined(__NetBSD__)
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.7 2012/12/20 21:42:27 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.8 2013/01/09 13:23:20 christos Exp $");
 #else
 static const char sccsid[] = "@(#)fil.c	1.36 6/5/96 (C) 1993-2000 Darren Reed";
 static const char rcsid[] = "@(#)Id: fil.c,v 1.1.1.2 2012/07/22 13:45:07 darrenr Exp $";
@@ -9664,6 +9664,7 @@ ipf_ht_node_del(host_track_t *htp, int f
 void
 ipf_rb_ht_init(host_track_t *head)
 {
+	memset(head, 0, sizeof(*head));
 	RBI_INIT(ipf_rb, &head->ht_root);
 }
 

Index: src/sys/external/bsd/ipf/netinet/ip_compat.h
diff -u src/sys/external/bsd/ipf/netinet/ip_compat.h:1.5 src/sys/external/bsd/ipf/netinet/ip_compat.h:1.6
--- src/sys/external/bsd/ipf/netinet/ip_compat.h:1.5	Thu Dec 20 16:42:28 2012
+++ src/sys/external/bsd/ipf/netinet/ip_compat.h	Wed Jan  9 08:23:20 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_compat.h,v 1.5 2012/12/20 21:42:28 christos Exp $	*/
+/*	$NetBSD: ip_compat.h,v 1.6 2013/01/09 13:23:20 christos Exp $	*/
 
 /*
  * Copyright (C) 2012 by Darren Reed.
@@ -928,6 +928,7 @@ typedef unsigned int    u_32_t;
 #  if (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499004900))
 #   define	POLLWAKEUP(x)	selnotify(softc->ipf_selwait+x, 0, 0)
 #  endif
+#  define	ASSERT(x)	KASSERT(x)
 typedef struct mbuf mb_t;
 # endif /* _KERNEL */
 # if (NetBSD <= 1991011) && (NetBSD >= 199606)
Index: src/sys/external/bsd/ipf/netinet/ip_nat.h
diff -u src/sys/external/bsd/ipf/netinet/ip_nat.h:1.5 src/sys/external/bsd/ipf/netinet/ip_nat.h:1.6
--- src/sys/external/bsd/ipf/netinet/ip_nat.h:1.5	Sat Jan  5 11:34:43 2013
+++ src/sys/external/bsd/ipf/netinet/ip_nat.h	Wed Jan  9 08:23:20 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_nat.h,v 1.5 2013/01/05 16:34:43 christos Exp $	*/
+/*	$NetBSD: ip_nat.h,v 1.6 2013/01/09 13:23:20 christos Exp $	*/
 
 /*
  * Copyright (C) 2012 by Darren Reed.
@@ -94,13 +94,28 @@ struct ap_session;
 /*
  * This structure is used in the active NAT table and represents an
  * active NAT session.
+ *
+ * Generally nat_t structures have references from at least two places.
+ * The first place gives them a position in a linked list of NAT sessions
+ * per instace of IPFilter. In this linked list, nat_next always points to
+ * the next entry in the list and nat_pnext points to the pointer that
+ * introduces the structure. That may be either the top of the list pointer
+ * or simply the nat_next of the previous link in the list. The second place
+ * that a nat_t structure is generally referenced from is the NAT hash table.
+ * Two references from this table are required, one for supporting the of
+ * matching packets being transmitted and one for supporting the matching of
+ * packets being received. The hash table is comprised of buckets, each one
+ * having its own chain of nat_t structures. To support these chains,
+ * nat_hnext is used to point to the next member of the chain and nat_phnext
+ * points back to the pointer that is pointing to the nat_t in the chain,
+ * be it the bucket at the top or simply the previous nat_t chain entry.
  */
 typedef	struct	nat	{
 	ipfmutex_t	nat_lock;
-	struct	nat	*nat_next;    /* next nat_t in global linked list */
-	struct	nat	**nat_pnext;  /* ptr to the nat_next that points here */
-	struct	nat	*nat_hnext[2];	 /* next nat_t in hashtable bucket */
-	struct	nat	**nat_phnext[2]; /* ptr to nat_hnext that points here */
+	struct	nat	*nat_next;
+	struct	nat	**nat_pnext;
+	struct	nat	*nat_hnext[2];
+	struct	nat	**nat_phnext[2];
 	struct	hostmap	*nat_hm;
 	void		*nat_data;
 	struct	nat	**nat_me;

Index: src/sys/external/bsd/ipf/netinet/ip_nat.c
diff -u src/sys/external/bsd/ipf/netinet/ip_nat.c:1.8 src/sys/external/bsd/ipf/netinet/ip_nat.c:1.9
--- src/sys/external/bsd/ipf/netinet/ip_nat.c:1.8	Sat Jan  5 11:34:43 2013
+++ src/sys/external/bsd/ipf/netinet/ip_nat.c	Wed Jan  9 08:23:20 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_nat.c,v 1.8 2013/01/05 16:34:43 christos Exp $	*/
+/*	$NetBSD: ip_nat.c,v 1.9 2013/01/09 13:23:20 christos Exp $	*/
 
 /*
  * Copyright (C) 2012 by Darren Reed.
@@ -113,7 +113,7 @@ extern struct ifnet vpnif;
 #if !defined(lint)
 #if defined(__NetBSD__)
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_nat.c,v 1.8 2013/01/05 16:34:43 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_nat.c,v 1.9 2013/01/09 13:23:20 christos Exp $");
 #else
 static const char sccsid[] = "@(#)ip_nat.c	1.11 6/5/96 (C) 1995 Darren Reed";
 static const char rcsid[] = "@(#)Id: ip_nat.c,v 1.1.1.2 2012/07/22 13:45:27 darrenr Exp";
@@ -226,7 +226,6 @@ static	void	ipf_nat_addrdr(ipf_nat_softc
 static	int	ipf_nat_builddivertmp(ipf_nat_softc_t *, ipnat_t *);
 static	int	ipf_nat_clearlist(ipf_main_softc_t *, ipf_nat_softc_t *);
 static	int	ipf_nat_cmp_rules(ipnat_t *, ipnat_t *);
-static	void	ipf_nat_compute_hashes(nat_t *nat);
 static	int	ipf_nat_decap(fr_info_t *, nat_t *);
 static	void	ipf_nat_delrule(ipf_main_softc_t *, ipf_nat_softc_t *,
 				     ipnat_t *, int);
@@ -2255,26 +2254,13 @@ ipf_nat_delete(ipf_main_softc_t *softc, 
 {
 	ipf_nat_softc_t *softn = softc->ipf_nat_soft;
 	int madeorphan = 0, removed = 0;
-	u_int hv0;
-	u_int hv1;
+	u_int bkt;
 	nat_stat_side_t *nss;
 	struct ipnat *ipn;
 
 	if (logtype != 0 && softn->ipf_nat_logging != 0)
 		ipf_nat_log(softc, softn, nat, logtype);
 
-	/* Get the hash values, swapped as necessary. */
-	hv0 = nat->nat_hv[0] % softn->ipf_nat_table_sz;
-	hv1 = nat->nat_hv[1] % softn->ipf_nat_table_sz;
-
-	if (nat->nat_dir == NAT_INBOUND || nat->nat_dir == NAT_DIVERTIN) {
-		u_int swap;
-
-		swap = hv0;
-		hv0 = hv1;
-		hv1 = swap;
-	}
-
 	/*
 	 * Take it as a general indication that all the pointers are set if
 	 * nat_pnext is set.
@@ -2282,15 +2268,19 @@ ipf_nat_delete(ipf_main_softc_t *softc, 
 	if (nat->nat_pnext != NULL) {
 		removed = 1;
 
+		bkt = nat->nat_hv[0] % softn->ipf_nat_table_sz;
 		nss = &softn->ipf_nat_stats.ns_side[0];
-		nss->ns_bucketlen[hv0]--;
-		if (nss->ns_bucketlen[hv0] == 0) {
+		ASSERT(nss->ns_bucketlen[bkt] > 0);
+		nss->ns_bucketlen[bkt]--;
+		if (nss->ns_bucketlen[bkt] == 0) {
 			nss->ns_inuse--;
 		}
 
+		bkt = nat->nat_hv[1] % softn->ipf_nat_table_sz;
 		nss = &softn->ipf_nat_stats.ns_side[1];
-		nss->ns_bucketlen[hv1]--;
-		if (nss->ns_bucketlen[hv1] == 0) {
+		ASSERT(nss->ns_bucketlen[bkt] > 0);
+		nss->ns_bucketlen[bkt]--;
+		if (nss->ns_bucketlen[bkt] == 0) {
 			nss->ns_inuse--;
 		}
 
@@ -3350,48 +3340,58 @@ ipf_nat_finalise(fr_info_t *fin, nat_t *
 
 
 /* ------------------------------------------------------------------------ */
-/* Function:    ipf_nat_compute_hashes                                              */
-/* Parameters:  nat(I) - pointer to NAT structure                           */
+/* Function:    ipf_nat_insert                                              */
+/* Returns:     int - 0 == sucess, -1 == failure                            */
+/* Parameters:  softc(I) - pointer to soft context main structure           */
+/*              softn(I) - pointer to NAT context structure                 */
+/*              nat(I) - pointer to NAT structure                           */
 /* Write Lock:  ipf_nat                                                     */
 /*                                                                          */
-/* Compute and set the values for nat->nat_hv[0] and nat->nat_hv[1]         */
+/* Insert a NAT entry into the hash tables for searching and add it to the  */
+/* list of active NAT entries.  Adjust global counters when complete.       */
 /* ------------------------------------------------------------------------ */
-void
-ipf_nat_compute_hashes(nat_t *nat)
+int
+ipf_nat_insert(ipf_main_softc_t *softc, ipf_nat_softc_t *softn, nat_t *nat)
 {
 	u_int hv0, hv1;
-	u_int sport, dport;
+	u_int sp, dp;
+	ipnat_t *in;
+	int ret;
 
+	/*
+	 * Try and return an error as early as possible, so calculate the hash
+	 * entry numbers first and then proceed.
+	 */
 	if ((nat->nat_flags & (SI_W_SPORT|SI_W_DPORT)) == 0) {
 		if ((nat->nat_flags & IPN_TCPUDP) != 0) {
-			sport = nat->nat_osport;
-			dport = nat->nat_odport;
+			sp = nat->nat_osport;
+			dp = nat->nat_odport;
 		} else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) {
-			sport = 0;
-			dport = nat->nat_oicmpid;
+			sp = 0;
+			dp = nat->nat_oicmpid;
 		} else {
-			sport = 0;
-			dport = 0;
+			sp = 0;
+			dp = 0;
 		}
-		hv0 = NAT_HASH_FN(nat->nat_osrcaddr, sport, 0xffffffff);
-		hv0 = NAT_HASH_FN(nat->nat_odstaddr, hv0 + dport, 0xffffffff);
+		hv0 = NAT_HASH_FN(nat->nat_osrcaddr, sp, 0xffffffff);
+		hv0 = NAT_HASH_FN(nat->nat_odstaddr, hv0 + dp, 0xffffffff);
 		/*
 		 * TRACE nat_osrcaddr, nat_osport, nat_odstaddr,
 		 * nat_odport, hv0
 		 */
 
 		if ((nat->nat_flags & IPN_TCPUDP) != 0) {
-			sport = nat->nat_nsport;
-			dport = nat->nat_ndport;
+			sp = nat->nat_nsport;
+			dp = nat->nat_ndport;
 		} else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) {
-			sport = 0;
-			dport = nat->nat_nicmpid;
+			sp = 0;
+			dp = nat->nat_nicmpid;
 		} else {
-			sport = 0;
-			dport = 0;
+			sp = 0;
+			dp = 0;
 		}
-		hv1 = NAT_HASH_FN(nat->nat_nsrcaddr, sport, 0xffffffff);
-		hv1 = NAT_HASH_FN(nat->nat_ndstaddr, hv1 + dport, 0xffffffff);
+		hv1 = NAT_HASH_FN(nat->nat_nsrcaddr, sp, 0xffffffff);
+		hv1 = NAT_HASH_FN(nat->nat_ndstaddr, hv1 + dp, 0xffffffff);
 		/*
 		 * TRACE nat_nsrcaddr, nat_nsport, nat_ndstaddr,
 		 * nat_ndport, hv1
@@ -3406,33 +3406,13 @@ ipf_nat_compute_hashes(nat_t *nat)
 		/* TRACE nat_nsrcaddr, nat_ndstaddr, hv1 */
 	}
 
-	nat->nat_hv[0] = hv0;
-	nat->nat_hv[1] = hv1;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    ipf_nat_insert                                              */
-/* Returns:     int - 0 == sucess, -1 == failure                            */
-/* Parameters:  softc(I) - pointer to soft context main structure           */
-/*              softn(I) - pointer to NAT context structure                 */
-/*              nat(I) - pointer to NAT structure                           */
-/* Write Lock:  ipf_nat                                                     */
-/*                                                                          */
-/* Insert a NAT entry into the hash tables for searching and add it to the  */
-/* list of active NAT entries.  Adjust global counters when complete.       */
-/* ------------------------------------------------------------------------ */
-int
-ipf_nat_insert(ipf_main_softc_t *softc, ipf_nat_softc_t *softn, nat_t *nat)
-{
-	ipnat_t *in;
-	int ret;
-
-	/*
-	 * Try and return an error as early as possible, so calculate the hash
-	 * entry numbers first and then proceed.
-	 */
-	ipf_nat_compute_hashes(nat);
+	if ((nat->nat_dir & NAT_OUTBOUND) == NAT_OUTBOUND) {
+		nat->nat_hv[0] = hv0;
+		nat->nat_hv[1] = hv1;
+	} else {
+		nat->nat_hv[0] = hv1;
+		nat->nat_hv[1] = hv0;
+	}
 
 	MUTEX_INIT(&nat->nat_lock, "nat entry lock");
 
@@ -3473,9 +3453,11 @@ ipf_nat_insert(ipf_main_softc_t *softc, 
 
 /* ------------------------------------------------------------------------ */
 /* Function:    ipf_nat_hashtab_add                                         */
+/* Returns:     int - 0 == sucess, -1 == failure                            */
 /* Parameters:  softc(I) - pointer to soft context main structure           */
 /*              softn(I) - pointer to NAT context structure                 */
 /*              nat(I) - pointer to NAT structure                           */
+/* Write Lock:  ipf_nat                                                     */
 /*                                                                          */
 /* Handle the insertion of a NAT entry into the table/list.                 */
 /* ------------------------------------------------------------------------ */
@@ -3489,14 +3471,6 @@ ipf_nat_hashtab_add(ipf_main_softc_t *so
 	hv0 = nat->nat_hv[0] % softn->ipf_nat_table_sz;
 	hv1 = nat->nat_hv[1] % softn->ipf_nat_table_sz;
 
-	if (nat->nat_dir == NAT_INBOUND || nat->nat_dir == NAT_DIVERTIN) {
-		u_int swap;
-
-		swap = hv0;
-		hv0 = hv1;
-		hv1 = swap;
-	}
-
 	if (softn->ipf_nat_stats.ns_side[0].ns_bucketlen[hv0] >=
 	    softn->ipf_nat_maxbucket) {
 		DT1(ns_bucket_max_0, int,
@@ -4298,12 +4272,15 @@ ipf_nat_tabmove(ipf_nat_softc_t *softn, 
 		nat->nat_hnext[0]->nat_phnext[0] = nat->nat_phnext[0];
 	*nat->nat_phnext[0] = nat->nat_hnext[0];
 	hv0 = nat->nat_hv[0] % softn->ipf_nat_table_sz;
+	hv1 = nat->nat_hv[1] % softn->ipf_nat_table_sz;
+
+	ASSERT(nsp->ns_side[0].ns_bucketlen[hv0] > 0);
 	nsp->ns_side[0].ns_bucketlen[hv0]--;
 
 	if (nat->nat_hnext[1])
 		nat->nat_hnext[1]->nat_phnext[1] = nat->nat_phnext[1];
 	*nat->nat_phnext[1] = nat->nat_hnext[1];
-	hv1 = nat->nat_hv[1] % softn->ipf_nat_table_sz;
+	ASSERT(nsp->ns_side[1].ns_bucketlen[hv1] > 0);
 	nsp->ns_side[1].ns_bucketlen[hv1]--;
 
 	/*
@@ -4316,21 +4293,20 @@ ipf_nat_tabmove(ipf_nat_softc_t *softn, 
 	rhv1 = NAT_HASH_FN(nat->nat_ndstaddr, rhv1 + nat->nat_ndport,
 			   0xffffffff);
 
-	hv0 = rhv0 % softn->ipf_nat_table_sz;
-	hv1 = rhv1 % softn->ipf_nat_table_sz;
-
-	if (nat->nat_dir == NAT_INBOUND || nat->nat_dir == NAT_DIVERTIN) {
-		u_int swap;
-
-		swap = hv0;
-		hv0 = hv1;
-		hv1 = swap;
+	if ((nat->nat_dir & NAT_OUTBOUND) == NAT_OUTBOUND) {
+		nat->nat_hv[0] = rhv0;
+		nat->nat_hv[1] = rhv1;
+	} else {
+		nat->nat_hv[0] = rhv1;
+		nat->nat_hv[1] = rhv0;
 	}
 
+	hv0 = nat->nat_hv[0] % softn->ipf_nat_table_sz;
+	hv1 = nat->nat_hv[1] % softn->ipf_nat_table_sz;
+
 	/* TRACE nat_osrcaddr, nat_osport, nat_odstaddr, nat_odport, hv0 */
 	/* TRACE nat_nsrcaddr, nat_nsport, nat_ndstaddr, nat_ndport, hv1 */
 
-	nat->nat_hv[0] = rhv0;
 	natp = &softn->ipf_nat_table[0][hv0];
 	if (*natp)
 		(*natp)->nat_phnext[0] = &nat->nat_hnext[0];
@@ -4339,7 +4315,6 @@ ipf_nat_tabmove(ipf_nat_softc_t *softn, 
 	*natp = nat;
 	nsp->ns_side[0].ns_bucketlen[hv0]++;
 
-	nat->nat_hv[1] = rhv1;
 	natp = &softn->ipf_nat_table[1][hv1];
 	if (*natp)
 		(*natp)->nat_phnext[1] = &nat->nat_hnext[1];
@@ -8015,8 +7990,6 @@ ipf_nat_rehash(ipf_main_softc_t *softc, 
 	softn->ipf_nat_stats.ns_side[0].ns_inuse = 0;
 	softn->ipf_nat_stats.ns_side[1].ns_inuse = 0;
 
-	/* XXX(gadams): Still need to deal with hv0/hv1 swapping! */
-
 	for (nat = softn->ipf_nat_instances; nat != NULL; nat = nat->nat_next) {
 		nat->nat_hnext[0] = NULL;
 		nat->nat_phnext[0] = NULL;

Index: src/sys/external/bsd/ipf/netinet/ip_nat6.c
diff -u src/sys/external/bsd/ipf/netinet/ip_nat6.c:1.3 src/sys/external/bsd/ipf/netinet/ip_nat6.c:1.4
--- src/sys/external/bsd/ipf/netinet/ip_nat6.c:1.3	Sun Jul 22 10:27:51 2012
+++ src/sys/external/bsd/ipf/netinet/ip_nat6.c	Wed Jan  9 08:23:20 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_nat6.c,v 1.3 2012/07/22 14:27:51 darrenr Exp $	*/
+/*	$NetBSD: ip_nat6.c,v 1.4 2013/01/09 13:23:20 christos Exp $	*/
 
 /*
  * Copyright (C) 2012 by Darren Reed.
@@ -1256,7 +1256,7 @@ ipf_nat6_finalise(fr_info_t *fin, nat_t 
 static int
 ipf_nat6_insert(ipf_main_softc_t *softc, ipf_nat_softc_t *softn, nat_t *nat)
 {
-	u_int hv1, hv2;
+	u_int hv0, hv1;
 	u_32_t sp, dp;
 	ipnat_t *in;
 
@@ -1275,13 +1275,13 @@ ipf_nat6_insert(ipf_main_softc_t *softc,
 			sp = 0;
 			dp = 0;
 		}
-		hv1 = NAT_HASH_FN6(&nat->nat_osrc6, sp, 0xffffffff);
-		hv1 = NAT_HASH_FN6(&nat->nat_odst6, hv1 + dp,
+		hv0 = NAT_HASH_FN6(&nat->nat_osrc6, sp, 0xffffffff);
+		hv0 = NAT_HASH_FN6(&nat->nat_odst6, hv0 + dp,
 				   softn->ipf_nat_table_sz);
 
 		/*
 		 * TRACE nat6_osrc6, nat6_osport, nat6_odst6,
-		 * nat6_odport, hv1
+		 * nat6_odport, hv0
 		 */
 
 		if ((nat->nat_flags & IPN_TCPUDP) != 0) {
@@ -1294,27 +1294,32 @@ ipf_nat6_insert(ipf_main_softc_t *softc,
 			sp = 0;
 			dp = 0;
 		}
-		hv2 = NAT_HASH_FN6(&nat->nat_nsrc6, sp, 0xffffffff);
-		hv2 = NAT_HASH_FN6(&nat->nat_ndst6, hv2 + dp,
+		hv1 = NAT_HASH_FN6(&nat->nat_nsrc6, sp, 0xffffffff);
+		hv1 = NAT_HASH_FN6(&nat->nat_ndst6, hv1 + dp,
 				   softn->ipf_nat_table_sz);
 		/*
 		 * TRACE nat6_nsrcaddr, nat6_nsport, nat6_ndstaddr,
-		 * nat6_ndport, hv1
+		 * nat6_ndport, hv0
 		 */
 	} else {
-		hv1 = NAT_HASH_FN6(&nat->nat_osrc6, 0, 0xffffffff);
-		hv1 = NAT_HASH_FN6(&nat->nat_odst6, hv1,
+		hv0 = NAT_HASH_FN6(&nat->nat_osrc6, 0, 0xffffffff);
+		hv0 = NAT_HASH_FN6(&nat->nat_odst6, hv0,
 				   softn->ipf_nat_table_sz);
-		/* TRACE nat6_osrcip6, nat6_odstip6, hv1 */
+		/* TRACE nat6_osrcip6, nat6_odstip6, hv0 */
 
-		hv2 = NAT_HASH_FN6(&nat->nat_nsrc6, 0, 0xffffffff);
-		hv2 = NAT_HASH_FN6(&nat->nat_ndst6, hv2,
+		hv1 = NAT_HASH_FN6(&nat->nat_nsrc6, 0, 0xffffffff);
+		hv1 = NAT_HASH_FN6(&nat->nat_ndst6, hv1,
 				   softn->ipf_nat_table_sz);
-		/* TRACE nat6_nsrcip6, nat6_ndstip6, hv2 */
+		/* TRACE nat6_nsrcip6, nat6_ndstip6, hv1 */
 	}
 
-	nat->nat_hv[0] = hv1;
-	nat->nat_hv[1] = hv2;
+	if ((nat->nat_dir & NAT_OUTBOUND) == NAT_OUTBOUND) {
+		nat->nat_hv[0] = hv0;
+		nat->nat_hv[1] = hv1;
+	} else {
+		nat->nat_hv[0] = hv1;
+		nat->nat_hv[1] = hv0;
+	}
 
 	MUTEX_INIT(&nat->nat_lock, "nat entry lock");
 
@@ -2108,8 +2113,8 @@ find_in_wild_ports:
 static void
 ipf_nat6_tabmove(ipf_nat_softc_t *softn, nat_t *nat)
 {
+	u_int rhv0, rhv1, hv0, hv1;
 	nat_t **natp;
-	u_int hv0, hv1;
 
 	if (nat->nat_flags & SI_CLONE)
 		return;
@@ -2130,25 +2135,27 @@ ipf_nat6_tabmove(ipf_nat_softc_t *softn,
 	/*
 	 * Add into the NAT table in the new position
 	 */
-	hv0 = NAT_HASH_FN6(&nat->nat_osrc6, nat->nat_osport, 0xffffffff);
-	hv0 = NAT_HASH_FN6(&nat->nat_odst6, hv0 + nat->nat_odport,
-			   softn->ipf_nat_table_sz);
-	hv1 = NAT_HASH_FN6(&nat->nat_nsrc6, nat->nat_nsport, 0xffffffff);
-	hv1 = NAT_HASH_FN6(&nat->nat_ndst6, hv1 + nat->nat_ndport,
-			   softn->ipf_nat_table_sz);
-
-	if (nat->nat_dir == NAT_INBOUND || nat->nat_dir == NAT_DIVERTIN) {
-		u_int swap;
-
-		swap = hv0;
-		hv0 = hv1;
-		hv1 = swap;
+	rhv0 = NAT_HASH_FN6(&nat->nat_osrc6, nat->nat_osport, 0xffffffff);
+	rhv0 = NAT_HASH_FN6(&nat->nat_odst6, rhv0 + nat->nat_odport,
+			    softn->ipf_nat_table_sz);
+	rhv1 = NAT_HASH_FN6(&nat->nat_nsrc6, nat->nat_nsport, 0xffffffff);
+	rhv1 = NAT_HASH_FN6(&nat->nat_ndst6, rhv1 + nat->nat_ndport,
+			    softn->ipf_nat_table_sz);
+
+	if ((nat->nat_dir & NAT_OUTBOUND) == NAT_OUTBOUND) {
+		nat->nat_hv[0] = rhv0;
+		nat->nat_hv[1] = rhv1;
+	} else {
+		nat->nat_hv[0] = rhv1;
+		nat->nat_hv[1] = rhv0;
 	}
 
+	hv0 = nat->nat_hv[0] % softn->ipf_nat_table_sz;
+        hv1 = nat->nat_hv[1] % softn->ipf_nat_table_sz;
+
 	/* TRACE nat_osrc6, nat_osport, nat_odst6, nat_odport, hv0 */
 	/* TRACE nat_nsrc6, nat_nsport, nat_ndst6, nat_ndport, hv1 */
 
-	nat->nat_hv[0] = hv0;
 	natp = &softn->ipf_nat_table[0][hv0];
 	if (*natp)
 		(*natp)->nat_phnext[0] = &nat->nat_hnext[0];
@@ -2157,7 +2164,6 @@ ipf_nat6_tabmove(ipf_nat_softc_t *softn,
 	*natp = nat;
 	softn->ipf_nat_stats.ns_side[0].ns_bucketlen[hv0]++;
 
-	nat->nat_hv[1] = hv1;
 	natp = &softn->ipf_nat_table[1][hv1];
 	if (*natp)
 		(*natp)->nat_phnext[1] = &nat->nat_hnext[1];

Index: src/sys/external/bsd/ipf/netinet/ip_state.c
diff -u src/sys/external/bsd/ipf/netinet/ip_state.c:1.4 src/sys/external/bsd/ipf/netinet/ip_state.c:1.5
--- src/sys/external/bsd/ipf/netinet/ip_state.c:1.4	Thu Dec 20 16:42:28 2012
+++ src/sys/external/bsd/ipf/netinet/ip_state.c	Wed Jan  9 08:23:20 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_state.c,v 1.4 2012/12/20 21:42:28 christos Exp $	*/
+/*	$NetBSD: ip_state.c,v 1.5 2013/01/09 13:23:20 christos Exp $	*/
 
 /*
  * Copyright (C) 2012 by Darren Reed.
@@ -100,7 +100,7 @@ struct file;
 #if !defined(lint)
 #if defined(__NetBSD__)
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_state.c,v 1.4 2012/12/20 21:42:28 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_state.c,v 1.5 2013/01/09 13:23:20 christos Exp $");
 #else
 static const char sccsid[] = "@(#)ip_state.c	1.8 6/5/96 (C) 1993-2000 Darren Reed";
 static const char rcsid[] = "@(#)Id: ip_state.c,v 1.1.1.2 2012/07/22 13:45:37 darrenr Exp";
@@ -3572,10 +3572,10 @@ ipf_state_del(ipf_main_softc_t *softc, i
 		is->is_me = NULL;
 		is->is_ref--;
 	}
-	if (is->is_ref > 1) {
+	is->is_ref--;
+	if (is->is_ref > 0) {
 		int refs;
 
-		is->is_ref--;
 		refs = is->is_ref;
 		MUTEX_EXIT(&is->is_lock);
 		if (!orphan)
@@ -3592,7 +3592,7 @@ ipf_state_del(ipf_main_softc_t *softc, i
 		}
 	}
 
-	is->is_ref = 0;
+	ASSERT(is->is_ref == 0);
 	MUTEX_EXIT(&is->is_lock);
 
 	if (is->is_tqehead[0] != NULL) {
Index: src/sys/external/bsd/ipf/netinet/ipf_rb.h
diff -u src/sys/external/bsd/ipf/netinet/ipf_rb.h:1.4 src/sys/external/bsd/ipf/netinet/ipf_rb.h:1.5
--- src/sys/external/bsd/ipf/netinet/ipf_rb.h:1.4	Thu Dec 20 16:42:28 2012
+++ src/sys/external/bsd/ipf/netinet/ipf_rb.h	Wed Jan  9 08:23:20 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ipf_rb.h,v 1.4 2012/12/20 21:42:28 christos Exp $	*/
+/*	$NetBSD: ipf_rb.h,v 1.5 2013/01/09 13:23:20 christos Exp $	*/
 
 /*
  * Copyright (C) 2012 by Darren Reed.
@@ -352,7 +352,6 @@ colour:									\
 void									\
 _n##_rb_init(struct _n##_rb_head *head)					\
 {									\
-	memset(head, 0, sizeof(*head));					\
 	memset(&_n##_rb_zero, 0, sizeof(_n##_rb_zero));			\
 	head->top._f.left = &_n##_rb_zero;				\
 	head->top._f.right = &_n##_rb_zero;				\

Reply via email to