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; }