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 |