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