1 /* 2 * Copyright (c) 2014 - 2018 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Bill Yuan <bycn82@dragonflybsd.org> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/param.h> 36 #include <sys/kernel.h> 37 #include <sys/malloc.h> 38 #include <sys/mbuf.h> 39 #include <sys/socketvar.h> 40 #include <sys/sysctl.h> 41 #include <sys/systimer.h> 42 #include <sys/thread2.h> 43 #include <sys/in_cksum.h> 44 #include <sys/systm.h> 45 #include <sys/proc.h> 46 #include <sys/socket.h> 47 #include <sys/syslog.h> 48 #include <sys/ucred.h> 49 #include <sys/lock.h> 50 #include <sys/mplock2.h> 51 52 #include <net/if.h> 53 #include <net/ethernet.h> 54 #include <net/netmsg2.h> 55 #include <net/netisr2.h> 56 #include <net/route.h> 57 58 #include <netinet/ip.h> 59 #include <netinet/in.h> 60 #include <netinet/in_systm.h> 61 #include <netinet/in_var.h> 62 #include <netinet/in_pcb.h> 63 #include <netinet/ip_var.h> 64 #include <netinet/ip_icmp.h> 65 #include <netinet/tcp.h> 66 #include <netinet/tcp_timer.h> 67 #include <netinet/tcp_var.h> 68 #include <netinet/tcpip.h> 69 #include <netinet/udp.h> 70 #include <netinet/udp_var.h> 71 #include <netinet/ip_divert.h> 72 #include <netinet/if_ether.h> 73 74 #include <net/ipfw3/ip_fw.h> 75 #include <net/ipfw3_basic/ip_fw3_state.h> 76 #include <net/ipfw3_basic/ip_fw3_table.h> 77 #include <net/ipfw3_basic/ip_fw3_sync.h> 78 79 MALLOC_DEFINE(M_IPFW3_STATE, "M_IPFW3_STATE", "mem for ipfw3 states"); 80 81 82 struct ipfw3_state_context *fw3_state_ctx[MAXCPU]; 83 extern struct ipfw3_context *fw3_ctx[MAXCPU]; 84 extern ip_fw_ctl_t *ip_fw3_ctl_state_ptr; 85 extern ipfw_sync_install_state_t *ipfw_sync_install_state_prt; 86 87 static struct callout ip_fw3_state_cleanup_callout; 88 static int sysctl_var_cleanup_interval = 1; 89 90 static int sysctl_var_state_max_tcp_in = 4096; 91 static int sysctl_var_state_max_udp_in = 4096; 92 static int sysctl_var_state_max_icmp_in = 10; 93 94 static int sysctl_var_state_max_tcp_out = 4096; 95 static int sysctl_var_state_max_udp_out = 4096; 96 static int sysctl_var_state_max_icmp_out = 10; 97 98 static int sysctl_var_icmp_timeout = 10; 99 static int sysctl_var_tcp_timeout = 60; 100 static int sysctl_var_udp_timeout = 30; 101 102 103 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw3_basic, CTLFLAG_RW, 0, "Firewall Basic"); 104 105 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, state_max_tcp_in, CTLFLAG_RW, 106 &sysctl_var_state_max_tcp_in, 0, "maximum of tcp state in"); 107 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, state_max_tcp_out, CTLFLAG_RW, 108 &sysctl_var_state_max_tcp_out, 0, "maximum of tcp state out"); 109 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, state_max_udp_in, CTLFLAG_RW, 110 &sysctl_var_state_max_udp_in, 0, "maximum of udp state in"); 111 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, state_max_udp_out, CTLFLAG_RW, 112 &sysctl_var_state_max_udp_out, 0, "maximum of udp state out"); 113 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, state_max_icmp_in, CTLFLAG_RW, 114 &sysctl_var_state_max_icmp_in, 0, "maximum of icmp state in"); 115 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, state_max_icmp_out, CTLFLAG_RW, 116 &sysctl_var_state_max_icmp_out, 0, "maximum of icmp state out"); 117 118 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, cleanup_interval, CTLFLAG_RW, 119 &sysctl_var_cleanup_interval, 0, 120 "default state expiry check interval"); 121 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, icmp_timeout, CTLFLAG_RW, 122 &sysctl_var_icmp_timeout, 0, "default icmp state life time"); 123 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, tcp_timeout, CTLFLAG_RW, 124 &sysctl_var_tcp_timeout, 0, "default tcp state life time"); 125 SYSCTL_INT(_net_inet_ip_fw3_basic, OID_AUTO, udp_timeout, CTLFLAG_RW, 126 &sysctl_var_udp_timeout, 0, "default udp state life time"); 127 128 RB_GENERATE(fw3_state_tree, ipfw3_state, entries, ip_fw3_state_cmp); 129 130 131 int 132 ip_fw3_state_cmp(struct ipfw3_state *s1, struct ipfw3_state *s2) 133 { 134 if (s1->src_addr > s2->src_addr) 135 return 1; 136 if (s1->src_addr < s2->src_addr) 137 return -1; 138 139 if (s1->dst_addr > s2->dst_addr) 140 return 1; 141 if (s1->dst_addr < s2->dst_addr) 142 return -1; 143 144 if (s1->src_port > s2->src_port) 145 return 1; 146 if (s1->src_port < s2->src_port) 147 return -1; 148 149 if (s1->dst_port > s2->dst_port) 150 return 1; 151 if (s1->dst_port < s2->dst_port) 152 return -1; 153 154 return 0; 155 } 156 157 void 158 check_check_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 159 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 160 { 161 /* state_tree 1 same direction, state_tree2 opposite direction */ 162 struct fw3_state_tree *state_tree1, *state_tree2; 163 struct ip *ip = mtod((*args)->m, struct ip *); 164 struct ipfw3_state_context *state_ctx = fw3_state_ctx[mycpuid]; 165 struct ipfw3_state *s, *k, key; 166 167 k = &key; 168 memset(k, 0, LEN_FW3_STATE); 169 170 if ((*args)->oif == NULL) { 171 switch (ip->ip_p) { 172 case IPPROTO_TCP: 173 state_tree1 = &state_ctx->rb_tcp_in; 174 state_tree2 = &state_ctx->rb_tcp_out; 175 break; 176 case IPPROTO_UDP: 177 state_tree1 = &state_ctx->rb_udp_in; 178 state_tree2 = &state_ctx->rb_udp_out; 179 break; 180 case IPPROTO_ICMP: 181 state_tree1 = &state_ctx->rb_icmp_in; 182 state_tree2 = &state_ctx->rb_icmp_out; 183 break; 184 default: 185 goto oops; 186 } 187 } else { 188 switch (ip->ip_p) { 189 case IPPROTO_TCP: 190 state_tree1 = &state_ctx->rb_tcp_out; 191 state_tree2 = &state_ctx->rb_tcp_in; 192 break; 193 case IPPROTO_UDP: 194 state_tree1 = &state_ctx->rb_udp_out; 195 state_tree2 = &state_ctx->rb_udp_in; 196 break; 197 case IPPROTO_ICMP: 198 state_tree1 = &state_ctx->rb_icmp_out; 199 state_tree2 = &state_ctx->rb_icmp_in; 200 break; 201 default: 202 goto oops; 203 } 204 } 205 206 k->src_addr = (*args)->f_id.src_ip; 207 k->dst_addr = (*args)->f_id.dst_ip; 208 k->src_port = (*args)->f_id.src_port; 209 k->dst_port = (*args)->f_id.dst_port; 210 s = RB_FIND(fw3_state_tree, state_tree1, k); 211 if (s != NULL) { 212 (*f)->pcnt++; 213 (*f)->bcnt += ip_len; 214 (*f)->timestamp = time_second; 215 *f = s->stub; 216 s->timestamp = time_uptime; 217 *cmd_val = IP_FW_PASS; 218 *cmd_ctl = IP_FW_CTL_CHK_STATE; 219 return; 220 } 221 k->dst_addr = (*args)->f_id.src_ip; 222 k->src_addr = (*args)->f_id.dst_ip; 223 k->dst_port = (*args)->f_id.src_port; 224 k->src_port = (*args)->f_id.dst_port; 225 s = RB_FIND(fw3_state_tree, state_tree2, k); 226 if (s != NULL) { 227 (*f)->pcnt++; 228 (*f)->bcnt += ip_len; 229 (*f)->timestamp = time_second; 230 *f = s->stub; 231 s->timestamp = time_uptime; 232 *cmd_val = IP_FW_PASS; 233 *cmd_ctl = IP_FW_CTL_CHK_STATE; 234 return; 235 } 236 oops: 237 *cmd_val = IP_FW_NOT_MATCH; 238 *cmd_ctl = IP_FW_CTL_NEXT; 239 } 240 241 void 242 check_keep_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 243 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 244 { 245 /* state_tree 1 same direction, state_tree2 opposite direction */ 246 struct fw3_state_tree *the_tree = NULL; 247 struct ip *ip = mtod((*args)->m, struct ip *); 248 struct ipfw3_state_context *state_ctx = fw3_state_ctx[mycpuid]; 249 struct ipfw3_state *s, *k, key; 250 int states_matched = 0, *the_count, the_max; 251 252 k = &key; 253 memset(k, 0, LEN_FW3_STATE); 254 if ((*args)->oif == NULL) { 255 switch (ip->ip_p) { 256 case IPPROTO_TCP: 257 the_tree = &state_ctx->rb_tcp_in; 258 the_count = &state_ctx->count_tcp_in; 259 the_max = sysctl_var_state_max_tcp_in; 260 break; 261 case IPPROTO_UDP: 262 the_tree = &state_ctx->rb_udp_in; 263 the_count = &state_ctx->count_udp_in; 264 the_max = sysctl_var_state_max_udp_in; 265 break; 266 case IPPROTO_ICMP: 267 the_tree = &state_ctx->rb_icmp_in; 268 the_count = &state_ctx->count_icmp_in; 269 the_max = sysctl_var_state_max_icmp_in; 270 break; 271 default: 272 goto done; 273 } 274 } else { 275 switch (ip->ip_p) { 276 case IPPROTO_TCP: 277 the_tree = &state_ctx->rb_tcp_out; 278 the_count = &state_ctx->count_tcp_out; 279 the_max = sysctl_var_state_max_tcp_out; 280 break; 281 case IPPROTO_UDP: 282 the_tree = &state_ctx->rb_udp_out; 283 the_count = &state_ctx->count_udp_out; 284 the_max = sysctl_var_state_max_udp_out; 285 break; 286 case IPPROTO_ICMP: 287 the_tree = &state_ctx->rb_icmp_out; 288 the_count = &state_ctx->count_icmp_out; 289 the_max = sysctl_var_state_max_icmp_out; 290 break; 291 default: 292 goto done; 293 } 294 } 295 *cmd_ctl = IP_FW_CTL_NO; 296 k->src_addr = (*args)->f_id.src_ip; 297 k->dst_addr = (*args)->f_id.dst_ip; 298 k->src_port = (*args)->f_id.src_port; 299 k->dst_port = (*args)->f_id.dst_port; 300 /* cmd->arg3 is `limit type` */ 301 if (cmd->arg3 == 0) { 302 s = RB_FIND(fw3_state_tree, the_tree, k); 303 if (s != NULL) { 304 goto done; 305 } 306 } else { 307 RB_FOREACH(s, fw3_state_tree, the_tree) { 308 if (cmd->arg3 == 1 && s->src_addr == k->src_addr) { 309 states_matched++; 310 } else if (cmd->arg3 == 2 && s->src_port == k->src_port) { 311 states_matched++; 312 } else if (cmd->arg3 == 3 && s->dst_addr == k->dst_addr) { 313 states_matched++; 314 } else if (cmd->arg3 == 4 && s->dst_port == k->dst_port) { 315 states_matched++; 316 } 317 } 318 if (states_matched >= cmd->arg1) { 319 goto done; 320 } 321 } 322 if (*the_count <= the_max) { 323 (*the_count)++; 324 s = kmalloc(LEN_FW3_STATE, M_IPFW3_STATE, 325 M_INTWAIT | M_NULLOK | M_ZERO); 326 s->src_addr = k->src_addr; 327 s->dst_addr = k->dst_addr; 328 s->src_port = k->src_port; 329 s->dst_port = k->dst_port; 330 s->stub = *f; 331 s->timestamp = time_uptime; 332 if (RB_INSERT(fw3_state_tree, the_tree, s)) { 333 kprintf("oops\n"); 334 } 335 } 336 done: 337 *cmd_ctl = IP_FW_CTL_NO; 338 *cmd_val = IP_FW_MATCH; 339 } 340 341 void 342 ip_fw3_state_append_dispatch(netmsg_t nmsg) 343 { 344 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1); 345 } 346 347 void 348 ip_fw3_state_delete_dispatch(netmsg_t nmsg) 349 { 350 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1); 351 } 352 353 int 354 ip_fw3_ctl_state_add(struct sockopt *sopt) 355 { 356 return 0; 357 } 358 359 int 360 ip_fw3_ctl_state_delete(struct sockopt *sopt) 361 { 362 return 0; 363 } 364 365 void 366 ip_fw3_state_flush_dispatch(netmsg_t nmsg) 367 { 368 struct ipfw3_state_context *state_ctx = fw3_state_ctx[mycpuid]; 369 struct ipfw3_state *s, *tmp; 370 371 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_icmp_in, tmp) { 372 RB_REMOVE(fw3_state_tree, &state_ctx->rb_icmp_in, s); 373 if (s != NULL) { 374 kfree(s, M_IPFW3_STATE); 375 } 376 } 377 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_icmp_out, tmp) { 378 RB_REMOVE(fw3_state_tree, &state_ctx->rb_icmp_out, s); 379 if (s != NULL) { 380 kfree(s, M_IPFW3_STATE); 381 } 382 } 383 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_tcp_in, tmp) { 384 RB_REMOVE(fw3_state_tree, &state_ctx->rb_tcp_in, s); 385 if (s != NULL) { 386 kfree(s, M_IPFW3_STATE); 387 } 388 } 389 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_tcp_out, tmp) { 390 RB_REMOVE(fw3_state_tree, &state_ctx->rb_tcp_out, s); 391 if (s != NULL) { 392 kfree(s, M_IPFW3_STATE); 393 } 394 } 395 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_udp_in, tmp) { 396 RB_REMOVE(fw3_state_tree, &state_ctx->rb_udp_in, s); 397 if (s != NULL) { 398 kfree(s, M_IPFW3_STATE); 399 } 400 } 401 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_udp_out, tmp) { 402 RB_REMOVE(fw3_state_tree, &state_ctx->rb_udp_out, s); 403 if (s != NULL) { 404 kfree(s, M_IPFW3_STATE); 405 } 406 } 407 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1); 408 } 409 410 void 411 ip_fw3_state_flush(struct ip_fw *rule) 412 { 413 struct netmsg_base msg; 414 netmsg_init(&msg, NULL, &curthread->td_msgport, 0, 415 ip_fw3_state_flush_dispatch); 416 netisr_domsg(&msg, 0); 417 } 418 419 int 420 ip_fw3_ctl_state_flush(struct sockopt *sopt) 421 { 422 423 return 0; 424 } 425 426 int 427 ip_fw3_ctl_state_get(struct sockopt *sopt) 428 { 429 struct ipfw3_state_context *state_ctx; 430 struct ipfw3_state *s; 431 432 size_t sopt_size, total_len = 0; 433 struct ipfw3_ioc_state *ioc; 434 int ioc_rule_id; 435 436 ioc_rule_id = *((int *)(sopt->sopt_val)); 437 sopt_size = sopt->sopt_valsize; 438 ioc = (struct ipfw3_ioc_state *)sopt->sopt_val; 439 /* icmp states only in CPU 0 */ 440 int cpu = 0; 441 442 /* icmp states */ 443 for (cpu = 0; cpu < ncpus; cpu++) { 444 state_ctx = fw3_state_ctx[cpu]; 445 RB_FOREACH(s, fw3_state_tree, &state_ctx->rb_icmp_in) { 446 total_len += LEN_IOC_FW3_STATE; 447 if (total_len > sopt_size) 448 goto nospace; 449 ioc->src_addr.s_addr = ntohl(s->src_addr); 450 ioc->dst_addr.s_addr = ntohl(s->dst_addr); 451 ioc->src_port = ntohs(s->src_port); 452 ioc->dst_port = ntohs(s->dst_port); 453 ioc->cpu_id = cpu; 454 ioc->rule_id = s->stub->rulenum; 455 ioc->proto = IPPROTO_ICMP; 456 ioc->life = s->timestamp + 457 sysctl_var_udp_timeout - time_uptime; 458 ioc++; 459 } 460 RB_FOREACH(s, fw3_state_tree, &state_ctx->rb_icmp_out) { 461 total_len += LEN_IOC_FW3_STATE; 462 if (total_len > sopt_size) 463 goto nospace; 464 ioc->src_addr.s_addr = ntohl(s->src_addr); 465 ioc->dst_addr.s_addr = ntohl(s->dst_addr); 466 ioc->src_port = ntohs(s->src_port); 467 ioc->dst_port = ntohs(s->dst_port); 468 ioc->cpu_id = cpu; 469 ioc->rule_id = s->stub->rulenum; 470 ioc->proto = IPPROTO_ICMP; 471 ioc->life = s->timestamp + 472 sysctl_var_udp_timeout - time_uptime; 473 ioc++; 474 } 475 RB_FOREACH(s, fw3_state_tree, &state_ctx->rb_tcp_in) { 476 total_len += LEN_IOC_FW3_STATE; 477 if (total_len > sopt_size) 478 goto nospace; 479 ioc->src_addr.s_addr = ntohl(s->src_addr); 480 ioc->dst_addr.s_addr = ntohl(s->dst_addr); 481 ioc->src_port = ntohs(s->src_port); 482 ioc->dst_port = ntohs(s->dst_port); 483 ioc->cpu_id = cpu; 484 ioc->rule_id = s->stub->rulenum; 485 ioc->proto = IPPROTO_TCP; 486 ioc->life = s->timestamp + 487 sysctl_var_udp_timeout - time_uptime; 488 ioc++; 489 } 490 RB_FOREACH(s, fw3_state_tree, &state_ctx->rb_tcp_out) { 491 total_len += LEN_IOC_FW3_STATE; 492 if (total_len > sopt_size) 493 goto nospace; 494 ioc->src_addr.s_addr = ntohl(s->src_addr); 495 ioc->dst_addr.s_addr = ntohl(s->dst_addr); 496 ioc->src_port = ntohs(s->src_port); 497 ioc->dst_port = ntohs(s->dst_port); 498 ioc->cpu_id = cpu; 499 ioc->rule_id = s->stub->rulenum; 500 ioc->proto = IPPROTO_TCP; 501 ioc->life = s->timestamp + 502 sysctl_var_udp_timeout - time_uptime; 503 ioc++; 504 } 505 RB_FOREACH(s, fw3_state_tree, &state_ctx->rb_udp_in) { 506 total_len += LEN_IOC_FW3_STATE; 507 if (total_len > sopt_size) 508 goto nospace; 509 ioc->src_addr.s_addr = ntohl(s->src_addr); 510 ioc->dst_addr.s_addr = ntohl(s->dst_addr); 511 ioc->src_port = ntohs(s->src_port); 512 ioc->dst_port = ntohs(s->dst_port); 513 ioc->cpu_id = cpu; 514 ioc->rule_id = s->stub->rulenum; 515 ioc->proto = IPPROTO_UDP; 516 ioc->life = s->timestamp + 517 sysctl_var_udp_timeout - time_uptime; 518 ioc++; 519 } 520 RB_FOREACH(s, fw3_state_tree, &state_ctx->rb_udp_out) { 521 total_len += LEN_IOC_FW3_STATE; 522 if (total_len > sopt_size) 523 goto nospace; 524 ioc->src_addr.s_addr = ntohl(s->src_addr); 525 ioc->dst_addr.s_addr = ntohl(s->dst_addr); 526 ioc->src_port = ntohs(s->src_port); 527 ioc->dst_port = ntohs(s->dst_port); 528 ioc->cpu_id = cpu; 529 ioc->rule_id = s->stub->rulenum; 530 ioc->proto = IPPROTO_UDP; 531 ioc->life = s->timestamp + 532 sysctl_var_udp_timeout - time_uptime; 533 ioc++; 534 } 535 } 536 537 sopt->sopt_valsize = total_len; 538 return 0; 539 nospace: 540 return 0; 541 } 542 543 void 544 ip_fw3_state_cleanup_dispatch(netmsg_t nmsg) 545 { 546 547 struct ipfw3_state_context *state_ctx = fw3_state_ctx[mycpuid]; 548 struct ipfw3_state *s, *tmp; 549 550 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_icmp_in, tmp) { 551 if (time_uptime - s->timestamp > sysctl_var_icmp_timeout) { 552 RB_REMOVE(fw3_state_tree, &state_ctx->rb_icmp_in, s); 553 kfree(s, M_IPFW3_STATE); 554 } 555 } 556 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_icmp_out, tmp) { 557 if (time_uptime - s->timestamp > sysctl_var_icmp_timeout) { 558 RB_REMOVE(fw3_state_tree, &state_ctx->rb_icmp_out, s); 559 kfree(s, M_IPFW3_STATE); 560 } 561 } 562 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_tcp_in, tmp) { 563 if (time_uptime - s->timestamp > sysctl_var_tcp_timeout) { 564 RB_REMOVE(fw3_state_tree, &state_ctx->rb_tcp_in, s); 565 kfree(s, M_IPFW3_STATE); 566 } 567 } 568 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_tcp_out, tmp) { 569 if (time_uptime - s->timestamp > sysctl_var_tcp_timeout) { 570 RB_REMOVE(fw3_state_tree, &state_ctx->rb_tcp_out, s); 571 kfree(s, M_IPFW3_STATE); 572 } 573 } 574 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_udp_in, tmp) { 575 if (time_uptime - s->timestamp > sysctl_var_udp_timeout) { 576 RB_REMOVE(fw3_state_tree, &state_ctx->rb_udp_in, s); 577 kfree(s, M_IPFW3_STATE); 578 } 579 } 580 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_udp_out, tmp) { 581 if (time_uptime - s->timestamp > sysctl_var_udp_timeout) { 582 RB_REMOVE(fw3_state_tree, &state_ctx->rb_udp_out, s); 583 kfree(s, M_IPFW3_STATE); 584 } 585 } 586 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1); 587 } 588 589 void 590 ip_fw3_state_cleanup(void *dummy __unused) 591 { 592 struct netmsg_base msg; 593 netmsg_init(&msg, NULL, &curthread->td_msgport, 0, 594 ip_fw3_state_cleanup_dispatch); 595 netisr_domsg(&msg, 0); 596 597 callout_reset(&ip_fw3_state_cleanup_callout, 598 sysctl_var_cleanup_interval * hz, 599 ip_fw3_state_cleanup, NULL); 600 } 601 602 int 603 ip_fw3_ctl_state_sockopt(struct sockopt *sopt) 604 { 605 int error = 0; 606 switch (sopt->sopt_name) { 607 case IP_FW_STATE_ADD: 608 error = ip_fw3_ctl_state_add(sopt); 609 break; 610 case IP_FW_STATE_DEL: 611 error = ip_fw3_ctl_state_delete(sopt); 612 break; 613 case IP_FW_STATE_FLUSH: 614 error = ip_fw3_ctl_state_flush(sopt); 615 break; 616 case IP_FW_STATE_GET: 617 error = ip_fw3_ctl_state_get(sopt); 618 break; 619 } 620 return error; 621 } 622 623 void 624 ip_fw3_state_init_dispatch(netmsg_t msg) 625 { 626 struct ipfw3_state_context *tmp; 627 628 tmp = kmalloc(LEN_STATE_CTX, M_IPFW3_STATE, M_WAITOK | M_ZERO); 629 RB_INIT(&tmp->rb_icmp_in); 630 RB_INIT(&tmp->rb_icmp_out); 631 RB_INIT(&tmp->rb_tcp_in); 632 RB_INIT(&tmp->rb_tcp_out); 633 RB_INIT(&tmp->rb_udp_in); 634 RB_INIT(&tmp->rb_udp_out); 635 fw3_state_ctx[mycpuid] = tmp; 636 netisr_forwardmsg_all(&msg->base, mycpuid + 1); 637 } 638 639 void 640 ip_fw3_state_fini_dispatch(netmsg_t msg) 641 { 642 struct ipfw3_state_context *state_ctx = fw3_state_ctx[mycpuid]; 643 struct ipfw3_state *s, *tmp; 644 645 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_icmp_in, tmp) { 646 RB_REMOVE(fw3_state_tree, &state_ctx->rb_icmp_in, s); 647 if (s != NULL) { 648 kfree(s, M_IPFW3_STATE); 649 } 650 } 651 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_icmp_out, tmp) { 652 RB_REMOVE(fw3_state_tree, &state_ctx->rb_icmp_out, s); 653 if (s != NULL) { 654 kfree(s, M_IPFW3_STATE); 655 } 656 } 657 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_tcp_in, tmp) { 658 RB_REMOVE(fw3_state_tree, &state_ctx->rb_tcp_in, s); 659 if (s != NULL) { 660 kfree(s, M_IPFW3_STATE); 661 } 662 } 663 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_tcp_out, tmp) { 664 RB_REMOVE(fw3_state_tree, &state_ctx->rb_tcp_out, s); 665 if (s != NULL) { 666 kfree(s, M_IPFW3_STATE); 667 } 668 } 669 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_udp_in, tmp) { 670 RB_REMOVE(fw3_state_tree, &state_ctx->rb_udp_in, s); 671 if (s != NULL) { 672 kfree(s, M_IPFW3_STATE); 673 } 674 } 675 RB_FOREACH_SAFE(s, fw3_state_tree, &state_ctx->rb_udp_out, tmp) { 676 RB_REMOVE(fw3_state_tree, &state_ctx->rb_udp_out, s); 677 if (s != NULL) { 678 kfree(s, M_IPFW3_STATE); 679 } 680 } 681 kfree(fw3_state_ctx[mycpuid], M_IPFW3_STATE); 682 fw3_state_ctx[mycpuid] = NULL; 683 netisr_forwardmsg_all(&msg->base, mycpuid + 1); 684 } 685 686 687 void 688 ip_fw3_state_fini(void) 689 { 690 struct netmsg_base msg; 691 692 netmsg_init(&msg, NULL, &curthread->td_msgport, 693 0, ip_fw3_state_fini_dispatch); 694 695 netisr_domsg(&msg, 0); 696 callout_stop(&ip_fw3_state_cleanup_callout); 697 } 698 699 void 700 ip_fw3_state_init(void) 701 { 702 struct netmsg_base msg; 703 704 ip_fw3_ctl_state_ptr = ip_fw3_ctl_state_sockopt; 705 callout_init_mp(&ip_fw3_state_cleanup_callout); 706 callout_reset(&ip_fw3_state_cleanup_callout, 707 sysctl_var_cleanup_interval * hz, 708 ip_fw3_state_cleanup, 709 NULL); 710 netmsg_init(&msg, NULL, &curthread->td_msgport, 711 0, ip_fw3_state_init_dispatch); 712 netisr_domsg(&msg, 0); 713 } 714 715 716 void 717 ip_fw3_state_modevent(int type) 718 { 719 switch (type) { 720 case MOD_LOAD: 721 ip_fw3_state_init(); 722 break; 723 case MOD_UNLOAD: 724 ip_fw3_state_fini(); 725 break; 726 } 727 } 728 729