Index: sys/netinet/ip_frag.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_frag.c,v
retrieving revision 1.10.2.3
diff -u -r1.10.2.3 ip_frag.c
--- sys/netinet/ip_frag.c	2001/02/17 20:42:07	1.10.2.3
+++ sys/netinet/ip_frag.c	2001/04/08 13:22:50
@@ -142,12 +142,15 @@
 u_int pass;
 ipfr_t *table[];
 {
-	ipfr_t	**fp, *fra, frag;
-	u_int	idx;
+	ipfr_t **fp, *fra, frag;
+	u_int idx, off;
 
 	if (ipfr_inuse >= IPFT_SIZE)
 		return NULL;
 
+	if (!(fin->fin_fi.fi_fl & FI_FRAG))
+		return NULL;
+
 	frag.ipfr_p = ip->ip_p;
 	idx = ip->ip_p;
 	frag.ipfr_id = ip->ip_id;
@@ -201,7 +204,10 @@
 	/*
 	 * Compute the offset of the expected start of the next packet.
 	 */
-	fra->ipfr_off = (ip->ip_off & IP_OFFMASK) + (fin->fin_dlen >> 3);
+	off = ip->ip_off & IP_OFFMASK;
+	if (!off)
+		fra->ipfr_seen0 = 1;
+	fra->ipfr_off = off + (fin->fin_dlen >> 3);
 	ATOMIC_INCL(ipfr_stats.ifs_new);
 	ATOMIC_INC32(ipfr_inuse);
 	return fra;
@@ -257,6 +263,9 @@
 	ipfr_t	*f, frag;
 	u_int	idx;
 
+	if (!(fin->fin_fi.fi_fl & FI_FRAG))
+		return NULL;
+
 	/*
 	 * For fragments, we record protocol, packet id, TOS and both IP#'s
 	 * (these should all be the same for all fragments of a packet).
@@ -284,6 +293,19 @@
 			  IPFR_CMPSZ)) {
 			u_short	atoff, off;
 
+			/*
+			 * XXX - We really need to be guarding against the
+			 * retransmission of (src,dst,id,offset-range) here
+			 * because a fragmented packet is never resent with
+			 * the same IP ID#.
+			 */
+			off = ip->ip_off & IP_OFFMASK;
+			if (f->ipfr_seen0) {
+				if (!off || (fin->fin_fi.fi_fl & FI_SHORT))
+					continue;
+			} else if (!off)
+				f->ipfr_seen0 = 1;
+
 			if (f != table[idx]) {
 				/*
 				 * move fragment info. to the top of the list
@@ -296,7 +318,6 @@
 				f->ipfr_prev = NULL;
 				table[idx] = f;
 			}
-			off = ip->ip_off & IP_OFFMASK;
 			atoff = off + (fin->fin_dlen >> 3);
 			/*
 			 * If we've follwed the fragments, and this is the
Index: sys/netinet/ip_frag.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_frag.h,v
retrieving revision 1.7.2.2
diff -u -r1.7.2.2 ip_frag.h
--- sys/netinet/ip_frag.h	2001/02/17 20:42:07	1.7.2.2
+++ sys/netinet/ip_frag.h	2001/04/08 13:22:50
@@ -25,7 +25,8 @@
 	u_char	ipfr_p;
 	u_char	ipfr_tos;
 	u_short	ipfr_off;
-	u_short	ipfr_ttl;
+	u_char	ipfr_ttl;
+	u_char	ipfr_seen0;
 	frentry_t *ipfr_rule;
 } ipfr_t;
 
@@ -41,7 +42,8 @@
 	struct	ipfr	**ifs_nattab;
 } ipfrstat_t;
 
-#define	IPFR_CMPSZ	(4 + 4 + 2 + 1 + 1)
+#define	IPFR_CMPSZ	(offsetof(ipfr_t, ipfr_off) - \
+			 offsetof(ipfr_t, ipfr_src))
 
 extern	int	fr_ipfrttl;
 extern	int	fr_frag_lock;
Index: sys/netinet/ip_nat.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_nat.c,v
retrieving revision 1.12.2.3
diff -u -r1.12.2.3 ip_nat.c
--- sys/netinet/ip_nat.c	2001/02/17 20:42:07	1.12.2.3
+++ sys/netinet/ip_nat.c	2001/04/08 13:22:50
@@ -2284,7 +2284,8 @@
 	 */
 	if (nat) {
 		np = nat->nat_ptr;
-		if (natadd && fin->fin_fi.fi_fl & FI_FRAG)
+		if (natadd && (fin->fin_fi.fi_fl & FI_FRAG) &&
+		    np && (np->in_flags & IPN_FRAG))
 			ipfr_nat_newfrag(ip, fin, 0, nat);
 		MUTEX_ENTER(&nat->nat_lock);
 		nat->nat_age = fr_defnatage;
@@ -2489,7 +2490,8 @@
 	if (nat) {
 		np = nat->nat_ptr;
 		fin->fin_fr = nat->nat_fr;
-		if (natadd && fin->fin_fi.fi_fl & FI_FRAG)
+		if (natadd && (fin->fin_fi.fi_fl & FI_FRAG) &&
+		    np && (np->in_flags & IPN_FRAG))
 			ipfr_nat_newfrag(ip, fin, 0, nat);
 		if ((np->in_apr != NULL) && (np->in_dport == 0 ||
 		    (tcp != NULL && sport == np->in_dport))) {
Index: sys/netinet/ip_nat.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_nat.h,v
retrieving revision 1.8.2.3
diff -u -r1.8.2.3 ip_nat.h
--- sys/netinet/ip_nat.h	2001/02/17 20:42:07	1.8.2.3
+++ sys/netinet/ip_nat.h	2001/04/08 13:22:50
@@ -227,6 +227,7 @@
 #define	IPN_ROUNDR	0x100
 #define	IPN_NOTSRC	0x080000
 #define	IPN_NOTDST	0x100000
+#define	IPN_FRAG	0x200000
 
 
 typedef	struct	natlog {
Index: sys/netinet/ip_state.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_state.c,v
retrieving revision 1.13.2.5
diff -u -r1.13.2.5 ip_state.c
--- sys/netinet/ip_state.c	2001/02/17 20:42:07	1.13.2.5
+++ sys/netinet/ip_state.c	2001/04/08 13:22:50
@@ -688,7 +688,7 @@
 #endif
 	RWLOCK_EXIT(&ipf_state);
 	fin->fin_rev = IP6NEQ(is->is_dst, fin->fin_fi.fi_dst);
-	if (fin->fin_fi.fi_fl & FI_FRAG)
+	if ((fin->fin_fi.fi_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
 		ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);
 	return is;
 }
@@ -1345,7 +1345,7 @@
 		fr_delstate(is);
 #endif
 	RWLOCK_EXIT(&ipf_state);
-	if (fin->fin_fi.fi_fl & FI_FRAG)
+	if ((fin->fin_fi.fi_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
 		ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);
 	return fr;
 }
