1 /* 2 * Copyright (c) 2014 - 2017 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/syslog.h> 42 #include <sys/systimer.h> 43 #include <sys/thread2.h> 44 #include <sys/in_cksum.h> 45 46 #include <net/if.h> 47 #include <net/ethernet.h> 48 #include <net/netmsg2.h> 49 #include <net/netisr2.h> 50 #include <net/route.h> 51 52 #include <netinet/ip.h> 53 #include <netinet/in.h> 54 #include <netinet/in_systm.h> 55 #include <netinet/in_var.h> 56 #include <netinet/in_pcb.h> 57 #include <netinet/ip_var.h> 58 #include <netinet/ip_icmp.h> 59 #include <netinet/tcp.h> 60 #include <netinet/tcp_timer.h> 61 #include <netinet/tcp_var.h> 62 #include <netinet/tcpip.h> 63 #include <netinet/udp.h> 64 #include <netinet/udp_var.h> 65 #include <netinet/ip_divert.h> 66 #include <netinet/if_ether.h> 67 68 #include <net/ipfw3/ip_fw.h> 69 #include <net/ipfw3/ip_fw3_table.h> 70 #include <net/ipfw3/ip_fw3_sync.h> 71 72 #include "ip_fw3_basic.h" 73 74 #define TIME_LEQ(a, b) ((int)((a) - (b)) <= 0) 75 76 extern struct ipfw_context *ipfw_ctx[MAXCPU]; 77 extern struct ipfw_sync_context sync_ctx; 78 extern int fw_verbose; 79 extern ipfw_basic_delete_state_t *ipfw_basic_flush_state_prt; 80 extern ipfw_basic_append_state_t *ipfw_basic_append_state_prt; 81 extern ipfw_sync_send_state_t *ipfw_sync_send_state_prt; 82 extern ipfw_sync_install_state_t *ipfw_sync_install_state_prt; 83 84 static int ip_fw_basic_loaded; 85 static struct netmsg_base ipfw_timeout_netmsg; /* schedule ipfw timeout */ 86 static struct callout ipfw_tick_callout; 87 static int state_lifetime = 20; 88 static int state_expiry_check_interval = 10; 89 static int state_count_max = 4096; 90 static int state_hash_size_old = 0; 91 static int state_hash_size = 4096; 92 93 94 static int ipfw_sysctl_adjust_hash_size(SYSCTL_HANDLER_ARGS); 95 void adjust_hash_size_dispatch(netmsg_t nmsg); 96 97 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw_basic, 98 CTLFLAG_RW, 0, "Firewall Basic"); 99 SYSCTL_PROC(_net_inet_ip_fw_basic, OID_AUTO, state_hash_size, 100 CTLTYPE_INT | CTLFLAG_RW, &state_hash_size, 0, 101 ipfw_sysctl_adjust_hash_size, "I", "Adjust hash size"); 102 103 SYSCTL_INT(_net_inet_ip_fw_basic, OID_AUTO, state_lifetime, CTLFLAG_RW, 104 &state_lifetime, 0, "default life time"); 105 SYSCTL_INT(_net_inet_ip_fw_basic, OID_AUTO, 106 state_expiry_check_interval, CTLFLAG_RW, 107 &state_expiry_check_interval, 0, 108 "default state expiry check interval"); 109 SYSCTL_INT(_net_inet_ip_fw_basic, OID_AUTO, state_count_max, CTLFLAG_RW, 110 &state_count_max, 0, "maximum of state"); 111 112 static int 113 ipfw_sysctl_adjust_hash_size(SYSCTL_HANDLER_ARGS) 114 { 115 int error, value = 0; 116 117 state_hash_size_old = state_hash_size; 118 value = state_hash_size; 119 error = sysctl_handle_int(oidp, &value, 0, req); 120 if (error || !req->newptr) { 121 goto back; 122 } 123 /* 124 * Make sure we have a power of 2 and 125 * do not allow more than 64k entries. 126 */ 127 error = EINVAL; 128 if (value <= 1 || value > 65536) { 129 goto back; 130 } 131 if ((value & (value - 1)) != 0) { 132 goto back; 133 } 134 135 error = 0; 136 if (state_hash_size != value) { 137 state_hash_size = value; 138 139 struct netmsg_base *msg, the_msg; 140 msg = &the_msg; 141 bzero(msg,sizeof(struct netmsg_base)); 142 143 netmsg_init(msg, NULL, &curthread->td_msgport, 144 0, adjust_hash_size_dispatch); 145 netisr_domsg(msg, 0); 146 } 147 back: 148 return error; 149 } 150 151 void 152 adjust_hash_size_dispatch(netmsg_t nmsg) 153 { 154 struct ipfw_state_context *state_ctx; 155 struct ip_fw_state *the_state, *state; 156 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 157 int i; 158 159 for (i = 0; i < state_hash_size_old; i++) { 160 state_ctx = &ctx->state_ctx[i]; 161 if (state_ctx != NULL) { 162 state = state_ctx->state; 163 while (state != NULL) { 164 the_state = state; 165 state = state->next; 166 kfree(the_state, M_IPFW3_BASIC); 167 the_state = NULL; 168 } 169 } 170 } 171 kfree(ctx->state_ctx,M_IPFW3_BASIC); 172 ctx->state_ctx = kmalloc(state_hash_size * 173 sizeof(struct ipfw_state_context), 174 M_IPFW3_BASIC, M_WAITOK | M_ZERO); 175 ctx->state_hash_size = state_hash_size; 176 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1); 177 } 178 179 180 /* prototype of the checker functions */ 181 void check_count(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 182 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 183 void check_skipto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 184 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 185 void check_forward(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 186 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 187 void check_check_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 188 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 189 190 void check_in(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 191 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 192 void check_out(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 193 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 194 void check_via(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 195 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 196 void check_proto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 197 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 198 void check_prob(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 199 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 200 void check_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 201 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 202 void check_from_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 203 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 204 void check_from_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 205 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 206 void check_from_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 207 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 208 void check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 209 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 210 void check_to_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 211 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 212 void check_to_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 213 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 214 void check_to_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 215 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 216 void check_keep_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 217 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 218 void check_tag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 219 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 220 void check_untag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 221 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 222 void check_tagged(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 223 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 224 void check_src_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 225 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 226 void check_dst_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 227 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 228 void check_src_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 229 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 230 void check_dst_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 231 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 232 233 /* prototype of the utility functions */ 234 int match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid, 235 struct ip_fw_state *state); 236 int count_match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid, 237 struct ip_fw_state *state, int *count); 238 239 static struct ip_fw *lookup_next_rule(struct ip_fw *me); 240 static int iface_match(struct ifnet *ifp, ipfw_insn_if *cmd); 241 static __inline int hash_packet(struct ipfw_flow_id *id); 242 243 static __inline int 244 hash_packet(struct ipfw_flow_id *id) 245 { 246 uint32_t i; 247 i = (id->proto) ^ (id->dst_ip) ^ (id->src_ip) ^ 248 (id->dst_port) ^ (id->src_port); 249 i &= state_hash_size - 1; 250 return i; 251 } 252 253 static struct ip_fw * 254 lookup_next_rule(struct ip_fw *me) 255 { 256 struct ip_fw *rule = NULL; 257 ipfw_insn *cmd; 258 259 /* look for action, in case it is a skipto */ 260 cmd = ACTION_PTR(me); 261 if ((int)cmd->module == MODULE_BASIC_ID && 262 (int)cmd->opcode == O_BASIC_SKIPTO) { 263 for (rule = me->next; rule; rule = rule->next) { 264 if (rule->rulenum >= cmd->arg1) 265 break; 266 } 267 } 268 if (rule == NULL) /* failure or not a skipto */ 269 rule = me->next; 270 271 me->next_rule = rule; 272 return rule; 273 } 274 275 /* 276 * return value 277 * 0 : not match 1: same direction 2: reverse direction 278 */ 279 int 280 match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid, struct ip_fw_state *state) 281 { 282 if (fid->src_ip == state->flow_id.src_ip && 283 fid->dst_ip == state->flow_id.dst_ip && 284 (fid->src_port == state->flow_id.src_port || 285 state->flow_id.src_port == 0) && 286 (fid->dst_port == state->flow_id.dst_port || 287 state->flow_id.dst_port == 0)) { 288 return 1; 289 } 290 if (fid->src_ip == state->flow_id.dst_ip && 291 fid->dst_ip == state->flow_id.src_ip && 292 (fid->src_port == state->flow_id.dst_port || 293 state->flow_id.dst_port == 0) && 294 (fid->dst_port == state->flow_id.src_port || 295 state->flow_id.src_port == 0)) { 296 return 2; 297 } 298 return 0; 299 } 300 301 /* 302 * return 1 when more states than limit 303 * arg3: limit type (1=src ip, 2=src port, 3=dst ip, 4=dst port) 304 * arg1: limit 305 */ 306 int 307 count_match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid, 308 struct ip_fw_state *state, int *count) 309 { 310 if ((cmd->arg3 == 1 && fid->src_ip == state->flow_id.src_ip) || 311 (cmd->arg3 == 2 && fid->src_port == state->flow_id.src_port) || 312 (cmd->arg3 == 3 && fid->dst_ip == state->flow_id.dst_ip) || 313 (cmd->arg3 == 4 && fid->dst_port == state->flow_id.dst_port)) { 314 *count = *count + 1; 315 if (*count >= cmd->arg1) 316 return 1; 317 } 318 return 0; 319 } 320 321 /* 322 * when all = 1, it will check all the state_ctx 323 * all = 1 during keep-state 324 * all = 0 during check-state 325 * 326 * in the cmd of keep_state 327 * arg3=type arg1=limit 328 */ 329 static struct ip_fw_state * 330 lookup_state(struct ip_fw_args *args, ipfw_insn *cmd, int *limited, int all) 331 { 332 struct ip_fw_state *state = NULL; 333 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 334 struct ipfw_state_context *state_ctx; 335 int start, end, i, count = 0; 336 337 if (all && cmd->arg1) { 338 start = 0; 339 end = state_hash_size - 1; 340 } else { 341 start = hash_packet(&args->f_id); 342 end = hash_packet(&args->f_id); 343 } 344 345 for (i = start; i <= end; i++) { 346 state_ctx = &ctx->state_ctx[i]; 347 if (state_ctx != NULL) { 348 state = state_ctx->state; 349 struct ipfw_flow_id *fid = &args->f_id; 350 while (state != NULL) { 351 /* has limit and already exceed the limit */ 352 if (cmd->arg1 && 353 count_match_state(cmd, fid, 354 state, &count) != 0) { 355 *limited = 1; 356 goto done; 357 } 358 359 if (fid->proto == state->flow_id.proto && 360 match_state(cmd, fid, state) != 0) 361 goto done; 362 363 state = state->next; 364 } 365 } 366 } 367 done: 368 return state; 369 } 370 371 static struct ip_fw_state * 372 install_state(struct ip_fw *rule, ipfw_insn *cmd, struct ip_fw_args *args) 373 { 374 struct ip_fw_state *state; 375 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 376 struct ipfw_state_context *state_ctx; 377 int hash = hash_packet(&args->f_id); 378 state_ctx = &ctx->state_ctx[hash]; 379 state = kmalloc(sizeof(struct ip_fw_state), 380 M_IPFW3_BASIC, M_NOWAIT | M_ZERO); 381 if (state == NULL) { 382 return NULL; 383 } 384 state->stub = rule; 385 state->lifetime = cmd->arg2 == 0 ? state_lifetime : cmd->arg2 ; 386 state->timestamp = time_second; 387 state->expiry = 0; 388 bcopy(&args->f_id,&state->flow_id,sizeof(struct ipfw_flow_id)); 389 //append the state into the state chian 390 if (state_ctx->last != NULL) 391 state_ctx->last->next = state; 392 else 393 state_ctx->state = state; 394 state_ctx->last = state; 395 state_ctx->count++; 396 397 if (sync_ctx.running & 2) { 398 ipfw_sync_send_state_prt(state, mycpuid, hash); 399 } 400 return state; 401 } 402 403 void 404 ipfw_sync_install_state(struct cmd_send_state *cmd) 405 { 406 struct ip_fw_state *state; 407 struct ipfw_context *ctx = ipfw_ctx[cmd->cpu]; 408 struct ipfw_state_context *state_ctx; 409 struct ip_fw *rule; 410 411 state_ctx = &ctx->state_ctx[cmd->hash]; 412 state = kmalloc(sizeof(struct ip_fw_state), 413 M_IPFW3_BASIC, M_NOWAIT | M_ZERO); 414 if (state == NULL) { 415 return; 416 } 417 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) { 418 if (rule->rulenum == cmd->rulenum) { 419 goto found; 420 } 421 } 422 return; 423 found: 424 state->stub = rule; 425 state->lifetime = cmd->lifetime; 426 state->timestamp = time_second; 427 state->expiry = 0; 428 bcopy(&cmd->flow, &state->flow_id, sizeof(struct ipfw_flow_id)); 429 //append the state into the state chian 430 if (state_ctx->last != NULL) 431 state_ctx->last->next = state; 432 else 433 state_ctx->state = state; 434 state_ctx->last = state; 435 state_ctx->count++; 436 } 437 438 static int 439 iface_match(struct ifnet *ifp, ipfw_insn_if *cmd) 440 { 441 if (ifp == NULL) /* no iface with this packet, match fails */ 442 return 0; 443 444 /* Check by name or by IP address */ 445 if (cmd->name[0] != '\0') { /* match by name */ 446 /* Check name */ 447 if (cmd->p.glob) { 448 if (kfnmatch(cmd->name, ifp->if_xname, 0) == 0) 449 return(1); 450 } else { 451 if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0) 452 return(1); 453 } 454 } else { 455 struct ifaddr_container *ifac; 456 457 TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) { 458 struct ifaddr *ia = ifac->ifa; 459 460 if (ia->ifa_addr == NULL) 461 continue; 462 if (ia->ifa_addr->sa_family != AF_INET) 463 continue; 464 if (cmd->p.ip.s_addr == 465 ((struct sockaddr_in *) 466 (ia->ifa_addr))->sin_addr.s_addr) 467 return(1); /* match */ 468 469 } 470 } 471 return 0; /* no match, fail ... */ 472 } 473 474 /* implimentation of the checker functions */ 475 void 476 check_count(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 477 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 478 { 479 (*f)->pcnt++; 480 (*f)->bcnt += ip_len; 481 (*f)->timestamp = time_second; 482 *cmd_ctl = IP_FW_CTL_NEXT; 483 } 484 485 void 486 check_skipto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 487 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 488 { 489 (*f)->pcnt++; 490 (*f)->bcnt += ip_len; 491 (*f)->timestamp = time_second; 492 if ((*f)->next_rule == NULL) 493 lookup_next_rule(*f); 494 *f = (*f)->next_rule; 495 *cmd_ctl = IP_FW_CTL_AGAIN; 496 } 497 498 void 499 check_forward(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 500 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 501 { 502 struct sockaddr_in *sin, *sa; 503 struct m_tag *mtag; 504 505 if ((*args)->eh) { /* not valid on layer2 pkts */ 506 *cmd_ctl=IP_FW_CTL_NEXT; 507 return; 508 } 509 510 (*f)->pcnt++; 511 (*f)->bcnt += ip_len; 512 (*f)->timestamp = time_second; 513 if ((*f)->next_rule == NULL) 514 lookup_next_rule(*f); 515 516 mtag = m_tag_get(PACKET_TAG_IPFORWARD, 517 sizeof(*sin), M_INTWAIT | M_NULLOK); 518 if (mtag == NULL) { 519 *cmd_val = IP_FW_DENY; 520 *cmd_ctl = IP_FW_CTL_DONE; 521 return; 522 } 523 sin = m_tag_data(mtag); 524 sa = &((ipfw_insn_sa *)cmd)->sa; 525 /* arg3: count of the dest, arg1: type of fwd */ 526 int i = 0; 527 if(cmd->arg3 > 1) { 528 if (cmd->arg1 == 0) { /* type: random */ 529 i = krandom() % cmd->arg3; 530 } else if (cmd->arg1 == 1) { /* type: round-robin */ 531 i = cmd->arg2++ % cmd->arg3; 532 } else if (cmd->arg1 == 2) { /* type: sticky */ 533 struct ip *ip = mtod((*args)->m, struct ip *); 534 i = ip->ip_src.s_addr & (cmd->arg3 - 1); 535 } 536 sa += i; 537 } 538 *sin = *sa; /* apply the destination */ 539 m_tag_prepend((*args)->m, mtag); 540 (*args)->m->m_pkthdr.fw_flags |= IPFORWARD_MBUF_TAGGED; 541 (*args)->m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED; 542 *cmd_ctl = IP_FW_CTL_DONE; 543 *cmd_val = IP_FW_PASS; 544 } 545 546 void 547 check_check_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 548 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 549 { 550 struct ip_fw_state *state=NULL; 551 int limited = 0 ; 552 state = lookup_state(*args, cmd, &limited, 0); 553 if (state != NULL) { 554 state->pcnt++; 555 state->bcnt += ip_len; 556 state->timestamp = time_second; 557 (*f)->pcnt++; 558 (*f)->bcnt += ip_len; 559 (*f)->timestamp = time_second; 560 *f = state->stub; 561 *cmd_ctl = IP_FW_CTL_CHK_STATE; 562 } else { 563 *cmd_ctl = IP_FW_CTL_NEXT; 564 } 565 } 566 567 void 568 check_in(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 569 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 570 { 571 *cmd_ctl = IP_FW_CTL_NO; 572 *cmd_val = ((*args)->oif == NULL); 573 } 574 575 void 576 check_out(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 577 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 578 { 579 *cmd_ctl = IP_FW_CTL_NO; 580 *cmd_val = ((*args)->oif != NULL); 581 } 582 583 void 584 check_via(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 585 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 586 { 587 *cmd_ctl = IP_FW_CTL_NO; 588 *cmd_val = iface_match((*args)->oif ? 589 (*args)->oif : (*args)->m->m_pkthdr.rcvif, 590 (ipfw_insn_if *)cmd); 591 } 592 593 void 594 check_proto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 595 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 596 { 597 *cmd_ctl = IP_FW_CTL_NO; 598 *cmd_val = ((*args)->f_id.proto == cmd->arg1); 599 } 600 601 void 602 check_prob(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 603 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 604 { 605 *cmd_ctl = IP_FW_CTL_NO; 606 *cmd_val = (krandom() % 100) < cmd->arg1; 607 } 608 609 void 610 check_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 611 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 612 { 613 struct in_addr src_ip; 614 u_int hlen = 0; 615 struct mbuf *m = (*args)->m; 616 struct ip *ip = mtod(m, struct ip *); 617 src_ip = ip->ip_src; 618 if ((*args)->eh == NULL || 619 (m->m_pkthdr.len >= sizeof(struct ip) && 620 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 621 hlen = ip->ip_hl << 2; 622 } 623 *cmd_val = (hlen > 0 && 624 ((ipfw_insn_ip *)cmd)->addr.s_addr == src_ip.s_addr); 625 *cmd_ctl = IP_FW_CTL_NO; 626 } 627 628 void 629 check_from_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 630 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 631 { 632 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 633 struct ipfw_table_context *table_ctx; 634 struct radix_node_head *rnh; 635 struct sockaddr_in sa; 636 637 struct mbuf *m = (*args)->m; 638 struct ip *ip = mtod(m, struct ip *); 639 struct in_addr src_ip = ip->ip_src; 640 641 *cmd_val = IP_FW_NOT_MATCH; 642 643 table_ctx = ctx->table_ctx; 644 table_ctx += cmd->arg1; 645 646 if (table_ctx->type != 0) { 647 rnh = table_ctx->node; 648 sa.sin_len = 8; 649 sa.sin_addr.s_addr = src_ip.s_addr; 650 if(rnh->rnh_lookup((char *)&sa, NULL, rnh) != NULL) 651 *cmd_val = IP_FW_MATCH; 652 } 653 *cmd_ctl = IP_FW_CTL_NO; 654 } 655 656 void 657 check_from_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 658 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 659 { 660 struct in_addr src_ip; 661 u_int hlen = 0; 662 struct mbuf *m = (*args)->m; 663 struct ip *ip = mtod(m, struct ip *); 664 src_ip = ip->ip_src; 665 if ((*args)->eh == NULL || 666 (m->m_pkthdr.len >= sizeof(struct ip) && 667 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 668 hlen = ip->ip_hl << 2; 669 } 670 *cmd_ctl = IP_FW_CTL_NO; 671 if (hlen > 0) { 672 struct ifnet *tif; 673 tif = INADDR_TO_IFP(&src_ip); 674 *cmd_val = (tif != NULL); 675 } else { 676 *cmd_val = IP_FW_NOT_MATCH; 677 } 678 } 679 680 void 681 check_from_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 682 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 683 { 684 struct in_addr src_ip; 685 u_int hlen = 0; 686 struct mbuf *m = (*args)->m; 687 struct ip *ip = mtod(m, struct ip *); 688 src_ip = ip->ip_src; 689 if ((*args)->eh == NULL || 690 (m->m_pkthdr.len >= sizeof(struct ip) && 691 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 692 hlen = ip->ip_hl << 2; 693 } 694 695 *cmd_ctl = IP_FW_CTL_NO; 696 *cmd_val = (hlen > 0 && 697 ((ipfw_insn_ip *)cmd)->addr.s_addr == 698 (src_ip.s_addr & 699 ((ipfw_insn_ip *)cmd)->mask.s_addr)); 700 } 701 702 void 703 check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 704 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 705 { 706 struct in_addr dst_ip; 707 u_int hlen = 0; 708 struct mbuf *m = (*args)->m; 709 struct ip *ip = mtod(m, struct ip *); 710 dst_ip = ip->ip_dst; 711 if ((*args)->eh == NULL || 712 (m->m_pkthdr.len >= sizeof(struct ip) && 713 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 714 hlen = ip->ip_hl << 2; 715 } 716 *cmd_val = (hlen > 0 && 717 ((ipfw_insn_ip *)cmd)->addr.s_addr == dst_ip.s_addr); 718 *cmd_ctl = IP_FW_CTL_NO; 719 } 720 721 void 722 check_to_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 723 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 724 { 725 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 726 struct ipfw_table_context *table_ctx; 727 struct radix_node_head *rnh; 728 struct sockaddr_in sa; 729 730 struct mbuf *m = (*args)->m; 731 struct ip *ip = mtod(m, struct ip *); 732 struct in_addr dst_ip = ip->ip_dst; 733 734 *cmd_val = IP_FW_NOT_MATCH; 735 736 table_ctx = ctx->table_ctx; 737 table_ctx += cmd->arg1; 738 739 if (table_ctx->type != 0) { 740 rnh = table_ctx->node; 741 sa.sin_len = 8; 742 sa.sin_addr.s_addr = dst_ip.s_addr; 743 if(rnh->rnh_lookup((char *)&sa, NULL, rnh) != NULL) 744 *cmd_val = IP_FW_MATCH; 745 } 746 *cmd_ctl = IP_FW_CTL_NO; 747 } 748 749 void 750 check_to_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 751 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 752 { 753 struct in_addr dst_ip; 754 u_int hlen = 0; 755 struct mbuf *m = (*args)->m; 756 struct ip *ip = mtod(m, struct ip *); 757 dst_ip = ip->ip_src; 758 if ((*args)->eh == NULL || 759 (m->m_pkthdr.len >= sizeof(struct ip) && 760 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 761 hlen = ip->ip_hl << 2; 762 } 763 *cmd_ctl = IP_FW_CTL_NO; 764 if (hlen > 0) { 765 struct ifnet *tif; 766 tif = INADDR_TO_IFP(&dst_ip); 767 *cmd_val = (tif != NULL); 768 } else { 769 *cmd_val = IP_FW_NOT_MATCH; 770 } 771 } 772 773 void 774 check_to_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 775 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 776 { 777 struct in_addr dst_ip; 778 u_int hlen = 0; 779 struct mbuf *m = (*args)->m; 780 struct ip *ip = mtod(m, struct ip *); 781 dst_ip = ip->ip_src; 782 if ((*args)->eh == NULL || 783 (m->m_pkthdr.len >= sizeof(struct ip) && 784 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 785 hlen = ip->ip_hl << 2; 786 } 787 788 *cmd_ctl = IP_FW_CTL_NO; 789 *cmd_val = (hlen > 0 && 790 ((ipfw_insn_ip *)cmd)->addr.s_addr == 791 (dst_ip.s_addr & 792 ((ipfw_insn_ip *)cmd)->mask.s_addr)); 793 } 794 795 void 796 check_keep_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 797 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 798 { 799 struct ip_fw_state *state; 800 int limited = 0; 801 802 *cmd_ctl = IP_FW_CTL_NO; 803 *cmd_val = IP_FW_MATCH; 804 state = lookup_state(*args, cmd, &limited, 1); 805 if (limited != 1) { 806 if (state == NULL) 807 state = install_state(*f, cmd, *args); 808 809 if (state != NULL) { 810 state->pcnt++; 811 state->bcnt += ip_len; 812 state->timestamp = time_second; 813 } 814 } 815 } 816 817 void 818 check_tag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 819 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 820 { 821 struct m_tag *mtag = m_tag_locate((*args)->m, 822 MTAG_IPFW, cmd->arg1, NULL); 823 if (mtag == NULL) { 824 mtag = m_tag_alloc(MTAG_IPFW,cmd->arg1, 0, M_NOWAIT); 825 if (mtag != NULL) 826 m_tag_prepend((*args)->m, mtag); 827 828 } 829 (*f)->pcnt++; 830 (*f)->bcnt += ip_len; 831 (*f)->timestamp = time_second; 832 *cmd_ctl = IP_FW_CTL_NEXT; 833 } 834 835 void 836 check_untag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 837 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 838 { 839 struct m_tag *mtag = m_tag_locate((*args)->m, 840 MTAG_IPFW, cmd->arg1, NULL); 841 if (mtag != NULL) 842 m_tag_delete((*args)->m, mtag); 843 844 (*f)->pcnt++; 845 (*f)->bcnt += ip_len; 846 (*f)->timestamp = time_second; 847 *cmd_ctl = IP_FW_CTL_NEXT; 848 } 849 850 void 851 check_tagged(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 852 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 853 { 854 *cmd_ctl = IP_FW_CTL_NO; 855 if (m_tag_locate( (*args)->m, MTAG_IPFW,cmd->arg1, NULL) != NULL ) 856 *cmd_val = IP_FW_MATCH; 857 else 858 *cmd_val = IP_FW_NOT_MATCH; 859 } 860 861 void 862 check_src_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 863 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 864 { 865 *cmd_ctl = IP_FW_CTL_NO; 866 if ((*args)->f_id.src_port == cmd->arg1) 867 *cmd_val = IP_FW_MATCH; 868 else 869 *cmd_val = IP_FW_NOT_MATCH; 870 } 871 872 void 873 check_dst_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 874 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 875 { 876 *cmd_ctl = IP_FW_CTL_NO; 877 if ((*args)->f_id.dst_port == cmd->arg1) 878 *cmd_val = IP_FW_MATCH; 879 else 880 *cmd_val = IP_FW_NOT_MATCH; 881 } 882 883 void 884 check_src_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 885 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 886 { 887 struct in_addr src_ip; 888 u_int hlen = 0; 889 struct mbuf *m = (*args)->m; 890 struct ip *ip = mtod(m, struct ip *); 891 src_ip = ip->ip_src; 892 if ((*args)->eh == NULL || 893 (m->m_pkthdr.len >= sizeof(struct ip) && 894 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 895 hlen = ip->ip_hl << 2; 896 } 897 *cmd_val = (hlen > 0 && ((ipfw_insn_ip *)cmd)->addr.s_addr == src_ip.s_addr); 898 *cmd_ctl = IP_FW_CTL_NO; 899 if (*cmd_val && (*args)->f_id.src_port == cmd->arg1) 900 *cmd_val = IP_FW_MATCH; 901 else 902 *cmd_val = IP_FW_NOT_MATCH; 903 } 904 905 void 906 check_dst_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 907 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 908 { 909 struct in_addr dst_ip; 910 u_int hlen = 0; 911 struct mbuf *m = (*args)->m; 912 struct ip *ip = mtod(m, struct ip *); 913 dst_ip = ip->ip_dst; 914 if ((*args)->eh == NULL || 915 (m->m_pkthdr.len >= sizeof(struct ip) && 916 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 917 hlen = ip->ip_hl << 2; 918 } 919 *cmd_val = (hlen > 0 && ((ipfw_insn_ip *)cmd)->addr.s_addr == dst_ip.s_addr); 920 *cmd_ctl = IP_FW_CTL_NO; 921 if (*cmd_val && (*args)->f_id.dst_port == cmd->arg1) 922 *cmd_val = IP_FW_MATCH; 923 else 924 *cmd_val = IP_FW_NOT_MATCH; 925 } 926 927 928 929 static void 930 ipfw_basic_add_state(struct ipfw_ioc_state *ioc_state) 931 { 932 struct ip_fw_state *state; 933 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 934 struct ipfw_state_context *state_ctx; 935 state_ctx = &ctx->state_ctx[hash_packet(&(ioc_state->flow_id))]; 936 state = kmalloc(sizeof(struct ip_fw_state), 937 M_IPFW3_BASIC, M_WAITOK | M_ZERO); 938 struct ip_fw *rule = ctx->ipfw_rule_chain; 939 while (rule != NULL) { 940 if (rule->rulenum == ioc_state->rulenum) { 941 break; 942 } 943 rule = rule->next; 944 } 945 if (rule == NULL) 946 return; 947 948 state->stub = rule; 949 950 state->lifetime = ioc_state->lifetime == 0 ? 951 state_lifetime : ioc_state->lifetime ; 952 state->timestamp = time_second; 953 state->expiry = ioc_state->expiry; 954 bcopy(&ioc_state->flow_id, &state->flow_id, 955 sizeof(struct ipfw_flow_id)); 956 //append the state into the state chian 957 if (state_ctx->last != NULL) 958 state_ctx->last->next = state; 959 else 960 state_ctx->state = state; 961 962 state_ctx->last = state; 963 state_ctx->count++; 964 } 965 966 /* 967 * if rule is NULL 968 * flush all states 969 * else 970 * flush states which stub is the rule 971 */ 972 static void 973 ipfw_basic_flush_state(struct ip_fw *rule) 974 { 975 struct ipfw_state_context *state_ctx; 976 struct ip_fw_state *state,*the_state, *prev_state; 977 struct ipfw_context *ctx; 978 int i; 979 980 ctx = ipfw_ctx[mycpuid]; 981 for (i = 0; i < state_hash_size; i++) { 982 state_ctx = &ctx->state_ctx[i]; 983 if (state_ctx != NULL) { 984 state = state_ctx->state; 985 prev_state = NULL; 986 while (state != NULL) { 987 if (rule != NULL && state->stub != rule) { 988 prev_state = state; 989 state = state->next; 990 } else { 991 if (prev_state == NULL) 992 state_ctx->state = state->next; 993 else 994 prev_state->next = state->next; 995 996 the_state = state; 997 state = state->next; 998 kfree(the_state, M_IPFW3_BASIC); 999 state_ctx->count--; 1000 if (state == NULL) 1001 state_ctx->last = prev_state; 1002 1003 } 1004 } 1005 } 1006 } 1007 } 1008 1009 /* 1010 * clean up expired state in every tick 1011 */ 1012 static void 1013 ipfw_cleanup_expired_state(netmsg_t nmsg) 1014 { 1015 struct ip_fw_state *state,*the_state,*prev_state; 1016 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 1017 struct ipfw_state_context *state_ctx; 1018 int i; 1019 1020 for (i = 0; i < state_hash_size; i++) { 1021 prev_state = NULL; 1022 state_ctx = &(ctx->state_ctx[i]); 1023 if (ctx->state_ctx != NULL) { 1024 state = state_ctx->state; 1025 while (state != NULL) { 1026 if (IS_EXPIRED(state)) { 1027 if (prev_state == NULL) 1028 state_ctx->state = state->next; 1029 else 1030 prev_state->next = state->next; 1031 1032 the_state =state; 1033 state = state->next; 1034 1035 if (the_state == state_ctx->last) 1036 state_ctx->last = NULL; 1037 1038 1039 kfree(the_state, M_IPFW3_BASIC); 1040 state_ctx->count--; 1041 } else { 1042 prev_state = state; 1043 state = state->next; 1044 } 1045 } 1046 } 1047 } 1048 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1); 1049 } 1050 1051 static void 1052 ipfw_tick(void *dummy __unused) 1053 { 1054 struct lwkt_msg *lmsg = &ipfw_timeout_netmsg.lmsg; 1055 KKASSERT(mycpuid == IPFW_CFGCPUID); 1056 1057 crit_enter(); 1058 KKASSERT(lmsg->ms_flags & MSGF_DONE); 1059 if (IPFW_BASIC_LOADED) { 1060 lwkt_sendmsg_oncpu(IPFW_CFGPORT, lmsg); 1061 /* ipfw_timeout_netmsg's handler reset this callout */ 1062 } 1063 crit_exit(); 1064 } 1065 1066 static void 1067 ipfw_tick_dispatch(netmsg_t nmsg) 1068 { 1069 IPFW_ASSERT_CFGPORT(&curthread->td_msgport); 1070 KKASSERT(IPFW_BASIC_LOADED); 1071 1072 /* Reply ASAP */ 1073 crit_enter(); 1074 lwkt_replymsg(&nmsg->lmsg, 0); 1075 crit_exit(); 1076 1077 callout_reset(&ipfw_tick_callout, 1078 state_expiry_check_interval * hz, ipfw_tick, NULL); 1079 1080 struct netmsg_base msg; 1081 netmsg_init(&msg, NULL, &curthread->td_msgport, 0, 1082 ipfw_cleanup_expired_state); 1083 netisr_domsg(&msg, 0); 1084 } 1085 1086 static void 1087 ipfw_basic_init_dispatch(netmsg_t nmsg) 1088 { 1089 IPFW_ASSERT_CFGPORT(&curthread->td_msgport); 1090 KKASSERT(IPFW3_LOADED); 1091 1092 int error = 0; 1093 callout_init_mp(&ipfw_tick_callout); 1094 netmsg_init(&ipfw_timeout_netmsg, NULL, &netisr_adone_rport, 1095 MSGF_DROPABLE | MSGF_PRIORITY, ipfw_tick_dispatch); 1096 callout_reset(&ipfw_tick_callout, 1097 state_expiry_check_interval * hz, ipfw_tick, NULL); 1098 lwkt_replymsg(&nmsg->lmsg, error); 1099 ip_fw_basic_loaded=1; 1100 } 1101 1102 static int 1103 ipfw_basic_init(void) 1104 { 1105 ipfw_basic_flush_state_prt = ipfw_basic_flush_state; 1106 ipfw_basic_append_state_prt = ipfw_basic_add_state; 1107 ipfw_sync_install_state_prt = ipfw_sync_install_state; 1108 1109 register_ipfw_module(MODULE_BASIC_ID, MODULE_BASIC_NAME); 1110 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_COUNT, 1111 (filter_func)check_count); 1112 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_SKIPTO, 1113 (filter_func)check_skipto); 1114 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_FORWARD, 1115 (filter_func)check_forward); 1116 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_KEEP_STATE, 1117 (filter_func)check_keep_state); 1118 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_CHECK_STATE, 1119 (filter_func)check_check_state); 1120 1121 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1122 O_BASIC_IN, (filter_func)check_in); 1123 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1124 O_BASIC_OUT, (filter_func)check_out); 1125 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1126 O_BASIC_VIA, (filter_func)check_via); 1127 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1128 O_BASIC_XMIT, (filter_func)check_via); 1129 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1130 O_BASIC_RECV, (filter_func)check_via); 1131 1132 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1133 O_BASIC_PROTO, (filter_func)check_proto); 1134 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1135 O_BASIC_PROB, (filter_func)check_prob); 1136 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1137 O_BASIC_IP_SRC, (filter_func)check_from); 1138 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1139 O_BASIC_IP_SRC_LOOKUP, (filter_func)check_from_lookup); 1140 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1141 O_BASIC_IP_SRC_ME, (filter_func)check_from_me); 1142 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1143 O_BASIC_IP_SRC_MASK, (filter_func)check_from_mask); 1144 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1145 O_BASIC_IP_DST, (filter_func)check_to); 1146 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1147 O_BASIC_IP_DST_LOOKUP, (filter_func)check_to_lookup); 1148 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1149 O_BASIC_IP_DST_ME, (filter_func)check_to_me); 1150 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1151 O_BASIC_IP_DST_MASK, (filter_func)check_to_mask); 1152 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1153 O_BASIC_TAG, (filter_func)check_tag); 1154 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1155 O_BASIC_UNTAG, (filter_func)check_untag); 1156 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1157 O_BASIC_TAGGED, (filter_func)check_tagged); 1158 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1159 O_BASIC_IP_SRCPORT, (filter_func)check_src_port); 1160 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1161 O_BASIC_IP_DSTPORT, (filter_func)check_dst_port); 1162 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1163 O_BASIC_IP_SRC_N_PORT, (filter_func)check_src_n_port); 1164 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1165 O_BASIC_IP_DST_N_PORT, (filter_func)check_dst_n_port); 1166 1167 int cpu; 1168 struct ipfw_context *ctx; 1169 1170 for (cpu = 0; cpu < ncpus; cpu++) { 1171 ctx = ipfw_ctx[cpu]; 1172 if (ctx != NULL) { 1173 ctx->state_ctx = kmalloc(state_hash_size * 1174 sizeof(struct ipfw_state_context), 1175 M_IPFW3_BASIC, M_WAITOK | M_ZERO); 1176 ctx->state_hash_size = state_hash_size; 1177 } 1178 } 1179 1180 struct netmsg_base smsg; 1181 netmsg_init(&smsg, NULL, &curthread->td_msgport, 1182 0, ipfw_basic_init_dispatch); 1183 lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0); 1184 return 0; 1185 } 1186 1187 static void 1188 ipfw_basic_stop_dispatch(netmsg_t nmsg) 1189 { 1190 IPFW_ASSERT_CFGPORT(&curthread->td_msgport); 1191 KKASSERT(IPFW3_LOADED); 1192 int error = 0; 1193 callout_stop(&ipfw_tick_callout); 1194 netmsg_service_sync(); 1195 crit_enter(); 1196 lwkt_dropmsg(&ipfw_timeout_netmsg.lmsg); 1197 crit_exit(); 1198 lwkt_replymsg(&nmsg->lmsg, error); 1199 ip_fw_basic_loaded=0; 1200 } 1201 1202 static int 1203 ipfw_basic_stop(void) 1204 { 1205 int cpu,i; 1206 struct ipfw_state_context *state_ctx; 1207 struct ip_fw_state *state,*the_state; 1208 struct ipfw_context *ctx; 1209 if (unregister_ipfw_module(MODULE_BASIC_ID) ==0 ) { 1210 ipfw_basic_flush_state_prt = NULL; 1211 ipfw_basic_append_state_prt = NULL; 1212 1213 for (cpu = 0; cpu < ncpus; cpu++) { 1214 ctx = ipfw_ctx[cpu]; 1215 if (ctx != NULL) { 1216 for (i = 0; i < state_hash_size; i++) { 1217 state_ctx = &ctx->state_ctx[i]; 1218 if (state_ctx != NULL) { 1219 state = state_ctx->state; 1220 while (state != NULL) { 1221 the_state = state; 1222 state = state->next; 1223 if (the_state == 1224 state_ctx->last) 1225 state_ctx->last = NULL; 1226 1227 kfree(the_state, 1228 M_IPFW3_BASIC); 1229 } 1230 } 1231 } 1232 ctx->state_hash_size = 0; 1233 kfree(ctx->state_ctx, M_IPFW3_BASIC); 1234 ctx->state_ctx = NULL; 1235 } 1236 } 1237 struct netmsg_base smsg; 1238 netmsg_init(&smsg, NULL, &curthread->td_msgport, 1239 0, ipfw_basic_stop_dispatch); 1240 return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0); 1241 } 1242 return 1; 1243 } 1244 1245 1246 static int 1247 ipfw3_basic_modevent(module_t mod, int type, void *data) 1248 { 1249 int err; 1250 switch (type) { 1251 case MOD_LOAD: 1252 err = ipfw_basic_init(); 1253 break; 1254 case MOD_UNLOAD: 1255 err = ipfw_basic_stop(); 1256 break; 1257 default: 1258 err = 1; 1259 } 1260 return err; 1261 } 1262 1263 static moduledata_t ipfw3_basic_mod = { 1264 "ipfw3_basic", 1265 ipfw3_basic_modevent, 1266 NULL 1267 }; 1268 DECLARE_MODULE(ipfw3_basic, ipfw3_basic_mod, SI_SUB_PROTO_END, SI_ORDER_ANY); 1269 MODULE_DEPEND(ipfw3_basic, ipfw3, 1, 1, 1); 1270 MODULE_VERSION(ipfw3_basic, 1); 1271