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