xref: /titanic_51/usr/src/uts/common/inet/ipf/ip_state.c (revision fc3af78a71855c71878866a294572d00e6720533)
1 /*
2  * Copyright (C) 1995-2003 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
7  * Use is subject to license terms.
8  */
9 
10 #if defined(KERNEL) || defined(_KERNEL)
11 # undef KERNEL
12 # undef _KERNEL
13 # define        KERNEL	1
14 # define        _KERNEL	1
15 #endif
16 #include <sys/errno.h>
17 #include <sys/types.h>
18 #include <sys/param.h>
19 #include <sys/file.h>
20 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
21     defined(_KERNEL)
22 # include "opt_ipfilter_log.h"
23 #endif
24 #if defined(_KERNEL) && defined(__FreeBSD_version) && \
25     (__FreeBSD_version >= 400000) && !defined(KLD_MODULE)
26 #include "opt_inet6.h"
27 #endif
28 #if !defined(_KERNEL) && !defined(__KERNEL__)
29 # include <stdio.h>
30 # include <stdlib.h>
31 # include <string.h>
32 # define _KERNEL
33 # ifdef __OpenBSD__
34 struct file;
35 # endif
36 # include <sys/uio.h>
37 # undef _KERNEL
38 #endif
39 #if defined(_KERNEL) && (__FreeBSD_version >= 220000)
40 # include <sys/filio.h>
41 # include <sys/fcntl.h>
42 # if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM)
43 #  include "opt_ipfilter.h"
44 # endif
45 #else
46 # include <sys/ioctl.h>
47 #endif
48 #include <sys/time.h>
49 #if !defined(linux)
50 # include <sys/protosw.h>
51 #endif
52 #include <sys/socket.h>
53 #if defined(_KERNEL)
54 # include <sys/systm.h>
55 # if !defined(__SVR4) && !defined(__svr4__)
56 #  include <sys/mbuf.h>
57 # endif
58 #endif
59 #if defined(__SVR4) || defined(__svr4__)
60 # include <sys/filio.h>
61 # include <sys/byteorder.h>
62 # ifdef _KERNEL
63 #  include <sys/dditypes.h>
64 # endif
65 # include <sys/stream.h>
66 # include <sys/kmem.h>
67 #endif
68 
69 #include <net/if.h>
70 #ifdef sun
71 # include <net/af.h>
72 #endif
73 #include <net/route.h>
74 #include <netinet/in.h>
75 #include <netinet/in_systm.h>
76 #include <netinet/ip.h>
77 #include <netinet/tcp.h>
78 #if !defined(linux)
79 # include <netinet/ip_var.h>
80 #endif
81 #if !defined(__hpux) && !defined(linux)
82 # include <netinet/tcp_fsm.h>
83 #endif
84 #include <netinet/udp.h>
85 #include <netinet/ip_icmp.h>
86 #include "netinet/ip_compat.h"
87 #include <netinet/tcpip.h>
88 #include "netinet/ip_fil.h"
89 #include "netinet/ip_nat.h"
90 #include "netinet/ip_frag.h"
91 #include "netinet/ip_state.h"
92 #include "netinet/ip_proxy.h"
93 #include "netinet/ipf_stack.h"
94 #ifdef	IPFILTER_SYNC
95 #include "netinet/ip_sync.h"
96 #endif
97 #ifdef	IPFILTER_SCAN
98 #include "netinet/ip_scan.h"
99 #endif
100 #ifdef	USE_INET6
101 #include <netinet/icmp6.h>
102 #endif
103 #if (__FreeBSD_version >= 300000)
104 # include <sys/malloc.h>
105 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
106 #  include <sys/libkern.h>
107 #  include <sys/systm.h>
108 # endif
109 #endif
110 /* END OF INCLUDES */
111 
112 
113 #if !defined(lint)
114 static const char sccsid[] = "@(#)ip_state.c	1.8 6/5/96 (C) 1993-2000 Darren Reed";
115 static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.186.2.36 2005/08/11 19:58:03 darrenr Exp $";
116 #endif
117 
118 #ifdef	USE_INET6
119 static ipstate_t *fr_checkicmp6matchingstate __P((fr_info_t *));
120 #endif
121 static ipstate_t *fr_matchsrcdst __P((fr_info_t *, ipstate_t *, i6addr_t *,
122 				      i6addr_t *, tcphdr_t *, u_32_t));
123 static ipstate_t *fr_checkicmpmatchingstate __P((fr_info_t *));
124 static int fr_state_flush __P((int, int, ipf_stack_t *));
125 static ips_stat_t *fr_statetstats __P((ipf_stack_t *));
126 static int fr_state_remove __P((caddr_t, ipf_stack_t *));
127 static void fr_ipsmove __P((ipstate_t *, u_int, ipf_stack_t *));
128 static int fr_tcpstate __P((fr_info_t *, tcphdr_t *, ipstate_t *));
129 static int fr_tcpoptions __P((fr_info_t *, tcphdr_t *, tcpdata_t *));
130 static ipstate_t *fr_stclone __P((fr_info_t *, tcphdr_t *, ipstate_t *));
131 static void fr_fixinisn __P((fr_info_t *, ipstate_t *));
132 static void fr_fixoutisn __P((fr_info_t *, ipstate_t *));
133 static void fr_checknewisn __P((fr_info_t *, ipstate_t *));
134 static int fr_stateiter __P((ipftoken_t *, ipfgeniter_t *, ipf_stack_t *));
135 
136 int fr_stputent __P((caddr_t, ipf_stack_t *));
137 int fr_stgetent __P((caddr_t, ipf_stack_t *));
138 
139 #define	ONE_DAY		IPF_TTLVAL(1 * 86400)	/* 1 day */
140 #define	FIVE_DAYS	(5 * ONE_DAY)
141 #define	DOUBLE_HASH(x, ifs)	\
142     (((x) + ifs->ifs_ips_seed[(x) % ifs->ifs_fr_statesize]) % ifs->ifs_fr_statesize)
143 
144 
145 /* ------------------------------------------------------------------------ */
146 /* Function:    fr_stateinit                                                */
147 /* Returns:     int - 0 == success, -1 == failure                           */
148 /* Parameters:  ifs - ipf stack instance                                    */
149 /*                                                                          */
150 /* Initialise all the global variables used within the state code.          */
151 /* This action also includes initiailising locks.                           */
152 /* ------------------------------------------------------------------------ */
153 int fr_stateinit(ifs)
154 ipf_stack_t *ifs;
155 {
156 #if defined(NEED_LOCAL_RAND) || !defined(_KERNEL)
157 	struct timeval tv;
158 #endif
159 	int i;
160 
161 	KMALLOCS(ifs->ifs_ips_table, ipstate_t **,
162 		 ifs->ifs_fr_statesize * sizeof(ipstate_t *));
163 	if (ifs->ifs_ips_table == NULL)
164 		return -1;
165 	bzero((char *)ifs->ifs_ips_table,
166 	      ifs->ifs_fr_statesize * sizeof(ipstate_t *));
167 
168 	KMALLOCS(ifs->ifs_ips_seed, u_long *,
169 		 ifs->ifs_fr_statesize * sizeof(*ifs->ifs_ips_seed));
170 	if (ifs->ifs_ips_seed == NULL)
171 		return -2;
172 #if defined(NEED_LOCAL_RAND) || !defined(_KERNEL)
173 	tv.tv_sec = 0;
174 	GETKTIME(&tv);
175 #endif
176 	for (i = 0; i < ifs->ifs_fr_statesize; i++) {
177 		/*
178 		 * XXX - ips_seed[X] should be a random number of sorts.
179 		 */
180 #if !defined(NEED_LOCAL_RAND) && defined(_KERNEL)
181 		ifs->ifs_ips_seed[i] = ipf_random();
182 #else
183 		ifs->ifs_ips_seed[i] = ((u_long)ifs->ifs_ips_seed + i) *
184 		    ifs->ifs_fr_statesize;
185 		ifs->ifs_ips_seed[i] += tv.tv_sec;
186 		ifs->ifs_ips_seed[i] *= (u_long)ifs->ifs_ips_seed;
187 		ifs->ifs_ips_seed[i] ^= 0x5a5aa5a5;
188 		ifs->ifs_ips_seed[i] *= ifs->ifs_fr_statemax;
189 #endif
190 	}
191 
192 	/* fill icmp reply type table */
193 	for (i = 0; i <= ICMP_MAXTYPE; i++)
194 		icmpreplytype4[i] = -1;
195 	icmpreplytype4[ICMP_ECHO] = ICMP_ECHOREPLY;
196 	icmpreplytype4[ICMP_TSTAMP] = ICMP_TSTAMPREPLY;
197 	icmpreplytype4[ICMP_IREQ] = ICMP_IREQREPLY;
198 	icmpreplytype4[ICMP_MASKREQ] = ICMP_MASKREPLY;
199 #ifdef	USE_INET6
200 	/* fill icmp reply type table */
201 	for (i = 0; i <= ICMP6_MAXTYPE; i++)
202 		icmpreplytype6[i] = -1;
203 	icmpreplytype6[ICMP6_ECHO_REQUEST] = ICMP6_ECHO_REPLY;
204 	icmpreplytype6[ICMP6_MEMBERSHIP_QUERY] = ICMP6_MEMBERSHIP_REPORT;
205 	icmpreplytype6[ICMP6_NI_QUERY] = ICMP6_NI_REPLY;
206 	icmpreplytype6[ND_ROUTER_SOLICIT] = ND_ROUTER_ADVERT;
207 	icmpreplytype6[ND_NEIGHBOR_SOLICIT] = ND_NEIGHBOR_ADVERT;
208 #endif
209 
210 	KMALLOCS(ifs->ifs_ips_stats.iss_bucketlen, u_long *,
211 		 ifs->ifs_fr_statesize * sizeof(u_long));
212 	if (ifs->ifs_ips_stats.iss_bucketlen == NULL)
213 		return -1;
214 	bzero((char *)ifs->ifs_ips_stats.iss_bucketlen,
215 	      ifs->ifs_fr_statesize * sizeof(u_long));
216 
217 	if (ifs->ifs_fr_state_maxbucket == 0) {
218 		for (i = ifs->ifs_fr_statesize; i > 0; i >>= 1)
219 			ifs->ifs_fr_state_maxbucket++;
220 		ifs->ifs_fr_state_maxbucket *= 2;
221 	}
222 
223 	fr_sttab_init(ifs->ifs_ips_tqtqb, ifs);
224 	ifs->ifs_ips_tqtqb[IPF_TCP_NSTATES - 1].ifq_next = &ifs->ifs_ips_udptq;
225 	ifs->ifs_ips_udptq.ifq_ttl = (u_long)ifs->ifs_fr_udptimeout;
226 	ifs->ifs_ips_udptq.ifq_ref = 1;
227 	ifs->ifs_ips_udptq.ifq_head = NULL;
228 	ifs->ifs_ips_udptq.ifq_tail = &ifs->ifs_ips_udptq.ifq_head;
229 	MUTEX_INIT(&ifs->ifs_ips_udptq.ifq_lock, "ipftq udp tab");
230 	ifs->ifs_ips_udptq.ifq_next = &ifs->ifs_ips_udpacktq;
231 	ifs->ifs_ips_udpacktq.ifq_ttl = (u_long)ifs->ifs_fr_udpacktimeout;
232 	ifs->ifs_ips_udpacktq.ifq_ref = 1;
233 	ifs->ifs_ips_udpacktq.ifq_head = NULL;
234 	ifs->ifs_ips_udpacktq.ifq_tail = &ifs->ifs_ips_udpacktq.ifq_head;
235 	MUTEX_INIT(&ifs->ifs_ips_udpacktq.ifq_lock, "ipftq udpack tab");
236 	ifs->ifs_ips_udpacktq.ifq_next = &ifs->ifs_ips_icmptq;
237 	ifs->ifs_ips_icmptq.ifq_ttl = (u_long)ifs->ifs_fr_icmptimeout;
238 	ifs->ifs_ips_icmptq.ifq_ref = 1;
239 	ifs->ifs_ips_icmptq.ifq_head = NULL;
240 	ifs->ifs_ips_icmptq.ifq_tail = &ifs->ifs_ips_icmptq.ifq_head;
241 	MUTEX_INIT(&ifs->ifs_ips_icmptq.ifq_lock, "ipftq icmp tab");
242 	ifs->ifs_ips_icmptq.ifq_next = &ifs->ifs_ips_icmpacktq;
243 	ifs->ifs_ips_icmpacktq.ifq_ttl = (u_long)ifs->ifs_fr_icmpacktimeout;
244 	ifs->ifs_ips_icmpacktq.ifq_ref = 1;
245 	ifs->ifs_ips_icmpacktq.ifq_head = NULL;
246 	ifs->ifs_ips_icmpacktq.ifq_tail = &ifs->ifs_ips_icmpacktq.ifq_head;
247 	MUTEX_INIT(&ifs->ifs_ips_icmpacktq.ifq_lock, "ipftq icmpack tab");
248 	ifs->ifs_ips_icmpacktq.ifq_next = &ifs->ifs_ips_iptq;
249 	ifs->ifs_ips_iptq.ifq_ttl = (u_long)ifs->ifs_fr_iptimeout;
250 	ifs->ifs_ips_iptq.ifq_ref = 1;
251 	ifs->ifs_ips_iptq.ifq_head = NULL;
252 	ifs->ifs_ips_iptq.ifq_tail = &ifs->ifs_ips_iptq.ifq_head;
253 	MUTEX_INIT(&ifs->ifs_ips_iptq.ifq_lock, "ipftq ip tab");
254 	ifs->ifs_ips_iptq.ifq_next = &ifs->ifs_ips_deletetq;
255 	/* entry's ttl in deletetq is just 1 tick */
256 	ifs->ifs_ips_deletetq.ifq_ttl = (u_long) 1;
257 	ifs->ifs_ips_deletetq.ifq_ref = 1;
258 	ifs->ifs_ips_deletetq.ifq_head = NULL;
259 	ifs->ifs_ips_deletetq.ifq_tail = &ifs->ifs_ips_deletetq.ifq_head;
260 	MUTEX_INIT(&ifs->ifs_ips_deletetq.ifq_lock, "state delete queue");
261 	ifs->ifs_ips_deletetq.ifq_next = NULL;
262 
263 	RWLOCK_INIT(&ifs->ifs_ipf_state, "ipf IP state rwlock");
264 	MUTEX_INIT(&ifs->ifs_ipf_stinsert, "ipf state insert mutex");
265 	ifs->ifs_fr_state_init = 1;
266 
267 	ifs->ifs_ips_last_force_flush = ifs->ifs_fr_ticks;
268 	return 0;
269 }
270 
271 
272 /* ------------------------------------------------------------------------ */
273 /* Function:    fr_stateunload                                              */
274 /* Returns:     Nil                                                         */
275 /* Parameters:  ifs - ipf stack instance                                    */
276 /*                                                                          */
277 /* Release and destroy any resources acquired or initialised so that        */
278 /* IPFilter can be unloaded or re-initialised.                              */
279 /* ------------------------------------------------------------------------ */
280 void fr_stateunload(ifs)
281 ipf_stack_t *ifs;
282 {
283 	ipftq_t *ifq, *ifqnext;
284 	ipstate_t *is;
285 
286 	while ((is = ifs->ifs_ips_list) != NULL)
287 	    (void) fr_delstate(is, 0, ifs);
288 
289 	/*
290 	 * Proxy timeout queues are not cleaned here because although they
291 	 * exist on the state list, appr_unload is called after fr_stateunload
292 	 * and the proxies actually are responsible for them being created.
293 	 * Should the proxy timeouts have their own list?  There's no real
294 	 * justification as this is the only complicationA
295 	 */
296 	for (ifq = ifs->ifs_ips_utqe; ifq != NULL; ifq = ifqnext) {
297 		ifqnext = ifq->ifq_next;
298 		if (((ifq->ifq_flags & IFQF_PROXY) == 0) &&
299 		    (fr_deletetimeoutqueue(ifq) == 0))
300 			fr_freetimeoutqueue(ifq, ifs);
301 	}
302 
303 	ifs->ifs_ips_stats.iss_inuse = 0;
304 	ifs->ifs_ips_num = 0;
305 
306 	if (ifs->ifs_fr_state_init == 1) {
307 		fr_sttab_destroy(ifs->ifs_ips_tqtqb);
308 		MUTEX_DESTROY(&ifs->ifs_ips_udptq.ifq_lock);
309 		MUTEX_DESTROY(&ifs->ifs_ips_icmptq.ifq_lock);
310 		MUTEX_DESTROY(&ifs->ifs_ips_udpacktq.ifq_lock);
311 		MUTEX_DESTROY(&ifs->ifs_ips_icmpacktq.ifq_lock);
312 		MUTEX_DESTROY(&ifs->ifs_ips_iptq.ifq_lock);
313 		MUTEX_DESTROY(&ifs->ifs_ips_deletetq.ifq_lock);
314 	}
315 
316 	if (ifs->ifs_ips_table != NULL) {
317 		KFREES(ifs->ifs_ips_table,
318 		       ifs->ifs_fr_statesize * sizeof(*ifs->ifs_ips_table));
319 		ifs->ifs_ips_table = NULL;
320 	}
321 
322 	if (ifs->ifs_ips_seed != NULL) {
323 		KFREES(ifs->ifs_ips_seed,
324 		       ifs->ifs_fr_statesize * sizeof(*ifs->ifs_ips_seed));
325 		ifs->ifs_ips_seed = NULL;
326 	}
327 
328 	if (ifs->ifs_ips_stats.iss_bucketlen != NULL) {
329 		KFREES(ifs->ifs_ips_stats.iss_bucketlen,
330 		       ifs->ifs_fr_statesize * sizeof(u_long));
331 		ifs->ifs_ips_stats.iss_bucketlen = NULL;
332 	}
333 
334 	if (ifs->ifs_fr_state_maxbucket_reset == 1)
335 		ifs->ifs_fr_state_maxbucket = 0;
336 
337 	if (ifs->ifs_fr_state_init == 1) {
338 		ifs->ifs_fr_state_init = 0;
339 		RW_DESTROY(&ifs->ifs_ipf_state);
340 		MUTEX_DESTROY(&ifs->ifs_ipf_stinsert);
341 	}
342 }
343 
344 
345 /* ------------------------------------------------------------------------ */
346 /* Function:    fr_statetstats                                              */
347 /* Returns:     ips_state_t* - pointer to state stats structure             */
348 /* Parameters:  Nil                                                         */
349 /*                                                                          */
350 /* Put all the current numbers and pointers into a single struct and return */
351 /* a pointer to it.                                                         */
352 /* ------------------------------------------------------------------------ */
353 static ips_stat_t *fr_statetstats(ifs)
354 ipf_stack_t *ifs;
355 {
356 	ifs->ifs_ips_stats.iss_active = ifs->ifs_ips_num;
357 	ifs->ifs_ips_stats.iss_statesize = ifs->ifs_fr_statesize;
358 	ifs->ifs_ips_stats.iss_statemax = ifs->ifs_fr_statemax;
359 	ifs->ifs_ips_stats.iss_table = ifs->ifs_ips_table;
360 	ifs->ifs_ips_stats.iss_list = ifs->ifs_ips_list;
361 	ifs->ifs_ips_stats.iss_ticks = ifs->ifs_fr_ticks;
362 	return &ifs->ifs_ips_stats;
363 }
364 
365 /* ------------------------------------------------------------------------ */
366 /* Function:    fr_state_remove                                             */
367 /* Returns:     int - 0 == success, != 0 == failure                         */
368 /* Parameters:  data(I) - pointer to state structure to delete from table   */
369 /*              ifs - ipf stack instance                                    */
370 /*                                                                          */
371 /* Search for a state structure that matches the one passed, according to   */
372 /* the IP addresses and other protocol specific information.                */
373 /* ------------------------------------------------------------------------ */
374 static int fr_state_remove(data, ifs)
375 caddr_t data;
376 ipf_stack_t *ifs;
377 {
378 	ipstate_t *sp, st;
379 	int error;
380 
381 	sp = &st;
382 	error = fr_inobj(data, &st, IPFOBJ_IPSTATE);
383 	if (error)
384 		return EFAULT;
385 
386 	WRITE_ENTER(&ifs->ifs_ipf_state);
387 	for (sp = ifs->ifs_ips_list; sp; sp = sp->is_next)
388 		if ((sp->is_p == st.is_p) && (sp->is_v == st.is_v) &&
389 		    !bcmp((caddr_t)&sp->is_src, (caddr_t)&st.is_src,
390 			  sizeof(st.is_src)) &&
391 		    !bcmp((caddr_t)&sp->is_dst, (caddr_t)&st.is_dst,
392 			  sizeof(st.is_dst)) &&
393 		    !bcmp((caddr_t)&sp->is_ps, (caddr_t)&st.is_ps,
394 			  sizeof(st.is_ps))) {
395 			(void) fr_delstate(sp, ISL_REMOVE, ifs);
396 			RWLOCK_EXIT(&ifs->ifs_ipf_state);
397 			return 0;
398 		}
399 	RWLOCK_EXIT(&ifs->ifs_ipf_state);
400 	return ESRCH;
401 }
402 
403 
404 /* ------------------------------------------------------------------------ */
405 /* Function:    fr_state_ioctl                                              */
406 /* Returns:     int - 0 == success, != 0 == failure                         */
407 /* Parameters:  data(I) - pointer to ioctl data                             */
408 /*              cmd(I)  - ioctl command integer                             */
409 /*              mode(I) - file mode bits used with open                     */
410 /*              uid(I)  - uid of caller                                     */
411 /*              ctx(I)  - pointer to give the uid context                   */
412 /*              ifs     - ipf stack instance                                */
413 /*                                                                          */
414 /* Processes an ioctl call made to operate on the IP Filter state device.   */
415 /* ------------------------------------------------------------------------ */
416 int fr_state_ioctl(data, cmd, mode, uid, ctx, ifs)
417 caddr_t data;
418 ioctlcmd_t cmd;
419 int mode, uid;
420 void *ctx;
421 ipf_stack_t *ifs;
422 {
423 	int arg, ret, error = 0;
424 
425 	switch (cmd)
426 	{
427 	/*
428 	 * Delete an entry from the state table.
429 	 */
430 	case SIOCDELST :
431 		error = fr_state_remove(data, ifs);
432 		break;
433 	/*
434 	 * Flush the state table
435 	 */
436 	case SIOCIPFFL :
437 		error = BCOPYIN(data, (char *)&arg, sizeof(arg));
438 		if (error != 0) {
439 			error = EFAULT;
440 		} else {
441 			if (VALID_TABLE_FLUSH_OPT(arg)) {
442 				WRITE_ENTER(&ifs->ifs_ipf_state);
443 				ret = fr_state_flush(arg, 4, ifs);
444 				RWLOCK_EXIT(&ifs->ifs_ipf_state);
445 				error = BCOPYOUT((char *)&ret, data,
446 						sizeof(ret));
447 				if (error != 0)
448 					return EFAULT;
449 			} else {
450 				error = EINVAL;
451 			}
452 		}
453 		break;
454 
455 #ifdef	USE_INET6
456 	case SIOCIPFL6 :
457 		error = BCOPYIN(data, (char *)&arg, sizeof(arg));
458 		if (error != 0) {
459 			error = EFAULT;
460 		} else {
461 			if (VALID_TABLE_FLUSH_OPT(arg)) {
462 				WRITE_ENTER(&ifs->ifs_ipf_state);
463 				ret = fr_state_flush(arg, 6, ifs);
464 				RWLOCK_EXIT(&ifs->ifs_ipf_state);
465 				error = BCOPYOUT((char *)&ret, data,
466 						sizeof(ret));
467 				if (error != 0)
468 					return EFAULT;
469 			} else {
470 				error = EINVAL;
471 			}
472 		}
473 		break;
474 #endif
475 #ifdef	IPFILTER_LOG
476 	/*
477 	 * Flush the state log.
478 	 */
479 	case SIOCIPFFB :
480 		if (!(mode & FWRITE))
481 			error = EPERM;
482 		else {
483 			int tmp;
484 
485 			tmp = ipflog_clear(IPL_LOGSTATE, ifs);
486 			error = BCOPYOUT((char *)&tmp, data, sizeof(tmp));
487 			if (error != 0)
488 				error = EFAULT;
489 		}
490 		break;
491 	/*
492 	 * Turn logging of state information on/off.
493 	 */
494 	case SIOCSETLG :
495 		if (!(mode & FWRITE)) {
496 			error = EPERM;
497 		} else {
498 			error = BCOPYIN((char *)data,
499 					(char *)&ifs->ifs_ipstate_logging,
500 					sizeof(ifs->ifs_ipstate_logging));
501 			if (error != 0)
502 				error = EFAULT;
503 		}
504 		break;
505 	/*
506 	 * Return the current state of logging.
507 	 */
508 	case SIOCGETLG :
509 		error = BCOPYOUT((char *)&ifs->ifs_ipstate_logging,
510 				(char *)data,
511 				sizeof(ifs->ifs_ipstate_logging));
512 		if (error != 0)
513 			error = EFAULT;
514 		break;
515 	/*
516 	 * Return the number of bytes currently waiting to be read.
517 	 */
518 	case FIONREAD :
519 		arg = ifs->ifs_iplused[IPL_LOGSTATE]; /* returned in an int */
520 		error = BCOPYOUT((char *)&arg, data, sizeof(arg));
521 		if (error != 0)
522 			error = EFAULT;
523 		break;
524 #endif
525 	/*
526 	 * Get the current state statistics.
527 	 */
528 	case SIOCGETFS :
529 		error = fr_outobj(data, fr_statetstats(ifs), IPFOBJ_STATESTAT);
530 		break;
531 	/*
532 	 * Lock/Unlock the state table.  (Locking prevents any changes, which
533 	 * means no packets match).
534 	 */
535 	case SIOCSTLCK :
536 		if (!(mode & FWRITE)) {
537 			error = EPERM;
538 		} else {
539 			error = fr_lock(data, &ifs->ifs_fr_state_lock);
540 		}
541 		break;
542 	/*
543 	 * Add an entry to the current state table.
544 	 */
545 	case SIOCSTPUT :
546 		if (!ifs->ifs_fr_state_lock || !(mode & FWRITE)) {
547 			error = EACCES;
548 			break;
549 		}
550 		error = fr_stputent(data, ifs);
551 		break;
552 	/*
553 	 * Get a state table entry.
554 	 */
555 	case SIOCSTGET :
556 		if (!ifs->ifs_fr_state_lock) {
557 			error = EACCES;
558 			break;
559 		}
560 		error = fr_stgetent(data, ifs);
561 		break;
562 
563 	case SIOCGENITER :
564 	    {
565 		ipftoken_t *token;
566 		ipfgeniter_t iter;
567 
568 		error = fr_inobj(data, &iter, IPFOBJ_GENITER);
569 		if (error != 0)
570 			break;
571 
572 		token = ipf_findtoken(IPFGENITER_STATE, uid, ctx, ifs);
573 		if (token != NULL)
574 			error = fr_stateiter(token, &iter, ifs);
575 		else
576 			error = ESRCH;
577 		RWLOCK_EXIT(&ifs->ifs_ipf_tokens);
578 		break;
579 	    }
580 
581 	case SIOCIPFDELTOK :
582 		error = BCOPYIN(data, (char *)&arg, sizeof(arg));
583 		if (error != 0) {
584 			error = EFAULT;
585 		} else {
586 			error = ipf_deltoken(arg, uid, ctx, ifs);
587 		}
588 		break;
589 
590 	default :
591 		error = EINVAL;
592 		break;
593 	}
594 	return error;
595 }
596 
597 
598 /* ------------------------------------------------------------------------ */
599 /* Function:    fr_stgetent                                                 */
600 /* Returns:     int - 0 == success, != 0 == failure                         */
601 /* Parameters:  data(I) - pointer to state structure to retrieve from table */
602 /*                                                                          */
603 /* Copy out state information from the kernel to a user space process.  If  */
604 /* there is a filter rule associated with the state entry, copy that out    */
605 /* as well.  The entry to copy out is taken from the value of "ips_next" in */
606 /* the struct passed in and if not null and not found in the list of current*/
607 /* state entries, the retrieval fails.                                      */
608 /* ------------------------------------------------------------------------ */
609 int fr_stgetent(data, ifs)
610 caddr_t data;
611 ipf_stack_t *ifs;
612 {
613 	ipstate_t *is, *isn;
614 	ipstate_save_t ips;
615 	int error;
616 
617 	error = fr_inobj(data, &ips, IPFOBJ_STATESAVE);
618 	if (error)
619 		return EFAULT;
620 
621 	isn = ips.ips_next;
622 	if (isn == NULL) {
623 		isn = ifs->ifs_ips_list;
624 		if (isn == NULL) {
625 			if (ips.ips_next == NULL)
626 				return ENOENT;
627 			return 0;
628 		}
629 	} else {
630 		/*
631 		 * Make sure the pointer we're copying from exists in the
632 		 * current list of entries.  Security precaution to prevent
633 		 * copying of random kernel data.
634 		 */
635 		for (is = ifs->ifs_ips_list; is; is = is->is_next)
636 			if (is == isn)
637 				break;
638 		if (!is)
639 			return ESRCH;
640 	}
641 	ips.ips_next = isn->is_next;
642 	bcopy((char *)isn, (char *)&ips.ips_is, sizeof(ips.ips_is));
643 	ips.ips_rule = isn->is_rule;
644 	if (isn->is_rule != NULL)
645 		bcopy((char *)isn->is_rule, (char *)&ips.ips_fr,
646 		      sizeof(ips.ips_fr));
647 	error = fr_outobj(data, &ips, IPFOBJ_STATESAVE);
648 	if (error)
649 		return EFAULT;
650 	return 0;
651 }
652 
653 
654 /* ------------------------------------------------------------------------ */
655 /* Function:    fr_stputent                                                 */
656 /* Returns:     int - 0 == success, != 0 == failure                         */
657 /* Parameters:  data(I) - pointer to state information struct               */
658 /*              ifs     - ipf stack instance                                */
659 /*                                                                          */
660 /* This function implements the SIOCSTPUT ioctl: insert a state entry into  */
661 /* the state table.  If the state info. includes a pointer to a filter rule */
662 /* then also add in an orphaned rule (will not show up in any "ipfstat -io" */
663 /* output.                                                                  */
664 /* ------------------------------------------------------------------------ */
665 int fr_stputent(data, ifs)
666 caddr_t data;
667 ipf_stack_t *ifs;
668 {
669 	ipstate_t *is, *isn;
670 	ipstate_save_t ips;
671 	int error, i;
672 	frentry_t *fr;
673 	char *name;
674 
675 	error = fr_inobj(data, &ips, IPFOBJ_STATESAVE);
676 	if (error)
677 		return EFAULT;
678 
679 	/*
680 	 * Trigger automatic call to fr_state_flush() if the
681 	 * table has reached capacity specified by hi watermark.
682 	 */
683 	if (ST_TAB_WATER_LEVEL(ifs) > ifs->ifs_state_flush_level_hi)
684 		ifs->ifs_fr_state_doflush = 1;
685 
686 	/*
687 	 * If automatic flushing did not do its job, and the table
688 	 * has filled up, don't try to create a new entry.
689 	 */
690 	if (ifs->ifs_ips_num >= ifs->ifs_fr_statemax) {
691 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_max);
692 		return ENOMEM;
693 	}
694 
695 	KMALLOC(isn, ipstate_t *);
696 	if (isn == NULL)
697 		return ENOMEM;
698 
699 	bcopy((char *)&ips.ips_is, (char *)isn, sizeof(*isn));
700 	bzero((char *)isn, offsetof(struct ipstate, is_pkts));
701 	isn->is_sti.tqe_pnext = NULL;
702 	isn->is_sti.tqe_next = NULL;
703 	isn->is_sti.tqe_ifq = NULL;
704 	isn->is_sti.tqe_parent = isn;
705 	isn->is_ifp[0] = NULL;
706 	isn->is_ifp[1] = NULL;
707 	isn->is_ifp[2] = NULL;
708 	isn->is_ifp[3] = NULL;
709 	isn->is_sync = NULL;
710 	fr = ips.ips_rule;
711 
712 	if (fr == NULL) {
713 		READ_ENTER(&ifs->ifs_ipf_state);
714 		fr_stinsert(isn, 0, ifs);
715 		MUTEX_EXIT(&isn->is_lock);
716 		RWLOCK_EXIT(&ifs->ifs_ipf_state);
717 		return 0;
718 	}
719 
720 	if (isn->is_flags & SI_NEWFR) {
721 		KMALLOC(fr, frentry_t *);
722 		if (fr == NULL) {
723 			KFREE(isn);
724 			return ENOMEM;
725 		}
726 		bcopy((char *)&ips.ips_fr, (char *)fr, sizeof(*fr));
727 		isn->is_rule = fr;
728 		ips.ips_is.is_rule = fr;
729 		MUTEX_NUKE(&fr->fr_lock);
730 		MUTEX_INIT(&fr->fr_lock, "state filter rule lock");
731 
732 		/*
733 		 * Look up all the interface names in the rule.
734 		 */
735 		for (i = 0; i < 4; i++) {
736 			name = fr->fr_ifnames[i];
737 			fr->fr_ifas[i] = fr_resolvenic(name, fr->fr_v, ifs);
738 			name = isn->is_ifname[i];
739 			isn->is_ifp[i] = fr_resolvenic(name, isn->is_v, ifs);
740 		}
741 
742 		fr->fr_ref = 0;
743 		fr->fr_dsize = 0;
744 		fr->fr_data = NULL;
745 		fr->fr_type = FR_T_NONE;
746 
747 		fr_resolvedest(&fr->fr_tif, fr->fr_v, ifs);
748 		fr_resolvedest(&fr->fr_dif, fr->fr_v, ifs);
749 		fr_resolvedest(&fr->fr_rif, fr->fr_v, ifs);
750 
751 		/*
752 		 * send a copy back to userland of what we ended up
753 		 * to allow for verification.
754 		 */
755 		error = fr_outobj(data, &ips, IPFOBJ_STATESAVE);
756 		if (error) {
757 			KFREE(isn);
758 			MUTEX_DESTROY(&fr->fr_lock);
759 			KFREE(fr);
760 			return EFAULT;
761 		}
762 		READ_ENTER(&ifs->ifs_ipf_state);
763 		fr_stinsert(isn, 0, ifs);
764 		MUTEX_EXIT(&isn->is_lock);
765 		RWLOCK_EXIT(&ifs->ifs_ipf_state);
766 
767 	} else {
768 		READ_ENTER(&ifs->ifs_ipf_state);
769 		for (is = ifs->ifs_ips_list; is; is = is->is_next)
770 			if (is->is_rule == fr) {
771 				fr_stinsert(isn, 0, ifs);
772 				MUTEX_EXIT(&isn->is_lock);
773 				break;
774 			}
775 
776 		if (is == NULL) {
777 			KFREE(isn);
778 			isn = NULL;
779 		}
780 		RWLOCK_EXIT(&ifs->ifs_ipf_state);
781 
782 		return (isn == NULL) ? ESRCH : 0;
783 	}
784 
785 	return 0;
786 }
787 
788 
789 /* ------------------------------------------------------------------------ */
790 /* Function:   fr_stinsert                                                  */
791 /* Returns:    Nil                                                          */
792 /* Parameters: is(I)  - pointer to state structure                          */
793 /*             rev(I) - flag indicating forward/reverse direction of packet */
794 /*                                                                          */
795 /* Inserts a state structure into the hash table (for lookups) and the list */
796 /* of state entries (for enumeration).  Resolves all of the interface names */
797 /* to pointers and adjusts running stats for the hash table as appropriate. */
798 /*                                                                          */
799 /* Locking: it is assumed that some kind of lock on ipf_state is held.      */
800 /*          Exits with is_lock initialised and held.                        */
801 /* ------------------------------------------------------------------------ */
802 void fr_stinsert(is, rev, ifs)
803 ipstate_t *is;
804 int rev;
805 ipf_stack_t *ifs;
806 {
807 	frentry_t *fr;
808 	u_int hv;
809 	int i;
810 
811 	MUTEX_INIT(&is->is_lock, "ipf state entry");
812 
813 	fr = is->is_rule;
814 	if (fr != NULL) {
815 		MUTEX_ENTER(&fr->fr_lock);
816 		fr->fr_ref++;
817 		fr->fr_statecnt++;
818 		MUTEX_EXIT(&fr->fr_lock);
819 	}
820 
821 	/*
822 	 * Look up all the interface names in the state entry.
823 	 */
824 	for (i = 0; i < 4; i++) {
825 		if (is->is_ifp[i] != NULL)
826 			continue;
827 		is->is_ifp[i] = fr_resolvenic(is->is_ifname[i], is->is_v, ifs);
828 	}
829 
830 	/*
831 	 * If we could trust is_hv, then the modulous would not be needed, but
832 	 * when running with IPFILTER_SYNC, this stops bad values.
833 	 */
834 	hv = is->is_hv % ifs->ifs_fr_statesize;
835 	is->is_hv = hv;
836 
837 	/*
838 	 * We need to get both of these locks...the first because it is
839 	 * possible that once the insert is complete another packet might
840 	 * come along, match the entry and want to update it.
841 	 */
842 	MUTEX_ENTER(&is->is_lock);
843 	MUTEX_ENTER(&ifs->ifs_ipf_stinsert);
844 
845 	/*
846 	 * add into list table.
847 	 */
848 	if (ifs->ifs_ips_list != NULL)
849 		ifs->ifs_ips_list->is_pnext = &is->is_next;
850 	is->is_pnext = &ifs->ifs_ips_list;
851 	is->is_next = ifs->ifs_ips_list;
852 	ifs->ifs_ips_list = is;
853 
854 	if (ifs->ifs_ips_table[hv] != NULL)
855 		ifs->ifs_ips_table[hv]->is_phnext = &is->is_hnext;
856 	else
857 		ifs->ifs_ips_stats.iss_inuse++;
858 	is->is_phnext = ifs->ifs_ips_table + hv;
859 	is->is_hnext = ifs->ifs_ips_table[hv];
860 	ifs->ifs_ips_table[hv] = is;
861 	ifs->ifs_ips_stats.iss_bucketlen[hv]++;
862 	ifs->ifs_ips_num++;
863 	MUTEX_EXIT(&ifs->ifs_ipf_stinsert);
864 
865 	fr_setstatequeue(is, rev, ifs);
866 }
867 
868 /* ------------------------------------------------------------------------ */
869 /* Function:	fr_match_ipv4addrs					    */
870 /* Returns:	int -	2 strong match (same addresses, same direction)	    */
871 /*			1 weak match (same address, opposite direction)	    */
872 /*			0 no match					    */
873 /*									    */
874 /* Function matches IPv4 addresses.					    */
875 /* ------------------------------------------------------------------------ */
876 static int fr_match_ipv4addrs(is1, is2)
877 ipstate_t *is1;
878 ipstate_t *is2;
879 {
880 	int	rv;
881 
882 	if (is1->is_saddr == is2->is_saddr && is1->is_daddr == is2->is_daddr)
883 		rv = 2;
884 	else if (is1->is_saddr == is2->is_daddr &&
885 	    is1->is_daddr == is2->is_saddr)
886 		rv = 1;
887 	else
888 		rv = 0;
889 
890 	return (rv);
891 }
892 
893 /* ------------------------------------------------------------------------ */
894 /* Function:	fr_match_ipv6addrs					    */
895 /* Returns:	int - 	2 strong match (same addresses, same direction)	    */
896 /*			1 weak match (same addresses, opposite direction)   */
897 /*			0 no match					    */
898 /*									    */
899 /* Function matches IPv6 addresses.					    */
900 /* ------------------------------------------------------------------------ */
901 static int fr_match_ipv6addrs(is1, is2)
902 ipstate_t *is1;
903 ipstate_t *is2;
904 {
905 	int	rv;
906 
907 	if (IP6_EQ(&is1->is_src, &is2->is_src) &&
908 	    IP6_EQ(&is1->is_dst, &is2->is_dst))
909 		rv = 2;
910 	else if (IP6_EQ(&is1->is_src, &is2->is_dst) &&
911 	    IP6_EQ(&is1->is_dst, &is2->is_src)) {
912 		rv = 1;
913 	}
914 	else
915 		rv = 0;
916 
917 	return (rv);
918 }
919 /* ------------------------------------------------------------------------ */
920 /* Function:	fr_match_addresses					    */
921 /* Returns:	int - 	2 strong match (same addresses, same direction)	    */
922 /*			1 weak match (same address, opposite directions)    */
923 /* 			0 no match					    */
924 /* Parameters:	is1, is2 pointers to states we are checking		    */
925 /*									    */
926 /* Matches addresses, function uses fr_match_ipvXaddrs() to deal with IPv4  */
927 /* and IPv6 address format.						    */
928 /* ------------------------------------------------------------------------ */
929 static int fr_match_addresses(is1, is2)
930 ipstate_t *is1;
931 ipstate_t *is2;
932 {
933 	int	rv;
934 
935 	if (is1->is_v == 4) {
936 		rv = fr_match_ipv4addrs(is1, is2);
937 	} else {
938 		rv = fr_match_ipv6addrs(is1, is2);
939 	}
940 
941 	return (rv);
942 }
943 
944 /* ------------------------------------------------------------------------ */
945 /* Function:	fr_match_ppairs						    */
946 /* Returns:	int - 	2 strong match (same ports, same direction)	    */
947 /*			1 weak match (same ports, different direction)	    */
948 /*			0 no match					    */
949 /* Parameters	ppairs1, ppairs - src, dst ports we want to match.	    */
950 /*									    */
951 /* Matches two port_pair_t types (port pairs). Each port pair contains	    */
952 /* src, dst port, which belong to session (state entry).		    */
953 /* ------------------------------------------------------------------------ */
954 static int fr_match_ppairs(ppairs1, ppairs2)
955 port_pair_t *ppairs1;
956 port_pair_t *ppairs2;
957 {
958 	int	rv;
959 
960 	if (ppairs1->pp_sport == ppairs2->pp_sport &&
961 	    ppairs1->pp_dport == ppairs2->pp_dport)
962 		rv = 2;
963 	else if (ppairs1->pp_sport == ppairs2->pp_dport &&
964 		    ppairs1->pp_dport == ppairs2->pp_sport)
965 		rv = 1;
966 	else
967 		rv = 0;
968 
969 	return (rv);
970 }
971 
972 /* ------------------------------------------------------------------------ */
973 /* Function:	fr_match_l4_hdr						    */
974 /* Returns:	int -	0 no match,					    */
975 /*			1 weak match (same ports, different directions)	    */
976 /*			2 strong match (same ports, same direction)	    */
977 /* Parameters	is1, is2 - states we want to match			    */
978 /*									    */
979 /* Function matches L4 header data (source ports for TCP, UDP, CallIds for  */
980 /* GRE protocol).							    */
981 /* ------------------------------------------------------------------------ */
982 static int fr_match_l4_hdr(is1, is2)
983 ipstate_t *is1;
984 ipstate_t *is2;
985 {
986 	int	rv = 0;
987 	port_pair_t	pp1;
988 	port_pair_t	pp2;
989 
990 	if (is1->is_p != is2->is_p)
991 		return (0);
992 
993 	switch (is1->is_p) {
994 		case	IPPROTO_TCP:
995 			pp1.pp_sport = is1->is_ps.is_ts.ts_sport;
996 			pp1.pp_dport = is1->is_ps.is_ts.ts_dport;
997 			pp2.pp_sport = is2->is_ps.is_ts.ts_sport;
998 			pp2.pp_dport = is2->is_ps.is_ts.ts_dport;
999 			rv = fr_match_ppairs(&pp1, &pp2);
1000 			break;
1001 		case	IPPROTO_UDP:
1002 			pp1.pp_sport = is1->is_ps.is_us.us_sport;
1003 			pp1.pp_dport = is1->is_ps.is_us.us_dport;
1004 			pp2.pp_sport = is2->is_ps.is_us.us_sport;
1005 			pp2.pp_dport = is2->is_ps.is_us.us_dport;
1006 			rv = fr_match_ppairs(&pp1, &pp2);
1007 			break;
1008 		case	IPPROTO_GRE:
1009 			/* greinfo_t can be also interprted as port pair */
1010 			pp1.pp_sport = is1->is_ps.is_ug.gs_call[0];
1011 			pp1.pp_dport = is1->is_ps.is_ug.gs_call[1];
1012 			pp2.pp_sport = is2->is_ps.is_ug.gs_call[0];
1013 			pp2.pp_dport = is2->is_ps.is_ug.gs_call[1];
1014 			rv = fr_match_ppairs(&pp1, &pp2);
1015 			break;
1016 		case	IPPROTO_ICMP:
1017 		case	IPPROTO_ICMPV6:
1018 			if (bcmp(&is1->is_ps, &is2->is_ps, sizeof (icmpinfo_t)))
1019 				rv = 1;
1020 			else
1021 				rv = 0;
1022 			break;
1023 		default:
1024 			rv = 0;
1025 	}
1026 
1027 	return (rv);
1028 }
1029 
1030 /* ------------------------------------------------------------------------ */
1031 /* Function:	fr_matchstates						    */
1032 /* Returns:	int - nonzero match, zero no match			    */
1033 /* Parameters	is1, is2 - states we want to match			    */
1034 /*									    */
1035 /* The state entries are equal (identical match) if they belong to the same */
1036 /* session. Any time new state entry is being added the fr_addstate()	    */
1037 /* function creates temporal state entry from the data it gets from IP and  */
1038 /* L4 header. The fr_matchstats() must be also aware of packet direction,   */
1039 /* which is also stored within the state entry. We should keep in mind the  */
1040 /* information about packet direction is spread accross L3 (addresses) and  */
1041 /* L4 (ports). There are three possible relationships betwee is1, is2:	    */
1042 /* 		- no match (match(is1, is2) == 0))			    */
1043 /*		- weak match same addresses (ports), but different	    */
1044 /*			directions (1)	(fr_match_xxxx(is1, is2) == 1)	    */
1045 /*		- strong match same addresses (ports) and same directions   */
1046 /*			 (2) (fr_match_xxxx(is1, is2) == 2)		    */
1047 /*									    */
1048 /* There are functions, which match match addresses (L3 header) in is1, is2 */
1049 /* and functions, which are used to compare ports (L4 header) data. We say  */
1050 /* the is1 and is2 are same (identical) if there is a match		    */
1051 /* (fr_match_l4_hdr(is1, is2) != 0) and matchlevels are same for entries    */
1052 /* (fr_match_l3_hdr(is1, is2) == fr_match_l4_hdr(is1, is2)) for is1, is2.   */
1053 /* Such requirement deals with case as follows:				    */
1054 /*	suppose there are two connections between hosts A, B. Connection 1: */
1055 /*			a.a.a.a:12345 <=> b.b.b.b:54321			    */
1056 /*		Connection 2:						    */
1057 /*			a.a.a.a:54321 <=> b.b.b.b:12345			    */
1058 /* since we've introduced match levels into our fr_matchstates(), we are    */
1059 /* able to identify, which packets belong to connection A and which belong  */
1060 /* to connection B.	Assume there are two entries is1, is2. is1 has been */
1061 /* from con. 1 packet, which travelled from A to B:			    */
1062 /*			a.a.a.a:12345 -> b.b.b.b:54321			    */
1063 /* while s2, has been created from packet which belongs to con. 2 and is    */
1064 /* also coming from A to B:						    */
1065 /*			a.a.a.a:54321 -> b.b.b.b:12345			    */
1066 /* fr_match_l3_hdr(is1, is2) == 2 -> strong match, while		    */
1067 /* fr_match_l4_hdr(is1, is2) == 1 -> weak match. Since match levels are	    */
1068 /* different the state entries are not identical -> no match as a final	    */
1069 /* result.								    */
1070 /* ------------------------------------------------------------------------ */
1071 static int fr_matchstates(is1, is2)
1072 ipstate_t *is1;
1073 ipstate_t *is2;
1074 {
1075 	int	rv;
1076 	int	amatch;
1077 	int	pmatch;
1078 
1079 	if (bcmp(&is1->is_pass, &is2->is_pass,
1080 		offsetof(struct ipstate, is_ps) -
1081 		offsetof(struct ipstate, is_pass)) == 0) {
1082 
1083 		pmatch = fr_match_l4_hdr(is1, is2);
1084 		amatch = fr_match_addresses(is1, is2);
1085 		/*
1086 		 * If addresses match (amatch != 0), then 'match levels'
1087 		 * must be same for matching entries. If amatch and pmatch
1088 		 * have different values (different match levels), then
1089 		 * is1 and is2 belong to different sessions.
1090 		 */
1091 		rv = (amatch != 0) && (amatch == pmatch);
1092 	}
1093 	else
1094 		rv = 0;
1095 
1096 	return (rv);
1097 }
1098 
1099 /* ------------------------------------------------------------------------ */
1100 /* Function:    fr_addstate                                                 */
1101 /* Returns:     ipstate_t* - NULL == failure, else pointer to new state     */
1102 /* Parameters:  fin(I)    - pointer to packet information                   */
1103 /*              stsave(O) - pointer to place to save pointer to created     */
1104 /*                          state structure.                                */
1105 /*              flags(I)  - flags to use when creating the structure        */
1106 /*                                                                          */
1107 /* Creates a new IP state structure from the packet information collected.  */
1108 /* Inserts it into the state table and appends to the bottom of the active  */
1109 /* list.  If the capacity of the table has reached the maximum allowed then */
1110 /* the call will fail and a flush is scheduled for the next timeout call.   */
1111 /* ------------------------------------------------------------------------ */
1112 ipstate_t *fr_addstate(fin, stsave, flags)
1113 fr_info_t *fin;
1114 ipstate_t **stsave;
1115 u_int flags;
1116 {
1117 	ipstate_t *is, ips;
1118 	struct icmp *ic;
1119 	u_int pass, hv;
1120 	frentry_t *fr;
1121 	tcphdr_t *tcp;
1122 	grehdr_t *gre;
1123 	void *ifp;
1124 	int out;
1125 	ipf_stack_t *ifs = fin->fin_ifs;
1126 
1127 	if (ifs->ifs_fr_state_lock ||
1128 	    (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGBODY|FI_BAD)))
1129 		return NULL;
1130 
1131 	if ((fin->fin_flx & FI_OOW) && !(fin->fin_tcpf & TH_SYN))
1132 		return NULL;
1133 
1134 	/*
1135 	 * Trigger automatic call to fr_state_flush() if the
1136 	 * table has reached capacity specified by hi watermark.
1137 	 */
1138 	if (ST_TAB_WATER_LEVEL(ifs) > ifs->ifs_state_flush_level_hi)
1139 		ifs->ifs_fr_state_doflush = 1;
1140 
1141 	/*
1142 	 * If the max number of state entries has been reached, and there is no
1143 	 * limit on the state count for the rule, then do not continue.  In the
1144 	 * case where a limit exists, it's ok allow the entries to be created as
1145 	 * long as specified limit itself has not been reached.
1146 	 *
1147 	 * Note that because the lock isn't held on fr, it is possible to exceed
1148 	 * the specified size of the table.  However, the cost of this is being
1149 	 * ignored here; as the number by which it can go over is a product of
1150 	 * the number of simultaneous threads that could be executing in here.
1151 	 * So, a limit of 100 won't result in 200, but could result in 101 or 102.
1152 	 *
1153 	 * Also note that, since the automatic flush should have been triggered
1154 	 * well before we reach the maximum number of state table entries, the
1155 	 * likelihood of reaching the max (and thus exceedng it) is minimal.
1156 	 */
1157 	fr = fin->fin_fr;
1158 	if (fr != NULL) {
1159 		if ((ifs->ifs_ips_num >= ifs->ifs_fr_statemax) &&
1160 		    (fr->fr_statemax == 0)) {
1161 			ATOMIC_INCL(ifs->ifs_ips_stats.iss_max);
1162 			return NULL;
1163 		}
1164 		if ((fr->fr_statemax != 0) &&
1165 		    (fr->fr_statecnt >= fr->fr_statemax)) {
1166 			ATOMIC_INCL(ifs->ifs_ips_stats.iss_maxref);
1167 			ifs->ifs_fr_state_doflush = 1;
1168 			return NULL;
1169 		}
1170 	}
1171 
1172 	ic = NULL;
1173 	tcp = NULL;
1174 	out = fin->fin_out;
1175 	is = &ips;
1176 	bzero((char *)is, sizeof(*is));
1177 
1178 	if (fr == NULL) {
1179 		pass = ifs->ifs_fr_flags;
1180 		is->is_tag = FR_NOLOGTAG;
1181 	} else {
1182 		pass = fr->fr_flags;
1183 	}
1184 
1185 	is->is_die = 1 + ifs->ifs_fr_ticks;
1186 	/*
1187 	 * We want to check everything that is a property of this packet,
1188 	 * but we don't (automatically) care about it's fragment status as
1189 	 * this may change.
1190 	 */
1191 	is->is_pass = pass;
1192 	is->is_v = fin->fin_v;
1193 	is->is_opt[0] = fin->fin_optmsk;
1194 	is->is_optmsk[0] = 0xffffffff;
1195 	is->is_optmsk[1] = 0xffffffff;
1196 	if (is->is_v == 6) {
1197 		is->is_opt[0] &= ~0x8;
1198 		is->is_optmsk[0] &= ~0x8;
1199 		is->is_optmsk[1] &= ~0x8;
1200 	}
1201 	is->is_sec = fin->fin_secmsk;
1202 	is->is_secmsk = 0xffff;
1203 	is->is_auth = fin->fin_auth;
1204 	is->is_authmsk = 0xffff;
1205 
1206 	/*
1207 	 * Copy and calculate...
1208 	 */
1209 	hv = (is->is_p = fin->fin_fi.fi_p);
1210 	is->is_src = fin->fin_fi.fi_src;
1211 	hv += is->is_saddr;
1212 	is->is_dst = fin->fin_fi.fi_dst;
1213 	hv += is->is_daddr;
1214 #ifdef	USE_INET6
1215 	if (fin->fin_v == 6) {
1216 		/*
1217 		 * For ICMPv6, we check to see if the destination address is
1218 		 * a multicast address.  If it is, do not include it in the
1219 		 * calculation of the hash because the correct reply will come
1220 		 * back from a real address, not a multicast address.
1221 		 */
1222 		if ((is->is_p == IPPROTO_ICMPV6) &&
1223 		    IN6_IS_ADDR_MULTICAST(&is->is_dst.in6)) {
1224 			/*
1225 			 * So you can do keep state with neighbour discovery.
1226 			 *
1227 			 * Here we could use the address from the neighbour
1228 			 * solicit message to put in the state structure and
1229 			 * we could use that without a wildcard flag too...
1230 			 */
1231 			is->is_flags |= SI_W_DADDR;
1232 			hv -= is->is_daddr;
1233 		} else {
1234 			hv += is->is_dst.i6[1];
1235 			hv += is->is_dst.i6[2];
1236 			hv += is->is_dst.i6[3];
1237 		}
1238 		hv += is->is_src.i6[1];
1239 		hv += is->is_src.i6[2];
1240 		hv += is->is_src.i6[3];
1241 	}
1242 #endif
1243 	if ((fin->fin_v == 4) &&
1244 	    (fin->fin_flx & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST))) {
1245 		if (fin->fin_out == 0) {
1246 			flags |= SI_W_DADDR|SI_CLONE;
1247 			hv -= is->is_daddr;
1248 		} else {
1249 			flags |= SI_W_SADDR|SI_CLONE;
1250 			hv -= is->is_saddr;
1251 		}
1252 	}
1253 
1254 	switch (is->is_p)
1255 	{
1256 #ifdef	USE_INET6
1257 	case IPPROTO_ICMPV6 :
1258 		ic = fin->fin_dp;
1259 
1260 		switch (ic->icmp_type)
1261 		{
1262 		case ICMP6_ECHO_REQUEST :
1263 			is->is_icmp.ici_type = ic->icmp_type;
1264 			hv += (is->is_icmp.ici_id = ic->icmp_id);
1265 			break;
1266 		case ICMP6_MEMBERSHIP_QUERY :
1267 		case ND_ROUTER_SOLICIT :
1268 		case ND_NEIGHBOR_SOLICIT :
1269 		case ICMP6_NI_QUERY :
1270 			is->is_icmp.ici_type = ic->icmp_type;
1271 			break;
1272 		default :
1273 			return NULL;
1274 		}
1275 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_icmp);
1276 		break;
1277 #endif
1278 	case IPPROTO_ICMP :
1279 		ic = fin->fin_dp;
1280 
1281 		switch (ic->icmp_type)
1282 		{
1283 		case ICMP_ECHO :
1284 		case ICMP_TSTAMP :
1285 		case ICMP_IREQ :
1286 		case ICMP_MASKREQ :
1287 			is->is_icmp.ici_type = ic->icmp_type;
1288 			hv += (is->is_icmp.ici_id = ic->icmp_id);
1289 			break;
1290 		default :
1291 			return NULL;
1292 		}
1293 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_icmp);
1294 		break;
1295 
1296 	case IPPROTO_GRE :
1297 		gre = fin->fin_dp;
1298 
1299 		is->is_gre.gs_flags = gre->gr_flags;
1300 		is->is_gre.gs_ptype = gre->gr_ptype;
1301 		if (GRE_REV(is->is_gre.gs_flags) == 1) {
1302 			is->is_call[0] = fin->fin_data[0];
1303 			is->is_call[1] = fin->fin_data[1];
1304 		}
1305 		break;
1306 
1307 	case IPPROTO_TCP :
1308 		tcp = fin->fin_dp;
1309 
1310 		if (tcp->th_flags & TH_RST)
1311 			return NULL;
1312 		/*
1313 		 * The endian of the ports doesn't matter, but the ack and
1314 		 * sequence numbers do as we do mathematics on them later.
1315 		 */
1316 		is->is_sport = htons(fin->fin_data[0]);
1317 		is->is_dport = htons(fin->fin_data[1]);
1318 		if ((flags & (SI_W_DPORT|SI_W_SPORT)) == 0) {
1319 			hv += is->is_sport;
1320 			hv += is->is_dport;
1321 		}
1322 
1323 		/*
1324 		 * If this is a real packet then initialise fields in the
1325 		 * state information structure from the TCP header information.
1326 		 */
1327 
1328 		is->is_maxdwin = 1;
1329 		is->is_maxswin = ntohs(tcp->th_win);
1330 		if (is->is_maxswin == 0)
1331 			is->is_maxswin = 1;
1332 
1333 		if ((fin->fin_flx & FI_IGNORE) == 0) {
1334 			is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen -
1335 				      (TCP_OFF(tcp) << 2) +
1336 				      ((tcp->th_flags & TH_SYN) ? 1 : 0) +
1337 				      ((tcp->th_flags & TH_FIN) ? 1 : 0);
1338 			is->is_maxsend = is->is_send;
1339 
1340 			/*
1341 			 * Window scale option is only present in
1342 			 * SYN/SYN-ACK packet.
1343 			 */
1344 			if ((tcp->th_flags & ~(TH_FIN|TH_ACK|TH_ECNALL)) ==
1345 			    TH_SYN &&
1346 			    (TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) {
1347 				if (fr_tcpoptions(fin, tcp,
1348 					&is->is_tcp.ts_data[0]) == -1) {
1349 					fin->fin_flx |= FI_BAD;
1350 				}
1351 			}
1352 
1353 			if ((fin->fin_out != 0) && (pass & FR_NEWISN) != 0) {
1354 				fr_checknewisn(fin, is);
1355 				fr_fixoutisn(fin, is);
1356 			}
1357 
1358 			if ((tcp->th_flags & TH_OPENING) == TH_SYN)
1359 				flags |= IS_TCPFSM;
1360 			else {
1361 				is->is_maxdwin = is->is_maxswin * 2;
1362 				is->is_dend = ntohl(tcp->th_ack);
1363 				is->is_maxdend = ntohl(tcp->th_ack);
1364 				is->is_maxdwin *= 2;
1365 			}
1366 		}
1367 
1368 		/*
1369 		 * If we're creating state for a starting connection, start the
1370 		 * timer on it as we'll never see an error if it fails to
1371 		 * connect.
1372 		 */
1373 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_tcp);
1374 		break;
1375 
1376 	case IPPROTO_UDP :
1377 		tcp = fin->fin_dp;
1378 
1379 		is->is_sport = htons(fin->fin_data[0]);
1380 		is->is_dport = htons(fin->fin_data[1]);
1381 		if ((flags & (SI_W_DPORT|SI_W_SPORT)) == 0) {
1382 			hv += tcp->th_dport;
1383 			hv += tcp->th_sport;
1384 		}
1385 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_udp);
1386 		break;
1387 
1388 	default :
1389 		break;
1390 	}
1391 	hv = DOUBLE_HASH(hv, ifs);
1392 	is->is_hv = hv;
1393 	is->is_rule = fr;
1394 	is->is_flags = flags & IS_INHERITED;
1395 
1396 	/*
1397 	 * Look for identical state.
1398 	 */
1399 	for (is = ifs->ifs_ips_table[is->is_hv % ifs->ifs_fr_statesize];
1400 	     is != NULL;
1401 	     is = is->is_hnext) {
1402 		if (fr_matchstates(&ips, is) == 1)
1403 			break;
1404 	}
1405 
1406 	/*
1407 	 * we've found a matching state -> state already exists,
1408 	 * we are not going to add a duplicate record.
1409 	 */
1410 	if (is != NULL)
1411 		return NULL;
1412 
1413 	if (ifs->ifs_ips_stats.iss_bucketlen[hv] >= ifs->ifs_fr_state_maxbucket) {
1414 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_bucketfull);
1415 		return NULL;
1416 	}
1417 	KMALLOC(is, ipstate_t *);
1418 	if (is == NULL) {
1419 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_nomem);
1420 		return NULL;
1421 	}
1422 	bcopy((char *)&ips, (char *)is, sizeof(*is));
1423 	/*
1424 	 * Do not do the modulous here, it is done in fr_stinsert().
1425 	 */
1426 	if (fr != NULL) {
1427 		(void) strncpy(is->is_group, fr->fr_group, FR_GROUPLEN);
1428 		if (fr->fr_age[0] != 0) {
1429 			is->is_tqehead[0] =
1430 			    fr_addtimeoutqueue(&ifs->ifs_ips_utqe,
1431 					       fr->fr_age[0], ifs);
1432 			is->is_sti.tqe_flags |= TQE_RULEBASED;
1433 		}
1434 		if (fr->fr_age[1] != 0) {
1435 			is->is_tqehead[1] =
1436 			    fr_addtimeoutqueue(&ifs->ifs_ips_utqe,
1437 					       fr->fr_age[1], ifs);
1438 			is->is_sti.tqe_flags |= TQE_RULEBASED;
1439 		}
1440 		is->is_tag = fr->fr_logtag;
1441 
1442 		is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1];
1443 		is->is_ifp[(1 - out) << 1] = fr->fr_ifas[2];
1444 		is->is_ifp[((1 - out) << 1) + 1] = fr->fr_ifas[3];
1445 
1446 		if (((ifp = fr->fr_ifas[1]) != NULL) &&
1447 		    (ifp != (void *)-1)) {
1448 			COPYIFNAME(ifp, is->is_ifname[(out << 1) + 1], fr->fr_v);
1449 		}
1450 		if (((ifp = fr->fr_ifas[2]) != NULL) &&
1451 		    (ifp != (void *)-1)) {
1452 			COPYIFNAME(ifp, is->is_ifname[(1 - out) << 1], fr->fr_v);
1453 		}
1454 		if (((ifp = fr->fr_ifas[3]) != NULL) &&
1455 		    (ifp != (void *)-1)) {
1456 			COPYIFNAME(ifp, is->is_ifname[((1 - out) << 1) + 1], fr->fr_v);
1457 		}
1458 	}
1459 
1460 	is->is_ifp[out << 1] = fin->fin_ifp;
1461 	if (fin->fin_ifp != NULL) {
1462 		COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1], fr->fr_v);
1463 	}
1464 
1465 	/*
1466 	 * It may seem strange to set is_ref to 2, but fr_check() will call
1467 	 * fr_statederef() after calling fr_addstate() and the idea is to
1468 	 * have it exist at the end of fr_check() with is_ref == 1.
1469 	 */
1470 	is->is_ref = 2;
1471 	is->is_pkts[0] = 0, is->is_bytes[0] = 0;
1472 	is->is_pkts[1] = 0, is->is_bytes[1] = 0;
1473 	is->is_pkts[2] = 0, is->is_bytes[2] = 0;
1474 	is->is_pkts[3] = 0, is->is_bytes[3] = 0;
1475 	if ((fin->fin_flx & FI_IGNORE) == 0) {
1476 		is->is_pkts[out] = 1;
1477 		is->is_bytes[out] = fin->fin_plen;
1478 		is->is_flx[out][0] = fin->fin_flx & FI_CMP;
1479 		is->is_flx[out][0] &= ~FI_OOW;
1480 	}
1481 
1482 	if (pass & FR_STSTRICT)
1483 		is->is_flags |= IS_STRICT;
1484 
1485 	if (pass & FR_STATESYNC)
1486 		is->is_flags |= IS_STATESYNC;
1487 
1488 	if (flags & (SI_WILDP|SI_WILDA)) {
1489 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_wild);
1490 	}
1491 	is->is_rulen = fin->fin_rule;
1492 
1493 
1494 	if (pass & FR_LOGFIRST)
1495 		is->is_pass &= ~(FR_LOGFIRST|FR_LOG);
1496 
1497 	READ_ENTER(&ifs->ifs_ipf_state);
1498 	is->is_me = stsave;
1499 
1500 	fr_stinsert(is, fin->fin_rev, ifs);
1501 
1502 	if (fin->fin_p == IPPROTO_TCP) {
1503 		/*
1504 		* If we're creating state for a starting connection, start the
1505 		* timer on it as we'll never see an error if it fails to
1506 		* connect.
1507 		*/
1508 		(void) fr_tcp_age(&is->is_sti, fin, ifs->ifs_ips_tqtqb,
1509 				  is->is_flags);
1510 		MUTEX_EXIT(&is->is_lock);
1511 #ifdef	IPFILTER_SCAN
1512 		if ((is->is_flags & SI_CLONE) == 0)
1513 			(void) ipsc_attachis(is);
1514 #endif
1515 	} else {
1516 		MUTEX_EXIT(&is->is_lock);
1517 	}
1518 #ifdef	IPFILTER_SYNC
1519 	if ((is->is_flags & IS_STATESYNC) && ((is->is_flags & SI_CLONE) == 0))
1520 		is->is_sync = ipfsync_new(SMC_STATE, fin, is);
1521 #endif
1522 	if (ifs->ifs_ipstate_logging)
1523 		ipstate_log(is, ISL_NEW, ifs);
1524 
1525 	RWLOCK_EXIT(&ifs->ifs_ipf_state);
1526 	fin->fin_state = is;
1527 	fin->fin_rev = IP6_NEQ(&is->is_dst, &fin->fin_daddr);
1528 	fin->fin_flx |= FI_STATE;
1529 	if (fin->fin_flx & FI_FRAG)
1530 		(void) fr_newfrag(fin, pass ^ FR_KEEPSTATE);
1531 
1532 	return is;
1533 }
1534 
1535 
1536 /* ------------------------------------------------------------------------ */
1537 /* Function:    fr_tcpoptions                                               */
1538 /* Returns:     int - 1 == packet matches state entry, 0 == it does not     */
1539 /* Parameters:  fin(I) - pointer to packet information                      */
1540 /*              tcp(I) - pointer to TCP packet header                       */
1541 /*              td(I)  - pointer to TCP data held as part of the state      */
1542 /*                                                                          */
1543 /* Look after the TCP header for any options and deal with those that are   */
1544 /* present.  Record details about those that we recogise.                   */
1545 /* ------------------------------------------------------------------------ */
1546 static int fr_tcpoptions(fin, tcp, td)
1547 fr_info_t *fin;
1548 tcphdr_t *tcp;
1549 tcpdata_t *td;
1550 {
1551 	int off, mlen, ol, i, len, retval;
1552 	char buf[64], *s, opt;
1553 	mb_t *m = NULL;
1554 
1555 	len = (TCP_OFF(tcp) << 2);
1556 	if (fin->fin_dlen < len)
1557 		return 0;
1558 	len -= sizeof(*tcp);
1559 
1560 	off = fin->fin_plen - fin->fin_dlen + sizeof(*tcp) + fin->fin_ipoff;
1561 
1562 	m = fin->fin_m;
1563 	mlen = MSGDSIZE(m) - off;
1564 	if (len > mlen) {
1565 		len = mlen;
1566 		retval = 0;
1567 	} else {
1568 		retval = 1;
1569 	}
1570 
1571 	COPYDATA(m, off, len, buf);
1572 
1573 	for (s = buf; len > 0; ) {
1574 		opt = *s;
1575 		if (opt == TCPOPT_EOL)
1576 			break;
1577 		else if (opt == TCPOPT_NOP)
1578 			ol = 1;
1579 		else {
1580 			if (len < 2)
1581 				break;
1582 			ol = (int)*(s + 1);
1583 			if (ol < 2 || ol > len)
1584 				break;
1585 
1586 			/*
1587 			 * Extract the TCP options we are interested in out of
1588 			 * the header and store them in the the tcpdata struct.
1589 			 */
1590 			switch (opt)
1591 			{
1592 			case TCPOPT_WINDOW :
1593 				if (ol == TCPOLEN_WINDOW) {
1594 					i = (int)*(s + 2);
1595 					if (i > TCP_WSCALE_MAX)
1596 						i = TCP_WSCALE_MAX;
1597 					else if (i < 0)
1598 						i = 0;
1599 					td->td_winscale = i;
1600 					td->td_winflags |= TCP_WSCALE_SEEN |
1601 							    TCP_WSCALE_FIRST;
1602 				} else
1603 					retval = -1;
1604 				break;
1605 			case TCPOPT_MAXSEG :
1606 				/*
1607 				 * So, if we wanted to set the TCP MAXSEG,
1608 				 * it should be done here...
1609 				 */
1610 				if (ol == TCPOLEN_MAXSEG) {
1611 					i = (int)*(s + 2);
1612 					i <<= 8;
1613 					i += (int)*(s + 3);
1614 					td->td_maxseg = i;
1615 				} else
1616 					retval = -1;
1617 				break;
1618 			case TCPOPT_SACK_PERMITTED :
1619 				if (ol == TCPOLEN_SACK_PERMITTED)
1620 					td->td_winflags |= TCP_SACK_PERMIT;
1621 				else
1622 					retval = -1;
1623 				break;
1624 			}
1625 		}
1626 		len -= ol;
1627 		s += ol;
1628 	}
1629 	return retval;
1630 }
1631 
1632 
1633 /* ------------------------------------------------------------------------ */
1634 /* Function:    fr_tcpstate                                                 */
1635 /* Returns:     int - 1 == packet matches state entry, 0 == it does not     */
1636 /* Parameters:  fin(I)   - pointer to packet information                    */
1637 /*              tcp(I)   - pointer to TCP packet header                     */
1638 /*              is(I)  - pointer to master state structure                  */
1639 /*                                                                          */
1640 /* Check to see if a packet with TCP headers fits within the TCP window.    */
1641 /* Change timeout depending on whether new packet is a SYN-ACK returning    */
1642 /* for a SYN or a RST or FIN which indicate time to close up shop.          */
1643 /* ------------------------------------------------------------------------ */
1644 static int fr_tcpstate(fin, tcp, is)
1645 fr_info_t *fin;
1646 tcphdr_t *tcp;
1647 ipstate_t *is;
1648 {
1649 	int source, ret = 0, flags;
1650 	tcpdata_t  *fdata, *tdata;
1651 	ipf_stack_t *ifs = fin->fin_ifs;
1652 
1653 	source = !fin->fin_rev;
1654 	if (((is->is_flags & IS_TCPFSM) != 0) && (source == 1) &&
1655 	    (ntohs(is->is_sport) != fin->fin_data[0]))
1656 		source = 0;
1657 	fdata = &is->is_tcp.ts_data[!source];
1658 	tdata = &is->is_tcp.ts_data[source];
1659 
1660 	MUTEX_ENTER(&is->is_lock);
1661 
1662 	/*
1663 	 * If a SYN packet is received for a connection that is in a half
1664 	 * closed state, then move its state entry to deletetq. In such case
1665 	 * the SYN packet will be consequently dropped. This allows new state
1666 	 * entry to be created with a retransmited SYN packet.
1667 	 */
1668 	if ((tcp->th_flags & TH_OPENING) == TH_SYN) {
1669 		if (((is->is_state[source] > IPF_TCPS_ESTABLISHED) ||
1670 		    (is->is_state[source] == IPF_TCPS_CLOSED)) &&
1671 		    ((is->is_state[!source] > IPF_TCPS_ESTABLISHED) ||
1672 		    (is->is_state[!source] == IPF_TCPS_CLOSED))) {
1673 			/*
1674 			 * Do not update is->is_sti.tqe_die in case state entry
1675 			 * is already present in deletetq. It prevents state
1676 			 * entry ttl update by retransmitted SYN packets, which
1677 			 * may arrive before timer tick kicks off. The SYN
1678 			 * packet will be dropped again.
1679 			 */
1680 			if (is->is_sti.tqe_ifq != &ifs->ifs_ips_deletetq)
1681 				fr_movequeue(&is->is_sti, is->is_sti.tqe_ifq,
1682 					&fin->fin_ifs->ifs_ips_deletetq,
1683 					fin->fin_ifs);
1684 
1685 			MUTEX_EXIT(&is->is_lock);
1686 			return 0;
1687 		}
1688 	}
1689 
1690 	if (fr_tcpinwindow(fin, fdata, tdata, tcp, is->is_flags)) {
1691 #ifdef	IPFILTER_SCAN
1692 		if (is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER)) {
1693 			ipsc_packet(fin, is);
1694 			if (FR_ISBLOCK(is->is_pass)) {
1695 				MUTEX_EXIT(&is->is_lock);
1696 				return 1;
1697 			}
1698 		}
1699 #endif
1700 
1701 		/*
1702 		 * Nearing end of connection, start timeout.
1703 		 */
1704 		ret = fr_tcp_age(&is->is_sti, fin, ifs->ifs_ips_tqtqb,
1705 				 is->is_flags);
1706 		if (ret == 0) {
1707 			MUTEX_EXIT(&is->is_lock);
1708 			return 0;
1709 		}
1710 
1711 		/*
1712 		 * set s0's as appropriate.  Use syn-ack packet as it
1713 		 * contains both pieces of required information.
1714 		 */
1715 		/*
1716 		 * Window scale option is only present in SYN/SYN-ACK packet.
1717 		 * Compare with ~TH_FIN to mask out T/TCP setups.
1718 		 */
1719 		flags = tcp->th_flags & ~(TH_FIN|TH_ECNALL);
1720 		if (flags == (TH_SYN|TH_ACK)) {
1721 			is->is_s0[source] = ntohl(tcp->th_ack);
1722 			is->is_s0[!source] = ntohl(tcp->th_seq) + 1;
1723 			if (TCP_OFF(tcp) > (sizeof (tcphdr_t) >> 2)) {
1724 				(void) fr_tcpoptions(fin, tcp, fdata);
1725 			}
1726 			if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN))
1727 				fr_checknewisn(fin, is);
1728 		} else if (flags == TH_SYN) {
1729 			is->is_s0[source] = ntohl(tcp->th_seq) + 1;
1730 			if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2)))
1731 				(void) fr_tcpoptions(fin, tcp, tdata);
1732 
1733 			if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN))
1734 				fr_checknewisn(fin, is);
1735 
1736 		}
1737 		ret = 1;
1738 	} else
1739 		fin->fin_flx |= FI_OOW;
1740 	MUTEX_EXIT(&is->is_lock);
1741 	return ret;
1742 }
1743 
1744 
1745 /* ------------------------------------------------------------------------ */
1746 /* Function:    fr_checknewisn                                              */
1747 /* Returns:     Nil                                                         */
1748 /* Parameters:  fin(I)   - pointer to packet information                    */
1749 /*              is(I)  - pointer to master state structure                  */
1750 /*                                                                          */
1751 /* Check to see if this TCP connection is expecting and needs a new         */
1752 /* sequence number for a particular direction of the connection.            */
1753 /*                                                                          */
1754 /* NOTE: This does not actually change the sequence numbers, only gets new  */
1755 /* one ready.                                                               */
1756 /* ------------------------------------------------------------------------ */
1757 static void fr_checknewisn(fin, is)
1758 fr_info_t *fin;
1759 ipstate_t *is;
1760 {
1761 	u_32_t sumd, old, new;
1762 	tcphdr_t *tcp;
1763 	int i;
1764 
1765 	i = fin->fin_rev;
1766 	tcp = fin->fin_dp;
1767 
1768 	if (((i == 0) && !(is->is_flags & IS_ISNSYN)) ||
1769 	    ((i == 1) && !(is->is_flags & IS_ISNACK))) {
1770 		old = ntohl(tcp->th_seq);
1771 		new = fr_newisn(fin);
1772 		is->is_isninc[i] = new - old;
1773 		CALC_SUMD(old, new, sumd);
1774 		is->is_sumd[i] = (sumd & 0xffff) + (sumd >> 16);
1775 
1776 		is->is_flags |= ((i == 0) ? IS_ISNSYN : IS_ISNACK);
1777 	}
1778 }
1779 
1780 
1781 /* ------------------------------------------------------------------------ */
1782 /* Function:    fr_tcpinwindow                                              */
1783 /* Returns:     int - 1 == packet inside TCP "window", 0 == not inside.     */
1784 /* Parameters:  fin(I)   - pointer to packet information                    */
1785 /*              fdata(I) - pointer to tcp state informatio (forward)        */
1786 /*              tdata(I) - pointer to tcp state informatio (reverse)        */
1787 /*              tcp(I)   - pointer to TCP packet header                     */
1788 /*                                                                          */
1789 /* Given a packet has matched addresses and ports, check to see if it is    */
1790 /* within the TCP data window.  In a show of generosity, allow packets that */
1791 /* are within the window space behind the current sequence # as well.       */
1792 /* ------------------------------------------------------------------------ */
1793 int fr_tcpinwindow(fin, fdata, tdata, tcp, flags)
1794 fr_info_t *fin;
1795 tcpdata_t  *fdata, *tdata;
1796 tcphdr_t *tcp;
1797 int flags;
1798 {
1799 	tcp_seq seq, ack, end;
1800 	int ackskew, tcpflags;
1801 	u_32_t win, maxwin;
1802 	int dsize, inseq;
1803 
1804 	/*
1805 	 * Find difference between last checked packet and this packet.
1806 	 */
1807 	tcpflags = tcp->th_flags;
1808 	seq = ntohl(tcp->th_seq);
1809 	ack = ntohl(tcp->th_ack);
1810 
1811 	if (tcpflags & TH_SYN)
1812 		win = ntohs(tcp->th_win);
1813 	else
1814 		win = ntohs(tcp->th_win) << fdata->td_winscale;
1815 
1816 	/*
1817 	 * win 0 means the receiving endpoint has closed the window, because it
1818 	 * has not enough memory to receive data from sender. In such case we
1819 	 * are pretending window size to be 1 to let TCP probe data through.
1820 	 * TCP probe data can be either 0 or 1 octet of data, the RFC does not
1821 	 * state this accurately, so we have to allow 1 octet (win = 1) even if
1822 	 * the window is closed (win == 0).
1823 	 */
1824 	if (win == 0)
1825 		win = 1;
1826 
1827 	dsize = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
1828 		((tcpflags & TH_SYN) ? 1 : 0) + ((tcpflags & TH_FIN) ? 1 : 0);
1829 
1830 	/*
1831 	 * if window scaling is present, the scaling is only allowed
1832 	 * for windows not in the first SYN packet. In that packet the
1833 	 * window is 65535 to specify the largest window possible
1834 	 * for receivers not implementing the window scale option.
1835 	 * Currently, we do not assume TTCP here. That means that
1836 	 * if we see a second packet from a host (after the initial
1837 	 * SYN), we can assume that the receiver of the SYN did
1838 	 * already send back the SYN/ACK (and thus that we know if
1839 	 * the receiver also does window scaling)
1840 	 */
1841 	if (!(tcpflags & TH_SYN) && (fdata->td_winflags & TCP_WSCALE_FIRST)) {
1842 		fdata->td_maxwin = win;
1843 	}
1844 
1845 	end = seq + dsize;
1846 
1847 	if ((fdata->td_end == 0) &&
1848 	    (!(flags & IS_TCPFSM) ||
1849 	     ((tcpflags & TH_OPENING) == TH_OPENING))) {
1850 		/*
1851 		 * Must be a (outgoing) SYN-ACK in reply to a SYN.
1852 		 */
1853 		fdata->td_end = end - 1;
1854 		fdata->td_maxwin = 1;
1855 		fdata->td_maxend = end + win;
1856 	}
1857 
1858 	if (!(tcpflags & TH_ACK)) {  /* Pretend an ack was sent */
1859 		ack = tdata->td_end;
1860 	} else if (((tcpflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) &&
1861 		   (ack == 0)) {
1862 		/* gross hack to get around certain broken tcp stacks */
1863 		ack = tdata->td_end;
1864 	}
1865 
1866 	maxwin = tdata->td_maxwin;
1867 	ackskew = tdata->td_end - ack;
1868 
1869 	/*
1870 	 * Strict sequencing only allows in-order delivery.
1871 	 */
1872 	if ((flags & IS_STRICT) != 0) {
1873 		if (seq != fdata->td_end) {
1874 			DTRACE_PROBE(strict_check);
1875 			return 0;
1876 		}
1877 	}
1878 
1879 #define	SEQ_GE(a,b)	((int)((a) - (b)) >= 0)
1880 #define	SEQ_GT(a,b)	((int)((a) - (b)) > 0)
1881 	inseq = 0;
1882 	DTRACE_PROBE4(
1883 		dyn_params,
1884 		int, dsize,
1885 		int, ackskew,
1886 		int, maxwin,
1887 		int, win
1888 	);
1889 	if (
1890 #if defined(_KERNEL)
1891 		/*
1892 		 * end <-> s + n
1893 		 * maxend <-> ack + win
1894 		 * this is upperbound check
1895 		 */
1896 	    (SEQ_GE(fdata->td_maxend, end)) &&
1897 		/*
1898 		 * this is lowerbound check
1899 		 */
1900 	    (SEQ_GE(seq, fdata->td_end - maxwin)) &&
1901 #endif
1902 /* XXX what about big packets */
1903 #define MAXACKWINDOW 66000
1904 	    (-ackskew <= (MAXACKWINDOW << fdata->td_winscale)) &&
1905 	    ( ackskew <= (MAXACKWINDOW << fdata->td_winscale))) {
1906 		inseq = 1;
1907 	/*
1908 	 * Microsoft Windows will send the next packet to the right of the
1909 	 * window if SACK is in use.
1910 	 */
1911 	} else if ((seq == fdata->td_maxend) && (ackskew == 0) &&
1912 	    (fdata->td_winflags & TCP_SACK_PERMIT) &&
1913 	    (tdata->td_winflags & TCP_SACK_PERMIT)) {
1914 		inseq = 1;
1915 	/*
1916 	 * RST ACK with SEQ equal to 0 is sent by some OSes (i.e. Solaris) as a
1917 	 * response to initial SYN packet, when  there is no application
1918 	 * listeing to on a port, where the SYN packet has came to.
1919 	 */
1920 	} else if ((seq == 0) && (tcpflags == (TH_RST|TH_ACK)) &&
1921 			(ackskew >= -1) && (ackskew <= 1)) {
1922 		inseq = 1;
1923 	} else if (!(flags & IS_TCPFSM)) {
1924 
1925 		if (!(fdata->td_winflags &
1926 			    (TCP_WSCALE_SEEN|TCP_WSCALE_FIRST))) {
1927 			/*
1928 			 * No TCPFSM and no window scaling, so make some
1929 			 * extra guesses.
1930 			 */
1931 			if ((seq == fdata->td_maxend) && (ackskew == 0))
1932 				inseq = 1;
1933 			else if (SEQ_GE(seq + maxwin, fdata->td_end - maxwin))
1934 				inseq = 1;
1935 		}
1936 	}
1937 
1938 	if (inseq) {
1939 		/* if ackskew < 0 then this should be due to fragmented
1940 		 * packets. There is no way to know the length of the
1941 		 * total packet in advance.
1942 		 * We do know the total length from the fragment cache though.
1943 		 * Note however that there might be more sessions with
1944 		 * exactly the same source and destination parameters in the
1945 		 * state cache (and source and destination is the only stuff
1946 		 * that is saved in the fragment cache). Note further that
1947 		 * some TCP connections in the state cache are hashed with
1948 		 * sport and dport as well which makes it not worthwhile to
1949 		 * look for them.
1950 		 * Thus, when ackskew is negative but still seems to belong
1951 		 * to this session, we bump up the destinations end value.
1952 		 */
1953 		if (ackskew < 0) {
1954 			DTRACE_PROBE2(end_update_td,
1955 				int, tdata->td_end,
1956 				int, ack
1957 			);
1958 			tdata->td_end = ack;
1959 		}
1960 
1961 		/* update max window seen */
1962 		if (fdata->td_maxwin < win) {
1963 			DTRACE_PROBE2(win_update_fd,
1964 				int, fdata->td_maxwin,
1965 				int, win
1966 			);
1967 			fdata->td_maxwin = win;
1968 		}
1969 
1970 		if (SEQ_GT(end, fdata->td_end)) {
1971 			DTRACE_PROBE2(end_update_fd,
1972 				int, fdata->td_end,
1973 				int, end
1974 			);
1975 			fdata->td_end = end;
1976 		}
1977 
1978 		if (SEQ_GE(ack + win, tdata->td_maxend)) {
1979 			DTRACE_PROBE2(max_end_update_td,
1980 				int, tdata->td_maxend,
1981 				int, ack + win
1982 			);
1983 			tdata->td_maxend = ack + win;
1984 		}
1985 
1986 		return 1;
1987 	}
1988 	fin->fin_flx |= FI_OOW;
1989 
1990 #if defined(_KERNEL)
1991 	if (!(SEQ_GE(seq, fdata->td_end - maxwin)))
1992 		fin->fin_flx |= FI_NEG_OOW;
1993 #endif
1994 
1995 	return 0;
1996 }
1997 
1998 
1999 /* ------------------------------------------------------------------------ */
2000 /* Function:    fr_stclone                                                  */
2001 /* Returns:     ipstate_t* - NULL == cloning failed,                        */
2002 /*                           else pointer to new state structure            */
2003 /* Parameters:  fin(I) - pointer to packet information                      */
2004 /*              tcp(I) - pointer to TCP/UDP header                          */
2005 /*              is(I)  - pointer to master state structure                  */
2006 /*                                                                          */
2007 /* Create a "duplcate" state table entry from the master.                   */
2008 /* ------------------------------------------------------------------------ */
2009 static ipstate_t *fr_stclone(fin, tcp, is)
2010 fr_info_t *fin;
2011 tcphdr_t *tcp;
2012 ipstate_t *is;
2013 {
2014 	ipstate_t *clone;
2015 	u_32_t send;
2016 	ipf_stack_t *ifs = fin->fin_ifs;
2017 
2018 	/*
2019 	 * Trigger automatic call to fr_state_flush() if the
2020 	 * table has reached capacity specified by hi watermark.
2021 	 */
2022 	if (ST_TAB_WATER_LEVEL(ifs) > ifs->ifs_state_flush_level_hi)
2023 		ifs->ifs_fr_state_doflush = 1;
2024 
2025 	/*
2026 	 * If automatic flushing did not do its job, and the table
2027 	 * has filled up, don't try to create a new entry.  A NULL
2028 	 * return will indicate that the cloning has failed.
2029 	 */
2030 	if (ifs->ifs_ips_num >= ifs->ifs_fr_statemax) {
2031 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_max);
2032 		return NULL;
2033 	}
2034 
2035 	KMALLOC(clone, ipstate_t *);
2036 	if (clone == NULL)
2037 		return NULL;
2038 	bcopy((char *)is, (char *)clone, sizeof(*clone));
2039 
2040 	MUTEX_NUKE(&clone->is_lock);
2041 
2042 	clone->is_die = ONE_DAY + ifs->ifs_fr_ticks;
2043 	clone->is_state[0] = 0;
2044 	clone->is_state[1] = 0;
2045 	send = ntohl(tcp->th_seq) + fin->fin_dlen - (TCP_OFF(tcp) << 2) +
2046 		((tcp->th_flags & TH_SYN) ? 1 : 0) +
2047 		((tcp->th_flags & TH_FIN) ? 1 : 0);
2048 
2049 	if (fin->fin_rev == 1) {
2050 		clone->is_dend = send;
2051 		clone->is_maxdend = send;
2052 		clone->is_send = 0;
2053 		clone->is_maxswin = 1;
2054 		clone->is_maxdwin = ntohs(tcp->th_win);
2055 		if (clone->is_maxdwin == 0)
2056 			clone->is_maxdwin = 1;
2057 	} else {
2058 		clone->is_send = send;
2059 		clone->is_maxsend = send;
2060 		clone->is_dend = 0;
2061 		clone->is_maxdwin = 1;
2062 		clone->is_maxswin = ntohs(tcp->th_win);
2063 		if (clone->is_maxswin == 0)
2064 			clone->is_maxswin = 1;
2065 	}
2066 
2067 	clone->is_flags &= ~SI_CLONE;
2068 	clone->is_flags |= SI_CLONED;
2069 	fr_stinsert(clone, fin->fin_rev, ifs);
2070 	clone->is_ref = 2;
2071 	if (clone->is_p == IPPROTO_TCP) {
2072 		(void) fr_tcp_age(&clone->is_sti, fin, ifs->ifs_ips_tqtqb,
2073 				  clone->is_flags);
2074 	}
2075 	MUTEX_EXIT(&clone->is_lock);
2076 #ifdef	IPFILTER_SCAN
2077 	(void) ipsc_attachis(is);
2078 #endif
2079 #ifdef	IPFILTER_SYNC
2080 	if (is->is_flags & IS_STATESYNC)
2081 		clone->is_sync = ipfsync_new(SMC_STATE, fin, clone);
2082 #endif
2083 	return clone;
2084 }
2085 
2086 
2087 /* ------------------------------------------------------------------------ */
2088 /* Function:    fr_matchsrcdst                                              */
2089 /* Returns:     Nil                                                         */
2090 /* Parameters:  fin(I) - pointer to packet information                      */
2091 /*              is(I)  - pointer to state structure                         */
2092 /*              src(I) - pointer to source address                          */
2093 /*              dst(I) - pointer to destination address                     */
2094 /*              tcp(I) - pointer to TCP/UDP header                          */
2095 /*                                                                          */
2096 /* Match a state table entry against an IP packet.  The logic below is that */
2097 /* ret gets set to one if the match succeeds, else remains 0.  If it is     */
2098 /* still 0 after the test. no match.                                        */
2099 /* ------------------------------------------------------------------------ */
2100 static ipstate_t *fr_matchsrcdst(fin, is, src, dst, tcp, cmask)
2101 fr_info_t *fin;
2102 ipstate_t *is;
2103 i6addr_t *src, *dst;
2104 tcphdr_t *tcp;
2105 u_32_t cmask;
2106 {
2107 	int ret = 0, rev, out, flags, flx = 0, idx;
2108 	u_short sp, dp;
2109 	u_32_t cflx;
2110 	void *ifp;
2111 	ipf_stack_t *ifs = fin->fin_ifs;
2112 
2113 	rev = IP6_NEQ(&is->is_dst, dst);
2114 	ifp = fin->fin_ifp;
2115 	out = fin->fin_out;
2116 	flags = is->is_flags;
2117 	sp = 0;
2118 	dp = 0;
2119 
2120 	if (tcp != NULL) {
2121 		sp = htons(fin->fin_sport);
2122 		dp = ntohs(fin->fin_dport);
2123 	}
2124 	if (!rev) {
2125 		if (tcp != NULL) {
2126 			if (!(flags & SI_W_SPORT) && (sp != is->is_sport))
2127 				rev = 1;
2128 			else if (!(flags & SI_W_DPORT) && (dp != is->is_dport))
2129 				rev = 1;
2130 		}
2131 	}
2132 
2133 	idx = (out << 1) + rev;
2134 
2135 	/*
2136 	 * If the interface for this 'direction' is set, make sure it matches.
2137 	 * An interface name that is not set matches any, as does a name of *.
2138 	 */
2139 	if ((is->is_ifp[idx] == NULL &&
2140 	    (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) ||
2141 	    is->is_ifp[idx] == ifp)
2142 		ret = 1;
2143 
2144 	if (ret == 0)
2145 		return NULL;
2146 	ret = 0;
2147 
2148 	/*
2149 	 * Match addresses and ports.
2150 	 */
2151 	if (rev == 0) {
2152 		if ((IP6_EQ(&is->is_dst, dst) || (flags & SI_W_DADDR)) &&
2153 		    (IP6_EQ(&is->is_src, src) || (flags & SI_W_SADDR))) {
2154 			if (tcp) {
2155 				if ((sp == is->is_sport || flags & SI_W_SPORT)&&
2156 				    (dp == is->is_dport || flags & SI_W_DPORT))
2157 					ret = 1;
2158 			} else {
2159 				ret = 1;
2160 			}
2161 		}
2162 	} else {
2163 		if ((IP6_EQ(&is->is_dst, src) || (flags & SI_W_DADDR)) &&
2164 		    (IP6_EQ(&is->is_src, dst) || (flags & SI_W_SADDR))) {
2165 			if (tcp) {
2166 				if ((dp == is->is_sport || flags & SI_W_SPORT)&&
2167 				    (sp == is->is_dport || flags & SI_W_DPORT))
2168 					ret = 1;
2169 			} else {
2170 				ret = 1;
2171 			}
2172 		}
2173 	}
2174 
2175 	if (ret == 0)
2176 		return NULL;
2177 
2178 	/*
2179 	 * Whether or not this should be here, is questionable, but the aim
2180 	 * is to get this out of the main line.
2181 	 */
2182 	if (tcp == NULL)
2183 		flags = is->is_flags & ~(SI_WILDP|SI_NEWFR|SI_CLONE|SI_CLONED);
2184 
2185 	/*
2186 	 * Only one of the source or destination address can be flaged as a
2187 	 * wildcard.  Fill in the missing address, if set.
2188 	 * For IPv6, if the address being copied in is multicast, then
2189 	 * don't reset the wild flag - multicast causes it to be set in the
2190 	 * first place!
2191 	 */
2192 	if ((flags & (SI_W_SADDR|SI_W_DADDR))) {
2193 		fr_ip_t *fi = &fin->fin_fi;
2194 
2195 		if ((flags & SI_W_SADDR) != 0) {
2196 			if (rev == 0) {
2197 #ifdef USE_INET6
2198 				if (is->is_v == 6 &&
2199 				    IN6_IS_ADDR_MULTICAST(&fi->fi_src.in6))
2200 					/*EMPTY*/;
2201 				else
2202 #endif
2203 				{
2204 					is->is_src = fi->fi_src;
2205 					is->is_flags &= ~SI_W_SADDR;
2206 				}
2207 			} else {
2208 #ifdef USE_INET6
2209 				if (is->is_v == 6 &&
2210 				    IN6_IS_ADDR_MULTICAST(&fi->fi_dst.in6))
2211 					/*EMPTY*/;
2212 				else
2213 #endif
2214 				{
2215 					is->is_src = fi->fi_dst;
2216 					is->is_flags &= ~SI_W_SADDR;
2217 				}
2218 			}
2219 		} else if ((flags & SI_W_DADDR) != 0) {
2220 			if (rev == 0) {
2221 #ifdef USE_INET6
2222 				if (is->is_v == 6 &&
2223 				    IN6_IS_ADDR_MULTICAST(&fi->fi_dst.in6))
2224 					/*EMPTY*/;
2225 				else
2226 #endif
2227 				{
2228 					is->is_dst = fi->fi_dst;
2229 					is->is_flags &= ~SI_W_DADDR;
2230 				}
2231 			} else {
2232 #ifdef USE_INET6
2233 				if (is->is_v == 6 &&
2234 				    IN6_IS_ADDR_MULTICAST(&fi->fi_src.in6))
2235 					/*EMPTY*/;
2236 				else
2237 #endif
2238 				{
2239 					is->is_dst = fi->fi_src;
2240 					is->is_flags &= ~SI_W_DADDR;
2241 				}
2242 			}
2243 		}
2244 		if ((is->is_flags & (SI_WILDA|SI_WILDP)) == 0) {
2245 			ATOMIC_DECL(ifs->ifs_ips_stats.iss_wild);
2246 		}
2247 	}
2248 
2249 	flx = fin->fin_flx & cmask;
2250 	cflx = is->is_flx[out][rev];
2251 
2252 	/*
2253 	 * Match up any flags set from IP options.
2254 	 */
2255 	if ((cflx && (flx != (cflx & cmask))) ||
2256 	    ((fin->fin_optmsk & is->is_optmsk[rev]) != is->is_opt[rev]) ||
2257 	    ((fin->fin_secmsk & is->is_secmsk) != is->is_sec) ||
2258 	    ((fin->fin_auth & is->is_authmsk) != is->is_auth))
2259 		return NULL;
2260 
2261 	/*
2262 	 * Only one of the source or destination port can be flagged as a
2263 	 * wildcard.  When filling it in, fill in a copy of the matched entry
2264 	 * if it has the cloning flag set.
2265 	 */
2266 	if ((fin->fin_flx & FI_IGNORE) != 0) {
2267 		fin->fin_rev = rev;
2268 		return is;
2269 	}
2270 
2271 	if ((flags & (SI_W_SPORT|SI_W_DPORT))) {
2272 		if ((flags & SI_CLONE) != 0) {
2273 			ipstate_t *clone;
2274 
2275 			clone = fr_stclone(fin, tcp, is);
2276 			if (clone == NULL)
2277 				return NULL;
2278 			is = clone;
2279 		} else {
2280 			ATOMIC_DECL(ifs->ifs_ips_stats.iss_wild);
2281 		}
2282 
2283 		if ((flags & SI_W_SPORT) != 0) {
2284 			if (rev == 0) {
2285 				is->is_sport = sp;
2286 				is->is_send = ntohl(tcp->th_seq);
2287 			} else {
2288 				is->is_sport = dp;
2289 				is->is_send = ntohl(tcp->th_ack);
2290 			}
2291 			is->is_maxsend = is->is_send + 1;
2292 		} else if ((flags & SI_W_DPORT) != 0) {
2293 			if (rev == 0) {
2294 				is->is_dport = dp;
2295 				is->is_dend = ntohl(tcp->th_ack);
2296 			} else {
2297 				is->is_dport = sp;
2298 				is->is_dend = ntohl(tcp->th_seq);
2299 			}
2300 			is->is_maxdend = is->is_dend + 1;
2301 		}
2302 		is->is_flags &= ~(SI_W_SPORT|SI_W_DPORT);
2303 		if ((flags & SI_CLONED) && ifs->ifs_ipstate_logging)
2304 			ipstate_log(is, ISL_CLONE, ifs);
2305 	}
2306 
2307 	ret = -1;
2308 
2309 	if (is->is_flx[out][rev] == 0) {
2310 		is->is_flx[out][rev] = flx;
2311 		is->is_opt[rev] = fin->fin_optmsk;
2312 		if (is->is_v == 6) {
2313 			is->is_opt[rev] &= ~0x8;
2314 			is->is_optmsk[rev] &= ~0x8;
2315 		}
2316 	}
2317 
2318 	/*
2319 	 * Check if the interface name for this "direction" is set and if not,
2320 	 * fill it in.
2321 	 */
2322 	if (is->is_ifp[idx] == NULL &&
2323 	    (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) {
2324 		is->is_ifp[idx] = ifp;
2325 		COPYIFNAME(ifp, is->is_ifname[idx], fin->fin_v);
2326 	}
2327 	fin->fin_rev = rev;
2328 	return is;
2329 }
2330 
2331 
2332 /* ------------------------------------------------------------------------ */
2333 /* Function:    fr_checkicmpmatchingstate                                   */
2334 /* Returns:     Nil                                                         */
2335 /* Parameters:  fin(I) - pointer to packet information                      */
2336 /*                                                                          */
2337 /* If we've got an ICMP error message, using the information stored in the  */
2338 /* ICMP packet, look for a matching state table entry.                      */
2339 /*                                                                          */
2340 /* If we return NULL then no lock on ipf_state is held.                     */
2341 /* If we return non-null then a read-lock on ipf_state is held.             */
2342 /* ------------------------------------------------------------------------ */
2343 static ipstate_t *fr_checkicmpmatchingstate(fin)
2344 fr_info_t *fin;
2345 {
2346 	ipstate_t *is, **isp;
2347 	u_short sport, dport;
2348 	u_char	pr;
2349 	int backward, i, oi;
2350 	i6addr_t dst, src;
2351 	struct icmp *ic;
2352 	u_short savelen;
2353 	icmphdr_t *icmp;
2354 	fr_info_t ofin;
2355 	tcphdr_t *tcp;
2356 	int len;
2357 	ip_t *oip;
2358 	u_int hv;
2359 	ipf_stack_t *ifs = fin->fin_ifs;
2360 
2361 	/*
2362 	 * Does it at least have the return (basic) IP header ?
2363 	 * Is it an actual recognised ICMP error type?
2364 	 * Only a basic IP header (no options) should be with
2365 	 * an ICMP error header.
2366 	 */
2367 	if ((fin->fin_v != 4) || (fin->fin_hlen != sizeof(ip_t)) ||
2368 	    (fin->fin_plen < ICMPERR_MINPKTLEN) ||
2369 	    !(fin->fin_flx & FI_ICMPERR))
2370 		return NULL;
2371 	ic = fin->fin_dp;
2372 
2373 	oip = (ip_t *)((char *)ic + ICMPERR_ICMPHLEN);
2374 	/*
2375 	 * Check if the at least the old IP header (with options) and
2376 	 * 8 bytes of payload is present.
2377 	 */
2378 	if (fin->fin_plen < ICMPERR_MAXPKTLEN + ((IP_HL(oip) - 5) << 2))
2379 		return NULL;
2380 
2381 	/*
2382 	 * Sanity Checks.
2383 	 */
2384 	len = fin->fin_dlen - ICMPERR_ICMPHLEN;
2385 	if ((len <= 0) || ((IP_HL(oip) << 2) > len))
2386 		return NULL;
2387 
2388 	/*
2389 	 * Is the buffer big enough for all of it ?  It's the size of the IP
2390 	 * header claimed in the encapsulated part which is of concern.  It
2391 	 * may be too big to be in this buffer but not so big that it's
2392 	 * outside the ICMP packet, leading to TCP deref's causing problems.
2393 	 * This is possible because we don't know how big oip_hl is when we
2394 	 * do the pullup early in fr_check() and thus can't guarantee it is
2395 	 * all here now.
2396 	 */
2397 #ifdef  _KERNEL
2398 	{
2399 	mb_t *m;
2400 
2401 	m = fin->fin_m;
2402 # if defined(MENTAT)
2403 	if ((char *)oip + len > (char *)m->b_wptr)
2404 		return NULL;
2405 # else
2406 	if ((char *)oip + len > (char *)fin->fin_ip + m->m_len)
2407 		return NULL;
2408 # endif
2409 	}
2410 #endif
2411 	bcopy((char *)fin, (char *)&ofin, sizeof(*fin));
2412 
2413 	/*
2414 	 * in the IPv4 case we must zero the i6addr union otherwise
2415 	 * the IP6_EQ and IP6_NEQ macros produce the wrong results because
2416 	 * of the 'junk' in the unused part of the union
2417 	 */
2418 	bzero((char *)&src, sizeof(src));
2419 	bzero((char *)&dst, sizeof(dst));
2420 
2421 	/*
2422 	 * we make an fin entry to be able to feed it to
2423 	 * matchsrcdst note that not all fields are encessary
2424 	 * but this is the cleanest way. Note further we fill
2425 	 * in fin_mp such that if someone uses it we'll get
2426 	 * a kernel panic. fr_matchsrcdst does not use this.
2427 	 *
2428 	 * watch out here, as ip is in host order and oip in network
2429 	 * order. Any change we make must be undone afterwards, like
2430 	 * oip->ip_off - it is still in network byte order so fix it.
2431 	 */
2432 	savelen = oip->ip_len;
2433 	oip->ip_len = len;
2434 	oip->ip_off = ntohs(oip->ip_off);
2435 
2436 	ofin.fin_flx = FI_NOCKSUM;
2437 	ofin.fin_v = 4;
2438 	ofin.fin_ip = oip;
2439 	ofin.fin_m = NULL;	/* if dereferenced, panic XXX */
2440 	ofin.fin_mp = NULL;	/* if dereferenced, panic XXX */
2441 	ofin.fin_plen = fin->fin_dlen - ICMPERR_ICMPHLEN;
2442 	(void) fr_makefrip(IP_HL(oip) << 2, oip, &ofin);
2443 	ofin.fin_ifp = fin->fin_ifp;
2444 	ofin.fin_out = !fin->fin_out;
2445 	/*
2446 	 * Reset the short and bad flag here because in fr_matchsrcdst()
2447 	 * the flags for the current packet (fin_flx) are compared against
2448 	 * those for the existing session.
2449 	 */
2450 	ofin.fin_flx &= ~(FI_BAD|FI_SHORT);
2451 
2452 	/*
2453 	 * Put old values of ip_len and ip_off back as we don't know
2454 	 * if we have to forward the packet (or process it again.
2455 	 */
2456 	oip->ip_len = savelen;
2457 	oip->ip_off = htons(oip->ip_off);
2458 
2459 	switch (oip->ip_p)
2460 	{
2461 	case IPPROTO_ICMP :
2462 		/*
2463 		 * an ICMP error can only be generated as a result of an
2464 		 * ICMP query, not as the response on an ICMP error
2465 		 *
2466 		 * XXX theoretically ICMP_ECHOREP and the other reply's are
2467 		 * ICMP query's as well, but adding them here seems strange XXX
2468 		 */
2469 		if ((ofin.fin_flx & FI_ICMPERR) != 0)
2470 		    	return NULL;
2471 
2472 		/*
2473 		 * perform a lookup of the ICMP packet in the state table
2474 		 */
2475 		icmp = (icmphdr_t *)((char *)oip + (IP_HL(oip) << 2));
2476 		hv = (pr = oip->ip_p);
2477 		src.in4 = oip->ip_src;
2478 		hv += src.in4.s_addr;
2479 		dst.in4 = oip->ip_dst;
2480 		hv += dst.in4.s_addr;
2481 		hv += icmp->icmp_id;
2482 		hv = DOUBLE_HASH(hv, ifs);
2483 
2484 		READ_ENTER(&ifs->ifs_ipf_state);
2485 		for (isp = &ifs->ifs_ips_table[hv]; ((is = *isp) != NULL); ) {
2486 			isp = &is->is_hnext;
2487 			if ((is->is_p != pr) || (is->is_v != 4))
2488 				continue;
2489 			if (is->is_pass & FR_NOICMPERR)
2490 				continue;
2491 			is = fr_matchsrcdst(&ofin, is, &src, &dst,
2492 					    NULL, FI_ICMPCMP);
2493 			if (is != NULL) {
2494 				if ((is->is_pass & FR_NOICMPERR) != 0) {
2495 					RWLOCK_EXIT(&ifs->ifs_ipf_state);
2496 					return NULL;
2497 				}
2498 				/*
2499 				 * i  : the index of this packet (the icmp
2500 				 *      unreachable)
2501 				 * oi : the index of the original packet found
2502 				 *      in the icmp header (i.e. the packet
2503 				 *      causing this icmp)
2504 				 * backward : original packet was backward
2505 				 *      compared to the state
2506 				 */
2507 				backward = IP6_NEQ(&is->is_src, &src);
2508 				fin->fin_rev = !backward;
2509 				i = (!backward << 1) + fin->fin_out;
2510 				oi = (backward << 1) + ofin.fin_out;
2511 				if (is->is_icmppkts[i] > is->is_pkts[oi])
2512 					continue;
2513 				ifs->ifs_ips_stats.iss_hits++;
2514 				is->is_icmppkts[i]++;
2515 				return is;
2516 			}
2517 		}
2518 		RWLOCK_EXIT(&ifs->ifs_ipf_state);
2519 		return NULL;
2520 	case IPPROTO_TCP :
2521 	case IPPROTO_UDP :
2522 		break;
2523 	default :
2524 		return NULL;
2525 	}
2526 
2527 	tcp = (tcphdr_t *)((char *)oip + (IP_HL(oip) << 2));
2528 	dport = tcp->th_dport;
2529 	sport = tcp->th_sport;
2530 
2531 	hv = (pr = oip->ip_p);
2532 	src.in4 = oip->ip_src;
2533 	hv += src.in4.s_addr;
2534 	dst.in4 = oip->ip_dst;
2535 	hv += dst.in4.s_addr;
2536 	hv += dport;
2537 	hv += sport;
2538 	hv = DOUBLE_HASH(hv, ifs);
2539 
2540 	READ_ENTER(&ifs->ifs_ipf_state);
2541 	for (isp = &ifs->ifs_ips_table[hv]; ((is = *isp) != NULL); ) {
2542 		isp = &is->is_hnext;
2543 		/*
2544 		 * Only allow this icmp though if the
2545 		 * encapsulated packet was allowed through the
2546 		 * other way around. Note that the minimal amount
2547 		 * of info present does not allow for checking against
2548 		 * tcp internals such as seq and ack numbers.   Only the
2549 		 * ports are known to be present and can be even if the
2550 		 * short flag is set.
2551 		 */
2552 		if ((is->is_p == pr) && (is->is_v == 4) &&
2553 		    (is = fr_matchsrcdst(&ofin, is, &src, &dst,
2554 					 tcp, FI_ICMPCMP))) {
2555 			/*
2556 			 * i  : the index of this packet (the icmp unreachable)
2557 			 * oi : the index of the original packet found in the
2558 			 *      icmp header (i.e. the packet causing this icmp)
2559 			 * backward : original packet was backward compared to
2560 			 *            the state
2561 			 */
2562 			backward = IP6_NEQ(&is->is_src, &src);
2563 			fin->fin_rev = !backward;
2564 			i = (!backward << 1) + fin->fin_out;
2565 			oi = (backward << 1) + ofin.fin_out;
2566 
2567 			if (((is->is_pass & FR_NOICMPERR) != 0) ||
2568 			    (is->is_icmppkts[i] > is->is_pkts[oi]))
2569 				break;
2570 			ifs->ifs_ips_stats.iss_hits++;
2571 			is->is_icmppkts[i]++;
2572 			/*
2573 			 * we deliberately do not touch the timeouts
2574 			 * for the accompanying state table entry.
2575 			 * It remains to be seen if that is correct. XXX
2576 			 */
2577 			return is;
2578 		}
2579 	}
2580 	RWLOCK_EXIT(&ifs->ifs_ipf_state);
2581 	return NULL;
2582 }
2583 
2584 
2585 /* ------------------------------------------------------------------------ */
2586 /* Function:    fr_ipsmove                                                  */
2587 /* Returns:     Nil                                                         */
2588 /* Parameters:  is(I) - pointer to state table entry                        */
2589 /*              hv(I) - new hash value for state table entry                */
2590 /* Write Locks: ipf_state                                                   */
2591 /*                                                                          */
2592 /* Move a state entry from one position in the hash table to another.       */
2593 /* ------------------------------------------------------------------------ */
2594 static void fr_ipsmove(is, hv, ifs)
2595 ipstate_t *is;
2596 u_int hv;
2597 ipf_stack_t *ifs;
2598 {
2599 	ipstate_t **isp;
2600 	u_int hvm;
2601 
2602 	ASSERT(rw_read_locked(&ifs->ifs_ipf_state.ipf_lk) == 0);
2603 
2604 	hvm = is->is_hv;
2605 	/*
2606 	 * Remove the hash from the old location...
2607 	 */
2608 	isp = is->is_phnext;
2609 	if (is->is_hnext)
2610 		is->is_hnext->is_phnext = isp;
2611 	*isp = is->is_hnext;
2612 	if (ifs->ifs_ips_table[hvm] == NULL)
2613 		ifs->ifs_ips_stats.iss_inuse--;
2614 	ifs->ifs_ips_stats.iss_bucketlen[hvm]--;
2615 
2616 	/*
2617 	 * ...and put the hash in the new one.
2618 	 */
2619 	hvm = DOUBLE_HASH(hv, ifs);
2620 	is->is_hv = hvm;
2621 	isp = &ifs->ifs_ips_table[hvm];
2622 	if (*isp)
2623 		(*isp)->is_phnext = &is->is_hnext;
2624 	else
2625 		ifs->ifs_ips_stats.iss_inuse++;
2626 	ifs->ifs_ips_stats.iss_bucketlen[hvm]++;
2627 	is->is_phnext = isp;
2628 	is->is_hnext = *isp;
2629 	*isp = is;
2630 }
2631 
2632 
2633 /* ------------------------------------------------------------------------ */
2634 /* Function:    fr_stlookup                                                 */
2635 /* Returns:     ipstate_t* - NULL == no matching state found,               */
2636 /*                           else pointer to state information is returned  */
2637 /* Parameters:  fin(I) - pointer to packet information                      */
2638 /*              tcp(I) - pointer to TCP/UDP header.                         */
2639 /*                                                                          */
2640 /* Search the state table for a matching entry to the packet described by   */
2641 /* the contents of *fin.                                                    */
2642 /*                                                                          */
2643 /* If we return NULL then no lock on ipf_state is held.                     */
2644 /* If we return non-null then a read-lock on ipf_state is held.             */
2645 /* ------------------------------------------------------------------------ */
2646 ipstate_t *fr_stlookup(fin, tcp, ifqp)
2647 fr_info_t *fin;
2648 tcphdr_t *tcp;
2649 ipftq_t **ifqp;
2650 {
2651 	u_int hv, hvm, pr, v, tryagain;
2652 	ipstate_t *is, **isp;
2653 	u_short dport, sport;
2654 	i6addr_t src, dst;
2655 	struct icmp *ic;
2656 	ipftq_t *ifq;
2657 	int oow;
2658 	ipf_stack_t *ifs = fin->fin_ifs;
2659 
2660 	is = NULL;
2661 	ifq = NULL;
2662 	tcp = fin->fin_dp;
2663 	ic = (struct icmp *)tcp;
2664 	hv = (pr = fin->fin_fi.fi_p);
2665 	src = fin->fin_fi.fi_src;
2666 	dst = fin->fin_fi.fi_dst;
2667 	hv += src.in4.s_addr;
2668 	hv += dst.in4.s_addr;
2669 
2670 	v = fin->fin_fi.fi_v;
2671 #ifdef	USE_INET6
2672 	if (v == 6) {
2673 		hv  += fin->fin_fi.fi_src.i6[1];
2674 		hv  += fin->fin_fi.fi_src.i6[2];
2675 		hv  += fin->fin_fi.fi_src.i6[3];
2676 
2677 		if ((fin->fin_p == IPPROTO_ICMPV6) &&
2678 		    IN6_IS_ADDR_MULTICAST(&fin->fin_fi.fi_dst.in6)) {
2679 			hv -= dst.in4.s_addr;
2680 		} else {
2681 			hv += fin->fin_fi.fi_dst.i6[1];
2682 			hv += fin->fin_fi.fi_dst.i6[2];
2683 			hv += fin->fin_fi.fi_dst.i6[3];
2684 		}
2685 	}
2686 #endif
2687 	if ((v == 4) &&
2688 	    (fin->fin_flx & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST))) {
2689 		if (fin->fin_out == 0) {
2690 			hv -= src.in4.s_addr;
2691 		} else {
2692 			hv -= dst.in4.s_addr;
2693 		}
2694 	}
2695 
2696 	/*
2697 	 * Search the hash table for matching packet header info.
2698 	 */
2699 	switch (pr)
2700 	{
2701 #ifdef	USE_INET6
2702 	case IPPROTO_ICMPV6 :
2703 		tryagain = 0;
2704 		if (v == 6) {
2705 			if ((ic->icmp_type == ICMP6_ECHO_REQUEST) ||
2706 			    (ic->icmp_type == ICMP6_ECHO_REPLY)) {
2707 				hv += ic->icmp_id;
2708 			}
2709 		}
2710 		READ_ENTER(&ifs->ifs_ipf_state);
2711 icmp6again:
2712 		hvm = DOUBLE_HASH(hv, ifs);
2713 		for (isp = &ifs->ifs_ips_table[hvm]; ((is = *isp) != NULL); ) {
2714 			isp = &is->is_hnext;
2715 			if ((is->is_p != pr) || (is->is_v != v))
2716 				continue;
2717 			is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP);
2718 			if (is != NULL &&
2719 			    fr_matchicmpqueryreply(v, &is->is_icmp,
2720 						   ic, fin->fin_rev)) {
2721 				if (fin->fin_rev)
2722 					ifq = &ifs->ifs_ips_icmpacktq;
2723 				else
2724 					ifq = &ifs->ifs_ips_icmptq;
2725 				break;
2726 			}
2727 		}
2728 
2729 		if (is != NULL) {
2730 			if ((tryagain != 0) && !(is->is_flags & SI_W_DADDR)) {
2731 				hv += fin->fin_fi.fi_src.i6[0];
2732 				hv += fin->fin_fi.fi_src.i6[1];
2733 				hv += fin->fin_fi.fi_src.i6[2];
2734 				hv += fin->fin_fi.fi_src.i6[3];
2735 				fr_ipsmove(is, hv, ifs);
2736 				MUTEX_DOWNGRADE(&ifs->ifs_ipf_state);
2737 			}
2738 			break;
2739 		}
2740 		RWLOCK_EXIT(&ifs->ifs_ipf_state);
2741 
2742 		/*
2743 		 * No matching icmp state entry. Perhaps this is a
2744 		 * response to another state entry.
2745 		 *
2746 		 * XXX With some ICMP6 packets, the "other" address is already
2747 		 * in the packet, after the ICMP6 header, and this could be
2748 		 * used in place of the multicast address.  However, taking
2749 		 * advantage of this requires some significant code changes
2750 		 * to handle the specific types where that is the case.
2751 		 */
2752 		if ((ifs->ifs_ips_stats.iss_wild != 0) && (v == 6) && (tryagain == 0) &&
2753 		    !IN6_IS_ADDR_MULTICAST(&fin->fin_fi.fi_src.in6)) {
2754 			hv -= fin->fin_fi.fi_src.i6[0];
2755 			hv -= fin->fin_fi.fi_src.i6[1];
2756 			hv -= fin->fin_fi.fi_src.i6[2];
2757 			hv -= fin->fin_fi.fi_src.i6[3];
2758 			tryagain = 1;
2759 			WRITE_ENTER(&ifs->ifs_ipf_state);
2760 			goto icmp6again;
2761 		}
2762 
2763 		is = fr_checkicmp6matchingstate(fin);
2764 		if (is != NULL)
2765 			return is;
2766 		break;
2767 #endif
2768 
2769 	case IPPROTO_ICMP :
2770 		if (v == 4) {
2771 			hv += ic->icmp_id;
2772 		}
2773 		hv = DOUBLE_HASH(hv, ifs);
2774 		READ_ENTER(&ifs->ifs_ipf_state);
2775 		for (isp = &ifs->ifs_ips_table[hv]; ((is = *isp) != NULL); ) {
2776 			isp = &is->is_hnext;
2777 			if ((is->is_p != pr) || (is->is_v != v))
2778 				continue;
2779 			is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP);
2780 			if (is != NULL &&
2781 			    fr_matchicmpqueryreply(v, &is->is_icmp,
2782 						   ic, fin->fin_rev)) {
2783 				if (fin->fin_rev)
2784 					ifq = &ifs->ifs_ips_icmpacktq;
2785 				else
2786 					ifq = &ifs->ifs_ips_icmptq;
2787 				break;
2788 			}
2789 		}
2790 		if (is == NULL) {
2791 			RWLOCK_EXIT(&ifs->ifs_ipf_state);
2792 		}
2793 		break;
2794 
2795 	case IPPROTO_TCP :
2796 	case IPPROTO_UDP :
2797 		ifqp = NULL;
2798 		sport = htons(fin->fin_data[0]);
2799 		hv += sport;
2800 		dport = htons(fin->fin_data[1]);
2801 		hv += dport;
2802 		oow = 0;
2803 		tryagain = 0;
2804 		READ_ENTER(&ifs->ifs_ipf_state);
2805 retry_tcpudp:
2806 		hvm = DOUBLE_HASH(hv, ifs);
2807 		for (isp = &ifs->ifs_ips_table[hvm]; ((is = *isp) != NULL); ) {
2808 			isp = &is->is_hnext;
2809 			if ((is->is_p != pr) || (is->is_v != v))
2810 				continue;
2811 			fin->fin_flx &= ~FI_OOW;
2812 			is = fr_matchsrcdst(fin, is, &src, &dst, tcp, FI_CMP);
2813 			if (is != NULL) {
2814 				if (pr == IPPROTO_TCP) {
2815 					if (!fr_tcpstate(fin, tcp, is)) {
2816 						oow |= fin->fin_flx & FI_OOW;
2817 						continue;
2818 					}
2819 				}
2820 				break;
2821 			}
2822 		}
2823 		if (is != NULL) {
2824 			if (tryagain &&
2825 			    !(is->is_flags & (SI_CLONE|SI_WILDP|SI_WILDA))) {
2826 				hv += dport;
2827 				hv += sport;
2828 				fr_ipsmove(is, hv, ifs);
2829 				MUTEX_DOWNGRADE(&ifs->ifs_ipf_state);
2830 			}
2831 			break;
2832 		}
2833 		RWLOCK_EXIT(&ifs->ifs_ipf_state);
2834 
2835 		if (ifs->ifs_ips_stats.iss_wild) {
2836 			if (tryagain == 0) {
2837 				hv -= dport;
2838 				hv -= sport;
2839 			} else if (tryagain == 1) {
2840 				hv = fin->fin_fi.fi_p;
2841 				/*
2842 				 * If we try to pretend this is a reply to a
2843 				 * multicast/broadcast packet then we need to
2844 				 * exclude part of the address from the hash
2845 				 * calculation.
2846 				 */
2847 				if (fin->fin_out == 0) {
2848 					hv += src.in4.s_addr;
2849 				} else {
2850 					hv += dst.in4.s_addr;
2851 				}
2852 				hv += dport;
2853 				hv += sport;
2854 			}
2855 			tryagain++;
2856 			if (tryagain <= 2) {
2857 				WRITE_ENTER(&ifs->ifs_ipf_state);
2858 				goto retry_tcpudp;
2859 			}
2860 		}
2861 		fin->fin_flx |= oow;
2862 		break;
2863 
2864 #if 0
2865 	case IPPROTO_GRE :
2866 		gre = fin->fin_dp;
2867 		if (GRE_REV(gre->gr_flags) == 1) {
2868 			hv += gre->gr_call;
2869 		}
2870 		/* FALLTHROUGH */
2871 #endif
2872 	default :
2873 		ifqp = NULL;
2874 		hvm = DOUBLE_HASH(hv, ifs);
2875 		READ_ENTER(&ifs->ifs_ipf_state);
2876 		for (isp = &ifs->ifs_ips_table[hvm]; ((is = *isp) != NULL); ) {
2877 			isp = &is->is_hnext;
2878 			if ((is->is_p != pr) || (is->is_v != v))
2879 				continue;
2880 			is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP);
2881 			if (is != NULL) {
2882 				ifq = &ifs->ifs_ips_iptq;
2883 				break;
2884 			}
2885 		}
2886 		if (is == NULL) {
2887 			RWLOCK_EXIT(&ifs->ifs_ipf_state);
2888 		}
2889 		break;
2890 	}
2891 
2892 	if ((is != NULL) && ((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) &&
2893 	    (is->is_tqehead[fin->fin_rev] != NULL))
2894 		ifq = is->is_tqehead[fin->fin_rev];
2895 	if (ifq != NULL && ifqp != NULL)
2896 		*ifqp = ifq;
2897 	return is;
2898 }
2899 
2900 
2901 /* ------------------------------------------------------------------------ */
2902 /* Function:    fr_updatestate                                              */
2903 /* Returns:     Nil                                                         */
2904 /* Parameters:  fin(I) - pointer to packet information                      */
2905 /*              is(I)  - pointer to state table entry                       */
2906 /* Read Locks:  ipf_state                                                   */
2907 /*                                                                          */
2908 /* Updates packet and byte counters for a newly received packet.  Seeds the */
2909 /* fragment cache with a new entry as required.                             */
2910 /* ------------------------------------------------------------------------ */
2911 void fr_updatestate(fin, is, ifq)
2912 fr_info_t *fin;
2913 ipstate_t *is;
2914 ipftq_t *ifq;
2915 {
2916 	ipftqent_t *tqe;
2917 	int i, pass;
2918 	ipf_stack_t *ifs = fin->fin_ifs;
2919 
2920 	i = (fin->fin_rev << 1) + fin->fin_out;
2921 
2922 	/*
2923 	 * For TCP packets, ifq == NULL.  For all others, check if this new
2924 	 * queue is different to the last one it was on and move it if so.
2925 	 */
2926 	tqe = &is->is_sti;
2927 	MUTEX_ENTER(&is->is_lock);
2928 	if ((tqe->tqe_flags & TQE_RULEBASED) != 0)
2929 		ifq = is->is_tqehead[fin->fin_rev];
2930 
2931 	if (ifq != NULL)
2932 		fr_movequeue(tqe, tqe->tqe_ifq, ifq, ifs);
2933 
2934 	is->is_pkts[i]++;
2935 	is->is_bytes[i] += fin->fin_plen;
2936 	MUTEX_EXIT(&is->is_lock);
2937 
2938 #ifdef	IPFILTER_SYNC
2939 	if (is->is_flags & IS_STATESYNC)
2940 		ipfsync_update(SMC_STATE, fin, is->is_sync);
2941 #endif
2942 
2943 	ATOMIC_INCL(ifs->ifs_ips_stats.iss_hits);
2944 
2945 	fin->fin_fr = is->is_rule;
2946 
2947 	/*
2948 	 * If this packet is a fragment and the rule says to track fragments,
2949 	 * then create a new fragment cache entry.
2950 	 */
2951 	pass = is->is_pass;
2952 	if ((fin->fin_flx & FI_FRAG) && FR_ISPASS(pass))
2953 		(void) fr_newfrag(fin, pass ^ FR_KEEPSTATE);
2954 }
2955 
2956 
2957 /* ------------------------------------------------------------------------ */
2958 /* Function:    fr_checkstate                                               */
2959 /* Returns:     frentry_t* - NULL == search failed,                         */
2960 /*                           else pointer to rule for matching state        */
2961 /* Parameters:  ifp(I)   - pointer to interface                             */
2962 /*              passp(I) - pointer to filtering result flags                */
2963 /*                                                                          */
2964 /* Check if a packet is associated with an entry in the state table.        */
2965 /* ------------------------------------------------------------------------ */
2966 frentry_t *fr_checkstate(fin, passp)
2967 fr_info_t *fin;
2968 u_32_t *passp;
2969 {
2970 	ipstate_t *is;
2971 	frentry_t *fr;
2972 	tcphdr_t *tcp;
2973 	ipftq_t *ifq;
2974 	u_int pass;
2975 	ipf_stack_t *ifs = fin->fin_ifs;
2976 
2977 	if (ifs->ifs_fr_state_lock || (ifs->ifs_ips_list == NULL) ||
2978 	    (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGBODY|FI_BAD)))
2979 		return NULL;
2980 
2981 	is = NULL;
2982 	if ((fin->fin_flx & FI_TCPUDP) ||
2983 	    (fin->fin_fi.fi_p == IPPROTO_ICMP)
2984 #ifdef	USE_INET6
2985 	    || (fin->fin_fi.fi_p == IPPROTO_ICMPV6)
2986 #endif
2987 	    )
2988 		tcp = fin->fin_dp;
2989 	else
2990 		tcp = NULL;
2991 
2992 	/*
2993 	 * Search the hash table for matching packet header info.
2994 	 */
2995 	ifq = NULL;
2996 	is = fin->fin_state;
2997 	if (is == NULL)
2998 		is = fr_stlookup(fin, tcp, &ifq);
2999 	switch (fin->fin_p)
3000 	{
3001 #ifdef	USE_INET6
3002 	case IPPROTO_ICMPV6 :
3003 		if (is != NULL)
3004 			break;
3005 		if (fin->fin_v == 6) {
3006 			is = fr_checkicmp6matchingstate(fin);
3007 			if (is != NULL)
3008 				goto matched;
3009 		}
3010 		break;
3011 #endif
3012 	case IPPROTO_ICMP :
3013 		if (is != NULL)
3014 			break;
3015 		/*
3016 		 * No matching icmp state entry. Perhaps this is a
3017 		 * response to another state entry.
3018 		 */
3019 		is = fr_checkicmpmatchingstate(fin);
3020 		if (is != NULL)
3021 			goto matched;
3022 		break;
3023 	case IPPROTO_TCP :
3024 		if (is == NULL)
3025 			break;
3026 
3027 		if (is->is_pass & FR_NEWISN) {
3028 			if (fin->fin_out == 0)
3029 				fr_fixinisn(fin, is);
3030 			else if (fin->fin_out == 1)
3031 				fr_fixoutisn(fin, is);
3032 		}
3033 		break;
3034 	default :
3035 		if (fin->fin_rev)
3036 			ifq = &ifs->ifs_ips_udpacktq;
3037 		else
3038 			ifq = &ifs->ifs_ips_udptq;
3039 		break;
3040 	}
3041 	if (is == NULL) {
3042 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_miss);
3043 		return NULL;
3044 	}
3045 
3046 matched:
3047 	fr = is->is_rule;
3048 	if (fr != NULL) {
3049 		if ((fin->fin_out == 0) && (fr->fr_nattag.ipt_num[0] != 0)) {
3050 			if (fin->fin_nattag == NULL)
3051 				return NULL;
3052 			if (fr_matchtag(&fr->fr_nattag, fin->fin_nattag) != 0)
3053 				return NULL;
3054 		}
3055 		(void) strncpy(fin->fin_group, fr->fr_group, FR_GROUPLEN);
3056 		fin->fin_icode = fr->fr_icode;
3057 	}
3058 
3059 	fin->fin_rule = is->is_rulen;
3060 	pass = is->is_pass;
3061 	fr_updatestate(fin, is, ifq);
3062 	if (fin->fin_out == 1)
3063 		fin->fin_nat = is->is_nat[fin->fin_rev];
3064 
3065 	fin->fin_state = is;
3066 	MUTEX_ENTER(&is->is_lock);
3067 	is->is_ref++;
3068 	MUTEX_EXIT(&is->is_lock);
3069 	RWLOCK_EXIT(&ifs->ifs_ipf_state);
3070 	fin->fin_flx |= FI_STATE;
3071 	if ((pass & FR_LOGFIRST) != 0)
3072 		pass &= ~(FR_LOGFIRST|FR_LOG);
3073 	*passp = pass;
3074 	return fr;
3075 }
3076 
3077 
3078 /* ------------------------------------------------------------------------ */
3079 /* Function:    fr_fixoutisn                                                */
3080 /* Returns:     Nil                                                         */
3081 /* Parameters:  fin(I)   - pointer to packet information                    */
3082 /*              is(I)  - pointer to master state structure                  */
3083 /*                                                                          */
3084 /* Called only for outbound packets, adjusts the sequence number and the    */
3085 /* TCP checksum to match that change.                                       */
3086 /* ------------------------------------------------------------------------ */
3087 static void fr_fixoutisn(fin, is)
3088 fr_info_t *fin;
3089 ipstate_t *is;
3090 {
3091 	tcphdr_t *tcp;
3092 	int rev;
3093 	u_32_t seq;
3094 
3095 	tcp = fin->fin_dp;
3096 	rev = fin->fin_rev;
3097 	if ((is->is_flags & IS_ISNSYN) != 0) {
3098 		if (rev == 0) {
3099 			seq = ntohl(tcp->th_seq);
3100 			seq += is->is_isninc[0];
3101 			tcp->th_seq = htonl(seq);
3102 			fix_outcksum(&tcp->th_sum, is->is_sumd[0]);
3103 		}
3104 	}
3105 	if ((is->is_flags & IS_ISNACK) != 0) {
3106 		if (rev == 1) {
3107 			seq = ntohl(tcp->th_seq);
3108 			seq += is->is_isninc[1];
3109 			tcp->th_seq = htonl(seq);
3110 			fix_outcksum(&tcp->th_sum, is->is_sumd[1]);
3111 		}
3112 	}
3113 }
3114 
3115 
3116 /* ------------------------------------------------------------------------ */
3117 /* Function:    fr_fixinisn                                                 */
3118 /* Returns:     Nil                                                         */
3119 /* Parameters:  fin(I)   - pointer to packet information                    */
3120 /*              is(I)  - pointer to master state structure                  */
3121 /*                                                                          */
3122 /* Called only for inbound packets, adjusts the acknowledge number and the  */
3123 /* TCP checksum to match that change.                                       */
3124 /* ------------------------------------------------------------------------ */
3125 static void fr_fixinisn(fin, is)
3126 fr_info_t *fin;
3127 ipstate_t *is;
3128 {
3129 	tcphdr_t *tcp;
3130 	int rev;
3131 	u_32_t ack;
3132 
3133 	tcp = fin->fin_dp;
3134 	rev = fin->fin_rev;
3135 	if ((is->is_flags & IS_ISNSYN) != 0) {
3136 		if (rev == 1) {
3137 			ack = ntohl(tcp->th_ack);
3138 			ack -= is->is_isninc[0];
3139 			tcp->th_ack = htonl(ack);
3140 			fix_incksum(&tcp->th_sum, is->is_sumd[0]);
3141 		}
3142 	}
3143 	if ((is->is_flags & IS_ISNACK) != 0) {
3144 		if (rev == 0) {
3145 			ack = ntohl(tcp->th_ack);
3146 			ack -= is->is_isninc[1];
3147 			tcp->th_ack = htonl(ack);
3148 			fix_incksum(&tcp->th_sum, is->is_sumd[1]);
3149 		}
3150 	}
3151 }
3152 
3153 
3154 /* ------------------------------------------------------------------------ */
3155 /* Function:    fr_statesync                                                */
3156 /* Returns:     Nil                                                         */
3157 /* Parameters:  action(I) - type of synchronisation to do                   */
3158 /*              v(I)      - IP version being sync'd (v4 or v6)              */
3159 /*              ifp(I)    - interface identifier associated with action     */
3160 /*              name(I)   - name associated with ifp parameter              */
3161 /*                                                                          */
3162 /* Walk through all state entries and if an interface pointer match is      */
3163 /* found then look it up again, based on its name in case the pointer has   */
3164 /* changed since last time.                                                 */
3165 /*                                                                          */
3166 /* If ifp is passed in as being non-null then we are only doing updates for */
3167 /* existing, matching, uses of it.                                          */
3168 /* ------------------------------------------------------------------------ */
3169 void fr_statesync(action, v, ifp, name, ifs)
3170 int action, v;
3171 void *ifp;
3172 char *name;
3173 ipf_stack_t *ifs;
3174 {
3175 	ipstate_t *is;
3176 	int i;
3177 
3178 	if (ifs->ifs_fr_running <= 0)
3179 		return;
3180 
3181 	WRITE_ENTER(&ifs->ifs_ipf_state);
3182 
3183 	if (ifs->ifs_fr_running <= 0) {
3184 		RWLOCK_EXIT(&ifs->ifs_ipf_state);
3185 		return;
3186 	}
3187 
3188 	switch (action)
3189 	{
3190 	case IPFSYNC_RESYNC :
3191 		for (is = ifs->ifs_ips_list; is; is = is->is_next) {
3192 			if (v != 0 && is->is_v != v)
3193 				continue;
3194 			/*
3195 			 * Look up all the interface names in the state entry.
3196 			 */
3197 			for (i = 0; i < 4; i++) {
3198 				is->is_ifp[i] = fr_resolvenic(is->is_ifname[i],
3199 							      is->is_v, ifs);
3200 			}
3201 		}
3202 		break;
3203 	case IPFSYNC_NEWIFP :
3204 		for (is = ifs->ifs_ips_list; is; is = is->is_next) {
3205 			if (v != 0 && is->is_v != v)
3206 				continue;
3207 			/*
3208 			 * Look up all the interface names in the state entry.
3209 			 */
3210 			for (i = 0; i < 4; i++) {
3211 				if (!strncmp(is->is_ifname[i], name,
3212 					     sizeof(is->is_ifname[i])))
3213 					is->is_ifp[i] = ifp;
3214 			}
3215 		}
3216 		break;
3217 	case IPFSYNC_OLDIFP :
3218 		for (is = ifs->ifs_ips_list; is; is = is->is_next) {
3219 			if (v != 0 && is->is_v != v)
3220 				continue;
3221 			/*
3222 			 * Look up all the interface names in the state entry.
3223 			 */
3224 			for (i = 0; i < 4; i++) {
3225 				if (is->is_ifp[i] == ifp)
3226 					is->is_ifp[i] = (void *)-1;
3227 			}
3228 		}
3229 		break;
3230 	}
3231 	RWLOCK_EXIT(&ifs->ifs_ipf_state);
3232 }
3233 
3234 
3235 /* ------------------------------------------------------------------------ */
3236 /* Function:    fr_delstate                                                 */
3237 /* Returns:     int - 0 = entry deleted, else ref count on entry            */
3238 /* Parameters:  is(I)  - pointer to state structure to delete               */
3239 /*              why(I) - if not 0, log reason why it was deleted            */
3240 /*              ifs    - ipf stack instance                                 */
3241 /* Write Locks: ipf_state/ipf_global                                        */
3242 /*                                                                          */
3243 /* Deletes a state entry from the enumerated list as well as the hash table */
3244 /* and timeout queue lists.  Make adjustments to hash table statistics and  */
3245 /* global counters as required.                                             */
3246 /* ------------------------------------------------------------------------ */
3247 int fr_delstate(is, why, ifs)
3248 ipstate_t *is;
3249 int why;
3250 ipf_stack_t *ifs;
3251 {
3252 	int removed = 0;
3253 
3254 	ASSERT(rw_write_held(&ifs->ifs_ipf_global.ipf_lk) == 0 ||
3255 		rw_write_held(&ifs->ifs_ipf_state.ipf_lk) == 0);
3256 
3257 	/*
3258 	 * Start by removing the entry from the hash table of state entries
3259 	 * so it will not be "used" again.
3260 	 *
3261 	 * It will remain in the "list" of state entries until all references
3262 	 * have been accounted for.
3263 	 */
3264 	if (is->is_phnext != NULL) {
3265 		removed = 1;
3266 		*is->is_phnext = is->is_hnext;
3267 		if (is->is_hnext != NULL)
3268 			is->is_hnext->is_phnext = is->is_phnext;
3269 		if (ifs->ifs_ips_table[is->is_hv] == NULL)
3270 			ifs->ifs_ips_stats.iss_inuse--;
3271 		ifs->ifs_ips_stats.iss_bucketlen[is->is_hv]--;
3272 
3273 		is->is_phnext = NULL;
3274 		is->is_hnext = NULL;
3275 	}
3276 
3277 	/*
3278 	 * Because ifs->ifs_ips_stats.iss_wild is a count of entries in the state
3279 	 * table that have wildcard flags set, only decerement it once
3280 	 * and do it here.
3281 	 */
3282 	if (is->is_flags & (SI_WILDP|SI_WILDA)) {
3283 		if (!(is->is_flags & SI_CLONED)) {
3284 			ATOMIC_DECL(ifs->ifs_ips_stats.iss_wild);
3285 		}
3286 		is->is_flags &= ~(SI_WILDP|SI_WILDA);
3287 	}
3288 
3289 	/*
3290 	 * Next, remove it from the timeout queue it is in.
3291 	 */
3292 	fr_deletequeueentry(&is->is_sti);
3293 
3294 	is->is_me = NULL;
3295 
3296 	/*
3297 	 * If it is still in use by something else, do not go any further,
3298 	 * but note that at this point it is now an orphan.
3299 	 */
3300 	MUTEX_ENTER(&is->is_lock);
3301 	if (is->is_ref > 1) {
3302 		is->is_ref--;
3303 		MUTEX_EXIT(&is->is_lock);
3304 		if (removed)
3305 			ifs->ifs_ips_stats.iss_orphans++;
3306 		return (is->is_ref);
3307 	}
3308 	MUTEX_EXIT(&is->is_lock);
3309 
3310 	is->is_ref = 0;
3311 
3312 	/*
3313 	 * If entry has already been removed from table,
3314 	 * it means we're simply cleaning up an orphan.
3315 	 */
3316 	if (!removed)
3317 		ifs->ifs_ips_stats.iss_orphans--;
3318 
3319 	if (is->is_tqehead[0] != NULL)
3320 		(void) fr_deletetimeoutqueue(is->is_tqehead[0]);
3321 
3322 	if (is->is_tqehead[1] != NULL)
3323 		(void) fr_deletetimeoutqueue(is->is_tqehead[1]);
3324 
3325 #ifdef	IPFILTER_SYNC
3326 	if (is->is_sync)
3327 		ipfsync_del(is->is_sync);
3328 #endif
3329 #ifdef	IPFILTER_SCAN
3330 	(void) ipsc_detachis(is);
3331 #endif
3332 
3333 	/*
3334 	 * Now remove it from master list of state table entries.
3335 	 */
3336 	if (is->is_pnext != NULL) {
3337 		*is->is_pnext = is->is_next;
3338 		if (is->is_next != NULL) {
3339 			is->is_next->is_pnext = is->is_pnext;
3340 			is->is_next = NULL;
3341 		}
3342 		is->is_pnext = NULL;
3343 	}
3344 
3345 	if (ifs->ifs_ipstate_logging != 0 && why != 0)
3346 		ipstate_log(is, why, ifs);
3347 
3348 	if (is->is_rule != NULL) {
3349 		is->is_rule->fr_statecnt--;
3350 		(void)fr_derefrule(&is->is_rule, ifs);
3351 	}
3352 
3353 	MUTEX_DESTROY(&is->is_lock);
3354 	KFREE(is);
3355 	ifs->ifs_ips_num--;
3356 
3357 	return (0);
3358 }
3359 
3360 
3361 /* ------------------------------------------------------------------------ */
3362 /* Function:    fr_timeoutstate                                             */
3363 /* Returns:     Nil                                                         */
3364 /* Parameters:  ifs - ipf stack instance                                    */
3365 /*                                                                          */
3366 /* Slowly expire held state for thingslike UDP and ICMP.  The algorithm     */
3367 /* used here is to keep the queue sorted with the oldest things at the top  */
3368 /* and the youngest at the bottom.  So if the top one doesn't need to be    */
3369 /* expired then neither will any under it.                                  */
3370 /* ------------------------------------------------------------------------ */
3371 void fr_timeoutstate(ifs)
3372 ipf_stack_t *ifs;
3373 {
3374 	ipftq_t *ifq, *ifqnext;
3375 	ipftqent_t *tqe, *tqn;
3376 	ipstate_t *is;
3377 	SPL_INT(s);
3378 
3379 	SPL_NET(s);
3380 	WRITE_ENTER(&ifs->ifs_ipf_state);
3381 	for (ifq = ifs->ifs_ips_tqtqb; ifq != NULL; ifq = ifq->ifq_next)
3382 		for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) {
3383 			if (tqe->tqe_die > ifs->ifs_fr_ticks)
3384 				break;
3385 			tqn = tqe->tqe_next;
3386 			is = tqe->tqe_parent;
3387 			(void) fr_delstate(is, ISL_EXPIRE, ifs);
3388 		}
3389 
3390 	for (ifq = ifs->ifs_ips_utqe; ifq != NULL; ifq = ifq->ifq_next) {
3391 		for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) {
3392 			if (tqe->tqe_die > ifs->ifs_fr_ticks)
3393 				break;
3394 			tqn = tqe->tqe_next;
3395 			is = tqe->tqe_parent;
3396 			(void) fr_delstate(is, ISL_EXPIRE, ifs);
3397 		}
3398 	}
3399 
3400 	for (ifq = ifs->ifs_ips_utqe; ifq != NULL; ifq = ifqnext) {
3401 		ifqnext = ifq->ifq_next;
3402 
3403 		if (((ifq->ifq_flags & IFQF_DELETE) != 0) &&
3404 		    (ifq->ifq_ref == 0)) {
3405 			fr_freetimeoutqueue(ifq, ifs);
3406 		}
3407 	}
3408 
3409 	if (ifs->ifs_fr_state_doflush) {
3410 		(void) fr_state_flush(FLUSH_TABLE_EXTRA, 0, ifs);
3411 		ifs->ifs_fr_state_doflush = 0;
3412 	}
3413 	RWLOCK_EXIT(&ifs->ifs_ipf_state);
3414 	SPL_X(s);
3415 }
3416 
3417 
3418 /* ---------------------------------------------------------------------- */
3419 /* Function:    fr_state_flush                                            */
3420 /* Returns:     int - 0 == success, -1 == failure                         */
3421 /* Parameters:  flush_option - how to flush the active State table	  */
3422 /*              proto    - IP version to flush (4, 6, or both)            */
3423 /*              ifs      - ipf stack instance                             */
3424 /* Write Locks: ipf_state                                                 */
3425 /*                                                                        */
3426 /* Flush state tables.  Three possible flush options currently defined:	  */
3427 /*                                                                        */
3428 /* FLUSH_TABLE_ALL	: Flush all state table entries			  */
3429 /*                                                                        */
3430 /* FLUSH_TABLE_CLOSING	: Flush entries with TCP connections which	  */
3431 /*			  have started to close on both ends using	  */
3432 /*			  ipf_flushclosing().				  */
3433 /*                                                                        */
3434 /* FLUSH_TABLE_EXTRA	: First, flush entries which are "almost" closed. */
3435 /*			  Then, if needed, flush entries with TCP	  */
3436 /*			  connections which have been idle for a long	  */
3437 /*			  time with ipf_extraflush().			  */
3438 /* ---------------------------------------------------------------------- */
3439 static int fr_state_flush(flush_option, proto, ifs)
3440 int flush_option, proto;
3441 ipf_stack_t *ifs;
3442 {
3443 	ipstate_t *is, *isn;
3444 	int removed;
3445 	SPL_INT(s);
3446 
3447 	removed = 0;
3448 
3449 	SPL_NET(s);
3450 	switch (flush_option)
3451 	{
3452 	case FLUSH_TABLE_ALL:
3453 		isn = ifs->ifs_ips_list;
3454 		while ((is = isn) != NULL) {
3455 			isn = is->is_next;
3456 			if ((proto != 0) && (is->is_v != proto))
3457 				continue;
3458 			if (fr_delstate(is, ISL_FLUSH, ifs) == 0)
3459 				removed++;
3460 		}
3461 		break;
3462 
3463 	case FLUSH_TABLE_CLOSING:
3464 		removed = ipf_flushclosing(STATE_FLUSH,
3465 					   IPF_TCPS_CLOSE_WAIT,
3466 					   ifs->ifs_ips_tqtqb,
3467 					   ifs->ifs_ips_utqe,
3468 					   ifs);
3469 		break;
3470 
3471 	case FLUSH_TABLE_EXTRA:
3472 		removed = ipf_flushclosing(STATE_FLUSH,
3473 					   IPF_TCPS_FIN_WAIT_2,
3474 					   ifs->ifs_ips_tqtqb,
3475 					   ifs->ifs_ips_utqe,
3476 					   ifs);
3477 
3478 		/*
3479 		 * Be sure we haven't done this in the last 10 seconds.
3480 		 */
3481 		if (ifs->ifs_fr_ticks - ifs->ifs_ips_last_force_flush <
3482 		    IPF_TTLVAL(10))
3483 			break;
3484 		ifs->ifs_ips_last_force_flush = ifs->ifs_fr_ticks;
3485                 removed += ipf_extraflush(STATE_FLUSH,
3486 					  &ifs->ifs_ips_tqtqb[IPF_TCPS_ESTABLISHED],
3487 					  ifs->ifs_ips_utqe,
3488 					  ifs);
3489 		break;
3490 
3491 	default: /* Flush Nothing */
3492 		break;
3493 	}
3494 
3495 	SPL_X(s);
3496 	return (removed);
3497 }
3498 
3499 
3500 /* ------------------------------------------------------------------------ */
3501 /* Function:    fr_tcp_age                                                  */
3502 /* Returns:     int - 1 == state transition made, 0 == no change (rejected) */
3503 /* Parameters:  tq(I)    - pointer to timeout queue information             */
3504 /*              fin(I)   - pointer to packet information                    */
3505 /*              tqtab(I) - TCP timeout queue table this is in               */
3506 /*              flags(I) - flags from state/NAT entry                       */
3507 /*                                                                          */
3508 /* Rewritten by Arjan de Vet <Arjan.deVet@adv.iae.nl>, 2000-07-29:          */
3509 /*                                                                          */
3510 /* - (try to) base state transitions on real evidence only,                 */
3511 /*   i.e. packets that are sent and have been received by ipfilter;         */
3512 /*   diagram 18.12 of TCP/IP volume 1 by W. Richard Stevens was used.       */
3513 /*                                                                          */
3514 /* - deal with half-closed connections correctly;                           */
3515 /*                                                                          */
3516 /* - store the state of the source in state[0] such that ipfstat            */
3517 /*   displays the state as source/dest instead of dest/source; the calls    */
3518 /*   to fr_tcp_age have been changed accordingly.                           */
3519 /*                                                                          */
3520 /* Internal Parameters:                                                     */
3521 /*                                                                          */
3522 /*    state[0] = state of source (host that initiated connection)           */
3523 /*    state[1] = state of dest   (host that accepted the connection)        */
3524 /*                                                                          */
3525 /*    dir == 0 : a packet from source to dest                               */
3526 /*    dir == 1 : a packet from dest to source                               */
3527 /*                                                                          */
3528 /* Locking: it is assumed that the parent of the tqe structure is locked.   */
3529 /* ------------------------------------------------------------------------ */
3530 int fr_tcp_age(tqe, fin, tqtab, flags)
3531 ipftqent_t *tqe;
3532 fr_info_t *fin;
3533 ipftq_t *tqtab;
3534 int flags;
3535 {
3536 	int dlen, ostate, nstate, rval, dir;
3537 	u_char tcpflags;
3538 	tcphdr_t *tcp;
3539 	ipf_stack_t *ifs = fin->fin_ifs;
3540 
3541 	tcp = fin->fin_dp;
3542 
3543 	rval = 0;
3544 	dir = fin->fin_rev;
3545 	tcpflags = tcp->th_flags;
3546 	dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
3547 
3548 	if (tcpflags & TH_RST) {
3549 		if (!(tcpflags & TH_PUSH) && !dlen)
3550 			nstate = IPF_TCPS_CLOSED;
3551 		else
3552 			nstate = IPF_TCPS_CLOSE_WAIT;
3553 		rval = 1;
3554 	} else {
3555 		ostate = tqe->tqe_state[1 - dir];
3556 		nstate = tqe->tqe_state[dir];
3557 
3558 		switch (nstate)
3559 		{
3560 		case IPF_TCPS_CLOSED: /* 0 */
3561 			if ((tcpflags & TH_OPENING) == TH_OPENING) {
3562 				/*
3563 				 * 'dir' received an S and sends SA in
3564 				 * response, CLOSED -> SYN_RECEIVED
3565 				 */
3566 				nstate = IPF_TCPS_SYN_RECEIVED;
3567 				rval = 1;
3568 			} else if ((tcpflags & TH_OPENING) == TH_SYN) {
3569 				/* 'dir' sent S, CLOSED -> SYN_SENT */
3570 				nstate = IPF_TCPS_SYN_SENT;
3571 				rval = 1;
3572 			}
3573 			/*
3574 			 * the next piece of code makes it possible to get
3575 			 * already established connections into the state table
3576 			 * after a restart or reload of the filter rules; this
3577 			 * does not work when a strict 'flags S keep state' is
3578 			 * used for tcp connections of course
3579 			 */
3580 			if (((flags & IS_TCPFSM) == 0) &&
3581 			    ((tcpflags & TH_ACKMASK) == TH_ACK)) {
3582 				/*
3583 				 * we saw an A, guess 'dir' is in ESTABLISHED
3584 				 * mode
3585 				 */
3586 				switch (ostate)
3587 				{
3588 				case IPF_TCPS_CLOSED :
3589 				case IPF_TCPS_SYN_RECEIVED :
3590 					nstate = IPF_TCPS_HALF_ESTAB;
3591 					rval = 1;
3592 					break;
3593 				case IPF_TCPS_HALF_ESTAB :
3594 				case IPF_TCPS_ESTABLISHED :
3595 					nstate = IPF_TCPS_ESTABLISHED;
3596 					rval = 1;
3597 					break;
3598 				default :
3599 					break;
3600 				}
3601 			}
3602 			/*
3603 			 * TODO: besides regular ACK packets we can have other
3604 			 * packets as well; it is yet to be determined how we
3605 			 * should initialize the states in those cases
3606 			 */
3607 			break;
3608 
3609 		case IPF_TCPS_LISTEN: /* 1 */
3610 			/* NOT USED */
3611 			break;
3612 
3613 		case IPF_TCPS_SYN_SENT: /* 2 */
3614 			if ((tcpflags & ~(TH_ECN|TH_CWR)) == TH_SYN) {
3615 				/*
3616 				 * A retransmitted SYN packet.  We do not reset
3617 				 * the timeout here to fr_tcptimeout because a
3618 				 * connection connect timeout does not renew
3619 				 * after every packet that is sent.  We need to
3620 				 * set rval so as to indicate the packet has
3621 				 * passed the check for its flags being valid
3622 				 * in the TCP FSM.  Setting rval to 2 has the
3623 				 * result of not resetting the timeout.
3624 				 */
3625 				rval = 2;
3626 			} else if ((tcpflags & (TH_SYN|TH_FIN|TH_ACK)) ==
3627 				   TH_ACK) {
3628 				/*
3629 				 * we see an A from 'dir' which is in SYN_SENT
3630 				 * state: 'dir' sent an A in response to an SA
3631 				 * which it received, SYN_SENT -> ESTABLISHED
3632 				 */
3633 				nstate = IPF_TCPS_ESTABLISHED;
3634 				rval = 1;
3635 			} else if (tcpflags & TH_FIN) {
3636 				/*
3637 				 * we see an F from 'dir' which is in SYN_SENT
3638 				 * state and wants to close its side of the
3639 				 * connection; SYN_SENT -> FIN_WAIT_1
3640 				 */
3641 				nstate = IPF_TCPS_FIN_WAIT_1;
3642 				rval = 1;
3643 			} else if ((tcpflags & TH_OPENING) == TH_OPENING) {
3644 				/*
3645 				 * we see an SA from 'dir' which is already in
3646 				 * SYN_SENT state, this means we have a
3647 				 * simultaneous open; SYN_SENT -> SYN_RECEIVED
3648 				 */
3649 				nstate = IPF_TCPS_SYN_RECEIVED;
3650 				rval = 1;
3651 			}
3652 			break;
3653 
3654 		case IPF_TCPS_SYN_RECEIVED: /* 3 */
3655 			if ((tcpflags & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK) {
3656 				/*
3657 				 * we see an A from 'dir' which was in
3658 				 * SYN_RECEIVED state so it must now be in
3659 				 * established state, SYN_RECEIVED ->
3660 				 * ESTABLISHED
3661 				 */
3662 				nstate = IPF_TCPS_ESTABLISHED;
3663 				rval = 1;
3664 			} else if ((tcpflags & ~(TH_ECN|TH_CWR)) ==
3665 				   TH_OPENING) {
3666 				/*
3667 				 * We see an SA from 'dir' which is already in
3668 				 * SYN_RECEIVED state.
3669 				 */
3670 				rval = 2;
3671 			} else if (tcpflags & TH_FIN) {
3672 				/*
3673 				 * we see an F from 'dir' which is in
3674 				 * SYN_RECEIVED state and wants to close its
3675 				 * side of the connection; SYN_RECEIVED ->
3676 				 * FIN_WAIT_1
3677 				 */
3678 				nstate = IPF_TCPS_FIN_WAIT_1;
3679 				rval = 1;
3680 			}
3681 			break;
3682 
3683 		case IPF_TCPS_HALF_ESTAB: /* 4 */
3684 			if (ostate >= IPF_TCPS_HALF_ESTAB) {
3685 				if ((tcpflags & TH_ACKMASK) == TH_ACK) {
3686 					nstate = IPF_TCPS_ESTABLISHED;
3687 				}
3688 			}
3689 			rval = 1;
3690 
3691 			break;
3692 
3693 		case IPF_TCPS_ESTABLISHED: /* 5 */
3694 			rval = 1;
3695 			if (tcpflags & TH_FIN) {
3696 				/*
3697 				 * 'dir' closed its side of the connection;
3698 				 * this gives us a half-closed connection;
3699 				 * ESTABLISHED -> FIN_WAIT_1
3700 				 */
3701 				nstate = IPF_TCPS_FIN_WAIT_1;
3702 			} else if (tcpflags & TH_ACK) {
3703 				/*
3704 				 * an ACK, should we exclude other flags here?
3705 				 */
3706 				if (ostate == IPF_TCPS_FIN_WAIT_1) {
3707 					/*
3708 					 * We know the other side did an active
3709 					 * close, so we are ACKing the recvd
3710 					 * FIN packet (does the window matching
3711 					 * code guarantee this?) and go into
3712 					 * CLOSE_WAIT state; this gives us a
3713 					 * half-closed connection
3714 					 */
3715 					nstate = IPF_TCPS_CLOSE_WAIT;
3716 				} else if (ostate < IPF_TCPS_CLOSE_WAIT) {
3717 					/*
3718 					 * still a fully established
3719 					 * connection reset timeout
3720 					 */
3721 					nstate = IPF_TCPS_ESTABLISHED;
3722 				}
3723 			}
3724 			break;
3725 
3726 		case IPF_TCPS_CLOSE_WAIT: /* 6 */
3727 			rval = 1;
3728 			if (tcpflags & TH_FIN) {
3729 				/*
3730 				 * application closed and 'dir' sent a FIN,
3731 				 * we're now going into LAST_ACK state
3732 				 */
3733 				nstate = IPF_TCPS_LAST_ACK;
3734 			} else {
3735 				/*
3736 				 * we remain in CLOSE_WAIT because the other
3737 				 * side has closed already and we did not
3738 				 * close our side yet; reset timeout
3739 				 */
3740 				nstate = IPF_TCPS_CLOSE_WAIT;
3741 			}
3742 			break;
3743 
3744 		case IPF_TCPS_FIN_WAIT_1: /* 7 */
3745 			rval = 1;
3746 			if ((tcpflags & TH_ACK) &&
3747 			    ostate > IPF_TCPS_CLOSE_WAIT) {
3748 				/*
3749 				 * if the other side is not active anymore
3750 				 * it has sent us a FIN packet that we are
3751 				 * ack'ing now with an ACK; this means both
3752 				 * sides have now closed the connection and
3753 				 * we go into TIME_WAIT
3754 				 */
3755 				/*
3756 				 * XXX: how do we know we really are ACKing
3757 				 * the FIN packet here? does the window code
3758 				 * guarantee that?
3759 				 */
3760 				nstate = IPF_TCPS_TIME_WAIT;
3761 			} else {
3762 				/*
3763 				 * we closed our side of the connection
3764 				 * already but the other side is still active
3765 				 * (ESTABLISHED/CLOSE_WAIT); continue with
3766 				 * this half-closed connection
3767 				 */
3768 				nstate = IPF_TCPS_FIN_WAIT_1;
3769 			}
3770 			break;
3771 
3772 		case IPF_TCPS_CLOSING: /* 8 */
3773 			/* NOT USED */
3774 			break;
3775 
3776 		case IPF_TCPS_LAST_ACK: /* 9 */
3777 			/*
3778 			 * We want to reset timer here to keep state in table.
3779 			 * If we would allow the state to time out here, while
3780 			 * there would still be packets being retransmitted, we
3781 			 * would cut off line between the two peers preventing
3782 			 * them to close connection properly.
3783 			 */
3784 			rval = 1;
3785 			break;
3786 
3787 		case IPF_TCPS_FIN_WAIT_2: /* 10 */
3788 			rval = 1;
3789 			if ((tcpflags & TH_OPENING) == TH_OPENING)
3790 				nstate = IPF_TCPS_SYN_RECEIVED;
3791 			else if (tcpflags & TH_SYN)
3792 				nstate = IPF_TCPS_SYN_SENT;
3793 			break;
3794 
3795 		case IPF_TCPS_TIME_WAIT: /* 11 */
3796 			/* we're in 2MSL timeout now */
3797 			rval = 1;
3798 			break;
3799 
3800 		default :
3801 #if defined(_KERNEL)
3802 # if SOLARIS
3803 			cmn_err(CE_NOTE,
3804 				"tcp %lx flags %x si %lx nstate %d ostate %d\n",
3805 				(u_long)tcp, tcpflags, (u_long)tqe,
3806 				nstate, ostate);
3807 # else
3808 			printf("tcp %lx flags %x si %lx nstate %d ostate %d\n",
3809 				(u_long)tcp, tcpflags, (u_long)tqe,
3810 				nstate, ostate);
3811 # endif
3812 #else
3813 			abort();
3814 #endif
3815 			break;
3816 		}
3817 	}
3818 
3819 	/*
3820 	 * If rval == 2 then do not update the queue position, but treat the
3821 	 * packet as being ok.
3822 	 */
3823 	if (rval == 2)
3824 		rval = 1;
3825 	else if (rval == 1) {
3826 		tqe->tqe_state[dir] = nstate;
3827 		if ((tqe->tqe_flags & TQE_RULEBASED) == 0)
3828 			fr_movequeue(tqe, tqe->tqe_ifq, tqtab + nstate, ifs);
3829 	}
3830 
3831 	return rval;
3832 }
3833 
3834 
3835 /* ------------------------------------------------------------------------ */
3836 /* Function:    ipstate_log                                                 */
3837 /* Returns:     Nil                                                         */
3838 /* Parameters:  is(I)   - pointer to state structure                        */
3839 /*              type(I) - type of log entry to create                       */
3840 /*                                                                          */
3841 /* Creates a state table log entry using the state structure and type info. */
3842 /* passed in.  Log packet/byte counts, source/destination address and other */
3843 /* protocol specific information.                                           */
3844 /* ------------------------------------------------------------------------ */
3845 void ipstate_log(is, type, ifs)
3846 struct ipstate *is;
3847 u_int type;
3848 ipf_stack_t *ifs;
3849 {
3850 #ifdef	IPFILTER_LOG
3851 	struct	ipslog	ipsl;
3852 	size_t sizes[1];
3853 	void *items[1];
3854 	int types[1];
3855 
3856 	/*
3857 	 * Copy information out of the ipstate_t structure and into the
3858 	 * structure used for logging.
3859 	 */
3860 	ipsl.isl_type = type;
3861 	ipsl.isl_pkts[0] = is->is_pkts[0] + is->is_icmppkts[0];
3862 	ipsl.isl_bytes[0] = is->is_bytes[0];
3863 	ipsl.isl_pkts[1] = is->is_pkts[1] + is->is_icmppkts[1];
3864 	ipsl.isl_bytes[1] = is->is_bytes[1];
3865 	ipsl.isl_pkts[2] = is->is_pkts[2] + is->is_icmppkts[2];
3866 	ipsl.isl_bytes[2] = is->is_bytes[2];
3867 	ipsl.isl_pkts[3] = is->is_pkts[3] + is->is_icmppkts[3];
3868 	ipsl.isl_bytes[3] = is->is_bytes[3];
3869 	ipsl.isl_src = is->is_src;
3870 	ipsl.isl_dst = is->is_dst;
3871 	ipsl.isl_p = is->is_p;
3872 	ipsl.isl_v = is->is_v;
3873 	ipsl.isl_flags = is->is_flags;
3874 	ipsl.isl_tag = is->is_tag;
3875 	ipsl.isl_rulen = is->is_rulen;
3876 	(void) strncpy(ipsl.isl_group, is->is_group, FR_GROUPLEN);
3877 
3878 	if (ipsl.isl_p == IPPROTO_TCP || ipsl.isl_p == IPPROTO_UDP) {
3879 		ipsl.isl_sport = is->is_sport;
3880 		ipsl.isl_dport = is->is_dport;
3881 		if (ipsl.isl_p == IPPROTO_TCP) {
3882 			ipsl.isl_state[0] = is->is_state[0];
3883 			ipsl.isl_state[1] = is->is_state[1];
3884 		}
3885 	} else if (ipsl.isl_p == IPPROTO_ICMP) {
3886 		ipsl.isl_itype = is->is_icmp.ici_type;
3887 	} else if (ipsl.isl_p == IPPROTO_ICMPV6) {
3888 		ipsl.isl_itype = is->is_icmp.ici_type;
3889 	} else {
3890 		ipsl.isl_ps.isl_filler[0] = 0;
3891 		ipsl.isl_ps.isl_filler[1] = 0;
3892 	}
3893 
3894 	items[0] = &ipsl;
3895 	sizes[0] = sizeof(ipsl);
3896 	types[0] = 0;
3897 
3898 	if (ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1, ifs)) {
3899 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_logged);
3900 	} else {
3901 		ATOMIC_INCL(ifs->ifs_ips_stats.iss_logfail);
3902 	}
3903 #endif
3904 }
3905 
3906 
3907 #ifdef	USE_INET6
3908 /* ------------------------------------------------------------------------ */
3909 /* Function:    fr_checkicmp6matchingstate                                  */
3910 /* Returns:     ipstate_t* - NULL == no match found,                        */
3911 /*                           else  pointer to matching state entry          */
3912 /* Parameters:  fin(I) - pointer to packet information                      */
3913 /* Locks:       NULL == no locks, else Read Lock on ipf_state               */
3914 /*                                                                          */
3915 /* If we've got an ICMPv6 error message, using the information stored in    */
3916 /* the ICMPv6 packet, look for a matching state table entry.                */
3917 /* ------------------------------------------------------------------------ */
3918 static ipstate_t *fr_checkicmp6matchingstate(fin)
3919 fr_info_t *fin;
3920 {
3921 	struct icmp6_hdr *ic6, *oic;
3922 	int backward, i;
3923 	ipstate_t *is, **isp;
3924 	u_short sport, dport;
3925 	i6addr_t dst, src;
3926 	u_short savelen;
3927 	icmpinfo_t *ic;
3928 	fr_info_t ofin;
3929 	tcphdr_t *tcp;
3930 	ip6_t *oip6;
3931 	u_char	pr;
3932 	u_int hv;
3933 	ipf_stack_t *ifs = fin->fin_ifs;
3934 
3935 	/*
3936 	 * Does it at least have the return (basic) IP header ?
3937 	 * Is it an actual recognised ICMP error type?
3938 	 * Only a basic IP header (no options) should be with
3939 	 * an ICMP error header.
3940 	 */
3941 	if ((fin->fin_v != 6) || (fin->fin_plen < ICMP6ERR_MINPKTLEN) ||
3942 	    !(fin->fin_flx & FI_ICMPERR))
3943 		return NULL;
3944 
3945 	ic6 = fin->fin_dp;
3946 
3947 	oip6 = (ip6_t *)((char *)ic6 + ICMPERR_ICMPHLEN);
3948 	if (fin->fin_plen < sizeof(*oip6))
3949 		return NULL;
3950 
3951 	bcopy((char *)fin, (char *)&ofin, sizeof(*fin));
3952 	ofin.fin_v = 6;
3953 	ofin.fin_ifp = fin->fin_ifp;
3954 	ofin.fin_out = !fin->fin_out;
3955 	ofin.fin_m = NULL;	/* if dereferenced, panic XXX */
3956 	ofin.fin_mp = NULL;	/* if dereferenced, panic XXX */
3957 
3958 	/*
3959 	 * We make a fin entry to be able to feed it to
3960 	 * matchsrcdst. Note that not all fields are necessary
3961 	 * but this is the cleanest way. Note further we fill
3962 	 * in fin_mp such that if someone uses it we'll get
3963 	 * a kernel panic. fr_matchsrcdst does not use this.
3964 	 *
3965 	 * watch out here, as ip is in host order and oip6 in network
3966 	 * order. Any change we make must be undone afterwards.
3967 	 */
3968 	savelen = oip6->ip6_plen;
3969 	oip6->ip6_plen = fin->fin_dlen - ICMPERR_ICMPHLEN;
3970 	ofin.fin_flx = FI_NOCKSUM;
3971 	ofin.fin_ip = (ip_t *)oip6;
3972 	ofin.fin_plen = oip6->ip6_plen;
3973 	(void) fr_makefrip(sizeof(*oip6), (ip_t *)oip6, &ofin);
3974 	ofin.fin_flx &= ~(FI_BAD|FI_SHORT);
3975 	oip6->ip6_plen = savelen;
3976 
3977 	if (oip6->ip6_nxt == IPPROTO_ICMPV6) {
3978 		oic = (struct icmp6_hdr *)(oip6 + 1);
3979 		/*
3980 		 * an ICMP error can only be generated as a result of an
3981 		 * ICMP query, not as the response on an ICMP error
3982 		 *
3983 		 * XXX theoretically ICMP_ECHOREP and the other reply's are
3984 		 * ICMP query's as well, but adding them here seems strange XXX
3985 		 */
3986 		 if (!(oic->icmp6_type & ICMP6_INFOMSG_MASK))
3987 		    	return NULL;
3988 
3989 		/*
3990 		 * perform a lookup of the ICMP packet in the state table
3991 		 */
3992 		hv = (pr = oip6->ip6_nxt);
3993 		src.in6 = oip6->ip6_src;
3994 		hv += src.in4.s_addr;
3995 		dst.in6 = oip6->ip6_dst;
3996 		hv += dst.in4.s_addr;
3997 		hv += oic->icmp6_id;
3998 		hv += oic->icmp6_seq;
3999 		hv = DOUBLE_HASH(hv, ifs);
4000 
4001 		READ_ENTER(&ifs->ifs_ipf_state);
4002 		for (isp = &ifs->ifs_ips_table[hv]; ((is = *isp) != NULL); ) {
4003 			ic = &is->is_icmp;
4004 			isp = &is->is_hnext;
4005 			if ((is->is_p == pr) &&
4006 			    !(is->is_pass & FR_NOICMPERR) &&
4007 			    (oic->icmp6_id == ic->ici_id) &&
4008 			    (oic->icmp6_seq == ic->ici_seq) &&
4009 			    (is = fr_matchsrcdst(&ofin, is, &src,
4010 						 &dst, NULL, FI_ICMPCMP))) {
4011 			    	/*
4012 			    	 * in the state table ICMP query's are stored
4013 			    	 * with the type of the corresponding ICMP
4014 			    	 * response. Correct here
4015 			    	 */
4016 				if (((ic->ici_type == ICMP6_ECHO_REPLY) &&
4017 				     (oic->icmp6_type == ICMP6_ECHO_REQUEST)) ||
4018 				     (ic->ici_type - 1 == oic->icmp6_type )) {
4019 				    	ifs->ifs_ips_stats.iss_hits++;
4020 					backward = IP6_NEQ(&is->is_dst, &src);
4021 					fin->fin_rev = !backward;
4022 					i = (backward << 1) + fin->fin_out;
4023     					is->is_icmppkts[i]++;
4024 					return is;
4025 				}
4026 			}
4027 		}
4028 		RWLOCK_EXIT(&ifs->ifs_ipf_state);
4029 		return NULL;
4030 	}
4031 
4032 	hv = (pr = oip6->ip6_nxt);
4033 	src.in6 = oip6->ip6_src;
4034 	hv += src.i6[0];
4035 	hv += src.i6[1];
4036 	hv += src.i6[2];
4037 	hv += src.i6[3];
4038 	dst.in6 = oip6->ip6_dst;
4039 	hv += dst.i6[0];
4040 	hv += dst.i6[1];
4041 	hv += dst.i6[2];
4042 	hv += dst.i6[3];
4043 
4044 	if ((oip6->ip6_nxt == IPPROTO_TCP) || (oip6->ip6_nxt == IPPROTO_UDP)) {
4045 		tcp = (tcphdr_t *)(oip6 + 1);
4046 		dport = tcp->th_dport;
4047 		sport = tcp->th_sport;
4048 		hv += dport;
4049 		hv += sport;
4050 	} else
4051 		tcp = NULL;
4052 	hv = DOUBLE_HASH(hv, ifs);
4053 
4054 	READ_ENTER(&ifs->ifs_ipf_state);
4055 	for (isp = &ifs->ifs_ips_table[hv]; ((is = *isp) != NULL); ) {
4056 		isp = &is->is_hnext;
4057 		/*
4058 		 * Only allow this icmp though if the
4059 		 * encapsulated packet was allowed through the
4060 		 * other way around. Note that the minimal amount
4061 		 * of info present does not allow for checking against
4062 		 * tcp internals such as seq and ack numbers.
4063 		 */
4064 		if ((is->is_p != pr) || (is->is_v != 6) ||
4065 		    (is->is_pass & FR_NOICMPERR))
4066 			continue;
4067 		is = fr_matchsrcdst(&ofin, is, &src, &dst, tcp, FI_ICMPCMP);
4068 		if (is != NULL) {
4069 			ifs->ifs_ips_stats.iss_hits++;
4070 			backward = IP6_NEQ(&is->is_dst, &src);
4071 			fin->fin_rev = !backward;
4072 			i = (backward << 1) + fin->fin_out;
4073 			is->is_icmppkts[i]++;
4074 			/*
4075 			 * we deliberately do not touch the timeouts
4076 			 * for the accompanying state table entry.
4077 			 * It remains to be seen if that is correct. XXX
4078 			 */
4079 			return is;
4080 		}
4081 	}
4082 	RWLOCK_EXIT(&ifs->ifs_ipf_state);
4083 	return NULL;
4084 }
4085 #endif
4086 
4087 
4088 /* ------------------------------------------------------------------------ */
4089 /* Function:    fr_sttab_init                                               */
4090 /* Returns:     Nil                                                         */
4091 /* Parameters:  tqp(I) - pointer to an array of timeout queues for TCP      */
4092 /*                                                                          */
4093 /* Initialise the array of timeout queues for TCP.                          */
4094 /* ------------------------------------------------------------------------ */
4095 void fr_sttab_init(tqp, ifs)
4096 ipftq_t *tqp;
4097 ipf_stack_t *ifs;
4098 {
4099 	int i;
4100 
4101 	for (i = IPF_TCP_NSTATES - 1; i >= 0; i--) {
4102 		tqp[i].ifq_ttl = 0;
4103 		tqp[i].ifq_ref = 1;
4104 		tqp[i].ifq_head = NULL;
4105 		tqp[i].ifq_tail = &tqp[i].ifq_head;
4106 		tqp[i].ifq_next = tqp + i + 1;
4107 		MUTEX_INIT(&tqp[i].ifq_lock, "ipftq tcp tab");
4108 	}
4109 	tqp[IPF_TCP_NSTATES - 1].ifq_next = NULL;
4110 	tqp[IPF_TCPS_CLOSED].ifq_ttl = ifs->ifs_fr_tcpclosed;
4111 	tqp[IPF_TCPS_LISTEN].ifq_ttl = ifs->ifs_fr_tcptimeout;
4112 	tqp[IPF_TCPS_SYN_SENT].ifq_ttl = ifs->ifs_fr_tcptimeout;
4113 	tqp[IPF_TCPS_SYN_RECEIVED].ifq_ttl = ifs->ifs_fr_tcptimeout;
4114 	tqp[IPF_TCPS_ESTABLISHED].ifq_ttl = ifs->ifs_fr_tcpidletimeout;
4115 	tqp[IPF_TCPS_CLOSE_WAIT].ifq_ttl = ifs->ifs_fr_tcphalfclosed;
4116 	tqp[IPF_TCPS_FIN_WAIT_1].ifq_ttl = ifs->ifs_fr_tcphalfclosed;
4117 	tqp[IPF_TCPS_CLOSING].ifq_ttl = ifs->ifs_fr_tcptimeout;
4118 	tqp[IPF_TCPS_LAST_ACK].ifq_ttl = ifs->ifs_fr_tcplastack;
4119 	tqp[IPF_TCPS_FIN_WAIT_2].ifq_ttl = ifs->ifs_fr_tcpclosewait;
4120 	tqp[IPF_TCPS_TIME_WAIT].ifq_ttl = ifs->ifs_fr_tcptimeout;
4121 	tqp[IPF_TCPS_HALF_ESTAB].ifq_ttl = ifs->ifs_fr_tcptimeout;
4122 }
4123 
4124 
4125 /* ------------------------------------------------------------------------ */
4126 /* Function:    fr_sttab_destroy                                            */
4127 /* Returns:     Nil                                                         */
4128 /* Parameters:  tqp(I) - pointer to an array of timeout queues for TCP      */
4129 /*                                                                          */
4130 /* Do whatever is necessary to "destroy" each of the entries in the array   */
4131 /* of timeout queues for TCP.                                               */
4132 /* ------------------------------------------------------------------------ */
4133 void fr_sttab_destroy(tqp)
4134 ipftq_t *tqp;
4135 {
4136 	int i;
4137 
4138 	for (i = IPF_TCP_NSTATES - 1; i >= 0; i--)
4139 		MUTEX_DESTROY(&tqp[i].ifq_lock);
4140 }
4141 
4142 
4143 /* ------------------------------------------------------------------------ */
4144 /* Function:    fr_statederef                                               */
4145 /* Returns:     Nil                                                         */
4146 /* Parameters:  isp(I) - pointer to pointer to state table entry            */
4147 /*              ifs - ipf stack instance                                    */
4148 /*                                                                          */
4149 /* Decrement the reference counter for this state table entry and free it   */
4150 /* if there are no more things using it.                                    */
4151 /*                                                                          */
4152 /* Internal parameters:                                                     */
4153 /*    state[0] = state of source (host that initiated connection)           */
4154 /*    state[1] = state of dest   (host that accepted the connection)        */
4155 /* ------------------------------------------------------------------------ */
4156 void fr_statederef(isp, ifs)
4157 ipstate_t **isp;
4158 ipf_stack_t *ifs;
4159 {
4160 	ipstate_t *is;
4161 
4162 	is = *isp;
4163 	*isp = NULL;
4164 
4165 	MUTEX_ENTER(&is->is_lock);
4166 	if (is->is_ref > 1) {
4167 		is->is_ref--;
4168 		MUTEX_EXIT(&is->is_lock);
4169 #ifndef	_KERNEL
4170 		if ((is->is_sti.tqe_state[0] > IPF_TCPS_ESTABLISHED) ||
4171 		   (is->is_sti.tqe_state[1] > IPF_TCPS_ESTABLISHED)) {
4172 			(void) fr_delstate(is, ISL_ORPHAN, ifs);
4173 		}
4174 #endif
4175 		return;
4176 	}
4177 	MUTEX_EXIT(&is->is_lock);
4178 
4179 	WRITE_ENTER(&ifs->ifs_ipf_state);
4180 	(void) fr_delstate(is, ISL_EXPIRE, ifs);
4181 	RWLOCK_EXIT(&ifs->ifs_ipf_state);
4182 }
4183 
4184 
4185 /* ------------------------------------------------------------------------ */
4186 /* Function:    fr_setstatequeue                                            */
4187 /* Returns:     Nil                                                         */
4188 /* Parameters:  is(I) - pointer to state structure                          */
4189 /*              rev(I) - forward(0) or reverse(1) direction                 */
4190 /* Locks:       ipf_state (read or write)                                   */
4191 /*                                                                          */
4192 /* Put the state entry on its default queue entry, using rev as a helped in */
4193 /* determining which queue it should be placed on.                          */
4194 /* ------------------------------------------------------------------------ */
4195 void fr_setstatequeue(is, rev, ifs)
4196 ipstate_t *is;
4197 int rev;
4198 ipf_stack_t *ifs;
4199 {
4200 	ipftq_t *oifq, *nifq;
4201 
4202 
4203 	if ((is->is_sti.tqe_flags & TQE_RULEBASED) != 0)
4204 		nifq = is->is_tqehead[rev];
4205 	else
4206 		nifq = NULL;
4207 
4208 	if (nifq == NULL) {
4209 		switch (is->is_p)
4210 		{
4211 #ifdef USE_INET6
4212 		case IPPROTO_ICMPV6 :
4213 			if (rev == 1)
4214 				nifq = &ifs->ifs_ips_icmpacktq;
4215 			else
4216 				nifq = &ifs->ifs_ips_icmptq;
4217 			break;
4218 #endif
4219 		case IPPROTO_ICMP :
4220 			if (rev == 1)
4221 				nifq = &ifs->ifs_ips_icmpacktq;
4222 			else
4223 				nifq = &ifs->ifs_ips_icmptq;
4224 			break;
4225 		case IPPROTO_TCP :
4226 			nifq = ifs->ifs_ips_tqtqb + is->is_state[rev];
4227 			break;
4228 
4229 		case IPPROTO_UDP :
4230 			if (rev == 1)
4231 				nifq = &ifs->ifs_ips_udpacktq;
4232 			else
4233 				nifq = &ifs->ifs_ips_udptq;
4234 			break;
4235 
4236 		default :
4237 			nifq = &ifs->ifs_ips_iptq;
4238 			break;
4239 		}
4240 	}
4241 
4242 	oifq = is->is_sti.tqe_ifq;
4243 	/*
4244 	 * If it's currently on a timeout queue, move it from one queue to
4245 	 * another, else put it on the end of the newly determined queue.
4246 	 */
4247 	if (oifq != NULL)
4248 		fr_movequeue(&is->is_sti, oifq, nifq, ifs);
4249 	else
4250 		fr_queueappend(&is->is_sti, nifq, is, ifs);
4251 	return;
4252 }
4253 
4254 
4255 /* ------------------------------------------------------------------------ */
4256 /* Function:    fr_stateiter                                                */
4257 /* Returns:     int - 0 == success, else error                              */
4258 /* Parameters:  token(I) - pointer to ipftoken structure                    */
4259 /*              itp(I)   - pointer to ipfgeniter structure                  */
4260 /*                                                                          */
4261 /* This function handles the SIOCGENITER ioctl for the state tables and     */
4262 /* walks through the list of entries in the state table list (ips_list.)    */
4263 /* ------------------------------------------------------------------------ */
4264 static int fr_stateiter(token, itp, ifs)
4265 ipftoken_t *token;
4266 ipfgeniter_t *itp;
4267 ipf_stack_t *ifs;
4268 {
4269 	ipstate_t *is, *next, zero;
4270 	int error, count;
4271 	char *dst;
4272 
4273 	if (itp->igi_data == NULL)
4274 		return EFAULT;
4275 
4276 	if (itp->igi_nitems == 0)
4277 		return EINVAL;
4278 
4279 	if (itp->igi_type != IPFGENITER_STATE)
4280 		return EINVAL;
4281 
4282 	error = 0;
4283 
4284 	READ_ENTER(&ifs->ifs_ipf_state);
4285 
4286 	/*
4287 	 * Get "previous" entry from the token and find the next entry.
4288 	 */
4289 	is = token->ipt_data;
4290 	if (is == NULL) {
4291 		next = ifs->ifs_ips_list;
4292 	} else {
4293 		next = is->is_next;
4294 	}
4295 
4296 	dst = itp->igi_data;
4297 	for (count = itp->igi_nitems; count > 0; count--) {
4298 		/*
4299 		 * If we found an entry, add a reference to it and update the token.
4300 		 * Otherwise, zero out data to be returned and NULL out token.
4301 		 */
4302 		if (next != NULL) {
4303 			MUTEX_ENTER(&next->is_lock);
4304 			next->is_ref++;
4305 			MUTEX_EXIT(&next->is_lock);
4306 			token->ipt_data = next;
4307 		} else {
4308 			bzero(&zero, sizeof(zero));
4309 			next = &zero;
4310 			token->ipt_data = NULL;
4311 		}
4312 
4313 		/*
4314 		 * Safe to release lock now the we have a reference.
4315 		 */
4316 		RWLOCK_EXIT(&ifs->ifs_ipf_state);
4317 
4318 		/*
4319 		 * Copy out data and clean up references and tokens.
4320 		 */
4321 		error = COPYOUT(next, dst, sizeof(*next));
4322 		if (error != 0)
4323 			error = EFAULT;
4324 		if (token->ipt_data == NULL) {
4325 			ipf_freetoken(token, ifs);
4326 			break;
4327 		} else {
4328 			if (is != NULL)
4329 				fr_statederef(&is, ifs);
4330 			if (next->is_next == NULL) {
4331 				ipf_freetoken(token, ifs);
4332 				break;
4333 			}
4334 		}
4335 
4336 		if ((count == 1) || (error != 0))
4337 			break;
4338 
4339 		READ_ENTER(&ifs->ifs_ipf_state);
4340 		dst += sizeof(*next);
4341 		is = next;
4342 		next = is->is_next;
4343 	}
4344 
4345 	return error;
4346 }
4347