Deleted Added
full compact
ip_state.c (89336) ip_state.c (92685)
1/*
1/*
2 * Copyright (C) 1995-2001 by Darren Reed.
2 * Copyright (C) 1995-2002 by Darren Reed.
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 */
6
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 */
6
7#ifdef __sgi
8# include <sys/ptimers.h>
9#endif
7#include <sys/errno.h>
8#include <sys/types.h>
9#include <sys/param.h>
10#include <sys/file.h>
11#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
12 defined(_KERNEL)
13# include "opt_ipfilter_log.h"
14#endif

--- 16 unchanged lines hidden (view full) ---

31# include <sys/fcntl.h>
32# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM)
33# include "opt_ipfilter.h"
34# endif
35#else
36# include <sys/ioctl.h>
37#endif
38#include <sys/time.h>
10#include <sys/errno.h>
11#include <sys/types.h>
12#include <sys/param.h>
13#include <sys/file.h>
14#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
15 defined(_KERNEL)
16# include "opt_ipfilter_log.h"
17#endif

--- 16 unchanged lines hidden (view full) ---

34# include <sys/fcntl.h>
35# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM)
36# include "opt_ipfilter.h"
37# endif
38#else
39# include <sys/ioctl.h>
40#endif
41#include <sys/time.h>
39#include <sys/uio.h>
40#ifndef linux
41# include <sys/protosw.h>
42#endif
43#include <sys/socket.h>
44#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
45# include <sys/systm.h>
46#endif
47#if !defined(__SVR4) && !defined(__svr4__)

--- 25 unchanged lines hidden (view full) ---

73#endif
74#include <netinet/udp.h>
75#include <netinet/ip_icmp.h>
76#include "netinet/ip_compat.h"
77#include <netinet/tcpip.h>
78#include "netinet/ip_fil.h"
79#include "netinet/ip_nat.h"
80#include "netinet/ip_frag.h"
42#ifndef linux
43# include <sys/protosw.h>
44#endif
45#include <sys/socket.h>
46#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
47# include <sys/systm.h>
48#endif
49#if !defined(__SVR4) && !defined(__svr4__)

--- 25 unchanged lines hidden (view full) ---

75#endif
76#include <netinet/udp.h>
77#include <netinet/ip_icmp.h>
78#include "netinet/ip_compat.h"
79#include <netinet/tcpip.h>
80#include "netinet/ip_fil.h"
81#include "netinet/ip_nat.h"
82#include "netinet/ip_frag.h"
81#include "netinet/ip_proxy.h"
82#include "netinet/ip_state.h"
83#ifdef USE_INET6
84#include <netinet/icmp6.h>
85#endif
86#if (__FreeBSD_version >= 300000)
87# include <sys/malloc.h>
88# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM)
89# include <sys/libkern.h>
90# include <sys/systm.h>
91# endif
92#endif
93
94#if !defined(lint)
95static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
96/* static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.38 2001/07/23 13:49:46 darrenr Exp $"; */
83#include "netinet/ip_state.h"
84#ifdef USE_INET6
85#include <netinet/icmp6.h>
86#endif
87#if (__FreeBSD_version >= 300000)
88# include <sys/malloc.h>
89# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM)
90# include <sys/libkern.h>
91# include <sys/systm.h>
92# endif
93#endif
94
95#if !defined(lint)
96static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
97/* static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.38 2001/07/23 13:49:46 darrenr Exp $"; */
97static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/ip_state.c 89336 2002-01-14 09:07:15Z alfred $";
98static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/ip_state.c 92685 2002-03-19 11:44:16Z darrenr $";
98#endif
99
100#ifndef MIN
101# define MIN(a,b) (((a)<(b))?(a):(b))
102#endif
103
104#define TCP_CLOSE (TH_FIN|TH_RST)
105
106static ipstate_t **ips_table = NULL;
99#endif
100
101#ifndef MIN
102# define MIN(a,b) (((a)<(b))?(a):(b))
103#endif
104
105#define TCP_CLOSE (TH_FIN|TH_RST)
106
107static ipstate_t **ips_table = NULL;
107static ipstate_t *ips_list = NULL;
108static int ips_num = 0;
109static int ips_wild = 0;
110static ips_stat_t ips_stats;
111#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
112extern KRWLOCK_T ipf_state, ipf_mutex;
113extern kmutex_t ipf_rw;
114#endif
115

--- 26 unchanged lines hidden (view full) ---

142 fr_udptimeout = 240,
143 fr_udpacktimeout = 24,
144 fr_icmptimeout = 120,
145 fr_icmpacktimeout = 12;
146int fr_statemax = IPSTATE_MAX,
147 fr_statesize = IPSTATE_SIZE;
148int fr_state_doflush = 0,
149 fr_state_lock = 0;
108static int ips_num = 0;
109static int ips_wild = 0;
110static ips_stat_t ips_stats;
111#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
112extern KRWLOCK_T ipf_state, ipf_mutex;
113extern kmutex_t ipf_rw;
114#endif
115

--- 26 unchanged lines hidden (view full) ---

142 fr_udptimeout = 240,
143 fr_udpacktimeout = 24,
144 fr_icmptimeout = 120,
145 fr_icmpacktimeout = 12;
146int fr_statemax = IPSTATE_MAX,
147 fr_statesize = IPSTATE_SIZE;
148int fr_state_doflush = 0,
149 fr_state_lock = 0;
150ipstate_t *ips_list = NULL;
150
151static int icmpreplytype4[ICMP_MAXTYPE + 1];
151
152static int icmpreplytype4[ICMP_MAXTYPE + 1];
153#ifdef USE_INET6
154static int icmpreplytype6[ICMP6_MAXTYPE + 1];
155#endif
152
153int fr_stateinit()
154{
155 int i;
156
157 KMALLOCS(ips_table, ipstate_t **, fr_statesize * sizeof(ipstate_t *));
158 if (ips_table != NULL)
159 bzero((char *)ips_table, fr_statesize * sizeof(ipstate_t *));
160 else
161 return -1;
162
163 /* fill icmp reply type table */
164 for (i = 0; i <= ICMP_MAXTYPE; i++)
165 icmpreplytype4[i] = -1;
166 icmpreplytype4[ICMP_ECHO] = ICMP_ECHOREPLY;
167 icmpreplytype4[ICMP_TSTAMP] = ICMP_TSTAMPREPLY;
168 icmpreplytype4[ICMP_IREQ] = ICMP_IREQREPLY;
169 icmpreplytype4[ICMP_MASKREQ] = ICMP_MASKREPLY;
156
157int fr_stateinit()
158{
159 int i;
160
161 KMALLOCS(ips_table, ipstate_t **, fr_statesize * sizeof(ipstate_t *));
162 if (ips_table != NULL)
163 bzero((char *)ips_table, fr_statesize * sizeof(ipstate_t *));
164 else
165 return -1;
166
167 /* fill icmp reply type table */
168 for (i = 0; i <= ICMP_MAXTYPE; i++)
169 icmpreplytype4[i] = -1;
170 icmpreplytype4[ICMP_ECHO] = ICMP_ECHOREPLY;
171 icmpreplytype4[ICMP_TSTAMP] = ICMP_TSTAMPREPLY;
172 icmpreplytype4[ICMP_IREQ] = ICMP_IREQREPLY;
173 icmpreplytype4[ICMP_MASKREQ] = ICMP_MASKREPLY;
174#ifdef USE_INET6
175 /* fill icmp reply type table */
176 for (i = 0; i <= ICMP6_MAXTYPE; i++)
177 icmpreplytype6[i] = -1;
178 icmpreplytype6[ICMP6_ECHO_REQUEST] = ICMP6_ECHO_REPLY;
179 icmpreplytype6[ICMP6_MEMBERSHIP_QUERY] = ICMP6_MEMBERSHIP_REPORT;
180 icmpreplytype6[ICMP6_NI_QUERY] = ICMP6_NI_REPLY;
181 icmpreplytype6[ND_ROUTER_SOLICIT] = ND_ROUTER_ADVERT;
182 icmpreplytype6[ND_NEIGHBOR_SOLICIT] = ND_NEIGHBOR_ADVERT;
183#endif
170
171 return 0;
172}
173
174
175static ips_stat_t *fr_statetstats()
176{
177 ips_stats.iss_active = ips_num;
178 ips_stats.iss_table = ips_table;
179 ips_stats.iss_list = ips_list;
180 return &ips_stats;
181}
182
183
184/*
185 * flush state tables. two actions currently defined:
186 * which == 0 : flush all state table entries
187 * which == 1 : flush TCP connections which have started to close but are
188 * stuck for some reason.
184
185 return 0;
186}
187
188
189static ips_stat_t *fr_statetstats()
190{
191 ips_stats.iss_active = ips_num;
192 ips_stats.iss_table = ips_table;
193 ips_stats.iss_list = ips_list;
194 return &ips_stats;
195}
196
197
198/*
199 * flush state tables. two actions currently defined:
200 * which == 0 : flush all state table entries
201 * which == 1 : flush TCP connections which have started to close but are
202 * stuck for some reason.
203 * which == 2 : flush TCP connections which have been idle for a long time,
204 * starting at > 4 days idle and working back in successive half-
205 * days to at most 12 hours old.
189 */
190static int fr_state_flush(which)
191int which;
192{
206 */
207static int fr_state_flush(which)
208int which;
209{
193 register ipstate_t *is, **isp;
210 ipstate_t *is, **isp;
194#if defined(_KERNEL) && !SOLARIS
195 int s;
196#endif
211#if defined(_KERNEL) && !SOLARIS
212 int s;
213#endif
197 int delete, removed = 0;
214 int delete, removed = 0, try;
198
199 SPL_NET(s);
200 for (isp = &ips_list; (is = *isp); ) {
201 delete = 0;
202
203 switch (which)
204 {
205 case 0 :
206 delete = 1;
207 break;
208 case 1 :
215
216 SPL_NET(s);
217 for (isp = &ips_list; (is = *isp); ) {
218 delete = 0;
219
220 switch (which)
221 {
222 case 0 :
223 delete = 1;
224 break;
225 case 1 :
226 case 2 :
209 if (is->is_p != IPPROTO_TCP)
210 break;
211 if ((is->is_state[0] != TCPS_ESTABLISHED) ||
212 (is->is_state[1] != TCPS_ESTABLISHED))
213 delete = 1;
214 break;
215 }
216

--- 5 unchanged lines hidden (view full) ---

222#ifdef IPFILTER_LOG
223 ipstate_log(is, ISL_FLUSH);
224#endif
225 fr_delstate(is);
226 removed++;
227 } else
228 isp = &is->is_next;
229 }
227 if (is->is_p != IPPROTO_TCP)
228 break;
229 if ((is->is_state[0] != TCPS_ESTABLISHED) ||
230 (is->is_state[1] != TCPS_ESTABLISHED))
231 delete = 1;
232 break;
233 }
234

--- 5 unchanged lines hidden (view full) ---

240#ifdef IPFILTER_LOG
241 ipstate_log(is, ISL_FLUSH);
242#endif
243 fr_delstate(is);
244 removed++;
245 } else
246 isp = &is->is_next;
247 }
248
249 /*
250 * Asked to remove inactive entries, try again if first attempt
251 * failed. In this case, 86400 is half a day because the counter is
252 * activated every half second.
253 */
254 if ((which == 2) && (removed == 0)) {
255 try = 86400; /* half a day */
256 for (; (try < FIVE_DAYS) && (removed == 0); try += 86400) {
257 for (isp = &ips_list; (is = *isp); ) {
258 delete = 0;
259 if ((is->is_p == IPPROTO_TCP) &&
260 ((is->is_state[0] == TCPS_ESTABLISHED) ||
261 (is->is_state[1] == TCPS_ESTABLISHED)) &&
262 (is->is_age < try)) {
263 ips_stats.iss_fin++;
264 delete = 1;
265 } else if ((is->is_p != IPPROTO_TCP) &&
266 (is->is_pkts > 1)) {
267 ips_stats.iss_expire++;
268 delete = 1;
269 }
270 if (delete) {
271#ifdef IPFILTER_LOG
272 ipstate_log(is, ISL_FLUSH);
273#endif
274 fr_delstate(is);
275 removed++;
276 } else
277 isp = &is->is_next;
278 }
279 }
280 }
281
230 SPL_X(s);
231 return removed;
232}
233
234
235static int fr_state_remove(data)
236caddr_t data;
237{

--- 96 unchanged lines hidden (view full) ---

334 default :
335 error = EINVAL;
336 break;
337 }
338 return error;
339}
340
341
282 SPL_X(s);
283 return removed;
284}
285
286
287static int fr_state_remove(data)
288caddr_t data;
289{

--- 96 unchanged lines hidden (view full) ---

386 default :
387 error = EINVAL;
388 break;
389 }
390 return error;
391}
392
393
394/*
395 * Copy out state information from the kernel to a user space process.
396 */
342int fr_stgetent(data)
343caddr_t data;
344{
345 register ipstate_t *is, *isn;
397int fr_stgetent(data)
398caddr_t data;
399{
400 register ipstate_t *is, *isn;
346 ipstate_save_t ips, *ipsp;
401 ipstate_save_t ips;
347 int error;
348
402 int error;
403
349 error = IRCOPY(data, (caddr_t)&ipsp, sizeof(ipsp));
404 error = IRCOPYPTR(data, (caddr_t)&ips, sizeof(ips));
350 if (error)
405 if (error)
351 return EFAULT;
352 error = IRCOPY((caddr_t)ipsp, (caddr_t)&ips, sizeof(ips));
353 if (error)
354 return EFAULT;
406 return error;
355
356 isn = ips.ips_next;
357 if (!isn) {
358 isn = ips_list;
359 if (isn == NULL) {
360 if (ips.ips_next == NULL)
361 return ENOENT;
362 return 0;

--- 10 unchanged lines hidden (view full) ---

373 if (!is)
374 return ESRCH;
375 }
376 ips.ips_next = isn->is_next;
377 bcopy((char *)isn, (char *)&ips.ips_is, sizeof(ips.ips_is));
378 if (isn->is_rule)
379 bcopy((char *)isn->is_rule, (char *)&ips.ips_fr,
380 sizeof(ips.ips_fr));
407
408 isn = ips.ips_next;
409 if (!isn) {
410 isn = ips_list;
411 if (isn == NULL) {
412 if (ips.ips_next == NULL)
413 return ENOENT;
414 return 0;

--- 10 unchanged lines hidden (view full) ---

425 if (!is)
426 return ESRCH;
427 }
428 ips.ips_next = isn->is_next;
429 bcopy((char *)isn, (char *)&ips.ips_is, sizeof(ips.ips_is));
430 if (isn->is_rule)
431 bcopy((char *)isn->is_rule, (char *)&ips.ips_fr,
432 sizeof(ips.ips_fr));
381 error = IWCOPY((caddr_t)&ips, ipsp, sizeof(ips));
433 error = IWCOPYPTR((caddr_t)&ips, data, sizeof(ips));
382 if (error)
383 error = EFAULT;
384 return error;
385}
386
387
388int fr_stputent(data)
389caddr_t data;
390{
391 register ipstate_t *is, *isn;
434 if (error)
435 error = EFAULT;
436 return error;
437}
438
439
440int fr_stputent(data)
441caddr_t data;
442{
443 register ipstate_t *is, *isn;
392 ipstate_save_t ips, *ipsp;
393 int error, out;
444 ipstate_save_t ips;
445 int error, out, i;
394 frentry_t *fr;
446 frentry_t *fr;
447 char *name;
395
448
396 error = IRCOPY(data, (caddr_t)&ipsp, sizeof(ipsp));
449 error = IRCOPYPTR(data, (caddr_t)&ips, sizeof(ips));
397 if (error)
450 if (error)
398 return EFAULT;
399 error = IRCOPY((caddr_t)ipsp, (caddr_t)&ips, sizeof(ips));
400 if (error)
401 return EFAULT;
451 return error;
402
403 KMALLOC(isn, ipstate_t *);
404 if (isn == NULL)
405 return ENOMEM;
406
407 bcopy((char *)&ips.ips_is, (char *)isn, sizeof(*isn));
408 fr = isn->is_rule;
409 if (fr != NULL) {
410 if (isn->is_flags & FI_NEWFR) {
411 KMALLOC(fr, frentry_t *);
412 if (fr == NULL) {
413 KFREE(isn);
414 return ENOMEM;
415 }
416 bcopy((char *)&ips.ips_fr, (char *)fr, sizeof(*fr));
417 out = fr->fr_flags & FR_OUTQUE ? 1 : 0;
418 isn->is_rule = fr;
419 ips.ips_is.is_rule = fr;
452
453 KMALLOC(isn, ipstate_t *);
454 if (isn == NULL)
455 return ENOMEM;
456
457 bcopy((char *)&ips.ips_is, (char *)isn, sizeof(*isn));
458 fr = isn->is_rule;
459 if (fr != NULL) {
460 if (isn->is_flags & FI_NEWFR) {
461 KMALLOC(fr, frentry_t *);
462 if (fr == NULL) {
463 KFREE(isn);
464 return ENOMEM;
465 }
466 bcopy((char *)&ips.ips_fr, (char *)fr, sizeof(*fr));
467 out = fr->fr_flags & FR_OUTQUE ? 1 : 0;
468 isn->is_rule = fr;
469 ips.ips_is.is_rule = fr;
420 if (*fr->fr_ifname) {
421 fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_v);
422 if (fr->fr_ifa == NULL)
423 fr->fr_ifa = (void *)-1;
424#ifdef _KERNEL
425 else {
426 strncpy(isn->is_ifname[out],
427 IFNAME(fr->fr_ifa), IFNAMSIZ);
428 isn->is_ifp[out] = fr->fr_ifa;
470
471 /*
472 * Look up all the interface names in the rule.
473 */
474 for (i = 0; i < 4; i++) {
475 name = fr->fr_ifnames[i];
476 if ((name[1] == '\0') &&
477 ((name[0] == '-') || (name[0] == '*'))) {
478 fr->fr_ifas[i] = NULL;
479 } else if (*name != '\0') {
480 fr->fr_ifas[i] = GETUNIT(name,
481 fr->fr_v);
482 if (fr->fr_ifas[i] == NULL)
483 fr->fr_ifas[i] = (void *)-1;
484 else {
485 strncpy(isn->is_ifname[i],
486 IFNAME(fr->fr_ifas[i]),
487 IFNAMSIZ);
488 }
429 }
489 }
430#endif
431 } else
432 fr->fr_ifa = NULL;
490 isn->is_ifp[out] = fr->fr_ifas[i];
491 }
492
433 /*
434 * send a copy back to userland of what we ended up
435 * to allow for verification.
436 */
493 /*
494 * send a copy back to userland of what we ended up
495 * to allow for verification.
496 */
437 error = IWCOPY((caddr_t)&ips, ipsp, sizeof(ips));
497 error = IWCOPYPTR((caddr_t)&ips, data, sizeof(ips));
438 if (error) {
439 KFREE(isn);
440 KFREE(fr);
441 return EFAULT;
442 }
443 } else {
444 for (is = ips_list; is; is = is->is_next)
445 if (is->is_rule == fr)

--- 4 unchanged lines hidden (view full) ---

450 }
451 }
452 }
453 fr_stinsert(isn);
454 return 0;
455}
456
457
498 if (error) {
499 KFREE(isn);
500 KFREE(fr);
501 return EFAULT;
502 }
503 } else {
504 for (is = ips_list; is; is = is->is_next)
505 if (is->is_rule == fr)

--- 4 unchanged lines hidden (view full) ---

510 }
511 }
512 }
513 fr_stinsert(isn);
514 return 0;
515}
516
517
518/*
519 * Insert a state table entry manually.
520 */
458void fr_stinsert(is)
459register ipstate_t *is;
460{
461 register u_int hv = is->is_hv;
521void fr_stinsert(is)
522register ipstate_t *is;
523{
524 register u_int hv = is->is_hv;
525 char *name;
526 int i;
462
463 MUTEX_INIT(&is->is_lock, "ipf state entry", NULL);
464
527
528 MUTEX_INIT(&is->is_lock, "ipf state entry", NULL);
529
465 is->is_ifname[0][sizeof(is->is_ifname[0]) - 1] = '\0';
466 if (is->is_ifname[0][0] != '\0') {
467 is->is_ifp[0] = GETUNIT(is->is_ifname[0], is->is_v);
530 /*
531 * Look up all the interface names in the state entry.
532 */
533 for (i = 0; i < 4; i++) {
534 name = is->is_ifname[i];
535 if ((name[1] == '\0') &&
536 ((name[0] == '-') || (name[0] == '*'))) {
537 is->is_ifp[0] = NULL;
538 } else if (*name != '\0') {
539 is->is_ifp[i] = GETUNIT(name, is->is_v);
540 if (is->is_ifp[i] == NULL)
541 is->is_ifp[i] = (void *)-1;
542 }
468 }
543 }
469 is->is_ifname[1][sizeof(is->is_ifname[0]) - 1] = '\0';
470 if (is->is_ifname[1][0] != '\0') {
471 is->is_ifp[1] = GETUNIT(is->is_ifname[1], is->is_v);
472 }
473
544
545
474 /*
475 * add into list table.
476 */
477 if (ips_list)
478 ips_list->is_pnext = &is->is_next;
479 is->is_pnext = &ips_list;
480 is->is_next = ips_list;
481 ips_list = is;

--- 6 unchanged lines hidden (view full) ---

488 ips_table[hv] = is;
489 ips_num++;
490}
491
492
493/*
494 * Create a new ipstate structure and hang it off the hash table.
495 */
546 /*
547 * add into list table.
548 */
549 if (ips_list)
550 ips_list->is_pnext = &is->is_next;
551 is->is_pnext = &ips_list;
552 is->is_next = ips_list;
553 ips_list = is;

--- 6 unchanged lines hidden (view full) ---

560 ips_table[hv] = is;
561 ips_num++;
562}
563
564
565/*
566 * Create a new ipstate structure and hang it off the hash table.
567 */
496ipstate_t *fr_addstate(ip, fin, flags)
568ipstate_t *fr_addstate(ip, fin, stsave, flags)
497ip_t *ip;
498fr_info_t *fin;
569ip_t *ip;
570fr_info_t *fin;
571ipstate_t **stsave;
499u_int flags;
500{
501 register tcphdr_t *tcp = NULL;
502 register ipstate_t *is;
503 register u_int hv;
572u_int flags;
573{
574 register tcphdr_t *tcp = NULL;
575 register ipstate_t *is;
576 register u_int hv;
577 struct icmp *ic;
504 ipstate_t ips;
505 u_int pass;
578 ipstate_t ips;
579 u_int pass;
580 void *ifp;
506 int out;
507
508 if (fr_state_lock || (fin->fin_off != 0) || (fin->fin_fl & FI_SHORT))
509 return NULL;
510 if (ips_num == fr_statemax) {
511 ips_stats.iss_max++;
512 fr_state_doflush = 1;
513 return NULL;
514 }
515 out = fin->fin_out;
516 is = &ips;
517 bzero((char *)is, sizeof(*is));
518 ips.is_age = 1;
581 int out;
582
583 if (fr_state_lock || (fin->fin_off != 0) || (fin->fin_fl & FI_SHORT))
584 return NULL;
585 if (ips_num == fr_statemax) {
586 ips_stats.iss_max++;
587 fr_state_doflush = 1;
588 return NULL;
589 }
590 out = fin->fin_out;
591 is = &ips;
592 bzero((char *)is, sizeof(*is));
593 ips.is_age = 1;
519 ips.is_state[0] = 0;
520 ips.is_state[1] = 0;
521 /*
522 * Copy and calculate...
523 */
524 hv = (is->is_p = fin->fin_fi.fi_p);
525 is->is_src = fin->fin_fi.fi_src;
526 hv += is->is_saddr;
527 is->is_dst = fin->fin_fi.fi_dst;
528 hv += is->is_daddr;
529#ifdef USE_INET6
530 if (fin->fin_v == 6) {
594 /*
595 * Copy and calculate...
596 */
597 hv = (is->is_p = fin->fin_fi.fi_p);
598 is->is_src = fin->fin_fi.fi_src;
599 hv += is->is_saddr;
600 is->is_dst = fin->fin_fi.fi_dst;
601 hv += is->is_daddr;
602#ifdef USE_INET6
603 if (fin->fin_v == 6) {
531 if (is->is_p == IPPROTO_ICMPV6) {
532 if (IN6_IS_ADDR_MULTICAST(&is->is_dst.in6))
533 flags |= FI_W_DADDR;
534 if (out)
535 hv -= is->is_daddr;
536 else
537 hv -= is->is_saddr;
604 if ((is->is_p == IPPROTO_ICMPV6) &&
605 IN6_IS_ADDR_MULTICAST(&is->is_dst.in6)) {
606 /*
607 * So you can do keep state with neighbour discovery.
608 */
609 flags |= FI_W_DADDR;
610 hv -= is->is_daddr;
611 } else {
612 hv += is->is_dst.i6[1];
613 hv += is->is_dst.i6[2];
614 hv += is->is_dst.i6[3];
538 }
615 }
616 hv += is->is_src.i6[1];
617 hv += is->is_src.i6[2];
618 hv += is->is_src.i6[3];
539 }
540#endif
541
542 switch (is->is_p)
543 {
544#ifdef USE_INET6
545 case IPPROTO_ICMPV6 :
619 }
620#endif
621
622 switch (is->is_p)
623 {
624#ifdef USE_INET6
625 case IPPROTO_ICMPV6 :
546#endif
547 case IPPROTO_ICMP :
548 {
549 struct icmp *ic = (struct icmp *)fin->fin_dp;
550
551#ifdef USE_INET6
552 if ((is->is_p == IPPROTO_ICMPV6) &&
553 ((ic->icmp_type & ICMP6_INFOMSG_MASK) == 0))
626 ic = (struct icmp *)fin->fin_dp;
627 if ((ic->icmp_type & ICMP6_INFOMSG_MASK) == 0)
554 return NULL;
628 return NULL;
555#endif
629
556 switch (ic->icmp_type)
557 {
630 switch (ic->icmp_type)
631 {
558#ifdef USE_INET6
559 case ICMP6_ECHO_REQUEST :
632 case ICMP6_ECHO_REQUEST :
560 is->is_icmp.ics_type = ICMP6_ECHO_REPLY;
633 is->is_icmp.ics_type = ic->icmp_type;
561 hv += (is->is_icmp.ics_id = ic->icmp_id);
562 hv += (is->is_icmp.ics_seq = ic->icmp_seq);
563 break;
564 case ICMP6_MEMBERSHIP_QUERY :
565 case ND_ROUTER_SOLICIT :
566 case ND_NEIGHBOR_SOLICIT :
634 hv += (is->is_icmp.ics_id = ic->icmp_id);
635 hv += (is->is_icmp.ics_seq = ic->icmp_seq);
636 break;
637 case ICMP6_MEMBERSHIP_QUERY :
638 case ND_ROUTER_SOLICIT :
639 case ND_NEIGHBOR_SOLICIT :
567 is->is_icmp.ics_type = ic->icmp_type + 1;
640 case ICMP6_NI_QUERY :
641 is->is_icmp.ics_type = ic->icmp_type;
568 break;
642 break;
643 default :
644 return NULL;
645 }
646 ATOMIC_INCL(ips_stats.iss_icmp);
647 is->is_age = fr_icmptimeout;
648 break;
569#endif
649#endif
650 case IPPROTO_ICMP :
651 ic = (struct icmp *)fin->fin_dp;
652
653 switch (ic->icmp_type)
654 {
570 case ICMP_ECHO :
571 case ICMP_TSTAMP :
572 case ICMP_IREQ :
573 case ICMP_MASKREQ :
574 is->is_icmp.ics_type = ic->icmp_type;
575 hv += (is->is_icmp.ics_id = ic->icmp_id);
576 hv += (is->is_icmp.ics_seq = ic->icmp_seq);
577 break;
578 default :
579 return NULL;
580 }
581 ATOMIC_INCL(ips_stats.iss_icmp);
582 is->is_age = fr_icmptimeout;
583 break;
655 case ICMP_ECHO :
656 case ICMP_TSTAMP :
657 case ICMP_IREQ :
658 case ICMP_MASKREQ :
659 is->is_icmp.ics_type = ic->icmp_type;
660 hv += (is->is_icmp.ics_id = ic->icmp_id);
661 hv += (is->is_icmp.ics_seq = ic->icmp_seq);
662 break;
663 default :
664 return NULL;
665 }
666 ATOMIC_INCL(ips_stats.iss_icmp);
667 is->is_age = fr_icmptimeout;
668 break;
584 }
585 case IPPROTO_TCP :
669 case IPPROTO_TCP :
586 {
587 tcp = (tcphdr_t *)fin->fin_dp;
588
589 if (tcp->th_flags & TH_RST)
590 return NULL;
591 /*
592 * The endian of the ports doesn't matter, but the ack and
593 * sequence numbers do as we do mathematics on them later.
594 */
670 tcp = (tcphdr_t *)fin->fin_dp;
671
672 if (tcp->th_flags & TH_RST)
673 return NULL;
674 /*
675 * The endian of the ports doesn't matter, but the ack and
676 * sequence numbers do as we do mathematics on them later.
677 */
595 is->is_dport = tcp->th_dport;
596 is->is_sport = tcp->th_sport;
678 is->is_sport = htons(fin->fin_data[0]);
679 is->is_dport = htons(fin->fin_data[1]);
597 if ((flags & (FI_W_DPORT|FI_W_SPORT)) == 0) {
680 if ((flags & (FI_W_DPORT|FI_W_SPORT)) == 0) {
598 hv += tcp->th_dport;
599 hv += tcp->th_sport;
681 hv += is->is_sport;
682 hv += is->is_dport;
600 }
601 is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen -
602 (tcp->th_off << 2) +
603 ((tcp->th_flags & TH_SYN) ? 1 : 0) +
604 ((tcp->th_flags & TH_FIN) ? 1 : 0);
605 is->is_maxsend = is->is_send;
606 is->is_dend = 0;
607 is->is_maxdwin = 1;
608 is->is_maxswin = ntohs(tcp->th_win);
609 if (is->is_maxswin == 0)
610 is->is_maxswin = 1;
611 /*
612 * If we're creating state for a starting connection, start the
613 * timer on it as we'll never see an error if it fails to
614 * connect.
615 */
616 ATOMIC_INCL(ips_stats.iss_tcp);
617 break;
683 }
684 is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen -
685 (tcp->th_off << 2) +
686 ((tcp->th_flags & TH_SYN) ? 1 : 0) +
687 ((tcp->th_flags & TH_FIN) ? 1 : 0);
688 is->is_maxsend = is->is_send;
689 is->is_dend = 0;
690 is->is_maxdwin = 1;
691 is->is_maxswin = ntohs(tcp->th_win);
692 if (is->is_maxswin == 0)
693 is->is_maxswin = 1;
694 /*
695 * If we're creating state for a starting connection, start the
696 * timer on it as we'll never see an error if it fails to
697 * connect.
698 */
699 ATOMIC_INCL(ips_stats.iss_tcp);
700 break;
618 }
701
619 case IPPROTO_UDP :
702 case IPPROTO_UDP :
620 {
621 tcp = (tcphdr_t *)fin->fin_dp;
622
703 tcp = (tcphdr_t *)fin->fin_dp;
704
623 is->is_dport = tcp->th_dport;
624 is->is_sport = tcp->th_sport;
705 is->is_sport = htons(fin->fin_data[0]);
706 is->is_dport = htons(fin->fin_data[1]);
625 if ((flags & (FI_W_DPORT|FI_W_SPORT)) == 0) {
707 if ((flags & (FI_W_DPORT|FI_W_SPORT)) == 0) {
626 hv += tcp->th_dport;
627 hv += tcp->th_sport;
708 hv += is->is_sport;
709 hv += is->is_dport;
628 }
629 ATOMIC_INCL(ips_stats.iss_udp);
630 is->is_age = fr_udptimeout;
631 break;
710 }
711 ATOMIC_INCL(ips_stats.iss_udp);
712 is->is_age = fr_udptimeout;
713 break;
632 }
633 default :
714 default :
634 return NULL;
715 is->is_age = fr_udptimeout;
716 break;
635 }
636
637 KMALLOC(is, ipstate_t *);
638 if (is == NULL) {
639 ATOMIC_INCL(ips_stats.iss_nomem);
640 return NULL;
641 }
642 bcopy((char *)&ips, (char *)is, sizeof(*is));
643 hv %= fr_statesize;
644 is->is_hv = hv;
645 is->is_rule = fin->fin_fr;
646 if (is->is_rule != NULL) {
647 ATOMIC_INC32(is->is_rule->fr_ref);
648 pass = is->is_rule->fr_flags;
717 }
718
719 KMALLOC(is, ipstate_t *);
720 if (is == NULL) {
721 ATOMIC_INCL(ips_stats.iss_nomem);
722 return NULL;
723 }
724 bcopy((char *)&ips, (char *)is, sizeof(*is));
725 hv %= fr_statesize;
726 is->is_hv = hv;
727 is->is_rule = fin->fin_fr;
728 if (is->is_rule != NULL) {
729 ATOMIC_INC32(is->is_rule->fr_ref);
730 pass = is->is_rule->fr_flags;
731 is->is_frage[0] = is->is_rule->fr_age[0];
732 is->is_frage[1] = is->is_rule->fr_age[1];
733 if (is->is_frage[0] != 0)
734 is->is_age = is->is_frage[0];
735
736 is->is_ifp[(out << 1) + 1] = is->is_rule->fr_ifas[1];
737 is->is_ifp[(1 - out) << 1] = is->is_rule->fr_ifas[2];
738 is->is_ifp[((1 - out) << 1) + 1] = is->is_rule->fr_ifas[3];
739
740 if (((ifp = is->is_rule->fr_ifas[1]) != NULL) &&
741 (ifp != (void *)-1))
742 strncpy(is->is_ifname[(out << 1) + 1],
743 IFNAME(ifp), IFNAMSIZ);
744 if (((ifp = is->is_rule->fr_ifas[2]) != NULL) &&
745 (ifp != (void *)-1))
746 strncpy(is->is_ifname[(1 - out) << 1],
747 IFNAME(ifp), IFNAMSIZ);
748 if (((ifp = is->is_rule->fr_ifas[3]) != NULL) &&
749 (ifp != (void *)-1))
750 strncpy(is->is_ifname[((1 - out) << 1) + 1],
751 IFNAME(ifp), IFNAMSIZ);
649 } else
650 pass = fr_flags;
752 } else
753 pass = fr_flags;
754
755 is->is_ifp[out << 1] = fin->fin_ifp;
756 strncpy(is->is_ifname[out << 1], IFNAME(fin->fin_ifp), IFNAMSIZ);
757
651 WRITE_ENTER(&ipf_state);
652
653 is->is_pass = pass;
758 WRITE_ENTER(&ipf_state);
759
760 is->is_pass = pass;
654 is->is_pkts = 1;
655 is->is_bytes = fin->fin_dlen + fin->fin_hlen;
761 if ((flags & FI_IGNOREPKT) == 0) {
762 is->is_pkts = 1;
763 is->is_bytes = fin->fin_dlen + fin->fin_hlen;
764 }
656 /*
657 * We want to check everything that is a property of this packet,
658 * but we don't (automatically) care about it's fragment status as
659 * this may change.
660 */
765 /*
766 * We want to check everything that is a property of this packet,
767 * but we don't (automatically) care about it's fragment status as
768 * this may change.
769 */
661 is->is_v = fin->fin_fi.fi_v;
770 is->is_v = fin->fin_v;
771 is->is_rulen = fin->fin_rule;
662 is->is_opt = fin->fin_fi.fi_optmsk;
663 is->is_optmsk = 0xffffffff;
664 is->is_sec = fin->fin_fi.fi_secmsk;
665 is->is_secmsk = 0xffff;
666 is->is_auth = fin->fin_fi.fi_auth;
667 is->is_authmsk = 0xffff;
668 is->is_flags = fin->fin_fl & FI_CMP;
669 is->is_flags |= FI_CMP << 4;
670 is->is_flags |= flags & (FI_WILDP|FI_WILDA);
671 if (flags & (FI_WILDP|FI_WILDA))
672 ips_wild++;
772 is->is_opt = fin->fin_fi.fi_optmsk;
773 is->is_optmsk = 0xffffffff;
774 is->is_sec = fin->fin_fi.fi_secmsk;
775 is->is_secmsk = 0xffff;
776 is->is_auth = fin->fin_fi.fi_auth;
777 is->is_authmsk = 0xffff;
778 is->is_flags = fin->fin_fl & FI_CMP;
779 is->is_flags |= FI_CMP << 4;
780 is->is_flags |= flags & (FI_WILDP|FI_WILDA);
781 if (flags & (FI_WILDP|FI_WILDA))
782 ips_wild++;
673 is->is_ifp[1 - out] = NULL;
674 is->is_ifp[out] = fin->fin_ifp;
675#ifdef _KERNEL
676 strncpy(is->is_ifname[out], IFNAME(fin->fin_ifp), IFNAMSIZ);
677#endif
678 is->is_ifname[1 - out][0] = '\0';
783
679 if (pass & FR_LOGFIRST)
680 is->is_pass &= ~(FR_LOGFIRST|FR_LOG);
681 fr_stinsert(is);
784 if (pass & FR_LOGFIRST)
785 is->is_pass &= ~(FR_LOGFIRST|FR_LOG);
786 fr_stinsert(is);
787 is->is_me = stsave;
682 if (is->is_p == IPPROTO_TCP) {
788 if (is->is_p == IPPROTO_TCP) {
683 MUTEX_ENTER(&is->is_lock);
684 fr_tcp_age(&is->is_age, is->is_state, fin,
685 0); /* 0 = packet from the source */
789 fr_tcp_age(&is->is_age, is->is_state, fin,
790 0); /* 0 = packet from the source */
686 MUTEX_EXIT(&is->is_lock);
687 }
688#ifdef IPFILTER_LOG
689 ipstate_log(is, ISL_NEW);
690#endif
691 RWLOCK_EXIT(&ipf_state);
692 fin->fin_rev = IP6NEQ(is->is_dst, fin->fin_fi.fi_dst);
693 if ((fin->fin_fi.fi_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
694 ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);

--- 103 unchanged lines hidden (view full) ---

798 fr_tcp_age(&is->is_age, is->is_state, fin, !source);
799 ret = 1;
800 }
801 MUTEX_EXIT(&is->is_lock);
802 return ret;
803}
804
805
791 }
792#ifdef IPFILTER_LOG
793 ipstate_log(is, ISL_NEW);
794#endif
795 RWLOCK_EXIT(&ipf_state);
796 fin->fin_rev = IP6NEQ(is->is_dst, fin->fin_fi.fi_dst);
797 if ((fin->fin_fi.fi_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
798 ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);

--- 103 unchanged lines hidden (view full) ---

902 fr_tcp_age(&is->is_age, is->is_state, fin, !source);
903 ret = 1;
904 }
905 MUTEX_EXIT(&is->is_lock);
906 return ret;
907}
908
909
910/*
911 * Match a state table entry against an IP packet.
912 */
806static int fr_matchsrcdst(is, src, dst, fin, tcp)
807ipstate_t *is;
808union i6addr src, dst;
809fr_info_t *fin;
810tcphdr_t *tcp;
811{
913static int fr_matchsrcdst(is, src, dst, fin, tcp)
914ipstate_t *is;
915union i6addr src, dst;
916fr_info_t *fin;
917tcphdr_t *tcp;
918{
812 int ret = 0, rev, out, flags;
919 int ret = 0, rev, out, flags, idx;
813 u_short sp, dp;
814 void *ifp;
815
816 rev = IP6NEQ(is->is_dst, dst);
817 ifp = fin->fin_ifp;
818 out = fin->fin_out;
920 u_short sp, dp;
921 void *ifp;
922
923 rev = IP6NEQ(is->is_dst, dst);
924 ifp = fin->fin_ifp;
925 out = fin->fin_out;
926 flags = is->is_flags & (FI_WILDA|FI_WILDP);
927 sp = 0;
928 dp = 0;
819
820 if (tcp != NULL) {
821 flags = is->is_flags;
822 sp = tcp->th_sport;
823 dp = tcp->th_dport;
824 if (!rev) {
825 if (!(flags & FI_W_SPORT) && (sp != is->is_sport))
826 rev = 1;
827 else if (!(flags & FI_W_DPORT) && (dp != is->is_dport))
828 rev = 1;
829 }
929
930 if (tcp != NULL) {
931 flags = is->is_flags;
932 sp = tcp->th_sport;
933 dp = tcp->th_dport;
934 if (!rev) {
935 if (!(flags & FI_W_SPORT) && (sp != is->is_sport))
936 rev = 1;
937 else if (!(flags & FI_W_DPORT) && (dp != is->is_dport))
938 rev = 1;
939 }
830 } else {
831 flags = is->is_flags & FI_WILDA;
832 sp = 0;
833 dp = 0;
834 }
835
940 }
941
836 if (rev == 0) {
837 if (!out) {
838 if (is->is_ifpin == NULL || is->is_ifpin == ifp)
839 ret = 1;
840 } else {
841 if (is->is_ifpout == NULL || is->is_ifpout == ifp)
842 ret = 1;
843 }
844 } else {
845 if (out) {
846 if (is->is_ifpin == NULL || is->is_ifpin == ifp)
847 ret = 1;
848 } else {
849 if (is->is_ifpout == NULL || is->is_ifpout == ifp)
850 ret = 1;
851 }
852 }
942 idx = (out << 1) + rev;
943
944 if ((is->is_ifp[idx] == NULL &&
945 (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) ||
946 is->is_ifp[idx] == ifp)
947 ret = 1;
948
853 if (ret == 0)
854 return 0;
855 ret = 0;
856
857 if (rev == 0) {
949 if (ret == 0)
950 return 0;
951 ret = 0;
952
953 if (rev == 0) {
858 if (
859 (IP6EQ(is->is_dst, dst) || (flags & FI_W_DADDR)) &&
954 if ((IP6EQ(is->is_dst, dst) || (flags & FI_W_DADDR)) &&
860 (IP6EQ(is->is_src, src) || (flags & FI_W_SADDR)) &&
861 (!tcp || ((sp == is->is_sport || flags & FI_W_SPORT) &&
862 (dp == is->is_dport || flags & FI_W_DPORT)))) {
863 ret = 1;
864 }
865 } else {
955 (IP6EQ(is->is_src, src) || (flags & FI_W_SADDR)) &&
956 (!tcp || ((sp == is->is_sport || flags & FI_W_SPORT) &&
957 (dp == is->is_dport || flags & FI_W_DPORT)))) {
958 ret = 1;
959 }
960 } else {
866 if (
867 (IP6EQ(is->is_dst, src) || (flags & FI_W_DADDR)) &&
961 if ((IP6EQ(is->is_dst, src) || (flags & FI_W_DADDR)) &&
868 (IP6EQ(is->is_src, dst) || (flags & FI_W_SADDR)) &&
869 (!tcp || ((sp == is->is_dport || flags & FI_W_DPORT) &&
870 (dp == is->is_sport || flags & FI_W_SPORT)))) {
871 ret = 1;
872 }
873 }
874 if (ret == 0)
875 return 0;

--- 6 unchanged lines hidden (view full) ---

882 flags = is->is_flags & (FI_CMP|(FI_CMP<<4));
883
884 if (((fin->fin_fl & (flags >> 4)) != (flags & FI_CMP)) ||
885 (fin->fin_fi.fi_optmsk != is->is_opt) ||
886 (fin->fin_fi.fi_secmsk != is->is_sec) ||
887 (fin->fin_fi.fi_auth != is->is_auth))
888 return 0;
889
962 (IP6EQ(is->is_src, dst) || (flags & FI_W_SADDR)) &&
963 (!tcp || ((sp == is->is_dport || flags & FI_W_DPORT) &&
964 (dp == is->is_sport || flags & FI_W_SPORT)))) {
965 ret = 1;
966 }
967 }
968 if (ret == 0)
969 return 0;

--- 6 unchanged lines hidden (view full) ---

976 flags = is->is_flags & (FI_CMP|(FI_CMP<<4));
977
978 if (((fin->fin_fl & (flags >> 4)) != (flags & FI_CMP)) ||
979 (fin->fin_fi.fi_optmsk != is->is_opt) ||
980 (fin->fin_fi.fi_secmsk != is->is_sec) ||
981 (fin->fin_fi.fi_auth != is->is_auth))
982 return 0;
983
984 flags = is->is_flags & (FI_WILDA|FI_WILDP);
985 if ((flags & (FI_W_SADDR|FI_W_DADDR))) {
986 if ((flags & FI_W_SADDR) != 0) {
987 if (rev == 0) {
988 is->is_src = fin->fin_fi.fi_src;
989 } else {
990 is->is_src = fin->fin_fi.fi_dst;
991 }
992 } else if ((flags & FI_W_DPORT) != 0) {
993 if (rev == 0) {
994 is->is_dst = fin->fin_fi.fi_dst;
995 } else {
996 is->is_dst = fin->fin_fi.fi_src;
997 }
998 }
999 is->is_flags &= ~(FI_W_SADDR|FI_W_DADDR);
1000 if ((is->is_flags & (FI_WILDA|FI_WILDP)) == 0)
1001 ips_wild--;
1002 }
1003
890 if ((flags & (FI_W_SPORT|FI_W_DPORT))) {
891 if ((flags & FI_W_SPORT) != 0) {
892 if (rev == 0) {
893 is->is_sport = sp;
894 is->is_send = htonl(tcp->th_seq);
895 } else {
896 is->is_sport = dp;
897 is->is_send = htonl(tcp->th_ack);

--- 10 unchanged lines hidden (view full) ---

908 is->is_maxdend = is->is_dend + 1;
909 }
910 is->is_flags &= ~(FI_W_SPORT|FI_W_DPORT);
911 ips_wild--;
912 }
913
914 ret = -1;
915
1004 if ((flags & (FI_W_SPORT|FI_W_DPORT))) {
1005 if ((flags & FI_W_SPORT) != 0) {
1006 if (rev == 0) {
1007 is->is_sport = sp;
1008 is->is_send = htonl(tcp->th_seq);
1009 } else {
1010 is->is_sport = dp;
1011 is->is_send = htonl(tcp->th_ack);

--- 10 unchanged lines hidden (view full) ---

1022 is->is_maxdend = is->is_dend + 1;
1023 }
1024 is->is_flags &= ~(FI_W_SPORT|FI_W_DPORT);
1025 ips_wild--;
1026 }
1027
1028 ret = -1;
1029
916 if (!rev) {
917 if (out) {
918 if (!is->is_ifpout)
919 ret = 1;
920 } else {
921 if (!is->is_ifpin)
922 ret = 0;
923 }
924 } else {
925 if (out) {
926 if (!is->is_ifpin)
927 ret = 0;
928 } else {
929 if (!is->is_ifpout)
930 ret = 1;
931 }
932 }
1030 if (is->is_ifp[idx] == NULL &&
1031 (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*'))
1032 ret = idx;
933
934 if (ret >= 0) {
935 is->is_ifp[ret] = ifp;
1033
1034 if (ret >= 0) {
1035 is->is_ifp[ret] = ifp;
936#ifdef _KERNEL
937 strncpy(is->is_ifname[ret], IFNAME(fin->fin_ifp),
1036 strncpy(is->is_ifname[ret], IFNAME(ifp),
938 sizeof(is->is_ifname[ret]));
1037 sizeof(is->is_ifname[ret]));
939#endif
940 }
941 fin->fin_rev = rev;
942 return 1;
943}
944
945static int fr_matchicmpqueryreply(v, is, icmp)
946int v;
947ipstate_t *is;
948icmphdr_t *icmp;
949{
950 if (v == 4) {
951 /*
952 * If we matched its type on the way in, then when going out
953 * it will still be the same type.
954 */
955 if (((icmp->icmp_type == is->is_type) ||
1038 }
1039 fin->fin_rev = rev;
1040 return 1;
1041}
1042
1043static int fr_matchicmpqueryreply(v, is, icmp)
1044int v;
1045ipstate_t *is;
1046icmphdr_t *icmp;
1047{
1048 if (v == 4) {
1049 /*
1050 * If we matched its type on the way in, then when going out
1051 * it will still be the same type.
1052 */
1053 if (((icmp->icmp_type == is->is_type) ||
956 (icmpreplytype4[is->is_type] == icmp->icmp_type)) &&
957 (icmp->icmp_id == is->is_icmp.ics_id) &&
958 (icmp->icmp_seq == is->is_icmp.ics_seq)) {
959 return 1;
960 };
1054 (icmpreplytype4[is->is_type] == icmp->icmp_type))) {
1055 if (icmp->icmp_type != ICMP_ECHOREPLY)
1056 return 1;
1057 if ((icmp->icmp_id == is->is_icmp.ics_id) &&
1058 (icmp->icmp_seq == is->is_icmp.ics_seq))
1059 return 1;
1060 }
961 }
962#ifdef USE_INET6
963 else if (is->is_v == 6) {
1061 }
1062#ifdef USE_INET6
1063 else if (is->is_v == 6) {
964 if ((is->is_type == ICMP6_ECHO_REPLY) &&
965 (icmp->icmp_type == ICMP6_ECHO_REQUEST) &&
966 (icmp->icmp_id == is->is_icmp.ics_id) &&
967 (icmp->icmp_seq == is->is_icmp.ics_seq)) {
968 return 1;
969 };
1064 if (((icmp->icmp_type == is->is_type) ||
1065 (icmpreplytype6[is->is_type] == icmp->icmp_type))) {
1066 if (icmp->icmp_type != ICMP6_ECHO_REPLY)
1067 return 1;
1068 if ((icmp->icmp_id == is->is_icmp.ics_id) &&
1069 (icmp->icmp_seq == is->is_icmp.ics_seq))
1070 return 1;
1071 }
970 }
971#endif
972 return 0;
973}
974
975static frentry_t *fr_checkicmpmatchingstate(ip, fin)
976ip_t *ip;
977fr_info_t *fin;

--- 15 unchanged lines hidden (view full) ---

993 /*
994 * Does it at least have the return (basic) IP header ?
995 * Only a basic IP header (no options) should be with
996 * an ICMP error header.
997 */
998 if (((ip->ip_v != 4) || (ip->ip_hl != 5)) ||
999 (fin->fin_plen < ICMPERR_MINPKTLEN))
1000 return NULL;
1072 }
1073#endif
1074 return 0;
1075}
1076
1077static frentry_t *fr_checkicmpmatchingstate(ip, fin)
1078ip_t *ip;
1079fr_info_t *fin;

--- 15 unchanged lines hidden (view full) ---

1095 /*
1096 * Does it at least have the return (basic) IP header ?
1097 * Only a basic IP header (no options) should be with
1098 * an ICMP error header.
1099 */
1100 if (((ip->ip_v != 4) || (ip->ip_hl != 5)) ||
1101 (fin->fin_plen < ICMPERR_MINPKTLEN))
1102 return NULL;
1103
1001 ic = (struct icmp *)fin->fin_dp;
1002 type = ic->icmp_type;
1003 /*
1004 * If it's not an error type, then return
1005 */
1006 if ((type != ICMP_UNREACH) && (type != ICMP_SOURCEQUENCH) &&
1007 (type != ICMP_REDIRECT) && (type != ICMP_TIMXCEED) &&
1008 (type != ICMP_PARAMPROB))

--- 37 unchanged lines hidden (view full) ---

1046
1047 /*
1048 * in the IPv4 case we must zero the i6addr union otherwise
1049 * the IP6EQ and IP6NEQ macros produce the wrong results because
1050 * of the 'junk' in the unused part of the union
1051 */
1052 bzero((char *)&src, sizeof(src));
1053 bzero((char *)&dst, sizeof(dst));
1104 ic = (struct icmp *)fin->fin_dp;
1105 type = ic->icmp_type;
1106 /*
1107 * If it's not an error type, then return
1108 */
1109 if ((type != ICMP_UNREACH) && (type != ICMP_SOURCEQUENCH) &&
1110 (type != ICMP_REDIRECT) && (type != ICMP_TIMXCEED) &&
1111 (type != ICMP_PARAMPROB))

--- 37 unchanged lines hidden (view full) ---

1149
1150 /*
1151 * in the IPv4 case we must zero the i6addr union otherwise
1152 * the IP6EQ and IP6NEQ macros produce the wrong results because
1153 * of the 'junk' in the unused part of the union
1154 */
1155 bzero((char *)&src, sizeof(src));
1156 bzero((char *)&dst, sizeof(dst));
1157 fr = NULL;
1054
1158
1055 if (oip->ip_p == IPPROTO_ICMP) {
1159 switch (oip->ip_p)
1160 {
1161 case IPPROTO_ICMP :
1056 icmp = (icmphdr_t *)((char *)oip + (oip->ip_hl << 2));
1057
1058 /*
1059 * a ICMP error can only be generated as a result of an
1060 * ICMP query, not as the response on an ICMP error
1061 *
1062 * XXX theoretically ICMP_ECHOREP and the other reply's are
1063 * ICMP query's as well, but adding them here seems strange XXX

--- 29 unchanged lines hidden (view full) ---

1093 for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext)
1094 if ((is->is_p == pr) && (is->is_v == 4) &&
1095 fr_matchsrcdst(is, src, dst, &ofin, NULL) &&
1096 fr_matchicmpqueryreply(is->is_v, is, icmp)) {
1097 ips_stats.iss_hits++;
1098 is->is_pkts++;
1099 is->is_bytes += ip->ip_len;
1100 fr = is->is_rule;
1162 icmp = (icmphdr_t *)((char *)oip + (oip->ip_hl << 2));
1163
1164 /*
1165 * a ICMP error can only be generated as a result of an
1166 * ICMP query, not as the response on an ICMP error
1167 *
1168 * XXX theoretically ICMP_ECHOREP and the other reply's are
1169 * ICMP query's as well, but adding them here seems strange XXX

--- 29 unchanged lines hidden (view full) ---

1199 for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext)
1200 if ((is->is_p == pr) && (is->is_v == 4) &&
1201 fr_matchsrcdst(is, src, dst, &ofin, NULL) &&
1202 fr_matchicmpqueryreply(is->is_v, is, icmp)) {
1203 ips_stats.iss_hits++;
1204 is->is_pkts++;
1205 is->is_bytes += ip->ip_len;
1206 fr = is->is_rule;
1101 RWLOCK_EXIT(&ipf_state);
1102 return fr;
1207 break;
1103 }
1104 RWLOCK_EXIT(&ipf_state);
1208 }
1209 RWLOCK_EXIT(&ipf_state);
1210 return fr;
1211
1212 case IPPROTO_TCP :
1213 case IPPROTO_UDP :
1214 break;
1215 default :
1105 return NULL;
1216 return NULL;
1106 };
1217 }
1107
1218
1108 if ((oip->ip_p != IPPROTO_TCP) && (oip->ip_p != IPPROTO_UDP))
1109 return NULL;
1110
1111 tcp = (tcphdr_t *)((char *)oip + (oip->ip_hl << 2));
1112 dport = tcp->th_dport;
1113 sport = tcp->th_sport;
1114
1115 hv = (pr = oip->ip_p);
1116 src.in4 = oip->ip_src;
1117 hv += src.in4.s_addr;
1118 dst.in4 = oip->ip_dst;

--- 34 unchanged lines hidden (view full) ---

1153 ips_stats.iss_hits++;
1154 is->is_pkts++;
1155 is->is_bytes += fin->fin_plen;
1156 /*
1157 * we deliberately do not touch the timeouts
1158 * for the accompanying state table entry.
1159 * It remains to be seen if that is correct. XXX
1160 */
1219 tcp = (tcphdr_t *)((char *)oip + (oip->ip_hl << 2));
1220 dport = tcp->th_dport;
1221 sport = tcp->th_sport;
1222
1223 hv = (pr = oip->ip_p);
1224 src.in4 = oip->ip_src;
1225 hv += src.in4.s_addr;
1226 dst.in4 = oip->ip_dst;

--- 34 unchanged lines hidden (view full) ---

1261 ips_stats.iss_hits++;
1262 is->is_pkts++;
1263 is->is_bytes += fin->fin_plen;
1264 /*
1265 * we deliberately do not touch the timeouts
1266 * for the accompanying state table entry.
1267 * It remains to be seen if that is correct. XXX
1268 */
1161 RWLOCK_EXIT(&ipf_state);
1162 return fr;
1269 break;
1163 }
1164 }
1165 RWLOCK_EXIT(&ipf_state);
1270 }
1271 }
1272 RWLOCK_EXIT(&ipf_state);
1166 return NULL;
1273 return fr;
1167}
1168
1169
1274}
1275
1276
1277/*
1278 * Move a state hash table entry from its old location at is->is_hv to
1279 * its new location, indexed by hv % fr_statesize.
1280 */
1170static void fr_ipsmove(isp, is, hv)
1171ipstate_t **isp, *is;
1172u_int hv;
1173{
1174 u_int hvm;
1175
1176 hvm = is->is_hv;
1177 /*

--- 30 unchanged lines hidden (view full) ---

1208{
1209 union i6addr dst, src;
1210 register ipstate_t *is, **isp;
1211 register u_char pr;
1212 u_int hv, hvm, hlen, tryagain, pass, v;
1213 struct icmp *ic;
1214 frentry_t *fr;
1215 tcphdr_t *tcp;
1281static void fr_ipsmove(isp, is, hv)
1282ipstate_t **isp, *is;
1283u_int hv;
1284{
1285 u_int hvm;
1286
1287 hvm = is->is_hv;
1288 /*

--- 30 unchanged lines hidden (view full) ---

1319{
1320 union i6addr dst, src;
1321 register ipstate_t *is, **isp;
1322 register u_char pr;
1323 u_int hv, hvm, hlen, tryagain, pass, v;
1324 struct icmp *ic;
1325 frentry_t *fr;
1326 tcphdr_t *tcp;
1327 int rev;
1216
1217 if (fr_state_lock || (fin->fin_off != 0) || (fin->fin_fl & FI_SHORT))
1218 return NULL;
1219
1220 is = NULL;
1221 hlen = fin->fin_hlen;
1222 tcp = (tcphdr_t *)((char *)ip + hlen);
1223 ic = (struct icmp *)tcp;
1224 hv = (pr = fin->fin_fi.fi_p);
1225 src = fin->fin_fi.fi_src;
1226 dst = fin->fin_fi.fi_dst;
1227 hv += src.in4.s_addr;
1228 hv += dst.in4.s_addr;
1229
1230 /*
1231 * Search the hash table for matching packet header info.
1328
1329 if (fr_state_lock || (fin->fin_off != 0) || (fin->fin_fl & FI_SHORT))
1330 return NULL;
1331
1332 is = NULL;
1333 hlen = fin->fin_hlen;
1334 tcp = (tcphdr_t *)((char *)ip + hlen);
1335 ic = (struct icmp *)tcp;
1336 hv = (pr = fin->fin_fi.fi_p);
1337 src = fin->fin_fi.fi_src;
1338 dst = fin->fin_fi.fi_dst;
1339 hv += src.in4.s_addr;
1340 hv += dst.in4.s_addr;
1341
1342 /*
1343 * Search the hash table for matching packet header info.
1344 * At the bottom of this switch statement, the following is expected:
1345 * is == NULL, no lock on ipf_state is held.
1346 * is != NULL, a lock on ipf_state is held.
1232 */
1233 v = fin->fin_fi.fi_v;
1347 */
1348 v = fin->fin_fi.fi_v;
1234 switch (fin->fin_fi.fi_p)
1349#ifdef USE_INET6
1350 if (v == 6) {
1351 hv += fin->fin_fi.fi_src.i6[1];
1352 hv += fin->fin_fi.fi_src.i6[2];
1353 hv += fin->fin_fi.fi_src.i6[3];
1354
1355 if ((fin->fin_p == IPPROTO_ICMPV6) &&
1356 IN6_IS_ADDR_MULTICAST(&fin->fin_fi.fi_dst.in6)) {
1357 hv -= dst.in4.s_addr;
1358 } else {
1359 hv += fin->fin_fi.fi_dst.i6[1];
1360 hv += fin->fin_fi.fi_dst.i6[2];
1361 hv += fin->fin_fi.fi_dst.i6[3];
1362 }
1363 }
1364#endif
1365
1366 switch (fin->fin_p)
1235 {
1236#ifdef USE_INET6
1237 case IPPROTO_ICMPV6 :
1367 {
1368#ifdef USE_INET6
1369 case IPPROTO_ICMPV6 :
1370 tcp = NULL;
1371 tryagain = 0;
1238 if (v == 6) {
1372 if (v == 6) {
1239 if (fin->fin_out)
1240 hv -= dst.in4.s_addr;
1241 else
1242 hv -= src.in4.s_addr;
1243 if ((ic->icmp_type == ICMP6_ECHO_REQUEST) ||
1244 (ic->icmp_type == ICMP6_ECHO_REPLY)) {
1245 hv += ic->icmp_id;
1246 hv += ic->icmp_seq;
1247 }
1248 }
1373 if ((ic->icmp_type == ICMP6_ECHO_REQUEST) ||
1374 (ic->icmp_type == ICMP6_ECHO_REPLY)) {
1375 hv += ic->icmp_id;
1376 hv += ic->icmp_seq;
1377 }
1378 }
1379 READ_ENTER(&ipf_state);
1380icmp6again:
1381 hvm = hv % fr_statesize;
1382 for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext)
1383 if ((is->is_p == pr) && (is->is_v == v) &&
1384 fr_matchsrcdst(is, src, dst, fin, NULL) &&
1385 fr_matchicmpqueryreply(v, is, ic)) {
1386 rev = fin->fin_rev;
1387 if (is->is_frage[rev] != 0)
1388 is->is_age = is->is_frage[rev];
1389 else if (fin->fin_rev)
1390 is->is_age = fr_icmpacktimeout;
1391 else
1392 is->is_age = fr_icmptimeout;
1393 break;
1394 }
1395
1396 if (is != NULL) {
1397 if (tryagain && !(is->is_flags & FI_W_DADDR)) {
1398 hv += fin->fin_fi.fi_src.i6[0];
1399 hv += fin->fin_fi.fi_src.i6[1];
1400 hv += fin->fin_fi.fi_src.i6[2];
1401 hv += fin->fin_fi.fi_src.i6[3];
1402 fr_ipsmove(isp, is, hv);
1403 MUTEX_DOWNGRADE(&ipf_state);
1404 }
1405 break;
1406 }
1407 RWLOCK_EXIT(&ipf_state);
1408
1409 /*
1410 * No matching icmp state entry. Perhaps this is a
1411 * response to another state entry.
1412 */
1413 if ((ips_wild != 0) && (v == 6) && (tryagain == 0) &&
1414 !IN6_IS_ADDR_MULTICAST(&fin->fin_fi.fi_src.in6)) {
1415 hv -= fin->fin_fi.fi_src.i6[0];
1416 hv -= fin->fin_fi.fi_src.i6[1];
1417 hv -= fin->fin_fi.fi_src.i6[2];
1418 hv -= fin->fin_fi.fi_src.i6[3];
1419 tryagain = 1;
1420 WRITE_ENTER(&ipf_state);
1421 goto icmp6again;
1422 }
1423
1424 fr = fr_checkicmp6matchingstate((ip6_t *)ip, fin);
1425 if (fr)
1426 return fr;
1427 break;
1249#endif
1250 case IPPROTO_ICMP :
1428#endif
1429 case IPPROTO_ICMP :
1430 tcp = NULL;
1251 if (v == 4) {
1252 hv += ic->icmp_id;
1253 hv += ic->icmp_seq;
1254 }
1431 if (v == 4) {
1432 hv += ic->icmp_id;
1433 hv += ic->icmp_seq;
1434 }
1255 hv %= fr_statesize;
1435 hvm = hv % fr_statesize;
1256 READ_ENTER(&ipf_state);
1436 READ_ENTER(&ipf_state);
1257 for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) {
1437 for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext)
1258 if ((is->is_p == pr) && (is->is_v == v) &&
1259 fr_matchsrcdst(is, src, dst, fin, NULL) &&
1260 fr_matchicmpqueryreply(v, is, ic)) {
1438 if ((is->is_p == pr) && (is->is_v == v) &&
1439 fr_matchsrcdst(is, src, dst, fin, NULL) &&
1440 fr_matchicmpqueryreply(v, is, ic)) {
1261 if (fin->fin_rev)
1441 rev = fin->fin_rev;
1442 if (is->is_frage[rev] != 0)
1443 is->is_age = is->is_frage[rev];
1444 else if (fin->fin_rev)
1262 is->is_age = fr_icmpacktimeout;
1263 else
1264 is->is_age = fr_icmptimeout;
1265 break;
1266 }
1445 is->is_age = fr_icmpacktimeout;
1446 else
1447 is->is_age = fr_icmptimeout;
1448 break;
1449 }
1267 }
1450
1268 if (is != NULL)
1269 break;
1270 RWLOCK_EXIT(&ipf_state);
1271 /*
1272 * No matching icmp state entry. Perhaps this is a
1273 * response to another state entry.
1274 */
1451 if (is != NULL)
1452 break;
1453 RWLOCK_EXIT(&ipf_state);
1454 /*
1455 * No matching icmp state entry. Perhaps this is a
1456 * response to another state entry.
1457 */
1275#ifdef USE_INET6
1276 if (v == 6)
1277 fr = fr_checkicmp6matchingstate((ip6_t *)ip, fin);
1278 else
1279#endif
1280 fr = fr_checkicmpmatchingstate(ip, fin);
1458 fr = fr_checkicmpmatchingstate(ip, fin);
1281 if (fr)
1282 return fr;
1283 break;
1284 case IPPROTO_TCP :
1459 if (fr)
1460 return fr;
1461 break;
1462 case IPPROTO_TCP :
1285 {
1286 register u_short dport, sport;
1287 register int i;
1288
1289 i = tcp->th_flags;
1290 /*
1291 * Just plain ignore RST flag set with either FIN or SYN.
1292 */
1463 /*
1464 * Just plain ignore RST flag set with either FIN or SYN.
1465 */
1293 if ((i & TH_RST) &&
1294 ((i & (TH_FIN|TH_SYN|TH_RST)) != TH_RST))
1466 if ((tcp->th_flags & TH_RST) &&
1467 ((tcp->th_flags & (TH_FIN|TH_SYN|TH_RST)) != TH_RST))
1295 break;
1296 case IPPROTO_UDP :
1468 break;
1469 case IPPROTO_UDP :
1470 {
1471 register u_short dport, sport;
1472
1297 dport = tcp->th_dport;
1298 sport = tcp->th_sport;
1299 tryagain = 0;
1300 hv += dport;
1301 hv += sport;
1302 READ_ENTER(&ipf_state);
1303retry_tcpudp:
1304 hvm = hv % fr_statesize;
1305 for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext)
1306 if ((is->is_p == pr) && (is->is_v == v) &&
1307 fr_matchsrcdst(is, src, dst, fin, tcp)) {
1473 dport = tcp->th_dport;
1474 sport = tcp->th_sport;
1475 tryagain = 0;
1476 hv += dport;
1477 hv += sport;
1478 READ_ENTER(&ipf_state);
1479retry_tcpudp:
1480 hvm = hv % fr_statesize;
1481 for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext)
1482 if ((is->is_p == pr) && (is->is_v == v) &&
1483 fr_matchsrcdst(is, src, dst, fin, tcp)) {
1484 rev = fin->fin_rev;
1308 if ((pr == IPPROTO_TCP)) {
1309 if (!fr_tcpstate(is, fin, ip, tcp)) {
1310 continue;
1311 }
1312 } else if ((pr == IPPROTO_UDP)) {
1485 if ((pr == IPPROTO_TCP)) {
1486 if (!fr_tcpstate(is, fin, ip, tcp)) {
1487 continue;
1488 }
1489 } else if ((pr == IPPROTO_UDP)) {
1313 if (fin->fin_rev)
1490 if (is->is_frage[rev] != 0)
1491 is->is_age = is->is_frage[rev];
1492 else if (fin->fin_rev)
1314 is->is_age = fr_udpacktimeout;
1315 else
1316 is->is_age = fr_udptimeout;
1317 }
1318 break;
1319 }
1320 if (is != NULL) {
1321 if (tryagain &&

--- 11 unchanged lines hidden (view full) ---

1333 hv -= sport;
1334 tryagain = 1;
1335 WRITE_ENTER(&ipf_state);
1336 goto retry_tcpudp;
1337 }
1338 break;
1339 }
1340 default :
1493 is->is_age = fr_udpacktimeout;
1494 else
1495 is->is_age = fr_udptimeout;
1496 }
1497 break;
1498 }
1499 if (is != NULL) {
1500 if (tryagain &&

--- 11 unchanged lines hidden (view full) ---

1512 hv -= sport;
1513 tryagain = 1;
1514 WRITE_ENTER(&ipf_state);
1515 goto retry_tcpudp;
1516 }
1517 break;
1518 }
1519 default :
1520 tcp = NULL;
1521 hv %= fr_statesize;
1522 READ_ENTER(&ipf_state);
1523 for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) {
1524 if ((is->is_p == pr) && (is->is_v == v) &&
1525 fr_matchsrcdst(is, src, dst, fin, NULL)) {
1526 rev = fin->fin_rev;
1527 if (is->is_frage[rev] != 0)
1528 is->is_age = is->is_frage[rev];
1529 else
1530 is->is_age = fr_udptimeout;
1531 break;
1532 }
1533 }
1534 if (is == NULL) {
1535 RWLOCK_EXIT(&ipf_state);
1536 }
1341 break;
1342 }
1537 break;
1538 }
1539
1343 if (is == NULL) {
1344 ATOMIC_INCL(ips_stats.iss_miss);
1345 return NULL;
1346 }
1540 if (is == NULL) {
1541 ATOMIC_INCL(ips_stats.iss_miss);
1542 return NULL;
1543 }
1544
1347 MUTEX_ENTER(&is->is_lock);
1348 is->is_bytes += fin->fin_plen;
1349 ips_stats.iss_hits++;
1350 is->is_pkts++;
1351 MUTEX_EXIT(&is->is_lock);
1352 fr = is->is_rule;
1545 MUTEX_ENTER(&is->is_lock);
1546 is->is_bytes += fin->fin_plen;
1547 ips_stats.iss_hits++;
1548 is->is_pkts++;
1549 MUTEX_EXIT(&is->is_lock);
1550 fr = is->is_rule;
1551 fin->fin_rule = is->is_rulen;
1552 if (fr != NULL) {
1553 fin->fin_group = fr->fr_group;
1554 fin->fin_icode = fr->fr_icode;
1555 }
1353 fin->fin_fr = fr;
1354 pass = is->is_pass;
1556 fin->fin_fr = fr;
1557 pass = is->is_pass;
1558 RWLOCK_EXIT(&ipf_state);
1559 if ((fin->fin_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
1560 ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);
1355#ifndef _KERNEL
1561#ifndef _KERNEL
1356 if (tcp->th_flags & TCP_CLOSE)
1562 if ((tcp != NULL) && (tcp->th_flags & TCP_CLOSE))
1357 fr_delstate(is);
1358#endif
1563 fr_delstate(is);
1564#endif
1359 RWLOCK_EXIT(&ipf_state);
1360 if ((fin->fin_fi.fi_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
1361 ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);
1362 return fr;
1363}
1364
1365
1565 return fr;
1566}
1567
1568
1569/*
1570 * Sync. state entries. If interfaces come or go or just change position,
1571 * this is needed.
1572 */
1366void ip_statesync(ifp)
1367void *ifp;
1368{
1369 register ipstate_t *is;
1573void ip_statesync(ifp)
1574void *ifp;
1575{
1576 register ipstate_t *is;
1577 int i;
1370
1371 WRITE_ENTER(&ipf_state);
1372 for (is = ips_list; is; is = is->is_next) {
1578
1579 WRITE_ENTER(&ipf_state);
1580 for (is = ips_list; is; is = is->is_next) {
1373 if (is->is_ifpin == ifp) {
1374 is->is_ifpin = GETUNIT(is->is_ifname[0], is->is_v);
1375 if (!is->is_ifpin)
1376 is->is_ifpin = (void *)-1;
1581 for (i = 0; i < 4; i++) {
1582 if (is->is_ifp[i] == ifp) {
1583 is->is_ifpin = GETUNIT(is->is_ifname[i],
1584 is->is_v);
1585 if (!is->is_ifp[i])
1586 is->is_ifp[i] = (void *)-1;
1587 }
1377 }
1588 }
1378 if (is->is_ifpout == ifp) {
1379 is->is_ifpout = GETUNIT(is->is_ifname[1], is->is_v);
1380 if (!is->is_ifpout)
1381 is->is_ifpout = (void *)-1;
1382 }
1383 }
1384 RWLOCK_EXIT(&ipf_state);
1385}
1386
1387
1388/*
1389 * Must always be called with fr_ipfstate held as a write lock.
1390 */

--- 7 unchanged lines hidden (view full) ---

1398 if (is->is_next)
1399 is->is_next->is_pnext = is->is_pnext;
1400 *is->is_pnext = is->is_next;
1401 if (is->is_hnext)
1402 is->is_hnext->is_phnext = is->is_phnext;
1403 *is->is_phnext = is->is_hnext;
1404 if (ips_table[is->is_hv] == NULL)
1405 ips_stats.iss_inuse--;
1589 }
1590 RWLOCK_EXIT(&ipf_state);
1591}
1592
1593
1594/*
1595 * Must always be called with fr_ipfstate held as a write lock.
1596 */

--- 7 unchanged lines hidden (view full) ---

1604 if (is->is_next)
1605 is->is_next->is_pnext = is->is_pnext;
1606 *is->is_pnext = is->is_next;
1607 if (is->is_hnext)
1608 is->is_hnext->is_phnext = is->is_phnext;
1609 *is->is_phnext = is->is_hnext;
1610 if (ips_table[is->is_hv] == NULL)
1611 ips_stats.iss_inuse--;
1612 if (is->is_me)
1613 *is->is_me = NULL;
1406
1407 fr = is->is_rule;
1408 if (fr != NULL) {
1409 fr->fr_ref--;
1410 if (fr->fr_ref == 0) {
1411 KFREE(fr);
1412 }
1413 }

--- 45 unchanged lines hidden (view full) ---

1459 ips_stats.iss_expire++;
1460#ifdef IPFILTER_LOG
1461 ipstate_log(is, ISL_EXPIRE);
1462#endif
1463 fr_delstate(is);
1464 } else
1465 isp = &is->is_next;
1466 if (fr_state_doflush) {
1614
1615 fr = is->is_rule;
1616 if (fr != NULL) {
1617 fr->fr_ref--;
1618 if (fr->fr_ref == 0) {
1619 KFREE(fr);
1620 }
1621 }

--- 45 unchanged lines hidden (view full) ---

1667 ips_stats.iss_expire++;
1668#ifdef IPFILTER_LOG
1669 ipstate_log(is, ISL_EXPIRE);
1670#endif
1671 fr_delstate(is);
1672 } else
1673 isp = &is->is_next;
1674 if (fr_state_doflush) {
1467 (void) fr_state_flush(1);
1675 (void) fr_state_flush(2);
1468 fr_state_doflush = 0;
1469 }
1470 RWLOCK_EXIT(&ipf_state);
1471 SPL_X(s);
1472}
1473
1474
1475/*

--- 67 unchanged lines hidden (view full) ---

1543 * The next piece of code makes it possible to get
1544 * already established connections into the state table
1545 * after a restart or reload of the filter rules; this
1546 * does not work when a strict 'flags S keep state' is
1547 * used for tcp connections of course
1548 */
1549 if ((flags & (TH_FIN|TH_SYN|TH_RST|TH_ACK)) == TH_ACK) {
1550 /* we saw an A, guess 'dir' is in ESTABLISHED mode */
1676 fr_state_doflush = 0;
1677 }
1678 RWLOCK_EXIT(&ipf_state);
1679 SPL_X(s);
1680}
1681
1682
1683/*

--- 67 unchanged lines hidden (view full) ---

1751 * The next piece of code makes it possible to get
1752 * already established connections into the state table
1753 * after a restart or reload of the filter rules; this
1754 * does not work when a strict 'flags S keep state' is
1755 * used for tcp connections of course
1756 */
1757 if ((flags & (TH_FIN|TH_SYN|TH_RST|TH_ACK)) == TH_ACK) {
1758 /* we saw an A, guess 'dir' is in ESTABLISHED mode */
1551 state[dir] = TCPS_ESTABLISHED;
1552 *age = fr_tcpidletimeout;
1759 if (state[1 - dir] == TCPS_CLOSED ||
1760 state[1 - dir] == TCPS_ESTABLISHED) {
1761 state[dir] = TCPS_ESTABLISHED;
1762 *age = fr_tcpidletimeout;
1763 }
1553 }
1554 /*
1555 * TODO: besides regular ACK packets we can have other
1556 * packets as well; it is yet to be determined how we
1557 * should initialize the states in those cases
1558 */
1559 break;
1560

--- 172 unchanged lines hidden (view full) ---

1733 ipsl.isl_flags = is->is_flags;
1734 if (ipsl.isl_p == IPPROTO_TCP || ipsl.isl_p == IPPROTO_UDP) {
1735 ipsl.isl_sport = is->is_sport;
1736 ipsl.isl_dport = is->is_dport;
1737 if (ipsl.isl_p == IPPROTO_TCP) {
1738 ipsl.isl_state[0] = is->is_state[0];
1739 ipsl.isl_state[1] = is->is_state[1];
1740 }
1764 }
1765 /*
1766 * TODO: besides regular ACK packets we can have other
1767 * packets as well; it is yet to be determined how we
1768 * should initialize the states in those cases
1769 */
1770 break;
1771

--- 172 unchanged lines hidden (view full) ---

1944 ipsl.isl_flags = is->is_flags;
1945 if (ipsl.isl_p == IPPROTO_TCP || ipsl.isl_p == IPPROTO_UDP) {
1946 ipsl.isl_sport = is->is_sport;
1947 ipsl.isl_dport = is->is_dport;
1948 if (ipsl.isl_p == IPPROTO_TCP) {
1949 ipsl.isl_state[0] = is->is_state[0];
1950 ipsl.isl_state[1] = is->is_state[1];
1951 }
1741 } else if (ipsl.isl_p == IPPROTO_ICMP)
1952 } else if (ipsl.isl_p == IPPROTO_ICMP) {
1742 ipsl.isl_itype = is->is_icmp.ics_type;
1953 ipsl.isl_itype = is->is_icmp.ics_type;
1743 else {
1954 } else if (ipsl.isl_p == IPPROTO_ICMPV6) {
1955 ipsl.isl_itype = is->is_icmp.ics_type;
1956 } else {
1744 ipsl.isl_ps.isl_filler[0] = 0;
1745 ipsl.isl_ps.isl_filler[1] = 0;
1746 }
1747 items[0] = &ipsl;
1748 sizes[0] = sizeof(ipsl);
1749 types[0] = 0;
1750
1751 (void) ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1);

--- 136 unchanged lines hidden (view full) ---

1888 * other way around. Note that the minimal amount
1889 * of info present does not allow for checking against
1890 * tcp internals such as seq and ack numbers.
1891 */
1892 if ((is->is_p == pr) && (is->is_v == 6) &&
1893 fr_matchsrcdst(is, src, dst, &ofin, tcp)) {
1894 fr = is->is_rule;
1895 ips_stats.iss_hits++;
1957 ipsl.isl_ps.isl_filler[0] = 0;
1958 ipsl.isl_ps.isl_filler[1] = 0;
1959 }
1960 items[0] = &ipsl;
1961 sizes[0] = sizeof(ipsl);
1962 types[0] = 0;
1963
1964 (void) ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1);

--- 136 unchanged lines hidden (view full) ---

2101 * other way around. Note that the minimal amount
2102 * of info present does not allow for checking against
2103 * tcp internals such as seq and ack numbers.
2104 */
2105 if ((is->is_p == pr) && (is->is_v == 6) &&
2106 fr_matchsrcdst(is, src, dst, &ofin, tcp)) {
2107 fr = is->is_rule;
2108 ips_stats.iss_hits++;
1896 /*
1897 * we must swap src and dst here because the icmp
1898 * comes the other way around
1899 */
1900 is->is_pkts++;
1901 is->is_bytes += fin->fin_plen;
1902 /*
1903 * we deliberately do not touch the timeouts
1904 * for the accompanying state table entry.
1905 * It remains to be seen if that is correct. XXX
1906 */
1907 RWLOCK_EXIT(&ipf_state);
1908 return fr;
1909 }
1910 }
1911 RWLOCK_EXIT(&ipf_state);
1912 return NULL;
1913}
1914#endif
2109 is->is_pkts++;
2110 is->is_bytes += fin->fin_plen;
2111 /*
2112 * we deliberately do not touch the timeouts
2113 * for the accompanying state table entry.
2114 * It remains to be seen if that is correct. XXX
2115 */
2116 RWLOCK_EXIT(&ipf_state);
2117 return fr;
2118 }
2119 }
2120 RWLOCK_EXIT(&ipf_state);
2121 return NULL;
2122}
2123#endif