1 /* 2 * Copyright (c) 2014 - 2016 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 int fw_verbose; 78 extern ipfw_basic_delete_state_t *ipfw_basic_flush_state_prt; 79 extern ipfw_basic_append_state_t *ipfw_basic_append_state_prt; 80 extern ipfw_sync_send_state_t *ipfw_sync_send_state_prt; 81 extern ipfw_sync_install_state_t *ipfw_sync_install_state_prt; 82 83 static int ip_fw_basic_loaded; 84 static struct netmsg_base ipfw_timeout_netmsg; /* schedule ipfw timeout */ 85 static struct callout ipfw_tick_callout; 86 static int state_lifetime = 20; 87 static int state_expiry_check_interval = 10; 88 static int state_count_max = 4096; 89 static int state_hash_size_old = 0; 90 static int state_hash_size = 4096; 91 92 93 static int ipfw_sysctl_adjust_hash_size(SYSCTL_HANDLER_ARGS); 94 void adjust_hash_size_dispatch(netmsg_t nmsg); 95 96 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw_basic, 97 CTLFLAG_RW, 0, "Firewall Basic"); 98 SYSCTL_PROC(_net_inet_ip_fw_basic, OID_AUTO, state_hash_size, 99 CTLTYPE_INT | CTLFLAG_RW, &state_hash_size, 0, 100 ipfw_sysctl_adjust_hash_size, "I", "Adjust hash size"); 101 102 SYSCTL_INT(_net_inet_ip_fw_basic, OID_AUTO, state_lifetime, CTLFLAG_RW, 103 &state_lifetime, 0, "default life time"); 104 SYSCTL_INT(_net_inet_ip_fw_basic, OID_AUTO, 105 state_expiry_check_interval, CTLFLAG_RW, 106 &state_expiry_check_interval, 0, 107 "default state expiry check interval"); 108 SYSCTL_INT(_net_inet_ip_fw_basic, OID_AUTO, state_count_max, CTLFLAG_RW, 109 &state_count_max, 0, "maximum of state"); 110 111 static int 112 ipfw_sysctl_adjust_hash_size(SYSCTL_HANDLER_ARGS) 113 { 114 int error, value = 0; 115 116 state_hash_size_old = state_hash_size; 117 value = state_hash_size; 118 error = sysctl_handle_int(oidp, &value, 0, req); 119 if (error || !req->newptr) { 120 goto back; 121 } 122 /* 123 * Make sure we have a power of 2 and 124 * do not allow more than 64k entries. 125 */ 126 error = EINVAL; 127 if (value <= 1 || value > 65536) { 128 goto back; 129 } 130 if ((value & (value - 1)) != 0) { 131 goto back; 132 } 133 134 error = 0; 135 if (state_hash_size != value) { 136 state_hash_size = value; 137 138 struct netmsg_base *msg, the_msg; 139 msg = &the_msg; 140 bzero(msg,sizeof(struct netmsg_base)); 141 142 netmsg_init(msg, NULL, &curthread->td_msgport, 143 0, adjust_hash_size_dispatch); 144 ifnet_domsg(&msg->lmsg, 0); 145 } 146 back: 147 return error; 148 } 149 150 void 151 adjust_hash_size_dispatch(netmsg_t nmsg) 152 { 153 struct ipfw_state_context *state_ctx; 154 struct ip_fw_state *the_state, *state; 155 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 156 int i; 157 158 for (i = 0; i < state_hash_size_old; i++) { 159 state_ctx = &ctx->state_ctx[i]; 160 if (state_ctx != NULL) { 161 state = state_ctx->state; 162 while (state != NULL) { 163 the_state = state; 164 state = state->next; 165 kfree(the_state, M_IPFW3_BASIC); 166 the_state = NULL; 167 } 168 } 169 } 170 kfree(ctx->state_ctx,M_IPFW3_BASIC); 171 ctx->state_ctx = kmalloc(state_hash_size * 172 sizeof(struct ipfw_state_context), 173 M_IPFW3_BASIC, M_WAITOK | M_ZERO); 174 ctx->state_hash_size = state_hash_size; 175 ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1); 176 } 177 178 179 /* prototype of the checker functions */ 180 void check_count(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 181 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 182 void check_skipto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 183 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 184 void check_forward(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 185 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 186 void check_check_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 187 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 188 189 void check_in(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 190 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 191 void check_out(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 192 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 193 void check_via(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 194 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 195 void check_proto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 196 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 197 void check_prob(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 198 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 199 void check_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 200 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 201 void check_from_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 202 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 203 void check_from_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 204 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 205 void check_from_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 206 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 207 void check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 208 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 209 void check_to_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 210 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 211 void check_to_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 212 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 213 void check_to_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 214 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 215 void check_keep_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 216 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 217 void check_tag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 218 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 219 void check_untag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 220 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 221 void check_tagged(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 222 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 223 void check_src_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 224 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 225 void check_dst_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 226 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 227 void check_src_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 228 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 229 void check_dst_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 230 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); 231 232 /* prototype of the utility functions */ 233 int match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid, 234 struct ip_fw_state *state); 235 int count_match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid, 236 struct ip_fw_state *state, int *count); 237 238 static struct ip_fw *lookup_next_rule(struct ip_fw *me); 239 static int iface_match(struct ifnet *ifp, ipfw_insn_if *cmd); 240 static __inline int hash_packet(struct ipfw_flow_id *id); 241 242 static __inline int 243 hash_packet(struct ipfw_flow_id *id) 244 { 245 uint32_t i; 246 i = (id->proto) ^ (id->dst_ip) ^ (id->src_ip) ^ 247 (id->dst_port) ^ (id->src_port); 248 i &= state_hash_size - 1; 249 return i; 250 } 251 252 static struct ip_fw * 253 lookup_next_rule(struct ip_fw *me) 254 { 255 struct ip_fw *rule = NULL; 256 ipfw_insn *cmd; 257 258 /* look for action, in case it is a skipto */ 259 cmd = ACTION_PTR(me); 260 if ((int)cmd->module == MODULE_BASIC_ID && 261 (int)cmd->opcode == O_BASIC_SKIPTO) { 262 for (rule = me->next; rule; rule = rule->next) { 263 if (rule->rulenum >= cmd->arg1) 264 break; 265 } 266 } 267 if (rule == NULL) /* failure or not a skipto */ 268 rule = me->next; 269 270 me->next_rule = rule; 271 return rule; 272 } 273 274 /* 275 * return value 276 * 0 : not match 1: same direction 2: reverse direction 277 */ 278 int 279 match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid, struct ip_fw_state *state) 280 { 281 if (fid->src_ip == state->flow_id.src_ip && 282 fid->dst_ip == state->flow_id.dst_ip && 283 (fid->src_port == state->flow_id.src_port || 284 state->flow_id.src_port == 0) && 285 (fid->dst_port == state->flow_id.dst_port || 286 state->flow_id.dst_port == 0)) { 287 return 1; 288 } 289 if (fid->src_ip == state->flow_id.dst_ip && 290 fid->dst_ip == state->flow_id.src_ip && 291 (fid->src_port == state->flow_id.dst_port || 292 state->flow_id.dst_port == 0) && 293 (fid->dst_port == state->flow_id.src_port || 294 state->flow_id.src_port == 0)) { 295 return 2; 296 } 297 return 0; 298 } 299 300 /* 301 * return 1 when more states than limit 302 * arg3: limit type (1=src ip, 2=src port, 3=dst ip, 4=dst port) 303 * arg1: limit 304 */ 305 int 306 count_match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid, 307 struct ip_fw_state *state, int *count) 308 { 309 if ((cmd->arg3 == 1 && fid->src_ip == state->flow_id.src_ip) || 310 (cmd->arg3 == 2 && fid->src_port == state->flow_id.src_port) || 311 (cmd->arg3 == 3 && fid->dst_ip == state->flow_id.dst_ip) || 312 (cmd->arg3 == 4 && fid->dst_port == state->flow_id.dst_port)) { 313 *count = *count + 1; 314 if (*count >= cmd->arg1) 315 return 1; 316 } 317 return 0; 318 } 319 320 /* 321 * when all = 1, it will check all the state_ctx 322 * all = 1 during keep-state 323 * all = 0 during check-state 324 * 325 * in the cmd of keep_state 326 * arg3=type arg1=limit 327 */ 328 static struct ip_fw_state * 329 lookup_state(struct ip_fw_args *args, ipfw_insn *cmd, int *limited, int all) 330 { 331 struct ip_fw_state *state = NULL; 332 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 333 struct ipfw_state_context *state_ctx; 334 int start, end, i, count = 0; 335 336 if (all && cmd->arg1) { 337 start = 0; 338 end = state_hash_size - 1; 339 } else { 340 start = hash_packet(&args->f_id); 341 end = hash_packet(&args->f_id); 342 } 343 344 for (i = start; i <= end; i++) { 345 state_ctx = &ctx->state_ctx[i]; 346 if (state_ctx != NULL) { 347 state = state_ctx->state; 348 struct ipfw_flow_id *fid = &args->f_id; 349 while (state != NULL) { 350 /* has limit and already exceed the limit */ 351 if (cmd->arg1 && 352 count_match_state(cmd, fid, 353 state, &count) != 0) { 354 *limited = 1; 355 goto done; 356 } 357 358 if (fid->proto == state->flow_id.proto && 359 match_state(cmd, fid, state) != 0) 360 goto done; 361 362 state = state->next; 363 } 364 } 365 } 366 done: 367 return state; 368 } 369 370 static struct ip_fw_state * 371 install_state(struct ip_fw *rule, ipfw_insn *cmd, struct ip_fw_args *args) 372 { 373 struct ip_fw_state *state; 374 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 375 struct ipfw_state_context *state_ctx; 376 int hash = hash_packet(&args->f_id); 377 state_ctx = &ctx->state_ctx[hash]; 378 state = kmalloc(sizeof(struct ip_fw_state), 379 M_IPFW3_BASIC, M_NOWAIT | M_ZERO); 380 if (state == NULL) { 381 return NULL; 382 } 383 state->stub = rule; 384 state->lifetime = cmd->arg2 == 0 ? state_lifetime : cmd->arg2 ; 385 state->timestamp = time_second; 386 state->expiry = 0; 387 bcopy(&args->f_id,&state->flow_id,sizeof(struct ipfw_flow_id)); 388 //append the state into the state chian 389 if (state_ctx->last != NULL) 390 state_ctx->last->next = state; 391 else 392 state_ctx->state = state; 393 state_ctx->last = state; 394 state_ctx->count++; 395 ipfw_sync_send_state_prt(state, mycpuid, hash); 396 return state; 397 } 398 399 void 400 ipfw_sync_install_state(struct cmd_send_state *cmd) 401 { 402 struct ip_fw_state *state; 403 struct ipfw_context *ctx = ipfw_ctx[cmd->cpu]; 404 struct ipfw_state_context *state_ctx; 405 struct ip_fw *rule; 406 407 state_ctx = &ctx->state_ctx[cmd->hash]; 408 state = kmalloc(sizeof(struct ip_fw_state), 409 M_IPFW3_BASIC, M_NOWAIT | M_ZERO); 410 if (state == NULL) { 411 return; 412 } 413 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) { 414 if (rule->rulenum == cmd->rulenum) { 415 goto found; 416 } 417 } 418 return; 419 found: 420 state->stub = rule; 421 state->lifetime = cmd->lifetime; 422 state->timestamp = time_second; 423 state->expiry = 0; 424 bcopy(&cmd->flow, &state->flow_id, sizeof(struct ipfw_flow_id)); 425 //append the state into the state chian 426 if (state_ctx->last != NULL) 427 state_ctx->last->next = state; 428 else 429 state_ctx->state = state; 430 state_ctx->last = state; 431 state_ctx->count++; 432 } 433 434 static int 435 iface_match(struct ifnet *ifp, ipfw_insn_if *cmd) 436 { 437 if (ifp == NULL) /* no iface with this packet, match fails */ 438 return 0; 439 440 /* Check by name or by IP address */ 441 if (cmd->name[0] != '\0') { /* match by name */ 442 /* Check name */ 443 if (cmd->p.glob) { 444 if (kfnmatch(cmd->name, ifp->if_xname, 0) == 0) 445 return(1); 446 } else { 447 if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0) 448 return(1); 449 } 450 } else { 451 struct ifaddr_container *ifac; 452 453 TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) { 454 struct ifaddr *ia = ifac->ifa; 455 456 if (ia->ifa_addr == NULL) 457 continue; 458 if (ia->ifa_addr->sa_family != AF_INET) 459 continue; 460 if (cmd->p.ip.s_addr == 461 ((struct sockaddr_in *) 462 (ia->ifa_addr))->sin_addr.s_addr) 463 return(1); /* match */ 464 465 } 466 } 467 return 0; /* no match, fail ... */ 468 } 469 470 /* implimentation of the checker functions */ 471 void 472 check_count(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 473 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 474 { 475 (*f)->pcnt++; 476 (*f)->bcnt += ip_len; 477 (*f)->timestamp = time_second; 478 *cmd_ctl = IP_FW_CTL_NEXT; 479 } 480 481 void 482 check_skipto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 483 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 484 { 485 (*f)->pcnt++; 486 (*f)->bcnt += ip_len; 487 (*f)->timestamp = time_second; 488 if ((*f)->next_rule == NULL) 489 lookup_next_rule(*f); 490 *f = (*f)->next_rule; 491 *cmd_ctl = IP_FW_CTL_AGAIN; 492 } 493 494 void 495 check_forward(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 496 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 497 { 498 struct sockaddr_in *sin, *sa; 499 struct m_tag *mtag; 500 501 if ((*args)->eh) { /* not valid on layer2 pkts */ 502 *cmd_ctl=IP_FW_CTL_NEXT; 503 return; 504 } 505 506 (*f)->pcnt++; 507 (*f)->bcnt += ip_len; 508 (*f)->timestamp = time_second; 509 if ((*f)->next_rule == NULL) 510 lookup_next_rule(*f); 511 512 mtag = m_tag_get(PACKET_TAG_IPFORWARD, 513 sizeof(*sin), M_NOWAIT); 514 if (mtag == NULL) { 515 *cmd_val = IP_FW_DENY; 516 *cmd_ctl = IP_FW_CTL_DONE; 517 return; 518 } 519 sin = m_tag_data(mtag); 520 sa = &((ipfw_insn_sa *)cmd)->sa; 521 /* arg3: count of the dest, arg1: type of fwd */ 522 int i = 0; 523 if(cmd->arg3 > 1) { 524 if (cmd->arg1 == 0) { /* type: random */ 525 i = krandom() % cmd->arg3; 526 } else if (cmd->arg1 == 1) { /* type: round-robin */ 527 i = cmd->arg2++ % cmd->arg3; 528 } else if (cmd->arg1 == 2) { /* type: sticky */ 529 struct ip *ip = mtod((*args)->m, struct ip *); 530 i = ip->ip_src.s_addr & (cmd->arg3 - 1); 531 } 532 sa += i; 533 } 534 *sin = *sa; /* apply the destination */ 535 m_tag_prepend((*args)->m, mtag); 536 (*args)->m->m_pkthdr.fw_flags |= IPFORWARD_MBUF_TAGGED; 537 (*args)->m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED; 538 *cmd_ctl = IP_FW_CTL_DONE; 539 *cmd_val = IP_FW_PASS; 540 } 541 542 void 543 check_check_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 544 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 545 { 546 struct ip_fw_state *state=NULL; 547 int limited = 0 ; 548 state = lookup_state(*args, cmd, &limited, 0); 549 if (state != NULL) { 550 state->pcnt++; 551 state->bcnt += ip_len; 552 state->timestamp = time_second; 553 (*f)->pcnt++; 554 (*f)->bcnt += ip_len; 555 (*f)->timestamp = time_second; 556 *f = state->stub; 557 *cmd_ctl = IP_FW_CTL_CHK_STATE; 558 } else { 559 *cmd_ctl = IP_FW_CTL_NEXT; 560 } 561 } 562 563 void 564 check_in(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 565 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 566 { 567 *cmd_ctl = IP_FW_CTL_NO; 568 *cmd_val = ((*args)->oif == NULL); 569 } 570 571 void 572 check_out(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 573 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 574 { 575 *cmd_ctl = IP_FW_CTL_NO; 576 *cmd_val = ((*args)->oif != NULL); 577 } 578 579 void 580 check_via(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 581 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 582 { 583 *cmd_ctl = IP_FW_CTL_NO; 584 *cmd_val = iface_match((*args)->oif ? 585 (*args)->oif : (*args)->m->m_pkthdr.rcvif, 586 (ipfw_insn_if *)cmd); 587 } 588 589 void 590 check_proto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 591 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 592 { 593 *cmd_ctl = IP_FW_CTL_NO; 594 *cmd_val = ((*args)->f_id.proto == cmd->arg1); 595 } 596 597 void 598 check_prob(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 599 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 600 { 601 *cmd_ctl = IP_FW_CTL_NO; 602 *cmd_val = (krandom() % 100) < cmd->arg1; 603 } 604 605 void 606 check_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 607 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 608 { 609 struct in_addr src_ip; 610 u_int hlen = 0; 611 struct mbuf *m = (*args)->m; 612 struct ip *ip = mtod(m, struct ip *); 613 src_ip = ip->ip_src; 614 if ((*args)->eh == NULL || 615 (m->m_pkthdr.len >= sizeof(struct ip) && 616 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 617 hlen = ip->ip_hl << 2; 618 } 619 *cmd_val = (hlen > 0 && 620 ((ipfw_insn_ip *)cmd)->addr.s_addr == src_ip.s_addr); 621 *cmd_ctl = IP_FW_CTL_NO; 622 } 623 624 void 625 check_from_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 626 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 627 { 628 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 629 struct ipfw_table_context *table_ctx; 630 struct radix_node_head *rnh; 631 struct sockaddr_in sa; 632 633 struct mbuf *m = (*args)->m; 634 struct ip *ip = mtod(m, struct ip *); 635 struct in_addr src_ip = ip->ip_src; 636 637 *cmd_val = IP_FW_NOT_MATCH; 638 639 table_ctx = ctx->table_ctx; 640 table_ctx += cmd->arg1; 641 642 if (table_ctx->type != 0) { 643 rnh = table_ctx->node; 644 sa.sin_len = 8; 645 sa.sin_addr.s_addr = src_ip.s_addr; 646 if(rnh->rnh_lookup((char *)&sa, NULL, rnh) != NULL) 647 *cmd_val = IP_FW_MATCH; 648 } 649 *cmd_ctl = IP_FW_CTL_NO; 650 } 651 652 void 653 check_from_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 654 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 655 { 656 struct in_addr src_ip; 657 u_int hlen = 0; 658 struct mbuf *m = (*args)->m; 659 struct ip *ip = mtod(m, struct ip *); 660 src_ip = ip->ip_src; 661 if ((*args)->eh == NULL || 662 (m->m_pkthdr.len >= sizeof(struct ip) && 663 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 664 hlen = ip->ip_hl << 2; 665 } 666 *cmd_ctl = IP_FW_CTL_NO; 667 if (hlen > 0) { 668 struct ifnet *tif; 669 tif = INADDR_TO_IFP(&src_ip); 670 *cmd_val = (tif != NULL); 671 } else { 672 *cmd_val = IP_FW_NOT_MATCH; 673 } 674 } 675 676 void 677 check_from_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 678 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 679 { 680 struct in_addr src_ip; 681 u_int hlen = 0; 682 struct mbuf *m = (*args)->m; 683 struct ip *ip = mtod(m, struct ip *); 684 src_ip = ip->ip_src; 685 if ((*args)->eh == NULL || 686 (m->m_pkthdr.len >= sizeof(struct ip) && 687 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 688 hlen = ip->ip_hl << 2; 689 } 690 691 *cmd_ctl = IP_FW_CTL_NO; 692 *cmd_val = (hlen > 0 && 693 ((ipfw_insn_ip *)cmd)->addr.s_addr == 694 (src_ip.s_addr & 695 ((ipfw_insn_ip *)cmd)->mask.s_addr)); 696 } 697 698 void 699 check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 700 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 701 { 702 struct in_addr dst_ip; 703 u_int hlen = 0; 704 struct mbuf *m = (*args)->m; 705 struct ip *ip = mtod(m, struct ip *); 706 dst_ip = ip->ip_dst; 707 if ((*args)->eh == NULL || 708 (m->m_pkthdr.len >= sizeof(struct ip) && 709 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 710 hlen = ip->ip_hl << 2; 711 } 712 *cmd_val = (hlen > 0 && 713 ((ipfw_insn_ip *)cmd)->addr.s_addr == dst_ip.s_addr); 714 *cmd_ctl = IP_FW_CTL_NO; 715 } 716 717 void 718 check_to_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 719 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 720 { 721 struct ipfw_context *ctx = ipfw_ctx[mycpuid]; 722 struct ipfw_table_context *table_ctx; 723 struct radix_node_head *rnh; 724 struct sockaddr_in sa; 725 726 struct mbuf *m = (*args)->m; 727 struct ip *ip = mtod(m, struct ip *); 728 struct in_addr dst_ip = ip->ip_dst; 729 730 *cmd_val = IP_FW_NOT_MATCH; 731 732 table_ctx = ctx->table_ctx; 733 table_ctx += cmd->arg1; 734 735 if (table_ctx->type != 0) { 736 rnh = table_ctx->node; 737 sa.sin_len = 8; 738 sa.sin_addr.s_addr = dst_ip.s_addr; 739 if(rnh->rnh_lookup((char *)&sa, NULL, rnh) != NULL) 740 *cmd_val = IP_FW_MATCH; 741 } 742 *cmd_ctl = IP_FW_CTL_NO; 743 } 744 745 void 746 check_to_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 747 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 748 { 749 struct in_addr dst_ip; 750 u_int hlen = 0; 751 struct mbuf *m = (*args)->m; 752 struct ip *ip = mtod(m, struct ip *); 753 dst_ip = ip->ip_src; 754 if ((*args)->eh == NULL || 755 (m->m_pkthdr.len >= sizeof(struct ip) && 756 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 757 hlen = ip->ip_hl << 2; 758 } 759 *cmd_ctl = IP_FW_CTL_NO; 760 if (hlen > 0) { 761 struct ifnet *tif; 762 tif = INADDR_TO_IFP(&dst_ip); 763 *cmd_val = (tif != NULL); 764 } else { 765 *cmd_val = IP_FW_NOT_MATCH; 766 } 767 } 768 769 void 770 check_to_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 771 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 772 { 773 struct in_addr dst_ip; 774 u_int hlen = 0; 775 struct mbuf *m = (*args)->m; 776 struct ip *ip = mtod(m, struct ip *); 777 dst_ip = ip->ip_src; 778 if ((*args)->eh == NULL || 779 (m->m_pkthdr.len >= sizeof(struct ip) && 780 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { 781 hlen = ip->ip_hl << 2; 782 } 783 784 *cmd_ctl = IP_FW_CTL_NO; 785 *cmd_val = (hlen > 0 && 786 ((ipfw_insn_ip *)cmd)->addr.s_addr == 787 (dst_ip.s_addr & 788 ((ipfw_insn_ip *)cmd)->mask.s_addr)); 789 } 790 791 void 792 check_keep_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 793 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 794 { 795 struct ip_fw_state *state; 796 int limited = 0; 797 798 *cmd_ctl = IP_FW_CTL_NO; 799 state = lookup_state(*args, cmd, &limited, 1); 800 if (limited == 1) { 801 *cmd_val = IP_FW_NOT_MATCH; 802 } else { 803 if (state == NULL) 804 state = install_state(*f, cmd, *args); 805 806 if (state != NULL) { 807 state->pcnt++; 808 state->bcnt += ip_len; 809 state->timestamp = time_second; 810 *cmd_val = IP_FW_MATCH; 811 } else { 812 *cmd_val = IP_FW_NOT_MATCH; 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 ifnet_forwardmsg(&nmsg->lmsg, 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 struct netmsg_base *msg; 1066 struct netmsg_base the_msg; 1067 msg = &the_msg; 1068 bzero(msg,sizeof(struct netmsg_base)); 1069 1070 netmsg_init(msg, NULL, &curthread->td_msgport, 0, 1071 ipfw_cleanup_expired_state); 1072 ifnet_domsg(&msg->lmsg, 0); 1073 } 1074 1075 static void 1076 ipfw_tick_dispatch(netmsg_t nmsg) 1077 { 1078 IPFW_ASSERT_CFGPORT(&curthread->td_msgport); 1079 KKASSERT(IPFW_BASIC_LOADED); 1080 1081 /* Reply ASAP */ 1082 crit_enter(); 1083 lwkt_replymsg(&nmsg->lmsg, 0); 1084 crit_exit(); 1085 1086 callout_reset(&ipfw_tick_callout, 1087 state_expiry_check_interval * hz, ipfw_tick, NULL); 1088 } 1089 1090 static void 1091 ipfw_basic_init_dispatch(netmsg_t nmsg) 1092 { 1093 IPFW_ASSERT_CFGPORT(&curthread->td_msgport); 1094 KKASSERT(IPFW3_LOADED); 1095 1096 int error = 0; 1097 callout_init_mp(&ipfw_tick_callout); 1098 netmsg_init(&ipfw_timeout_netmsg, NULL, &netisr_adone_rport, 1099 MSGF_DROPABLE | MSGF_PRIORITY, ipfw_tick_dispatch); 1100 callout_reset(&ipfw_tick_callout, 1101 state_expiry_check_interval * hz, ipfw_tick, NULL); 1102 lwkt_replymsg(&nmsg->lmsg, error); 1103 ip_fw_basic_loaded=1; 1104 } 1105 1106 static int 1107 ipfw_basic_init(void) 1108 { 1109 ipfw_basic_flush_state_prt = ipfw_basic_flush_state; 1110 ipfw_basic_append_state_prt = ipfw_basic_add_state; 1111 ipfw_sync_install_state_prt = ipfw_sync_install_state; 1112 1113 register_ipfw_module(MODULE_BASIC_ID, MODULE_BASIC_NAME); 1114 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_COUNT, 1115 (filter_func)check_count); 1116 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_SKIPTO, 1117 (filter_func)check_skipto); 1118 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_FORWARD, 1119 (filter_func)check_forward); 1120 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_KEEP_STATE, 1121 (filter_func)check_keep_state); 1122 register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_CHECK_STATE, 1123 (filter_func)check_check_state); 1124 1125 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1126 O_BASIC_IN, (filter_func)check_in); 1127 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1128 O_BASIC_OUT, (filter_func)check_out); 1129 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1130 O_BASIC_VIA, (filter_func)check_via); 1131 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1132 O_BASIC_XMIT, (filter_func)check_via); 1133 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1134 O_BASIC_RECV, (filter_func)check_via); 1135 1136 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1137 O_BASIC_PROTO, (filter_func)check_proto); 1138 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1139 O_BASIC_PROB, (filter_func)check_prob); 1140 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1141 O_BASIC_IP_SRC, (filter_func)check_from); 1142 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1143 O_BASIC_IP_SRC_LOOKUP, (filter_func)check_from_lookup); 1144 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1145 O_BASIC_IP_SRC_ME, (filter_func)check_from_me); 1146 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1147 O_BASIC_IP_SRC_MASK, (filter_func)check_from_mask); 1148 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1149 O_BASIC_IP_DST, (filter_func)check_to); 1150 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1151 O_BASIC_IP_DST_LOOKUP, (filter_func)check_to_lookup); 1152 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1153 O_BASIC_IP_DST_ME, (filter_func)check_to_me); 1154 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1155 O_BASIC_IP_DST_MASK, (filter_func)check_to_mask); 1156 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1157 O_BASIC_TAG, (filter_func)check_tag); 1158 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1159 O_BASIC_UNTAG, (filter_func)check_untag); 1160 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1161 O_BASIC_TAGGED, (filter_func)check_tagged); 1162 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1163 O_BASIC_IP_SRCPORT, (filter_func)check_src_port); 1164 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1165 O_BASIC_IP_DSTPORT, (filter_func)check_dst_port); 1166 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1167 O_BASIC_IP_SRC_N_PORT, (filter_func)check_src_n_port); 1168 register_ipfw_filter_funcs(MODULE_BASIC_ID, 1169 O_BASIC_IP_DST_N_PORT, (filter_func)check_dst_n_port); 1170 1171 int cpu; 1172 struct ipfw_context *ctx; 1173 1174 for (cpu = 0; cpu < ncpus; cpu++) { 1175 ctx = ipfw_ctx[cpu]; 1176 if (ctx != NULL) { 1177 ctx->state_ctx = kmalloc(state_hash_size * 1178 sizeof(struct ipfw_state_context), 1179 M_IPFW3_BASIC, M_WAITOK | M_ZERO); 1180 ctx->state_hash_size = state_hash_size; 1181 } 1182 } 1183 1184 struct netmsg_base smsg; 1185 netmsg_init(&smsg, NULL, &curthread->td_msgport, 1186 0, ipfw_basic_init_dispatch); 1187 lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0); 1188 return 0; 1189 } 1190 1191 static void 1192 ipfw_basic_stop_dispatch(netmsg_t nmsg) 1193 { 1194 IPFW_ASSERT_CFGPORT(&curthread->td_msgport); 1195 KKASSERT(IPFW3_LOADED); 1196 int error = 0; 1197 callout_stop(&ipfw_tick_callout); 1198 netmsg_service_sync(); 1199 crit_enter(); 1200 lwkt_dropmsg(&ipfw_timeout_netmsg.lmsg); 1201 crit_exit(); 1202 lwkt_replymsg(&nmsg->lmsg, error); 1203 ip_fw_basic_loaded=0; 1204 } 1205 1206 static int 1207 ipfw_basic_stop(void) 1208 { 1209 int cpu,i; 1210 struct ipfw_state_context *state_ctx; 1211 struct ip_fw_state *state,*the_state; 1212 struct ipfw_context *ctx; 1213 if (unregister_ipfw_module(MODULE_BASIC_ID) ==0 ) { 1214 ipfw_basic_flush_state_prt = NULL; 1215 ipfw_basic_append_state_prt = NULL; 1216 1217 for (cpu = 0; cpu < ncpus; cpu++) { 1218 ctx = ipfw_ctx[cpu]; 1219 if (ctx != NULL) { 1220 for (i = 0; i < state_hash_size; i++) { 1221 state_ctx = &ctx->state_ctx[i]; 1222 if (state_ctx != NULL) { 1223 state = state_ctx->state; 1224 while (state != NULL) { 1225 the_state = state; 1226 state = state->next; 1227 if (the_state == 1228 state_ctx->last) 1229 state_ctx->last = NULL; 1230 1231 kfree(the_state, 1232 M_IPFW3_BASIC); 1233 } 1234 } 1235 } 1236 ctx->state_hash_size = 0; 1237 kfree(ctx->state_ctx, M_IPFW3_BASIC); 1238 ctx->state_ctx = NULL; 1239 } 1240 } 1241 struct netmsg_base smsg; 1242 netmsg_init(&smsg, NULL, &curthread->td_msgport, 1243 0, ipfw_basic_stop_dispatch); 1244 return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0); 1245 } 1246 return 1; 1247 } 1248 1249 1250 static int 1251 ipfw3_basic_modevent(module_t mod, int type, void *data) 1252 { 1253 int err; 1254 switch (type) { 1255 case MOD_LOAD: 1256 err = ipfw_basic_init(); 1257 break; 1258 case MOD_UNLOAD: 1259 err = ipfw_basic_stop(); 1260 break; 1261 default: 1262 err = 1; 1263 } 1264 return err; 1265 } 1266 1267 static moduledata_t ipfw3_basic_mod = { 1268 "ipfw3_basic", 1269 ipfw3_basic_modevent, 1270 NULL 1271 }; 1272 DECLARE_MODULE(ipfw3_basic, ipfw3_basic_mod, SI_SUB_PROTO_END, SI_ORDER_ANY); 1273 MODULE_DEPEND(ipfw3_basic, ipfw3, 1, 1, 1); 1274 MODULE_VERSION(ipfw3_basic, 1); 1275