Deleted Added
full compact
0a1,2
> /* $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_frag.c 145522 2005-04-25 18:43:14Z darrenr $ */
>
2c4
< * Copyright (C) 1993-2001 by Darren Reed.
---
> * Copyright (C) 1993-2003 by Darren Reed.
6,7c8,12
< #if defined(KERNEL) && !defined(_KERNEL)
< # define _KERNEL
---
> #if defined(KERNEL) || defined(_KERNEL)
> # undef KERNEL
> # undef _KERNEL
> # define KERNEL 1
> # define _KERNEL 1
9,12d13
<
< #if defined(__sgi) && (IRIX > 602)
< # include <sys/ptimers.h>
< #endif
18c19,22
< #if !defined(_KERNEL) && !defined(KERNEL)
---
> #ifdef __hpux
> # include <sys/timeout.h>
> #endif
> #if !defined(_KERNEL)
21a26,31
> # define _KERNEL
> # ifdef __OpenBSD__
> struct file;
> # endif
> # include <sys/uio.h>
> # undef _KERNEL
23c33
< #if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000)
---
> #if defined(_KERNEL) && (__FreeBSD_version >= 220000)
29c39
< #ifndef linux
---
> #if !defined(linux)
33c43
< #if defined(_KERNEL) && !defined(linux)
---
> #if defined(_KERNEL)
34a45,47
> # if !defined(__SVR4) && !defined(__svr4__)
> # include <sys/mbuf.h>
> # endif
40,42d52
< # ifndef linux
< # include <sys/mbuf.h>
< # endif
59c69
< #ifndef linux
---
> #if !defined(linux)
71a82
> #include "netinet/ip_proxy.h"
74c85
< # if (defined(KERNEL) || defined(_KERNEL))
---
> # if defined(_KERNEL)
79c90
< extern struct callout_handle ipfr_slowtimer_ch;
---
> extern struct callout_handle fr_slowtimer_ch;
84c95
< extern struct callout ipfr_slowtimer_ch;
---
> extern struct callout fr_slowtimer_ch;
88c99
< extern struct timeout ipfr_slowtimer_ch;
---
> extern struct timeout fr_slowtimer_ch;
89a101
> /* END OF INCLUDES */
93c105,106
< static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/ip_frag.c 139255 2004-12-24 09:14:26Z darrenr $";
---
> static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/ip_frag.c 145522 2005-04-25 18:43:14Z darrenr $";
> static const char rcsid[] = "@(#)Id: ip_frag.c,v 2.77 2004/01/27 00:24:54 darrenr Exp";
97,98c110,121
< static ipfr_t *ipfr_heads[IPFT_SIZE];
< static ipfr_t *ipfr_nattab[IPFT_SIZE];
---
> static ipfr_t *ipfr_list = NULL;
> static ipfr_t **ipfr_tail = &ipfr_list;
> static ipfr_t **ipfr_heads;
>
> static ipfr_t *ipfr_natlist = NULL;
> static ipfr_t **ipfr_nattail = &ipfr_natlist;
> static ipfr_t **ipfr_nattab;
>
> static ipfr_t *ipfr_ipidlist = NULL;
> static ipfr_t **ipfr_ipidtail = &ipfr_ipidlist;
> static ipfr_t **ipfr_ipidtab;
>
100a124
> int ipfr_size = IPFT_SIZE;
103a128,129
> int fr_frag_init = 0;
> u_long fr_ticks = 0;
105,120d130
< #ifdef _KERNEL
< # if SOLARIS2 >= 7
< extern timeout_id_t ipfr_timer_id;
< # else
< extern int ipfr_timer_id;
< # endif
< #endif
< #ifdef USE_MUTEX
< extern KRWLOCK_T ipf_frag, ipf_natfrag, ipf_nat, ipf_mutex;
< # if SOLARIS
< extern KRWLOCK_T ipf_solaris;
< # else
< KRWLOCK_T ipf_solaris;
< # endif
< extern kmutex_t ipf_rw;
< #endif
121a132,134
> static ipfr_t *ipfr_newfrag __P((fr_info_t *, u_32_t, ipfr_t **));
> static ipfr_t *fr_fraglookup __P((fr_info_t *, ipfr_t **));
> static void fr_fragdelete __P((ipfr_t *, ipfr_t ***));
123,125d135
< static ipfr_t *ipfr_new __P((ip_t *, fr_info_t *, ipfr_t **));
< static ipfr_t *ipfr_lookup __P((ip_t *, fr_info_t *, ipfr_t **));
< static void ipfr_delete __P((ipfr_t *));
126a137,149
> /* ------------------------------------------------------------------------ */
> /* Function: fr_fraginit */
> /* Returns: int - 0 == success, -1 == error */
> /* Parameters: Nil */
> /* */
> /* Initialise the hash tables for the fragment cache lookups. */
> /* ------------------------------------------------------------------------ */
> int fr_fraginit()
> {
> KMALLOCS(ipfr_heads, ipfr_t **, ipfr_size * sizeof(ipfr_t *));
> if (ipfr_heads == NULL)
> return -1;
> bzero((char *)ipfr_heads, ipfr_size * sizeof(ipfr_t *));
128c151,175
< ipfrstat_t *ipfr_fragstats()
---
> KMALLOCS(ipfr_nattab, ipfr_t **, ipfr_size * sizeof(ipfr_t *));
> if (ipfr_nattab == NULL)
> return -1;
> bzero((char *)ipfr_nattab, ipfr_size * sizeof(ipfr_t *));
>
> KMALLOCS(ipfr_ipidtab, ipfr_t **, ipfr_size * sizeof(ipfr_t *));
> if (ipfr_ipidtab == NULL)
> return -1;
> bzero((char *)ipfr_ipidtab, ipfr_size * sizeof(ipfr_t *));
>
> RWLOCK_INIT(&ipf_frag, "ipf fragment rwlock");
> fr_frag_init = 1;
>
> return 0;
> }
>
>
> /* ------------------------------------------------------------------------ */
> /* Function: fr_fragunload */
> /* Returns: Nil */
> /* Parameters: Nil */
> /* */
> /* Free all memory allocated whilst running and from initialisation. */
> /* ------------------------------------------------------------------------ */
> void fr_fragunload()
129a177,206
> if (fr_frag_init == 1) {
> fr_fragclear();
>
> RW_DESTROY(&ipf_frag);
> fr_frag_init = 0;
> }
>
> if (ipfr_heads != NULL)
> KFREES(ipfr_heads, ipfr_size * sizeof(ipfr_t *));
> ipfr_heads = NULL;
>
> if (ipfr_nattab != NULL)
> KFREES(ipfr_nattab, ipfr_size * sizeof(ipfr_t *));
> ipfr_nattab = NULL;
>
> if (ipfr_ipidtab != NULL)
> KFREES(ipfr_ipidtab, ipfr_size * sizeof(ipfr_t *));
> ipfr_ipidtab = NULL;
> }
>
>
> /* ------------------------------------------------------------------------ */
> /* Function: fr_fragstats */
> /* Returns: ipfrstat_t* - pointer to struct with current frag stats */
> /* Parameters: Nil */
> /* */
> /* Updates ipfr_stats with current information and returns a pointer to it */
> /* ------------------------------------------------------------------------ */
> ipfrstat_t *fr_fragstats()
> {
137,142c214,223
< /*
< * add a new entry to the fragment cache, registering it as having come
< * through this box, with the result of the filter operation.
< */
< static ipfr_t *ipfr_new(ip, fin, table)
< ip_t *ip;
---
> /* ------------------------------------------------------------------------ */
> /* Function: ipfr_newfrag */
> /* Returns: ipfr_t * - pointer to fragment cache state info or NULL */
> /* Parameters: fin(I) - pointer to packet information */
> /* table(I) - pointer to frag table to add to */
> /* */
> /* Add a new entry to the fragment cache, registering it as having come */
> /* through this box, with the result of the filter operation. */
> /* ------------------------------------------------------------------------ */
> static ipfr_t *ipfr_newfrag(fin, pass, table)
143a225
> u_32_t pass;
146c228
< ipfr_t **fp, *fra, frag;
---
> ipfr_t *fra, frag;
147a230
> ip_t *ip;
152c235
< if (!(fin->fin_fl & FI_FRAG))
---
> if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG)
154a238,243
> ip = fin->fin_ip;
>
> if (pass & FR_FRSTRICT)
> if ((ip->ip_off & IP_OFFMASK) != 0)
> return NULL;
>
175,176c264,265
< for (fp = &table[idx]; (fra = *fp); fp = &fra->ipfr_next)
< if (!bcmp((char *)&frag.ipfr_src, (char *)&fra->ipfr_src,
---
> for (fra = table[idx]; (fra != NULL); fra = fra->ipfr_hnext)
> if (!bcmp((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp,
178c267
< ATOMIC_INCL(ipfr_stats.ifs_exists);
---
> ipfr_stats.ifs_exists++;
188c277
< ATOMIC_INCL(ipfr_stats.ifs_nomem);
---
> ipfr_stats.ifs_nomem++;
192,194c281,282
< if ((fra->ipfr_rule = fin->fin_fr) != NULL) {
< ATOMIC_INC32(fin->fin_fr->fr_ref);
< }
---
> if ((fra->ipfr_rule = fin->fin_fr) != NULL)
> fin->fin_fr->fr_ref++;
196d283
<
202,204c289,291
< if ((fra->ipfr_next = table[idx]))
< table[idx]->ipfr_prev = fra;
< fra->ipfr_prev = NULL;
---
> if ((fra->ipfr_hnext = table[idx]) != NULL)
> table[idx]->ipfr_hprev = &fra->ipfr_hnext;
> fra->ipfr_hprev = table + idx;
207,208c294,296
< bcopy((char *)&frag.ipfr_src, (char *)&fra->ipfr_src, IPFR_CMPSZ);
< fra->ipfr_ttl = fr_ipfrttl;
---
> bcopy((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp, IPFR_CMPSZ);
> fra->ipfr_ttl = fr_ticks + fr_ipfrttl;
>
213c301
< if (!off)
---
> if (off == 0)
216,217c304,306
< ATOMIC_INCL(ipfr_stats.ifs_new);
< ATOMIC_INC32(ipfr_inuse);
---
> fra->ipfr_pass = pass;
> ipfr_stats.ifs_new++;
> ipfr_inuse++;
222,223c311,319
< int ipfr_newfrag(ip, fin)
< ip_t *ip;
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_newfrag */
> /* Returns: int - 0 == success, -1 == error */
> /* Parameters: fin(I) - pointer to packet information */
> /* */
> /* Add a new entry to the fragment cache table based on the current packet */
> /* ------------------------------------------------------------------------ */
> int fr_newfrag(fin, pass)
> u_32_t pass;
226c322
< ipfr_t *ipf;
---
> ipfr_t *fra;
228c324
< if ((ip->ip_v != 4) || (fr_frag_lock))
---
> if ((fin->fin_v != 4) || (fr_frag_lock != 0))
229a326
>
231,235c328,335
< ipf = ipfr_new(ip, fin, ipfr_heads);
< RWLOCK_EXIT(&ipf_frag);
< if (ipf == NULL) {
< ATOMIC_INCL(frstats[fin->fin_out].fr_bnfr);
< return -1;
---
> fra = ipfr_newfrag(fin, pass, ipfr_heads);
> if (fra != NULL) {
> *ipfr_tail = fra;
> fra->ipfr_prev = ipfr_tail;
> ipfr_tail = &fra->ipfr_next;
> if (ipfr_list == NULL)
> ipfr_list = fra;
> fra->ipfr_next = NULL;
237,238c337,338
< ATOMIC_INCL(frstats[fin->fin_out].fr_nfr);
< return 0;
---
> RWLOCK_EXIT(&ipf_frag);
> return fra ? 0 : -1;
242,243c342,351
< int ipfr_nat_newfrag(ip, fin, nat)
< ip_t *ip;
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_nat_newfrag */
> /* Returns: int - 0 == success, -1 == error */
> /* Parameters: fin(I) - pointer to packet information */
> /* nat(I) - pointer to NAT structure */
> /* */
> /* Create a new NAT fragment cache entry based on the current packet and */
> /* the NAT structure for this "session". */
> /* ------------------------------------------------------------------------ */
> int fr_nat_newfrag(fin, pass, nat)
244a353
> u_32_t pass;
247,248c356
< ipfr_t *ipf;
< int off;
---
> ipfr_t *fra;
250,251c358,359
< if ((ip->ip_v != 4) || (fr_frag_lock))
< return -1;
---
> if ((fin->fin_v != 4) || (fr_frag_lock != 0))
> return 0;
253,257d360
< off = fin->fin_off;
< off <<= 3;
< if ((off + fin->fin_dlen) > 0xffff || (fin->fin_dlen == 0))
< return -1;
<
259,262c362,369
< ipf = ipfr_new(ip, fin, ipfr_nattab);
< if (ipf != NULL) {
< ipf->ipfr_data = nat;
< nat->nat_data = ipf;
---
> fra = ipfr_newfrag(fin, pass, ipfr_nattab);
> if (fra != NULL) {
> fra->ipfr_data = nat;
> nat->nat_data = fra;
> *ipfr_nattail = fra;
> fra->ipfr_prev = ipfr_nattail;
> ipfr_nattail = &fra->ipfr_next;
> fra->ipfr_next = NULL;
265c372
< return ipf ? 0 : -1;
---
> return fra ? 0 : -1;
269,274c376,385
< /*
< * check the fragment cache to see if there is already a record of this packet
< * with its filter result known.
< */
< static ipfr_t *ipfr_lookup(ip, fin, table)
< ip_t *ip;
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_ipid_newfrag */
> /* Returns: int - 0 == success, -1 == error */
> /* Parameters: fin(I) - pointer to packet information */
> /* ipid(I) - new IP ID for this fragmented packet */
> /* */
> /* Create a new fragment cache entry for this packet and store, as a data */
> /* pointer, the new IP ID value. */
> /* ------------------------------------------------------------------------ */
> int fr_ipid_newfrag(fin, ipid)
275a387,419
> u_32_t ipid;
> {
> ipfr_t *fra;
>
> if ((fin->fin_v != 4) || (fr_frag_lock))
> return 0;
>
> WRITE_ENTER(&ipf_ipidfrag);
> fra = ipfr_newfrag(fin, 0, ipfr_ipidtab);
> if (fra != NULL) {
> fra->ipfr_data = (void *)ipid;
> *ipfr_ipidtail = fra;
> fra->ipfr_prev = ipfr_ipidtail;
> ipfr_ipidtail = &fra->ipfr_next;
> fra->ipfr_next = NULL;
> }
> RWLOCK_EXIT(&ipf_ipidfrag);
> return fra ? 0 : -1;
> }
>
>
> /* ------------------------------------------------------------------------ */
> /* Function: fr_fraglookup */
> /* Returns: ipfr_t * - pointer to ipfr_t structure if there's a */
> /* matching entry in the frag table, else NULL */
> /* Parameters: fin(I) - pointer to packet information */
> /* table(I) - pointer to fragment cache table to search */
> /* */
> /* Check the fragment cache to see if there is already a record of this */
> /* packet with its filter result known. */
> /* ------------------------------------------------------------------------ */
> static ipfr_t *fr_fraglookup(fin, table)
> fr_info_t *fin;
278,279c422,424
< ipfr_t *f, frag;
< u_int idx;
---
> ipfr_t *f, frag;
> u_int idx;
> ip_t *ip;
280a426,428
> if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG)
> return NULL;
>
286a435
> ip = fin->fin_ip;
307,308c456,457
< for (f = table[idx]; f; f = f->ipfr_next)
< if (!bcmp((char *)&frag.ipfr_src, (char *)&f->ipfr_src,
---
> for (f = table[idx]; f; f = f->ipfr_hnext)
> if (!bcmp((char *)&frag.ipfr_ifp, (char *)&f->ipfr_ifp,
310c459
< u_short atoff, off;
---
> u_short off;
312c461,474
< off = fin->fin_off;
---
> /*
> * We don't want to let short packets match because
> * they could be compromising the security of other
> * rules that want to match on layer 4 fields (and
> * can't because they have been fragmented off.)
> * Why do this check here? The counter acts as an
> * indicator of this kind of attack, whereas if it was
> * elsewhere, it wouldn't know if other matching
> * packets had been seen.
> */
> if (fin->fin_flx & FI_SHORT) {
> ATOMIC_INCL(ipfr_stats.ifs_short);
> continue;
> }
318c480
< * the same IP ID#.
---
> * the same IP ID# (or shouldn't).
319a482
> off = ip->ip_off & IP_OFFMASK;
321c484,485
< if (!off || (fin->fin_fl & FI_SHORT))
---
> if (off == 0) {
> ATOMIC_INCL(ipfr_stats.ifs_retrans0);
323c487,488
< } else if (!off)
---
> }
> } else if (off == 0)
326a492,493
> ipfr_t **fp;
>
328,329c495,496
< * move fragment info. to the top of the list
< * to speed up searches.
---
> * Move fragment info. to the top of the list
> * to speed up searches. First, delink...
331,335c498,507
< if ((f->ipfr_prev->ipfr_next = f->ipfr_next))
< f->ipfr_next->ipfr_prev = f->ipfr_prev;
< f->ipfr_next = table[idx];
< table[idx]->ipfr_prev = f;
< f->ipfr_prev = NULL;
---
> fp = f->ipfr_hprev;
> (*fp) = f->ipfr_hnext;
> if (f->ipfr_hnext != NULL)
> f->ipfr_hnext->ipfr_hprev = fp;
> /*
> * Then put back at the top of the chain.
> */
> f->ipfr_hnext = table[idx];
> table[idx]->ipfr_hprev = &f->ipfr_hnext;
> f->ipfr_hprev = table + idx;
338c510
< atoff = off + (fin->fin_dlen >> 3);
---
>
345,348c517,520
< f->ipfr_ttl = 1;
< else
< f->ipfr_off = atoff;
< }
---
> f->ipfr_ttl = fr_ticks + 1;
> f->ipfr_off = (fin->fin_dlen >> 3) + off;
> } else if (f->ipfr_pass & FR_FRSTRICT)
> continue;
356,360c528,536
< /*
< * functional interface for NAT lookups of the NAT fragment cache
< */
< nat_t *ipfr_nat_knownfrag(ip, fin)
< ip_t *ip;
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_nat_knownfrag */
> /* Returns: nat_t* - pointer to 'parent' NAT structure if frag table */
> /* match found, else NULL */
> /* Parameters: fin(I) - pointer to packet information */
> /* */
> /* Functional interface for NAT lookups of the NAT fragment cache */
> /* ------------------------------------------------------------------------ */
> nat_t *fr_nat_knownfrag(fin)
363,365c539,540
< ipfr_t *ipf;
< nat_t *nat;
< int off;
---
> nat_t *nat;
> ipfr_t *ipf;
367c542
< if ((fin->fin_v != 4) || (fr_frag_lock))
---
> if ((fin->fin_v != 4) || (fr_frag_lock) || !ipfr_natlist)
369,374d543
<
< off = fin->fin_off;
< off <<= 3;
< if ((off + fin->fin_dlen) > 0xffff || (fin->fin_dlen == 0))
< return NULL;
<
376c545
< ipf = ipfr_lookup(ip, fin, ipfr_nattab);
---
> ipf = fr_fraglookup(fin, ipfr_nattab);
382c551
< if ((ipf->ipfr_ttl == 1) && (nat != NULL)) {
---
> if ((ipf->ipfr_ttl == fr_ticks + 1) && (nat != NULL)) {
393,397c562,570
< /*
< * functional interface for normal lookups of the fragment cache
< */
< frentry_t *ipfr_knownfrag(ip, fin)
< ip_t *ip;
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_ipid_knownfrag */
> /* Returns: u_32_t - IPv4 ID for this packet if match found, else */
> /* return 0xfffffff to indicate no match. */
> /* Parameters: fin(I) - pointer to packet information */
> /* */
> /* Functional interface for IP ID lookups of the IP ID fragment cache */
> /* ------------------------------------------------------------------------ */
> u_32_t fr_ipid_knownfrag(fin)
400,402c573,574
< frentry_t *fr;
< ipfr_t *fra;
< int off;
---
> ipfr_t *ipf;
> u_32_t id;
404,405c576,577
< if ((fin->fin_v != 4) || (fr_frag_lock))
< return NULL;
---
> if ((fin->fin_v != 4) || (fr_frag_lock) || !ipfr_ipidlist)
> return 0xffffffff;
407,409c579,609
< off = fin->fin_off;
< off <<= 3;
< if ((off + fin->fin_dlen) > 0xffff || (fin->fin_dlen == 0))
---
> READ_ENTER(&ipf_ipidfrag);
> ipf = fr_fraglookup(fin, ipfr_ipidtab);
> if (ipf != NULL)
> id = (u_32_t)ipf->ipfr_data;
> else
> id = 0xffffffff;
> RWLOCK_EXIT(&ipf_ipidfrag);
> return id;
> }
>
>
> /* ------------------------------------------------------------------------ */
> /* Function: fr_knownfrag */
> /* Returns: frentry_t* - pointer to filter rule if a match is found in */
> /* the frag cache table, else NULL. */
> /* Parameters: fin(I) - pointer to packet information */
> /* passp(O) - pointer to where to store rule flags resturned */
> /* */
> /* Functional interface for normal lookups of the fragment cache. If a */
> /* match is found, return the rule pointer and flags from the rule, except */
> /* that if FR_LOGFIRST is set, reset FR_LOG. */
> /* ------------------------------------------------------------------------ */
> frentry_t *fr_knownfrag(fin, passp)
> fr_info_t *fin;
> u_32_t *passp;
> {
> frentry_t *fr = NULL;
> ipfr_t *fra;
> u_32_t pass;
>
> if ((fin->fin_v != 4) || (fr_frag_lock) || (ipfr_list == NULL))
413,414c613,614
< fra = ipfr_lookup(ip, fin, ipfr_heads);
< if (fra != NULL)
---
> fra = fr_fraglookup(fin, ipfr_heads);
> if (fra != NULL) {
416,417c616,623
< else
< fr = NULL;
---
> fin->fin_fr = fr;
> if (fr != NULL) {
> pass = fr->fr_flags;
> if ((pass & FR_LOGFIRST) != 0)
> pass &= ~(FR_LOGFIRST|FR_LOG);
> *passp = pass;
> }
> }
423,426c629,637
< /*
< * forget any references to this external object.
< */
< void ipfr_forget(ptr)
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_forget */
> /* Returns: Nil */
> /* Parameters: ptr(I) - pointer to data structure */
> /* */
> /* Search through all of the fragment cache entries and wherever a pointer */
> /* is found to match ptr, reset it to NULL. */
> /* ------------------------------------------------------------------------ */
> void fr_forget(ptr)
430d640
< int idx;
433,437c643,645
< for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
< for (fr = ipfr_heads[idx]; fr; fr = fr->ipfr_next)
< if (fr->ipfr_data == ptr)
< fr->ipfr_data = NULL;
<
---
> for (fr = ipfr_list; fr; fr = fr->ipfr_next)
> if (fr->ipfr_data == ptr)
> fr->ipfr_data = NULL;
442,446c650,659
< /*
< * forget any references to this external object.
< */
< void ipfr_forgetnat(nat)
< void *nat;
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_forgetnat */
> /* Returns: Nil */
> /* Parameters: ptr(I) - pointer to data structure */
> /* */
> /* Search through all of the fragment cache entries for NAT and wherever a */
> /* pointer is found to match ptr, reset it to NULL. */
> /* ------------------------------------------------------------------------ */
> void fr_forgetnat(ptr)
> void *ptr;
449d661
< int idx;
452,456c664,666
< for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
< for (fr = ipfr_nattab[idx]; fr; fr = fr->ipfr_next)
< if (fr->ipfr_data == nat)
< fr->ipfr_data = NULL;
<
---
> for (fr = ipfr_natlist; fr; fr = fr->ipfr_next)
> if (fr->ipfr_data == ptr)
> fr->ipfr_data = NULL;
461,462c671,683
< static void ipfr_delete(fra)
< ipfr_t *fra;
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_fragdelete */
> /* Returns: Nil */
> /* Parameters: fra(I) - pointer to fragment structure to delete */
> /* tail(IO) - pointer to the pointer to the tail of the frag */
> /* list */
> /* */
> /* Remove a fragment cache table entry from the table & list. Also free */
> /* the filter rule it is associated with it if it is no longer used as a */
> /* result of decreasing the reference count. */
> /* ------------------------------------------------------------------------ */
> static void fr_fragdelete(fra, tail)
> ipfr_t *fra, ***tail;
467,473c688,690
< if (fr != NULL) {
< ATOMIC_DEC32(fr->fr_ref);
< if (fr->fr_ref == 0)
< KFREE(fr);
< }
< if (fra->ipfr_prev)
< fra->ipfr_prev->ipfr_next = fra->ipfr_next;
---
> if (fr != NULL)
> (void)fr_derefrule(&fr);
>
475a693,699
> *fra->ipfr_prev = fra->ipfr_next;
> if (*tail == &fra->ipfr_next)
> *tail = fra->ipfr_prev;
>
> if (fra->ipfr_hnext)
> fra->ipfr_hnext->ipfr_hprev = fra->ipfr_hprev;
> *fra->ipfr_hprev = fra->ipfr_hnext;
480,483c704,712
< /*
< * Free memory in use by fragment state info. kept.
< */
< void ipfr_unload()
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_fragclear */
> /* Returns: Nil */
> /* Parameters: Nil */
> /* */
> /* Free memory in use by fragment state information kept. Do the normal */
> /* fragment state stuff first and then the NAT-fragment table. */
> /* ------------------------------------------------------------------------ */
> void fr_fragclear()
485c714
< ipfr_t **fp, *fra;
---
> ipfr_t *fra;
487d715
< int idx;
490,494c718,720
< for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
< for (fp = &ipfr_heads[idx]; (fra = *fp); ) {
< *fp = fra->ipfr_next;
< ipfr_delete(fra);
< }
---
> while ((fra = ipfr_list) != NULL)
> fr_fragdelete(fra, &ipfr_tail);
> ipfr_tail = &ipfr_list;
499,507c725,729
< for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
< for (fp = &ipfr_nattab[idx]; (fra = *fp); ) {
< *fp = fra->ipfr_next;
< nat = fra->ipfr_data;
< if (nat != NULL) {
< if (nat->nat_data == fra)
< nat->nat_data = NULL;
< }
< ipfr_delete(fra);
---
> while ((fra = ipfr_natlist) != NULL) {
> nat = fra->ipfr_data;
> if (nat != NULL) {
> if (nat->nat_data == fra)
> nat->nat_data = NULL;
508a731,733
> fr_fragdelete(fra, &ipfr_nattail);
> }
> ipfr_nattail = &ipfr_natlist;
514c739,746
< void ipfr_fragexpire()
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_fragexpire */
> /* Returns: Nil */
> /* Parameters: Nil */
> /* */
> /* Expire entries in the fragment cache table that have been there too long */
> /* ------------------------------------------------------------------------ */
> void fr_fragexpire()
518,520c750
< int idx;
< #if defined(_KERNEL)
< # if !SOLARIS
---
> #if defined(USE_SPL) && defined(_KERNEL)
522d751
< # endif
530d758
<
533,534c761
< * decreasing the ttl by one for each entry. If it reaches 0,
< * remove it from the chain and free it.
---
> * which is indicated by the ttl being less than or equal to fr_ticks.
536,546c763,769
< for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
< for (fp = &ipfr_heads[idx]; (fra = *fp); ) {
< --fra->ipfr_ttl;
< if (fra->ipfr_ttl == 0) {
< *fp = fra->ipfr_next;
< ipfr_delete(fra);
< ATOMIC_INCL(ipfr_stats.ifs_expire);
< ATOMIC_DEC32(ipfr_inuse);
< } else
< fp = &fra->ipfr_next;
< }
---
> for (fp = &ipfr_list; ((fra = *fp) != NULL); ) {
> if (fra->ipfr_ttl > fr_ticks)
> break;
> fr_fragdelete(fra, &ipfr_tail);
> ipfr_stats.ifs_expire++;
> ipfr_inuse--;
> }
548a772,781
> WRITE_ENTER(&ipf_ipidfrag);
> for (fp = &ipfr_ipidlist; ((fra = *fp) != NULL); ) {
> if (fra->ipfr_ttl > fr_ticks)
> break;
> fr_fragdelete(fra, &ipfr_ipidtail);
> ipfr_stats.ifs_expire++;
> ipfr_inuse--;
> }
> RWLOCK_EXIT(&ipf_ipidfrag);
>
558,572c791,797
< for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
< for (fp = &ipfr_nattab[idx]; (fra = *fp); ) {
< --fra->ipfr_ttl;
< if (fra->ipfr_ttl == 0) {
< ATOMIC_INCL(ipfr_stats.ifs_expire);
< ATOMIC_DEC32(ipfr_inuse);
< nat = fra->ipfr_data;
< if (nat != NULL) {
< if (nat->nat_data == fra)
< nat->nat_data = NULL;
< }
< *fp = fra->ipfr_next;
< ipfr_delete(fra);
< } else
< fp = &fra->ipfr_next;
---
> for (fp = &ipfr_natlist; ((fra = *fp) != NULL); ) {
> if (fra->ipfr_ttl > fr_ticks)
> break;
> nat = fra->ipfr_data;
> if (nat != NULL) {
> if (nat->nat_data == fra)
> nat->nat_data = NULL;
573a799,802
> fr_fragdelete(fra, &ipfr_nattail);
> ipfr_stats.ifs_expire++;
> ipfr_inuse--;
> }
580,590c809,820
< /*
< * Slowly expire held state for fragments. Timeouts are set * in expectation
< * of this being called twice per second.
< */
< #ifdef _KERNEL
< # if (BSD >= 199306) || SOLARIS || defined(__sgi)
< # if defined(SOLARIS2) && (SOLARIS2 < 7)
< void ipfr_slowtimer()
< # else
< void ipfr_slowtimer __P((void *ptr))
< # endif
---
> /* ------------------------------------------------------------------------ */
> /* Function: fr_slowtimer */
> /* Returns: Nil */
> /* Parameters: Nil */
> /* */
> /* Slowly expire held state for fragments. Timeouts are set * in */
> /* expectation of this being called twice per second. */
> /* ------------------------------------------------------------------------ */
> #if !defined(_KERNEL) || (!SOLARIS && !defined(__hpux) && !defined(__sgi) && \
> !defined(__osf__))
> # if defined(_KERNEL) && ((BSD >= 199103) || defined(__sgi))
> void fr_slowtimer __P((void *ptr))
592c822
< int ipfr_slowtimer()
---
> int fr_slowtimer()
594,596d823
< #else
< void ipfr_slowtimer()
< #endif
598,599c825
< #if defined(_KERNEL) && SOLARIS
< extern int fr_running;
---
> READ_ENTER(&ipf_global);
601,610c827
< if (fr_running <= 0)
< return;
< READ_ENTER(&ipf_solaris);
< #endif
<
< #if defined(__sgi) && defined(_KERNEL)
< ipfilter_sgi_intfsync();
< #endif
<
< ipfr_fragexpire();
---
> fr_fragexpire();
612c829
< ip_natexpire();
---
> fr_natexpire();
614,618c831,834
< #if defined(_KERNEL)
< # if SOLARIS
< ipfr_timer_id = timeout(ipfr_slowtimer, NULL, drv_usectohz(500000));
< RWLOCK_EXIT(&ipf_solaris);
< # else
---
> fr_ticks++;
> if (fr_running <= 0)
> goto done;
> # ifdef _KERNEL
620c836
< callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL);
---
> callout_reset(&fr_slowtimer_ch, hz / 2, fr_slowtimer, NULL);
622,623c838,839
< # if (__FreeBSD_version >= 300000)
< ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
---
> # if defined(__OpenBSD__)
> timeout_add(&fr_slowtimer_ch, hz/2);
625,626c841,842
< # if defined(__OpenBSD__)
< timeout_add(&ipfr_slowtimer_ch, hz/2);
---
> # if (__FreeBSD_version >= 300000)
> fr_slowtimer_ch = timeout(fr_slowtimer, NULL, hz/2);
628,633c844,850
< timeout(ipfr_slowtimer, NULL, hz/2);
< # endif
< # endif
< # if (BSD < 199306) && !defined(__sgi)
< return 0;
< # endif /* FreeBSD */
---
> # ifdef linux
> ;
> # else
> timeout(fr_slowtimer, NULL, hz/2);
> # endif
> # endif /* FreeBSD */
> # endif /* OpenBSD */
635,636c852,857
< # endif /* SOLARIS */
< #endif /* defined(_KERNEL) */
---
> # endif
> done:
> RWLOCK_EXIT(&ipf_global);
> # if (BSD < 199103) || !defined(_KERNEL)
> return 0;
> # endif
637a859
> #endif /* !SOLARIS && !defined(__hpux) && !defined(__sgi) */