ip_frag.c (139255) | ip_frag.c (145522) |
---|---|
1/* $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_frag.c 145522 2005-04-25 18:43:14Z darrenr $ */ 2 |
|
1/* | 3/* |
2 * Copyright (C) 1993-2001 by Darren Reed. | 4 * Copyright (C) 1993-2003 by Darren Reed. |
3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 */ | 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 */ |
6#if defined(KERNEL) && !defined(_KERNEL) 7# define _KERNEL | 8#if defined(KERNEL) || defined(_KERNEL) 9# undef KERNEL 10# undef _KERNEL 11# define KERNEL 1 12# define _KERNEL 1 |
8#endif | 13#endif |
9 10#if defined(__sgi) && (IRIX > 602) 11# include <sys/ptimers.h> 12#endif | |
13#include <sys/errno.h> 14#include <sys/types.h> 15#include <sys/param.h> 16#include <sys/time.h> 17#include <sys/file.h> | 14#include <sys/errno.h> 15#include <sys/types.h> 16#include <sys/param.h> 17#include <sys/time.h> 18#include <sys/file.h> |
18#if !defined(_KERNEL) && !defined(KERNEL) | 19#ifdef __hpux 20# include <sys/timeout.h> 21#endif 22#if !defined(_KERNEL) |
19# include <stdio.h> 20# include <string.h> 21# include <stdlib.h> | 23# include <stdio.h> 24# include <string.h> 25# include <stdlib.h> |
26# define _KERNEL 27# ifdef __OpenBSD__ 28struct file; 29# endif 30# include <sys/uio.h> 31# undef _KERNEL |
|
22#endif | 32#endif |
23#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) | 33#if defined(_KERNEL) && (__FreeBSD_version >= 220000) |
24# include <sys/filio.h> 25# include <sys/fcntl.h> 26#else 27# include <sys/ioctl.h> 28#endif | 34# include <sys/filio.h> 35# include <sys/fcntl.h> 36#else 37# include <sys/ioctl.h> 38#endif |
29#ifndef linux | 39#if !defined(linux) |
30# include <sys/protosw.h> 31#endif 32#include <sys/socket.h> | 40# include <sys/protosw.h> 41#endif 42#include <sys/socket.h> |
33#if defined(_KERNEL) && !defined(linux) | 43#if defined(_KERNEL) |
34# include <sys/systm.h> | 44# include <sys/systm.h> |
45# if !defined(__SVR4) && !defined(__svr4__) 46# include <sys/mbuf.h> 47# endif |
|
35#endif 36#if !defined(__SVR4) && !defined(__svr4__) 37# if defined(_KERNEL) && !defined(__sgi) 38# include <sys/kernel.h> 39# endif | 48#endif 49#if !defined(__SVR4) && !defined(__svr4__) 50# if defined(_KERNEL) && !defined(__sgi) 51# include <sys/kernel.h> 52# endif |
40# ifndef linux 41# include <sys/mbuf.h> 42# endif | |
43#else 44# include <sys/byteorder.h> 45# ifdef _KERNEL 46# include <sys/dditypes.h> 47# endif 48# include <sys/stream.h> 49# include <sys/kmem.h> 50#endif 51#include <net/if.h> 52#ifdef sun 53# include <net/af.h> 54#endif 55#include <net/route.h> 56#include <netinet/in.h> 57#include <netinet/in_systm.h> 58#include <netinet/ip.h> | 53#else 54# include <sys/byteorder.h> 55# ifdef _KERNEL 56# include <sys/dditypes.h> 57# endif 58# include <sys/stream.h> 59# include <sys/kmem.h> 60#endif 61#include <net/if.h> 62#ifdef sun 63# include <net/af.h> 64#endif 65#include <net/route.h> 66#include <netinet/in.h> 67#include <netinet/in_systm.h> 68#include <netinet/ip.h> |
59#ifndef linux | 69#if !defined(linux) |
60# include <netinet/ip_var.h> 61#endif 62#include <netinet/tcp.h> 63#include <netinet/udp.h> 64#include <netinet/ip_icmp.h> 65#include "netinet/ip_compat.h" 66#include <netinet/tcpip.h> 67#include "netinet/ip_fil.h" 68#include "netinet/ip_nat.h" 69#include "netinet/ip_frag.h" 70#include "netinet/ip_state.h" 71#include "netinet/ip_auth.h" | 70# include <netinet/ip_var.h> 71#endif 72#include <netinet/tcp.h> 73#include <netinet/udp.h> 74#include <netinet/ip_icmp.h> 75#include "netinet/ip_compat.h" 76#include <netinet/tcpip.h> 77#include "netinet/ip_fil.h" 78#include "netinet/ip_nat.h" 79#include "netinet/ip_frag.h" 80#include "netinet/ip_state.h" 81#include "netinet/ip_auth.h" |
82#include "netinet/ip_proxy.h" |
|
72#if (__FreeBSD_version >= 300000) 73# include <sys/malloc.h> | 83#if (__FreeBSD_version >= 300000) 84# include <sys/malloc.h> |
74# if (defined(KERNEL) || defined(_KERNEL)) | 85# if defined(_KERNEL) |
75# ifndef IPFILTER_LKM 76# include <sys/libkern.h> 77# include <sys/systm.h> 78# endif | 86# ifndef IPFILTER_LKM 87# include <sys/libkern.h> 88# include <sys/systm.h> 89# endif |
79extern struct callout_handle ipfr_slowtimer_ch; | 90extern struct callout_handle fr_slowtimer_ch; |
80# endif 81#endif 82#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) 83# include <sys/callout.h> | 91# endif 92#endif 93#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) 94# include <sys/callout.h> |
84extern struct callout ipfr_slowtimer_ch; | 95extern struct callout fr_slowtimer_ch; |
85#endif 86#if defined(__OpenBSD__) 87# include <sys/timeout.h> | 96#endif 97#if defined(__OpenBSD__) 98# include <sys/timeout.h> |
88extern struct timeout ipfr_slowtimer_ch; | 99extern struct timeout fr_slowtimer_ch; |
89#endif | 100#endif |
101/* END OF INCLUDES */ |
|
90 91#if !defined(lint) 92static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed"; | 102 103#if !defined(lint) 104static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed"; |
93static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/ip_frag.c 139255 2004-12-24 09:14:26Z darrenr $"; | 105static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/ip_frag.c 145522 2005-04-25 18:43:14Z darrenr $"; 106static const char rcsid[] = "@(#)Id: ip_frag.c,v 2.77 2004/01/27 00:24:54 darrenr Exp"; |
94#endif 95 96 | 107#endif 108 109 |
97static ipfr_t *ipfr_heads[IPFT_SIZE]; 98static ipfr_t *ipfr_nattab[IPFT_SIZE]; | 110static ipfr_t *ipfr_list = NULL; 111static ipfr_t **ipfr_tail = &ipfr_list; 112static ipfr_t **ipfr_heads; 113 114static ipfr_t *ipfr_natlist = NULL; 115static ipfr_t **ipfr_nattail = &ipfr_natlist; 116static ipfr_t **ipfr_nattab; 117 118static ipfr_t *ipfr_ipidlist = NULL; 119static ipfr_t **ipfr_ipidtail = &ipfr_ipidlist; 120static ipfr_t **ipfr_ipidtab; 121 |
99static ipfrstat_t ipfr_stats; 100static int ipfr_inuse = 0; | 122static ipfrstat_t ipfr_stats; 123static int ipfr_inuse = 0; |
124int ipfr_size = IPFT_SIZE; |
|
101 102int fr_ipfrttl = 120; /* 60 seconds */ 103int fr_frag_lock = 0; | 125 126int fr_ipfrttl = 120; /* 60 seconds */ 127int fr_frag_lock = 0; |
128int fr_frag_init = 0; 129u_long fr_ticks = 0; |
|
104 | 130 |
105#ifdef _KERNEL 106# if SOLARIS2 >= 7 107extern timeout_id_t ipfr_timer_id; 108# else 109extern int ipfr_timer_id; 110# endif 111#endif 112#ifdef USE_MUTEX 113extern KRWLOCK_T ipf_frag, ipf_natfrag, ipf_nat, ipf_mutex; 114# if SOLARIS 115extern KRWLOCK_T ipf_solaris; 116# else 117KRWLOCK_T ipf_solaris; 118# endif 119extern kmutex_t ipf_rw; 120#endif | |
121 | 131 |
132static ipfr_t *ipfr_newfrag __P((fr_info_t *, u_32_t, ipfr_t **)); 133static ipfr_t *fr_fraglookup __P((fr_info_t *, ipfr_t **)); 134static void fr_fragdelete __P((ipfr_t *, ipfr_t ***)); |
|
122 | 135 |
123static ipfr_t *ipfr_new __P((ip_t *, fr_info_t *, ipfr_t **)); 124static ipfr_t *ipfr_lookup __P((ip_t *, fr_info_t *, ipfr_t **)); 125static void ipfr_delete __P((ipfr_t *)); | |
126 | 136 |
137/* ------------------------------------------------------------------------ */ 138/* Function: fr_fraginit */ 139/* Returns: int - 0 == success, -1 == error */ 140/* Parameters: Nil */ 141/* */ 142/* Initialise the hash tables for the fragment cache lookups. */ 143/* ------------------------------------------------------------------------ */ 144int fr_fraginit() 145{ 146 KMALLOCS(ipfr_heads, ipfr_t **, ipfr_size * sizeof(ipfr_t *)); 147 if (ipfr_heads == NULL) 148 return -1; 149 bzero((char *)ipfr_heads, ipfr_size * sizeof(ipfr_t *)); |
|
127 | 150 |
128ipfrstat_t *ipfr_fragstats() | 151 KMALLOCS(ipfr_nattab, ipfr_t **, ipfr_size * sizeof(ipfr_t *)); 152 if (ipfr_nattab == NULL) 153 return -1; 154 bzero((char *)ipfr_nattab, ipfr_size * sizeof(ipfr_t *)); 155 156 KMALLOCS(ipfr_ipidtab, ipfr_t **, ipfr_size * sizeof(ipfr_t *)); 157 if (ipfr_ipidtab == NULL) 158 return -1; 159 bzero((char *)ipfr_ipidtab, ipfr_size * sizeof(ipfr_t *)); 160 161 RWLOCK_INIT(&ipf_frag, "ipf fragment rwlock"); 162 fr_frag_init = 1; 163 164 return 0; 165} 166 167 168/* ------------------------------------------------------------------------ */ 169/* Function: fr_fragunload */ 170/* Returns: Nil */ 171/* Parameters: Nil */ 172/* */ 173/* Free all memory allocated whilst running and from initialisation. */ 174/* ------------------------------------------------------------------------ */ 175void fr_fragunload() |
129{ | 176{ |
177 if (fr_frag_init == 1) { 178 fr_fragclear(); 179 180 RW_DESTROY(&ipf_frag); 181 fr_frag_init = 0; 182 } 183 184 if (ipfr_heads != NULL) 185 KFREES(ipfr_heads, ipfr_size * sizeof(ipfr_t *)); 186 ipfr_heads = NULL; 187 188 if (ipfr_nattab != NULL) 189 KFREES(ipfr_nattab, ipfr_size * sizeof(ipfr_t *)); 190 ipfr_nattab = NULL; 191 192 if (ipfr_ipidtab != NULL) 193 KFREES(ipfr_ipidtab, ipfr_size * sizeof(ipfr_t *)); 194 ipfr_ipidtab = NULL; 195} 196 197 198/* ------------------------------------------------------------------------ */ 199/* Function: fr_fragstats */ 200/* Returns: ipfrstat_t* - pointer to struct with current frag stats */ 201/* Parameters: Nil */ 202/* */ 203/* Updates ipfr_stats with current information and returns a pointer to it */ 204/* ------------------------------------------------------------------------ */ 205ipfrstat_t *fr_fragstats() 206{ |
|
130 ipfr_stats.ifs_table = ipfr_heads; 131 ipfr_stats.ifs_nattab = ipfr_nattab; 132 ipfr_stats.ifs_inuse = ipfr_inuse; 133 return &ipfr_stats; 134} 135 136 | 207 ipfr_stats.ifs_table = ipfr_heads; 208 ipfr_stats.ifs_nattab = ipfr_nattab; 209 ipfr_stats.ifs_inuse = ipfr_inuse; 210 return &ipfr_stats; 211} 212 213 |
137/* 138 * add a new entry to the fragment cache, registering it as having come 139 * through this box, with the result of the filter operation. 140 */ 141static ipfr_t *ipfr_new(ip, fin, table) 142ip_t *ip; | 214/* ------------------------------------------------------------------------ */ 215/* Function: ipfr_newfrag */ 216/* Returns: ipfr_t * - pointer to fragment cache state info or NULL */ 217/* Parameters: fin(I) - pointer to packet information */ 218/* table(I) - pointer to frag table to add to */ 219/* */ 220/* Add a new entry to the fragment cache, registering it as having come */ 221/* through this box, with the result of the filter operation. */ 222/* ------------------------------------------------------------------------ */ 223static ipfr_t *ipfr_newfrag(fin, pass, table) |
143fr_info_t *fin; | 224fr_info_t *fin; |
225u_32_t pass; |
|
144ipfr_t *table[]; 145{ | 226ipfr_t *table[]; 227{ |
146 ipfr_t **fp, *fra, frag; | 228 ipfr_t *fra, frag; |
147 u_int idx, off; | 229 u_int idx, off; |
230 ip_t *ip; |
|
148 149 if (ipfr_inuse >= IPFT_SIZE) 150 return NULL; 151 | 231 232 if (ipfr_inuse >= IPFT_SIZE) 233 return NULL; 234 |
152 if (!(fin->fin_fl & FI_FRAG)) | 235 if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG) |
153 return NULL; 154 | 236 return NULL; 237 |
238 ip = fin->fin_ip; 239 240 if (pass & FR_FRSTRICT) 241 if ((ip->ip_off & IP_OFFMASK) != 0) 242 return NULL; 243 |
|
155 frag.ipfr_p = ip->ip_p; 156 idx = ip->ip_p; 157 frag.ipfr_id = ip->ip_id; 158 idx += ip->ip_id; 159 frag.ipfr_tos = ip->ip_tos; 160 frag.ipfr_src.s_addr = ip->ip_src.s_addr; 161 idx += ip->ip_src.s_addr; 162 frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; --- 4 unchanged lines hidden (view full) --- 167 168 frag.ipfr_optmsk = fin->fin_fi.fi_optmsk & IPF_OPTCOPY; 169 frag.ipfr_secmsk = fin->fin_fi.fi_secmsk; 170 frag.ipfr_auth = fin->fin_fi.fi_auth; 171 172 /* 173 * first, make sure it isn't already there... 174 */ | 244 frag.ipfr_p = ip->ip_p; 245 idx = ip->ip_p; 246 frag.ipfr_id = ip->ip_id; 247 idx += ip->ip_id; 248 frag.ipfr_tos = ip->ip_tos; 249 frag.ipfr_src.s_addr = ip->ip_src.s_addr; 250 idx += ip->ip_src.s_addr; 251 frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; --- 4 unchanged lines hidden (view full) --- 256 257 frag.ipfr_optmsk = fin->fin_fi.fi_optmsk & IPF_OPTCOPY; 258 frag.ipfr_secmsk = fin->fin_fi.fi_secmsk; 259 frag.ipfr_auth = fin->fin_fi.fi_auth; 260 261 /* 262 * first, make sure it isn't already there... 263 */ |
175 for (fp = &table[idx]; (fra = *fp); fp = &fra->ipfr_next) 176 if (!bcmp((char *)&frag.ipfr_src, (char *)&fra->ipfr_src, | 264 for (fra = table[idx]; (fra != NULL); fra = fra->ipfr_hnext) 265 if (!bcmp((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp, |
177 IPFR_CMPSZ)) { | 266 IPFR_CMPSZ)) { |
178 ATOMIC_INCL(ipfr_stats.ifs_exists); | 267 ipfr_stats.ifs_exists++; |
179 return NULL; 180 } 181 182 /* 183 * allocate some memory, if possible, if not, just record that we 184 * failed to do so. 185 */ 186 KMALLOC(fra, ipfr_t *); 187 if (fra == NULL) { | 268 return NULL; 269 } 270 271 /* 272 * allocate some memory, if possible, if not, just record that we 273 * failed to do so. 274 */ 275 KMALLOC(fra, ipfr_t *); 276 if (fra == NULL) { |
188 ATOMIC_INCL(ipfr_stats.ifs_nomem); | 277 ipfr_stats.ifs_nomem++; |
189 return NULL; 190 } 191 | 278 return NULL; 279 } 280 |
192 if ((fra->ipfr_rule = fin->fin_fr) != NULL) { 193 ATOMIC_INC32(fin->fin_fr->fr_ref); 194 } | 281 if ((fra->ipfr_rule = fin->fin_fr) != NULL) 282 fin->fin_fr->fr_ref++; |
195 | 283 |
196 | |
197 /* 198 * Insert the fragment into the fragment table, copy the struct used 199 * in the search using bcopy rather than reassign each field. 200 * Set the ttl to the default. 201 */ | 284 /* 285 * Insert the fragment into the fragment table, copy the struct used 286 * in the search using bcopy rather than reassign each field. 287 * Set the ttl to the default. 288 */ |
202 if ((fra->ipfr_next = table[idx])) 203 table[idx]->ipfr_prev = fra; 204 fra->ipfr_prev = NULL; | 289 if ((fra->ipfr_hnext = table[idx]) != NULL) 290 table[idx]->ipfr_hprev = &fra->ipfr_hnext; 291 fra->ipfr_hprev = table + idx; |
205 fra->ipfr_data = NULL; 206 table[idx] = fra; | 292 fra->ipfr_data = NULL; 293 table[idx] = fra; |
207 bcopy((char *)&frag.ipfr_src, (char *)&fra->ipfr_src, IPFR_CMPSZ); 208 fra->ipfr_ttl = fr_ipfrttl; | 294 bcopy((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp, IPFR_CMPSZ); 295 fra->ipfr_ttl = fr_ticks + fr_ipfrttl; 296 |
209 /* 210 * Compute the offset of the expected start of the next packet. 211 */ 212 off = ip->ip_off & IP_OFFMASK; | 297 /* 298 * Compute the offset of the expected start of the next packet. 299 */ 300 off = ip->ip_off & IP_OFFMASK; |
213 if (!off) | 301 if (off == 0) |
214 fra->ipfr_seen0 = 1; 215 fra->ipfr_off = off + (fin->fin_dlen >> 3); | 302 fra->ipfr_seen0 = 1; 303 fra->ipfr_off = off + (fin->fin_dlen >> 3); |
216 ATOMIC_INCL(ipfr_stats.ifs_new); 217 ATOMIC_INC32(ipfr_inuse); | 304 fra->ipfr_pass = pass; 305 ipfr_stats.ifs_new++; 306 ipfr_inuse++; |
218 return fra; 219} 220 221 | 307 return fra; 308} 309 310 |
222int ipfr_newfrag(ip, fin) 223ip_t *ip; | 311/* ------------------------------------------------------------------------ */ 312/* Function: fr_newfrag */ 313/* Returns: int - 0 == success, -1 == error */ 314/* Parameters: fin(I) - pointer to packet information */ 315/* */ 316/* Add a new entry to the fragment cache table based on the current packet */ 317/* ------------------------------------------------------------------------ */ 318int fr_newfrag(fin, pass) 319u_32_t pass; |
224fr_info_t *fin; 225{ | 320fr_info_t *fin; 321{ |
226 ipfr_t *ipf; | 322 ipfr_t *fra; |
227 | 323 |
228 if ((ip->ip_v != 4) || (fr_frag_lock)) | 324 if ((fin->fin_v != 4) || (fr_frag_lock != 0)) |
229 return -1; | 325 return -1; |
326 |
|
230 WRITE_ENTER(&ipf_frag); | 327 WRITE_ENTER(&ipf_frag); |
231 ipf = ipfr_new(ip, fin, ipfr_heads); 232 RWLOCK_EXIT(&ipf_frag); 233 if (ipf == NULL) { 234 ATOMIC_INCL(frstats[fin->fin_out].fr_bnfr); 235 return -1; | 328 fra = ipfr_newfrag(fin, pass, ipfr_heads); 329 if (fra != NULL) { 330 *ipfr_tail = fra; 331 fra->ipfr_prev = ipfr_tail; 332 ipfr_tail = &fra->ipfr_next; 333 if (ipfr_list == NULL) 334 ipfr_list = fra; 335 fra->ipfr_next = NULL; |
236 } | 336 } |
237 ATOMIC_INCL(frstats[fin->fin_out].fr_nfr); 238 return 0; | 337 RWLOCK_EXIT(&ipf_frag); 338 return fra ? 0 : -1; |
239} 240 241 | 339} 340 341 |
242int ipfr_nat_newfrag(ip, fin, nat) 243ip_t *ip; | 342/* ------------------------------------------------------------------------ */ 343/* Function: fr_nat_newfrag */ 344/* Returns: int - 0 == success, -1 == error */ 345/* Parameters: fin(I) - pointer to packet information */ 346/* nat(I) - pointer to NAT structure */ 347/* */ 348/* Create a new NAT fragment cache entry based on the current packet and */ 349/* the NAT structure for this "session". */ 350/* ------------------------------------------------------------------------ */ 351int fr_nat_newfrag(fin, pass, nat) |
244fr_info_t *fin; | 352fr_info_t *fin; |
353u_32_t pass; |
|
245nat_t *nat; 246{ | 354nat_t *nat; 355{ |
247 ipfr_t *ipf; 248 int off; | 356 ipfr_t *fra; |
249 | 357 |
250 if ((ip->ip_v != 4) || (fr_frag_lock)) 251 return -1; | 358 if ((fin->fin_v != 4) || (fr_frag_lock != 0)) 359 return 0; |
252 | 360 |
253 off = fin->fin_off; 254 off <<= 3; 255 if ((off + fin->fin_dlen) > 0xffff || (fin->fin_dlen == 0)) 256 return -1; 257 | |
258 WRITE_ENTER(&ipf_natfrag); | 361 WRITE_ENTER(&ipf_natfrag); |
259 ipf = ipfr_new(ip, fin, ipfr_nattab); 260 if (ipf != NULL) { 261 ipf->ipfr_data = nat; 262 nat->nat_data = ipf; | 362 fra = ipfr_newfrag(fin, pass, ipfr_nattab); 363 if (fra != NULL) { 364 fra->ipfr_data = nat; 365 nat->nat_data = fra; 366 *ipfr_nattail = fra; 367 fra->ipfr_prev = ipfr_nattail; 368 ipfr_nattail = &fra->ipfr_next; 369 fra->ipfr_next = NULL; |
263 } 264 RWLOCK_EXIT(&ipf_natfrag); | 370 } 371 RWLOCK_EXIT(&ipf_natfrag); |
265 return ipf ? 0 : -1; | 372 return fra ? 0 : -1; |
266} 267 268 | 373} 374 375 |
269/* 270 * check the fragment cache to see if there is already a record of this packet 271 * with its filter result known. 272 */ 273static ipfr_t *ipfr_lookup(ip, fin, table) 274ip_t *ip; | 376/* ------------------------------------------------------------------------ */ 377/* Function: fr_ipid_newfrag */ 378/* Returns: int - 0 == success, -1 == error */ 379/* Parameters: fin(I) - pointer to packet information */ 380/* ipid(I) - new IP ID for this fragmented packet */ 381/* */ 382/* Create a new fragment cache entry for this packet and store, as a data */ 383/* pointer, the new IP ID value. */ 384/* ------------------------------------------------------------------------ */ 385int fr_ipid_newfrag(fin, ipid) |
275fr_info_t *fin; | 386fr_info_t *fin; |
387u_32_t ipid; 388{ 389 ipfr_t *fra; 390 391 if ((fin->fin_v != 4) || (fr_frag_lock)) 392 return 0; 393 394 WRITE_ENTER(&ipf_ipidfrag); 395 fra = ipfr_newfrag(fin, 0, ipfr_ipidtab); 396 if (fra != NULL) { 397 fra->ipfr_data = (void *)ipid; 398 *ipfr_ipidtail = fra; 399 fra->ipfr_prev = ipfr_ipidtail; 400 ipfr_ipidtail = &fra->ipfr_next; 401 fra->ipfr_next = NULL; 402 } 403 RWLOCK_EXIT(&ipf_ipidfrag); 404 return fra ? 0 : -1; 405} 406 407 408/* ------------------------------------------------------------------------ */ 409/* Function: fr_fraglookup */ 410/* Returns: ipfr_t * - pointer to ipfr_t structure if there's a */ 411/* matching entry in the frag table, else NULL */ 412/* Parameters: fin(I) - pointer to packet information */ 413/* table(I) - pointer to fragment cache table to search */ 414/* */ 415/* Check the fragment cache to see if there is already a record of this */ 416/* packet with its filter result known. */ 417/* ------------------------------------------------------------------------ */ 418static ipfr_t *fr_fraglookup(fin, table) 419fr_info_t *fin; |
|
276ipfr_t *table[]; 277{ | 420ipfr_t *table[]; 421{ |
278 ipfr_t *f, frag; 279 u_int idx; | 422 ipfr_t *f, frag; 423 u_int idx; 424 ip_t *ip; |
280 | 425 |
426 if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG) 427 return NULL; 428 |
|
281 /* 282 * For fragments, we record protocol, packet id, TOS and both IP#'s 283 * (these should all be the same for all fragments of a packet). 284 * 285 * build up a hash value to index the table with. 286 */ | 429 /* 430 * For fragments, we record protocol, packet id, TOS and both IP#'s 431 * (these should all be the same for all fragments of a packet). 432 * 433 * build up a hash value to index the table with. 434 */ |
435 ip = fin->fin_ip; |
|
287 frag.ipfr_p = ip->ip_p; 288 idx = ip->ip_p; 289 frag.ipfr_id = ip->ip_id; 290 idx += ip->ip_id; 291 frag.ipfr_tos = ip->ip_tos; 292 frag.ipfr_src.s_addr = ip->ip_src.s_addr; 293 idx += ip->ip_src.s_addr; 294 frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; --- 4 unchanged lines hidden (view full) --- 299 300 frag.ipfr_optmsk = fin->fin_fi.fi_optmsk & IPF_OPTCOPY; 301 frag.ipfr_secmsk = fin->fin_fi.fi_secmsk; 302 frag.ipfr_auth = fin->fin_fi.fi_auth; 303 304 /* 305 * check the table, careful to only compare the right amount of data 306 */ | 436 frag.ipfr_p = ip->ip_p; 437 idx = ip->ip_p; 438 frag.ipfr_id = ip->ip_id; 439 idx += ip->ip_id; 440 frag.ipfr_tos = ip->ip_tos; 441 frag.ipfr_src.s_addr = ip->ip_src.s_addr; 442 idx += ip->ip_src.s_addr; 443 frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; --- 4 unchanged lines hidden (view full) --- 448 449 frag.ipfr_optmsk = fin->fin_fi.fi_optmsk & IPF_OPTCOPY; 450 frag.ipfr_secmsk = fin->fin_fi.fi_secmsk; 451 frag.ipfr_auth = fin->fin_fi.fi_auth; 452 453 /* 454 * check the table, careful to only compare the right amount of data 455 */ |
307 for (f = table[idx]; f; f = f->ipfr_next) 308 if (!bcmp((char *)&frag.ipfr_src, (char *)&f->ipfr_src, | 456 for (f = table[idx]; f; f = f->ipfr_hnext) 457 if (!bcmp((char *)&frag.ipfr_ifp, (char *)&f->ipfr_ifp, |
309 IPFR_CMPSZ)) { | 458 IPFR_CMPSZ)) { |
310 u_short atoff, off; | 459 u_short off; |
311 | 460 |
312 off = fin->fin_off; | 461 /* 462 * We don't want to let short packets match because 463 * they could be compromising the security of other 464 * rules that want to match on layer 4 fields (and 465 * can't because they have been fragmented off.) 466 * Why do this check here? The counter acts as an 467 * indicator of this kind of attack, whereas if it was 468 * elsewhere, it wouldn't know if other matching 469 * packets had been seen. 470 */ 471 if (fin->fin_flx & FI_SHORT) { 472 ATOMIC_INCL(ipfr_stats.ifs_short); 473 continue; 474 } |
313 314 /* 315 * XXX - We really need to be guarding against the 316 * retransmission of (src,dst,id,offset-range) here 317 * because a fragmented packet is never resent with | 475 476 /* 477 * XXX - We really need to be guarding against the 478 * retransmission of (src,dst,id,offset-range) here 479 * because a fragmented packet is never resent with |
318 * the same IP ID#. | 480 * the same IP ID# (or shouldn't). |
319 */ | 481 */ |
482 off = ip->ip_off & IP_OFFMASK; |
|
320 if (f->ipfr_seen0) { | 483 if (f->ipfr_seen0) { |
321 if (!off || (fin->fin_fl & FI_SHORT)) | 484 if (off == 0) { 485 ATOMIC_INCL(ipfr_stats.ifs_retrans0); |
322 continue; | 486 continue; |
323 } else if (!off) | 487 } 488 } else if (off == 0) |
324 f->ipfr_seen0 = 1; 325 326 if (f != table[idx]) { | 489 f->ipfr_seen0 = 1; 490 491 if (f != table[idx]) { |
492 ipfr_t **fp; 493 |
|
327 /* | 494 /* |
328 * move fragment info. to the top of the list 329 * to speed up searches. | 495 * Move fragment info. to the top of the list 496 * to speed up searches. First, delink... |
330 */ | 497 */ |
331 if ((f->ipfr_prev->ipfr_next = f->ipfr_next)) 332 f->ipfr_next->ipfr_prev = f->ipfr_prev; 333 f->ipfr_next = table[idx]; 334 table[idx]->ipfr_prev = f; 335 f->ipfr_prev = NULL; | 498 fp = f->ipfr_hprev; 499 (*fp) = f->ipfr_hnext; 500 if (f->ipfr_hnext != NULL) 501 f->ipfr_hnext->ipfr_hprev = fp; 502 /* 503 * Then put back at the top of the chain. 504 */ 505 f->ipfr_hnext = table[idx]; 506 table[idx]->ipfr_hprev = &f->ipfr_hnext; 507 f->ipfr_hprev = table + idx; |
336 table[idx] = f; 337 } | 508 table[idx] = f; 509 } |
338 atoff = off + (fin->fin_dlen >> 3); | 510 |
339 /* 340 * If we've follwed the fragments, and this is the 341 * last (in order), shrink expiration time. 342 */ 343 if (off == f->ipfr_off) { 344 if (!(ip->ip_off & IP_MF)) | 511 /* 512 * If we've follwed the fragments, and this is the 513 * last (in order), shrink expiration time. 514 */ 515 if (off == f->ipfr_off) { 516 if (!(ip->ip_off & IP_MF)) |
345 f->ipfr_ttl = 1; 346 else 347 f->ipfr_off = atoff; 348 } | 517 f->ipfr_ttl = fr_ticks + 1; 518 f->ipfr_off = (fin->fin_dlen >> 3) + off; 519 } else if (f->ipfr_pass & FR_FRSTRICT) 520 continue; |
349 ATOMIC_INCL(ipfr_stats.ifs_hits); 350 return f; 351 } 352 return NULL; 353} 354 355 | 521 ATOMIC_INCL(ipfr_stats.ifs_hits); 522 return f; 523 } 524 return NULL; 525} 526 527 |
356/* 357 * functional interface for NAT lookups of the NAT fragment cache 358 */ 359nat_t *ipfr_nat_knownfrag(ip, fin) 360ip_t *ip; | 528/* ------------------------------------------------------------------------ */ 529/* Function: fr_nat_knownfrag */ 530/* Returns: nat_t* - pointer to 'parent' NAT structure if frag table */ 531/* match found, else NULL */ 532/* Parameters: fin(I) - pointer to packet information */ 533/* */ 534/* Functional interface for NAT lookups of the NAT fragment cache */ 535/* ------------------------------------------------------------------------ */ 536nat_t *fr_nat_knownfrag(fin) |
361fr_info_t *fin; 362{ | 537fr_info_t *fin; 538{ |
363 ipfr_t *ipf; 364 nat_t *nat; 365 int off; | 539 nat_t *nat; 540 ipfr_t *ipf; |
366 | 541 |
367 if ((fin->fin_v != 4) || (fr_frag_lock)) | 542 if ((fin->fin_v != 4) || (fr_frag_lock) || !ipfr_natlist) |
368 return NULL; | 543 return NULL; |
369 370 off = fin->fin_off; 371 off <<= 3; 372 if ((off + fin->fin_dlen) > 0xffff || (fin->fin_dlen == 0)) 373 return NULL; 374 | |
375 READ_ENTER(&ipf_natfrag); | 544 READ_ENTER(&ipf_natfrag); |
376 ipf = ipfr_lookup(ip, fin, ipfr_nattab); | 545 ipf = fr_fraglookup(fin, ipfr_nattab); |
377 if (ipf != NULL) { 378 nat = ipf->ipfr_data; 379 /* 380 * This is the last fragment for this packet. 381 */ | 546 if (ipf != NULL) { 547 nat = ipf->ipfr_data; 548 /* 549 * This is the last fragment for this packet. 550 */ |
382 if ((ipf->ipfr_ttl == 1) && (nat != NULL)) { | 551 if ((ipf->ipfr_ttl == fr_ticks + 1) && (nat != NULL)) { |
383 nat->nat_data = NULL; 384 ipf->ipfr_data = NULL; 385 } 386 } else 387 nat = NULL; 388 RWLOCK_EXIT(&ipf_natfrag); 389 return nat; 390} 391 392 | 552 nat->nat_data = NULL; 553 ipf->ipfr_data = NULL; 554 } 555 } else 556 nat = NULL; 557 RWLOCK_EXIT(&ipf_natfrag); 558 return nat; 559} 560 561 |
393/* 394 * functional interface for normal lookups of the fragment cache 395 */ 396frentry_t *ipfr_knownfrag(ip, fin) 397ip_t *ip; | 562/* ------------------------------------------------------------------------ */ 563/* Function: fr_ipid_knownfrag */ 564/* Returns: u_32_t - IPv4 ID for this packet if match found, else */ 565/* return 0xfffffff to indicate no match. */ 566/* Parameters: fin(I) - pointer to packet information */ 567/* */ 568/* Functional interface for IP ID lookups of the IP ID fragment cache */ 569/* ------------------------------------------------------------------------ */ 570u_32_t fr_ipid_knownfrag(fin) |
398fr_info_t *fin; 399{ | 571fr_info_t *fin; 572{ |
400 frentry_t *fr; 401 ipfr_t *fra; 402 int off; | 573 ipfr_t *ipf; 574 u_32_t id; |
403 | 575 |
404 if ((fin->fin_v != 4) || (fr_frag_lock)) 405 return NULL; | 576 if ((fin->fin_v != 4) || (fr_frag_lock) || !ipfr_ipidlist) 577 return 0xffffffff; |
406 | 578 |
407 off = fin->fin_off; 408 off <<= 3; 409 if ((off + fin->fin_dlen) > 0xffff || (fin->fin_dlen == 0)) | 579 READ_ENTER(&ipf_ipidfrag); 580 ipf = fr_fraglookup(fin, ipfr_ipidtab); 581 if (ipf != NULL) 582 id = (u_32_t)ipf->ipfr_data; 583 else 584 id = 0xffffffff; 585 RWLOCK_EXIT(&ipf_ipidfrag); 586 return id; 587} 588 589 590/* ------------------------------------------------------------------------ */ 591/* Function: fr_knownfrag */ 592/* Returns: frentry_t* - pointer to filter rule if a match is found in */ 593/* the frag cache table, else NULL. */ 594/* Parameters: fin(I) - pointer to packet information */ 595/* passp(O) - pointer to where to store rule flags resturned */ 596/* */ 597/* Functional interface for normal lookups of the fragment cache. If a */ 598/* match is found, return the rule pointer and flags from the rule, except */ 599/* that if FR_LOGFIRST is set, reset FR_LOG. */ 600/* ------------------------------------------------------------------------ */ 601frentry_t *fr_knownfrag(fin, passp) 602fr_info_t *fin; 603u_32_t *passp; 604{ 605 frentry_t *fr = NULL; 606 ipfr_t *fra; 607 u_32_t pass; 608 609 if ((fin->fin_v != 4) || (fr_frag_lock) || (ipfr_list == NULL)) |
410 return NULL; 411 412 READ_ENTER(&ipf_frag); | 610 return NULL; 611 612 READ_ENTER(&ipf_frag); |
413 fra = ipfr_lookup(ip, fin, ipfr_heads); 414 if (fra != NULL) | 613 fra = fr_fraglookup(fin, ipfr_heads); 614 if (fra != NULL) { |
415 fr = fra->ipfr_rule; | 615 fr = fra->ipfr_rule; |
416 else 417 fr = NULL; | 616 fin->fin_fr = fr; 617 if (fr != NULL) { 618 pass = fr->fr_flags; 619 if ((pass & FR_LOGFIRST) != 0) 620 pass &= ~(FR_LOGFIRST|FR_LOG); 621 *passp = pass; 622 } 623 } |
418 RWLOCK_EXIT(&ipf_frag); 419 return fr; 420} 421 422 | 624 RWLOCK_EXIT(&ipf_frag); 625 return fr; 626} 627 628 |
423/* 424 * forget any references to this external object. 425 */ 426void ipfr_forget(ptr) | 629/* ------------------------------------------------------------------------ */ 630/* Function: fr_forget */ 631/* Returns: Nil */ 632/* Parameters: ptr(I) - pointer to data structure */ 633/* */ 634/* Search through all of the fragment cache entries and wherever a pointer */ 635/* is found to match ptr, reset it to NULL. */ 636/* ------------------------------------------------------------------------ */ 637void fr_forget(ptr) |
427void *ptr; 428{ 429 ipfr_t *fr; | 638void *ptr; 639{ 640 ipfr_t *fr; |
430 int idx; | |
431 432 WRITE_ENTER(&ipf_frag); | 641 642 WRITE_ENTER(&ipf_frag); |
433 for (idx = IPFT_SIZE - 1; idx >= 0; idx--) 434 for (fr = ipfr_heads[idx]; fr; fr = fr->ipfr_next) 435 if (fr->ipfr_data == ptr) 436 fr->ipfr_data = NULL; 437 | 643 for (fr = ipfr_list; fr; fr = fr->ipfr_next) 644 if (fr->ipfr_data == ptr) 645 fr->ipfr_data = NULL; |
438 RWLOCK_EXIT(&ipf_frag); 439} 440 441 | 646 RWLOCK_EXIT(&ipf_frag); 647} 648 649 |
442/* 443 * forget any references to this external object. 444 */ 445void ipfr_forgetnat(nat) 446void *nat; | 650/* ------------------------------------------------------------------------ */ 651/* Function: fr_forgetnat */ 652/* Returns: Nil */ 653/* Parameters: ptr(I) - pointer to data structure */ 654/* */ 655/* Search through all of the fragment cache entries for NAT and wherever a */ 656/* pointer is found to match ptr, reset it to NULL. */ 657/* ------------------------------------------------------------------------ */ 658void fr_forgetnat(ptr) 659void *ptr; |
447{ 448 ipfr_t *fr; | 660{ 661 ipfr_t *fr; |
449 int idx; | |
450 451 WRITE_ENTER(&ipf_natfrag); | 662 663 WRITE_ENTER(&ipf_natfrag); |
452 for (idx = IPFT_SIZE - 1; idx >= 0; idx--) 453 for (fr = ipfr_nattab[idx]; fr; fr = fr->ipfr_next) 454 if (fr->ipfr_data == nat) 455 fr->ipfr_data = NULL; 456 | 664 for (fr = ipfr_natlist; fr; fr = fr->ipfr_next) 665 if (fr->ipfr_data == ptr) 666 fr->ipfr_data = NULL; |
457 RWLOCK_EXIT(&ipf_natfrag); 458} 459 460 | 667 RWLOCK_EXIT(&ipf_natfrag); 668} 669 670 |
461static void ipfr_delete(fra) 462ipfr_t *fra; | 671/* ------------------------------------------------------------------------ */ 672/* Function: fr_fragdelete */ 673/* Returns: Nil */ 674/* Parameters: fra(I) - pointer to fragment structure to delete */ 675/* tail(IO) - pointer to the pointer to the tail of the frag */ 676/* list */ 677/* */ 678/* Remove a fragment cache table entry from the table & list. Also free */ 679/* the filter rule it is associated with it if it is no longer used as a */ 680/* result of decreasing the reference count. */ 681/* ------------------------------------------------------------------------ */ 682static void fr_fragdelete(fra, tail) 683ipfr_t *fra, ***tail; |
463{ 464 frentry_t *fr; 465 466 fr = fra->ipfr_rule; | 684{ 685 frentry_t *fr; 686 687 fr = fra->ipfr_rule; |
467 if (fr != NULL) { 468 ATOMIC_DEC32(fr->fr_ref); 469 if (fr->fr_ref == 0) 470 KFREE(fr); 471 } 472 if (fra->ipfr_prev) 473 fra->ipfr_prev->ipfr_next = fra->ipfr_next; | 688 if (fr != NULL) 689 (void)fr_derefrule(&fr); 690 |
474 if (fra->ipfr_next) 475 fra->ipfr_next->ipfr_prev = fra->ipfr_prev; | 691 if (fra->ipfr_next) 692 fra->ipfr_next->ipfr_prev = fra->ipfr_prev; |
693 *fra->ipfr_prev = fra->ipfr_next; 694 if (*tail == &fra->ipfr_next) 695 *tail = fra->ipfr_prev; 696 697 if (fra->ipfr_hnext) 698 fra->ipfr_hnext->ipfr_hprev = fra->ipfr_hprev; 699 *fra->ipfr_hprev = fra->ipfr_hnext; |
|
476 KFREE(fra); 477} 478 479 | 700 KFREE(fra); 701} 702 703 |
480/* 481 * Free memory in use by fragment state info. kept. 482 */ 483void ipfr_unload() | 704/* ------------------------------------------------------------------------ */ 705/* Function: fr_fragclear */ 706/* Returns: Nil */ 707/* Parameters: Nil */ 708/* */ 709/* Free memory in use by fragment state information kept. Do the normal */ 710/* fragment state stuff first and then the NAT-fragment table. */ 711/* ------------------------------------------------------------------------ */ 712void fr_fragclear() |
484{ | 713{ |
485 ipfr_t **fp, *fra; | 714 ipfr_t *fra; |
486 nat_t *nat; | 715 nat_t *nat; |
487 int idx; | |
488 489 WRITE_ENTER(&ipf_frag); | 716 717 WRITE_ENTER(&ipf_frag); |
490 for (idx = IPFT_SIZE - 1; idx >= 0; idx--) 491 for (fp = &ipfr_heads[idx]; (fra = *fp); ) { 492 *fp = fra->ipfr_next; 493 ipfr_delete(fra); 494 } | 718 while ((fra = ipfr_list) != NULL) 719 fr_fragdelete(fra, &ipfr_tail); 720 ipfr_tail = &ipfr_list; |
495 RWLOCK_EXIT(&ipf_frag); 496 497 WRITE_ENTER(&ipf_nat); 498 WRITE_ENTER(&ipf_natfrag); | 721 RWLOCK_EXIT(&ipf_frag); 722 723 WRITE_ENTER(&ipf_nat); 724 WRITE_ENTER(&ipf_natfrag); |
499 for (idx = IPFT_SIZE - 1; idx >= 0; idx--) 500 for (fp = &ipfr_nattab[idx]; (fra = *fp); ) { 501 *fp = fra->ipfr_next; 502 nat = fra->ipfr_data; 503 if (nat != NULL) { 504 if (nat->nat_data == fra) 505 nat->nat_data = NULL; 506 } 507 ipfr_delete(fra); | 725 while ((fra = ipfr_natlist) != NULL) { 726 nat = fra->ipfr_data; 727 if (nat != NULL) { 728 if (nat->nat_data == fra) 729 nat->nat_data = NULL; |
508 } | 730 } |
731 fr_fragdelete(fra, &ipfr_nattail); 732 } 733 ipfr_nattail = &ipfr_natlist; |
|
509 RWLOCK_EXIT(&ipf_natfrag); 510 RWLOCK_EXIT(&ipf_nat); 511} 512 513 | 734 RWLOCK_EXIT(&ipf_natfrag); 735 RWLOCK_EXIT(&ipf_nat); 736} 737 738 |
514void ipfr_fragexpire() | 739/* ------------------------------------------------------------------------ */ 740/* Function: fr_fragexpire */ 741/* Returns: Nil */ 742/* Parameters: Nil */ 743/* */ 744/* Expire entries in the fragment cache table that have been there too long */ 745/* ------------------------------------------------------------------------ */ 746void fr_fragexpire() |
515{ 516 ipfr_t **fp, *fra; 517 nat_t *nat; | 747{ 748 ipfr_t **fp, *fra; 749 nat_t *nat; |
518 int idx; 519#if defined(_KERNEL) 520# if !SOLARIS | 750#if defined(USE_SPL) && defined(_KERNEL) |
521 int s; | 751 int s; |
522# endif | |
523#endif 524 525 if (fr_frag_lock) 526 return; 527 528 SPL_NET(s); 529 WRITE_ENTER(&ipf_frag); | 752#endif 753 754 if (fr_frag_lock) 755 return; 756 757 SPL_NET(s); 758 WRITE_ENTER(&ipf_frag); |
530 | |
531 /* 532 * Go through the entire table, looking for entries to expire, | 759 /* 760 * Go through the entire table, looking for entries to expire, |
533 * decreasing the ttl by one for each entry. If it reaches 0, 534 * remove it from the chain and free it. | 761 * which is indicated by the ttl being less than or equal to fr_ticks. |
535 */ | 762 */ |
536 for (idx = IPFT_SIZE - 1; idx >= 0; idx--) 537 for (fp = &ipfr_heads[idx]; (fra = *fp); ) { 538 --fra->ipfr_ttl; 539 if (fra->ipfr_ttl == 0) { 540 *fp = fra->ipfr_next; 541 ipfr_delete(fra); 542 ATOMIC_INCL(ipfr_stats.ifs_expire); 543 ATOMIC_DEC32(ipfr_inuse); 544 } else 545 fp = &fra->ipfr_next; 546 } | 763 for (fp = &ipfr_list; ((fra = *fp) != NULL); ) { 764 if (fra->ipfr_ttl > fr_ticks) 765 break; 766 fr_fragdelete(fra, &ipfr_tail); 767 ipfr_stats.ifs_expire++; 768 ipfr_inuse--; 769 } |
547 RWLOCK_EXIT(&ipf_frag); 548 | 770 RWLOCK_EXIT(&ipf_frag); 771 |
772 WRITE_ENTER(&ipf_ipidfrag); 773 for (fp = &ipfr_ipidlist; ((fra = *fp) != NULL); ) { 774 if (fra->ipfr_ttl > fr_ticks) 775 break; 776 fr_fragdelete(fra, &ipfr_ipidtail); 777 ipfr_stats.ifs_expire++; 778 ipfr_inuse--; 779 } 780 RWLOCK_EXIT(&ipf_ipidfrag); 781 |
|
549 /* 550 * Same again for the NAT table, except that if the structure also 551 * still points to a NAT structure, and the NAT structure points back 552 * at the one to be free'd, NULL the reference from the NAT struct. 553 * NOTE: We need to grab both mutex's early, and in this order so as 554 * to prevent a deadlock if both try to expire at the same time. 555 */ 556 WRITE_ENTER(&ipf_nat); 557 WRITE_ENTER(&ipf_natfrag); | 782 /* 783 * Same again for the NAT table, except that if the structure also 784 * still points to a NAT structure, and the NAT structure points back 785 * at the one to be free'd, NULL the reference from the NAT struct. 786 * NOTE: We need to grab both mutex's early, and in this order so as 787 * to prevent a deadlock if both try to expire at the same time. 788 */ 789 WRITE_ENTER(&ipf_nat); 790 WRITE_ENTER(&ipf_natfrag); |
558 for (idx = IPFT_SIZE - 1; idx >= 0; idx--) 559 for (fp = &ipfr_nattab[idx]; (fra = *fp); ) { 560 --fra->ipfr_ttl; 561 if (fra->ipfr_ttl == 0) { 562 ATOMIC_INCL(ipfr_stats.ifs_expire); 563 ATOMIC_DEC32(ipfr_inuse); 564 nat = fra->ipfr_data; 565 if (nat != NULL) { 566 if (nat->nat_data == fra) 567 nat->nat_data = NULL; 568 } 569 *fp = fra->ipfr_next; 570 ipfr_delete(fra); 571 } else 572 fp = &fra->ipfr_next; | 791 for (fp = &ipfr_natlist; ((fra = *fp) != NULL); ) { 792 if (fra->ipfr_ttl > fr_ticks) 793 break; 794 nat = fra->ipfr_data; 795 if (nat != NULL) { 796 if (nat->nat_data == fra) 797 nat->nat_data = NULL; |
573 } | 798 } |
799 fr_fragdelete(fra, &ipfr_nattail); 800 ipfr_stats.ifs_expire++; 801 ipfr_inuse--; 802 } |
|
574 RWLOCK_EXIT(&ipf_natfrag); 575 RWLOCK_EXIT(&ipf_nat); 576 SPL_X(s); 577} 578 579 | 803 RWLOCK_EXIT(&ipf_natfrag); 804 RWLOCK_EXIT(&ipf_nat); 805 SPL_X(s); 806} 807 808 |
580/* 581 * Slowly expire held state for fragments. Timeouts are set * in expectation 582 * of this being called twice per second. 583 */ 584#ifdef _KERNEL 585# if (BSD >= 199306) || SOLARIS || defined(__sgi) 586# if defined(SOLARIS2) && (SOLARIS2 < 7) 587void ipfr_slowtimer() 588# else 589void ipfr_slowtimer __P((void *ptr)) 590# endif | 809/* ------------------------------------------------------------------------ */ 810/* Function: fr_slowtimer */ 811/* Returns: Nil */ 812/* Parameters: Nil */ 813/* */ 814/* Slowly expire held state for fragments. Timeouts are set * in */ 815/* expectation of this being called twice per second. */ 816/* ------------------------------------------------------------------------ */ 817#if !defined(_KERNEL) || (!SOLARIS && !defined(__hpux) && !defined(__sgi) && \ 818 !defined(__osf__)) 819# if defined(_KERNEL) && ((BSD >= 199103) || defined(__sgi)) 820void fr_slowtimer __P((void *ptr)) |
591# else | 821# else |
592int ipfr_slowtimer() | 822int fr_slowtimer() |
593# endif | 823# endif |
594#else 595void ipfr_slowtimer() 596#endif | |
597{ | 824{ |
598#if defined(_KERNEL) && SOLARIS 599 extern int fr_running; | 825 READ_ENTER(&ipf_global); |
600 | 826 |
601 if (fr_running <= 0) 602 return; 603 READ_ENTER(&ipf_solaris); 604#endif 605 606#if defined(__sgi) && defined(_KERNEL) 607 ipfilter_sgi_intfsync(); 608#endif 609 610 ipfr_fragexpire(); | 827 fr_fragexpire(); |
611 fr_timeoutstate(); | 828 fr_timeoutstate(); |
612 ip_natexpire(); | 829 fr_natexpire(); |
613 fr_authexpire(); | 830 fr_authexpire(); |
614#if defined(_KERNEL) 615# if SOLARIS 616 ipfr_timer_id = timeout(ipfr_slowtimer, NULL, drv_usectohz(500000)); 617 RWLOCK_EXIT(&ipf_solaris); 618# else | 831 fr_ticks++; 832 if (fr_running <= 0) 833 goto done; 834# ifdef _KERNEL |
619# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104240000) | 835# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104240000) |
620 callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL); | 836 callout_reset(&fr_slowtimer_ch, hz / 2, fr_slowtimer, NULL); |
621# else | 837# else |
622# if (__FreeBSD_version >= 300000) 623 ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2); | 838# if defined(__OpenBSD__) 839 timeout_add(&fr_slowtimer_ch, hz/2); |
624# else | 840# else |
625# if defined(__OpenBSD__) 626 timeout_add(&ipfr_slowtimer_ch, hz/2); | 841# if (__FreeBSD_version >= 300000) 842 fr_slowtimer_ch = timeout(fr_slowtimer, NULL, hz/2); |
627# else | 843# else |
628 timeout(ipfr_slowtimer, NULL, hz/2); 629# endif 630# endif 631# if (BSD < 199306) && !defined(__sgi) 632 return 0; 633# endif /* FreeBSD */ | 844# ifdef linux 845 ; 846# else 847 timeout(fr_slowtimer, NULL, hz/2); 848# endif 849# endif /* FreeBSD */ 850# endif /* OpenBSD */ |
634# endif /* NetBSD */ | 851# endif /* NetBSD */ |
635# endif /* SOLARIS */ 636#endif /* defined(_KERNEL) */ | 852# endif 853done: 854 RWLOCK_EXIT(&ipf_global); 855# if (BSD < 199103) || !defined(_KERNEL) 856 return 0; 857# endif |
637} | 858} |
859#endif /* !SOLARIS && !defined(__hpux) && !defined(__sgi) */ |
|