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