2 * Copyright (c) 1993 Daniel Boulet
3 * Copyright (c) 1994 Ugen J.S.Antsilevich
4 * Copyright (c) 2002 Luigi Rizzo, Universita` di Pisa
5 * Copyright (c) 2014 - 2018 The DragonFly Project. All rights reserved.
7 * This code is derived from software contributed to The DragonFly Project
8 * by Bill Yuan <bycn82@dragonflybsd.org>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
20 * 3. Neither the name of The DragonFly Project nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific, prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 #error IPFIREWALL3 requires INET.
45 #include <sys/param.h>
46 #include <sys/kernel.h>
47 #include <sys/malloc.h>
49 #include <sys/socketvar.h>
50 #include <sys/sysctl.h>
51 #include <sys/systimer.h>
52 #include <sys/thread2.h>
53 #include <sys/in_cksum.h>
54 #include <sys/systm.h>
56 #include <sys/socket.h>
57 #include <sys/syslog.h>
58 #include <sys/ucred.h>
60 #include <sys/mplock2.h>
63 #include <net/radix.h>
64 #include <net/route.h>
66 #include <net/netmsg2.h>
68 #include <netinet/in.h>
69 #include <netinet/in_systm.h>
70 #include <netinet/in_var.h>
71 #include <netinet/in_pcb.h>
72 #include <netinet/ip.h>
73 #include <netinet/ip_var.h>
74 #include <netinet/ip_icmp.h>
75 #include <netinet/tcp.h>
76 #include <netinet/tcp_timer.h>
77 #include <netinet/tcp_var.h>
78 #include <netinet/tcpip.h>
79 #include <netinet/udp.h>
80 #include <netinet/udp_var.h>
81 #include <netinet/ip_divert.h>
82 #include <netinet/if_ether.h>
84 #include <net/ipfw3/ip_fw.h>
85 #include <net/ipfw3/ip_fw3_set.h>
86 #include <net/ipfw3_basic/ip_fw3_log.h>
87 #include <net/ipfw3_basic/ip_fw3_table.h>
88 #include <net/ipfw3_basic/ip_fw3_sync.h>
89 #include <net/ipfw3_basic/ip_fw3_basic.h>
90 #include <net/ipfw3_basic/ip_fw3_state.h>
91 #include <net/ipfw3_nat/ip_fw3_nat.h>
92 #include <net/dummynet3/ip_dummynet3.h>
94 MALLOC_DEFINE(M_IPFW3, "IPFW3", "ipfw3 module");
97 #define MAX_OPCODE_PER_MODULE 100
99 #define IPFW_AUTOINC_STEP_MIN 1
100 #define IPFW_AUTOINC_STEP_MAX 1000
101 #define IPFW_AUTOINC_STEP_DEF 100
105 struct netmsg_base base;
106 const struct ipfw_ioc_rule *ioc_rule;
108 struct ip_fw *next_rule;
109 struct ip_fw *prev_rule;
110 struct ip_fw *sibling; /* sibling in prevous CPU */
114 struct netmsg_base base;
116 struct ip_fw *start_rule;
117 struct ip_fw *prev_rule;
118 struct ipfw_ioc_state *ioc_state;
126 struct netmsg_base base;
127 struct ip_fw *start_rule;
132 ip_fw_ctl_t *ip_fw3_ctl_nat_ptr = NULL;
133 ip_fw_ctl_t *ip_fw3_ctl_state_ptr = NULL;
134 ip_fw_ctl_t *ip_fw3_ctl_table_ptr = NULL;
135 ip_fw_ctl_t *ip_fw3_ctl_sync_ptr = NULL;
136 ip_fw_log_t *ip_fw3_log_ptr = NULL;
138 extern int ip_fw_loaded;
139 extern struct ipfw3_state_context *fw3_state_ctx[MAXCPU];
140 int sysctl_var_fw3_enable = 1;
141 int sysctl_var_fw3_one_pass = 1;
142 int sysctl_var_fw3_verbose = 0;
143 static int sysctl_var_fw3_flushing;
144 static int sysctl_var_fw3_debug;
145 static int sysctl_var_autoinc_step = IPFW_AUTOINC_STEP_DEF;
147 int ip_fw3_sysctl_enable(SYSCTL_HANDLER_ARGS);
148 int ip_fw3_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS);
150 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw3, CTLFLAG_RW, 0, "Firewall");
151 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, enable, CTLTYPE_INT | CTLFLAG_RW,
152 &sysctl_var_fw3_enable, 0, ip_fw3_sysctl_enable, "I", "Enable ipfw");
153 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, sysctl_var_autoinc_step,
154 CTLTYPE_INT | CTLFLAG_RW, &sysctl_var_autoinc_step, 0,
155 ip_fw3_sysctl_autoinc_step, "I", "Rule number autincrement step");
156 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO,one_pass,CTLFLAG_RW,
157 &sysctl_var_fw3_one_pass, 0,
158 "Only do a single pass through ipfw3 when using dummynet(4)");
159 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, debug, CTLFLAG_RW,
160 &sysctl_var_fw3_debug, 0, "Enable printing of debug ip_fw statements");
161 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, verbose, CTLFLAG_RW,
162 &sysctl_var_fw3_verbose, 0, "Log matches to ipfw3 rules");
165 filter_func filter_funcs[MAX_MODULE][MAX_OPCODE_PER_MODULE];
166 struct ipfw3_module fw3_modules[MAX_MODULE];
167 struct ipfw3_context *fw3_ctx[MAXCPU];
168 struct ipfw3_sync_context fw3_sync_ctx;
172 ip_fw3_register_module(int module_id,char *module_name)
174 struct ipfw3_module *tmp;
178 for (i=0; i < MAX_MODULE; i++) {
179 if (tmp->type == 0) {
182 strncpy(tmp->name, module_name, strlen(module_name));
187 kprintf("ipfw3 module %s loaded\n", module_name);
191 ip_fw3_unregister_module(int module_id)
193 struct ipfw3_module *tmp;
196 int i, len, cmdlen, found;
200 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
202 for (; fw; fw = fw->next) {
203 for (len = fw->cmd_len, cmd = fw->cmd; len > 0;
205 cmd = (ipfw_insn *)((uint32_t *)cmd + cmdlen)) {
207 if (cmd->module == 0 &&
208 (cmd->opcode == 0 || cmd->opcode == 1)) {
209 //action accept or deny
210 } else if (cmd->module == module_id) {
220 for (i = 0; i < MAX_MODULE; i++) {
221 if (tmp->type == 1 && tmp->id == module_id) {
223 kprintf("ipfw3 module %s unloaded\n",
230 for (i = 0; i < MAX_OPCODE_PER_MODULE; i++) {
231 if (module_id == 0) {
232 if (i ==0 || i == 1) {
236 filter_funcs[module_id][i] = NULL;
243 ip_fw3_register_filter_funcs(int module, int opcode, filter_func func)
245 filter_funcs[module][opcode] = func;
249 check_accept(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
250 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
252 *cmd_val = IP_FW_PASS;
253 *cmd_ctl = IP_FW_CTL_DONE;
254 if (cmd->arg3 && ip_fw3_log_ptr != NULL) {
255 ip_fw3_log_ptr((*args)->m, (*args)->eh, cmd->arg1);
260 check_deny(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
261 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
263 *cmd_val = IP_FW_DENY;
264 *cmd_ctl = IP_FW_CTL_DONE;
265 if (cmd->arg3 && ip_fw3_log_ptr != NULL) {
266 ip_fw3_log_ptr((*args)->m, (*args)->eh, cmd->arg1);
273 memset(fw3_modules, 0, sizeof(struct ipfw3_module) * MAX_MODULE);
274 memset(filter_funcs, 0, sizeof(filter_func) *
275 MAX_OPCODE_PER_MODULE * MAX_MODULE);
276 ip_fw3_register_filter_funcs(0, O_BASIC_ACCEPT,
277 (filter_func)check_accept);
278 ip_fw3_register_filter_funcs(0, O_BASIC_DENY, (filter_func)check_deny);
282 ip_fw3_free_rule(struct ip_fw *rule)
284 kfree(rule, M_IPFW3);
289 static struct ip_fw *
290 lookup_next_rule(struct ip_fw *me)
292 struct ip_fw *rule = NULL;
295 /* look for action, in case it is a skipto */
296 cmd = ACTION_PTR(me);
297 if ((int)cmd->module == MODULE_BASIC_ID &&
298 (int)cmd->opcode == O_BASIC_SKIPTO) {
299 for (rule = me->next; rule; rule = rule->next) {
300 if (rule->rulenum >= cmd->arg1)
304 if (rule == NULL) { /* failure or not a skipto */
307 me->next_rule = rule;
312 * rules are stored in ctx->ipfw_rule_chain.
313 * and each rule is combination of multiple cmds.(ipfw_insn)
314 * in each rule, it begin with filter cmds. and end with action cmds.
315 * 'outer/inner loop' are looping the rules/cmds.
316 * it will invoke the cmds relatived function according to the cmd's
317 * module id and opcode id. and process according to return value.
320 ip_fw3_chk(struct ip_fw_args *args)
326 struct mbuf *m = args->m;
327 struct ip *ip = mtod(m, struct ip *);
328 struct ip_fw *f = NULL; /* matching rule */
329 int cmd_val = IP_FW_PASS;
331 struct divert_info *divinfo;
334 * hlen The length of the IPv4 header.
335 * hlen >0 means we have an IPv4 packet.
337 u_int hlen = 0; /* hlen >0 means we have an IP pkt */
340 * offset The offset of a fragment. offset != 0 means that
341 * we have a fragment at this offset of an IPv4 packet.
342 * offset == 0 means that (if this is an IPv4 packet)
343 * this is the first or only fragment.
348 uint16_t src_port = 0, dst_port = 0; /* NOTE: host format */
349 struct in_addr src_ip, dst_ip; /* NOTE: network format */
351 uint8_t prev_module = -1, prev_opcode = -1; /* previous module & opcode */
352 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
354 if (m->m_pkthdr.fw_flags & IPFW_MBUF_GENERATED)
355 return IP_FW_PASS; /* accept */
357 if (args->eh == NULL || /* layer 3 packet */
358 (m->m_pkthdr.len >= sizeof(struct ip) &&
359 ntohs(args->eh->ether_type) == ETHERTYPE_IP))
360 hlen = ip->ip_hl << 2;
363 * Collect parameters into local variables for faster matching.
365 if (hlen == 0) { /* do not grab addresses for non-ip pkts */
366 proto = args->f_id.proto = 0; /* mark f_id invalid */
367 goto after_ip_checks;
370 proto = args->f_id.proto = ip->ip_p;
373 if (args->eh != NULL) { /* layer 2 packets are as on the wire */
374 offset = ntohs(ip->ip_off) & IP_OFFMASK;
375 ip_len = ntohs(ip->ip_len);
377 offset = ip->ip_off & IP_OFFMASK;
381 #define PULLUP_TO(len) \
383 if (m->m_len < (len)) { \
384 args->m = m = m_pullup(m, (len)); \
386 goto pullup_failed; \
387 ip = mtod(m, struct ip *); \
394 PULLUP_TO(hlen + sizeof(struct tcphdr));
395 tcp = L3HDR(struct tcphdr, ip);
396 dst_port = tcp->th_dport;
397 src_port = tcp->th_sport;
398 args->f_id.flags = tcp->th_flags;
401 PULLUP_TO(hlen + sizeof(struct udphdr));
402 udp = L3HDR(struct udphdr, ip);
403 dst_port = udp->uh_dport;
404 src_port = udp->uh_sport;
408 icmp = L3HDR(struct icmp, ip);
409 args->f_id.flags = icmp->icmp_type;
410 dst_port = icmp->icmp_id;
420 args->f_id.src_ip = ntohl(src_ip.s_addr);
421 args->f_id.dst_ip = ntohl(dst_ip.s_addr);
422 args->f_id.src_port = src_port = ntohs(src_port);
423 args->f_id.dst_port = dst_port = ntohs(dst_port);
428 * Packet has already been tagged. Look for the next rule
429 * to restart processing.
431 * If sysctl_var_fw3_one_pass != 0 then just accept it.
432 * XXX should not happen here, but optimized out in
435 if (sysctl_var_fw3_one_pass)
438 /* This rule is being/has been flushed */
439 if (sysctl_var_fw3_flushing)
442 f = args->rule->next_rule;
444 f = lookup_next_rule(args->rule);
447 * Find the starting rule. It can be either the first
448 * one, or the one after divert_rule if asked so.
452 mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
454 divinfo = m_tag_data(mtag);
455 skipto = divinfo->skipto;
461 if (args->eh == NULL && skipto != 0) {
462 /* No skipto during rule flushing */
463 if (sysctl_var_fw3_flushing) {
466 if (skipto >= IPFW_DEFAULT_RULE) {
467 return IP_FW_DENY; /* invalid */
469 while (f && f->rulenum <= skipto) {
472 if (f == NULL) { /* drop packet */
475 } else if (sysctl_var_fw3_flushing) {
476 /* Rules are being flushed; skip to default rule */
477 f = ctx->default_rule;
480 if ((mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL)) != NULL) {
481 m_tag_delete(m, mtag);
485 * Now scan the rules, and parse microinstructions for each rule.
487 int prev_val; /* previous result of 'or' filter */
491 /* foreach rule in chain */
492 for (; f; f = f->next) {
493 again: /* check the rule again*/
494 if (ctx->sets & (1 << f->set)) {
499 /* foreach cmd in rule */
500 for (l = f->cmd_len, cmd = f->cmd; l > 0; l -= cmdlen,
501 cmd = (ipfw_insn *)((uint32_t *)cmd+ cmdlen)) {
504 /* skip 'or' filter when already match */
505 if (cmd->len & F_OR &&
506 cmd->module == prev_module &&
507 cmd->opcode == prev_opcode &&
512 check_body: /* check the body of the rule again.*/
513 (filter_funcs[cmd->module][cmd->opcode])
514 (&cmd_ctl, &cmd_val, &args, &f, cmd, ip_len);
517 if (prev_val == 0) /* but 'or' failed */
520 case IP_FW_CTL_AGAIN:
527 case IP_FW_CTL_CHK_STATE:
528 /* update the cmd and l */
530 l = f->cmd_len - f->act_ofs;
533 if (cmd->len & F_NOT)
536 if (cmd->len & F_OR) { /* has 'or' */
537 if (!cmd_val) { /* not matched */
538 if(prev_val == -1){ /* first 'or' */
540 prev_module = cmd->module;
541 prev_opcode = cmd->opcode;
542 } else if (prev_module == cmd->module &&
543 prev_opcode == cmd->opcode) {
544 /* continuous 'or' filter */
545 } else if (prev_module != cmd->module ||
546 prev_opcode != cmd->opcode) {
547 /* 'or' filter changed */
552 prev_module = cmd->module;
553 prev_opcode = cmd->opcode;
556 } else { /* has 'or' and matched */
558 prev_module = cmd->module;
559 prev_opcode = cmd->opcode;
562 if (!cmd_val) { /* not matched */
566 /* previous 'or' not matched */
574 } /* end of inner for, scan opcodes */
575 next_rule:; /* try next rule */
576 } /* end of outer for, scan rules */
577 kprintf("+++ ipfw: ouch!, skip past end of rules, denying packet\n");
581 /* Update statistics */
584 f->timestamp = time_second;
588 if (sysctl_var_fw3_verbose)
589 kprintf("pullup failed\n");
594 ip_fw3_dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa)
599 const struct ipfw_flow_id *id;
600 struct dn_flow_id *fid;
604 mtag = m_tag_get(PACKET_TAG_DUMMYNET, sizeof(*pkt),
605 M_INTWAIT | M_NULLOK);
610 m_tag_prepend(m, mtag);
612 pkt = m_tag_data(mtag);
613 bzero(pkt, sizeof(*pkt));
615 cmd = (ipfw_insn *)((uint32_t *)fwa->rule->cmd + fwa->rule->act_ofs);
616 KASSERT(cmd->opcode == O_DUMMYNET_PIPE ||
617 cmd->opcode == O_DUMMYNET_QUEUE,
618 ("Rule is not PIPE or QUEUE, opcode %d", cmd->opcode));
621 pkt->dn_flags = (dir & DN_FLAGS_DIR_MASK);
623 pkt->pipe_nr = pipe_nr;
625 pkt->cpuid = mycpuid;
626 pkt->msgport = netisr_curport();
630 fid->fid_dst_ip = id->dst_ip;
631 fid->fid_src_ip = id->src_ip;
632 fid->fid_dst_port = id->dst_port;
633 fid->fid_src_port = id->src_port;
634 fid->fid_proto = id->proto;
635 fid->fid_flags = id->flags;
637 pkt->dn_priv = fwa->rule;
639 if ((int)cmd->opcode == O_DUMMYNET_PIPE)
640 pkt->dn_flags |= DN_FLAGS_IS_PIPE;
642 m->m_pkthdr.fw_flags |= DUMMYNET_MBUF_TAGGED;
648 add_rule_dispatch(netmsg_t nmsg)
650 struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
651 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
652 struct ip_fw *rule, *prev,*next;
653 const struct ipfw_ioc_rule *ioc_rule;
655 ioc_rule = fwmsg->ioc_rule;
656 // create rule by ioc_rule
657 rule = kmalloc(RULESIZE(ioc_rule), M_IPFW3, M_WAITOK | M_ZERO);
658 rule->act_ofs = ioc_rule->act_ofs;
659 rule->cmd_len = ioc_rule->cmd_len;
660 rule->rulenum = ioc_rule->rulenum;
661 rule->set = ioc_rule->set;
662 bcopy(ioc_rule->cmd, rule->cmd, rule->cmd_len * 4);
664 for (prev = NULL, next = ctx->rules;
665 next; prev = next, next = next->next) {
666 if (next->rulenum > ioc_rule->rulenum) {
670 KASSERT(next != NULL, ("no default rule?!"));
673 * Insert rule into the pre-determined position
679 rule->next = ctx->rules;
684 * if sibiling in last CPU is exists,
685 * then it's sibling should be current rule
687 if (fwmsg->sibling != NULL) {
688 fwmsg->sibling->sibling = rule;
690 /* prepare for next CPU */
691 fwmsg->sibling = rule;
693 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
697 * confirm the rulenumber
698 * call dispatch function to add rule into the list
699 * Update the statistic
702 ip_fw3_add_rule(struct ipfw_ioc_rule *ioc_rule)
704 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
705 struct netmsg_ipfw fwmsg;
706 struct netmsg_base *nmsg;
709 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
712 * If rulenum is 0, find highest numbered rule before the
713 * default rule, and add rule number incremental step.
715 if (ioc_rule->rulenum == 0) {
716 int step = sysctl_var_autoinc_step;
718 KKASSERT(step >= IPFW_AUTOINC_STEP_MIN &&
719 step <= IPFW_AUTOINC_STEP_MAX);
722 * Locate the highest numbered rule before default
724 for (f = ctx->rules; f; f = f->next) {
725 if (f->rulenum == IPFW_DEFAULT_RULE)
727 ioc_rule->rulenum = f->rulenum;
729 if (ioc_rule->rulenum < IPFW_DEFAULT_RULE - step)
730 ioc_rule->rulenum += step;
732 KASSERT(ioc_rule->rulenum != IPFW_DEFAULT_RULE &&
733 ioc_rule->rulenum != 0,
734 ("invalid rule num %d", ioc_rule->rulenum));
736 bzero(&fwmsg, sizeof(fwmsg));
738 netmsg_init(nmsg, NULL, &curthread->td_msgport,
739 0, add_rule_dispatch);
740 fwmsg.ioc_rule = ioc_rule;
742 netisr_domsg(nmsg, 0);
744 IPFW3_DEBUG("++ installed rule %d, static count now %d\n",
745 ioc_rule->rulenum, static_count);
749 * Free storage associated with a static rule (including derived
751 * The caller is in charge of clearing rule pointers to avoid
753 * @return a pointer to the next entry.
754 * Arguments are not checked, so they better be correct.
755 * Must be called at splimp().
758 ip_fw3_delete_rule(struct ipfw3_context *ctx,
759 struct ip_fw *prev, struct ip_fw *rule)
762 ctx->rules = rule->next;
764 prev->next = rule->next;
766 kfree(rule, M_IPFW3);
772 flush_rule_dispatch(netmsg_t nmsg)
774 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
775 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
776 struct ip_fw *rule, *the_rule;
777 int kill_default = dmsg->kill_default;
780 while (rule != NULL) {
781 if (rule->rulenum == IPFW_DEFAULT_RULE && kill_default == 0) {
788 kfree(the_rule, M_IPFW3);
791 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
796 * Deletes all rules from a chain (including the default rule
797 * if the second argument is set).
798 * Must be called at splimp().
801 ip_fw3_ctl_flush_rule(int kill_default)
803 struct netmsg_del dmsg;
805 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
808 sysctl_var_fw3_flushing = 1;
809 netmsg_service_sync();
812 * Press the 'flush' button
814 bzero(&dmsg, sizeof(dmsg));
815 netmsg_init(&dmsg.base, NULL, &curthread->td_msgport,
816 0, flush_rule_dispatch);
817 dmsg.kill_default = kill_default;
818 netisr_domsg(&dmsg.base, 0);
821 sysctl_var_fw3_flushing = 0;
825 delete_rule_dispatch(netmsg_t nmsg)
827 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
828 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
829 struct ip_fw *rule, *prev = NULL;
833 if (rule->rulenum == dmsg->rulenum) {
834 ip_fw3_delete_rule(ctx, prev, rule);
841 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
845 ip_fw3_ctl_delete_rule(struct sockopt *sopt)
847 struct netmsg_del dmsg;
848 struct netmsg_base *nmsg;
851 rulenum = (int *) sopt->sopt_val;
855 * Get rid of the rule duplications on all CPUs
857 bzero(&dmsg, sizeof(dmsg));
859 netmsg_init(nmsg, NULL, &curthread->td_msgport,
860 0, delete_rule_dispatch);
861 dmsg.rulenum = *rulenum;
862 netisr_domsg(nmsg, 0);
867 * Clear counters for a specific rule.
870 ip_fw3_clear_counters(struct ip_fw *rule)
872 rule->bcnt = rule->pcnt = 0;
877 ip_fw3_zero_entry_dispatch(netmsg_t nmsg)
879 struct netmsg_zent *zmsg = (struct netmsg_zent *)nmsg;
880 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
883 if (zmsg->rulenum == 0) {
884 for (rule = ctx->rules; rule; rule = rule->next) {
885 ip_fw3_clear_counters(rule);
888 for (rule = ctx->rules; rule; rule = rule->next) {
889 if (rule->rulenum == zmsg->rulenum) {
890 ip_fw3_clear_counters(rule);
894 ip_fw3_clear_counters(ctx->default_rule);
895 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
899 * Reset some or all counters on firewall rules.
900 * @arg frwl is null to clear all entries, or contains a specific
902 * @arg log_only is 1 if we only want to reset logs, zero otherwise.
905 ip_fw3_ctl_zero_entry(int rulenum, int log_only)
907 struct netmsg_zent zmsg;
908 struct netmsg_base *nmsg;
910 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
912 bzero(&zmsg, sizeof(zmsg));
914 netmsg_init(nmsg, NULL, &curthread->td_msgport,
915 0, ip_fw3_zero_entry_dispatch);
916 zmsg.log_only = log_only;
919 msg = log_only ? "ipfw: All logging counts reset.\n"
920 : "ipfw: Accounting cleared.\n";
925 * Locate the first rule with 'rulenum'
927 for (rule = ctx->rules; rule; rule = rule->next) {
928 if (rule->rulenum == rulenum)
931 if (rule == NULL) /* we did not find any matching rules */
933 zmsg.start_rule = rule;
934 zmsg.rulenum = rulenum;
936 msg = log_only ? "ipfw: Entry %d logging count reset.\n"
937 : "ipfw: Entry %d cleared.\n";
939 netisr_domsg(nmsg, 0);
940 KKASSERT(zmsg.start_rule == NULL);
942 if (sysctl_var_fw3_verbose)
943 log(LOG_SECURITY | LOG_NOTICE, msg, rulenum);
948 * Get the ioc_rule from the sopt
949 * call ip_fw3_add_rule to add the rule
952 ip_fw3_ctl_add_rule(struct sockopt *sopt)
954 struct ipfw_ioc_rule *ioc_rule;
957 size = sopt->sopt_valsize;
958 if (size > (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX) ||
959 size < sizeof(*ioc_rule)) {
962 if (size != (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX)) {
963 sopt->sopt_val = krealloc(sopt->sopt_val, sizeof(uint32_t) *
964 IPFW_RULE_SIZE_MAX, M_TEMP, M_WAITOK);
966 ioc_rule = sopt->sopt_val;
968 ip_fw3_add_rule(ioc_rule);
973 ip_fw3_ctl_get_modules(struct sockopt *sopt)
976 struct ipfw3_module *mod;
977 char module_str[1024];
978 memset(module_str,0,1024);
979 for (i = 0, mod = fw3_modules; i < MAX_MODULE; i++, mod++) {
980 if (mod->type != 0) {
982 strcat(module_str,",");
983 strcat(module_str,mod->name);
986 bzero(sopt->sopt_val, sopt->sopt_valsize);
987 bcopy(module_str, sopt->sopt_val, strlen(module_str));
988 sopt->sopt_valsize = strlen(module_str);
993 * Copy all static rules and states on all CPU
996 ip_fw3_ctl_get_rules(struct sockopt *sopt)
998 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
1000 struct ipfw_ioc_rule *ioc;
1001 const struct ip_fw *sibling;
1004 ioc = (struct ipfw_ioc_rule *)sopt->sopt_val;
1006 for (rule = ctx->rules; rule; rule = rule->next) {
1007 total_len += IOC_RULESIZE(rule);
1008 if (total_len > sopt->sopt_valsize) {
1009 bzero(sopt->sopt_val, sopt->sopt_valsize);
1012 ioc->act_ofs = rule->act_ofs;
1013 ioc->cmd_len = rule->cmd_len;
1014 ioc->rulenum = rule->rulenum;
1015 ioc->set = rule->set;
1017 ioc->sets = fw3_ctx[mycpuid]->sets;
1021 for (sibling = rule; sibling != NULL; sibling = sibling->sibling) {
1022 ioc->pcnt += sibling->pcnt;
1023 ioc->bcnt += sibling->bcnt;
1024 if (sibling->timestamp > ioc->timestamp)
1025 ioc->timestamp = sibling->timestamp;
1027 bcopy(rule->cmd, ioc->cmd, ioc->cmd_len * 4);
1028 ioc = (struct ipfw_ioc_rule *)((uint8_t *)ioc + IOC_RULESIZE(ioc));
1030 sopt->sopt_valsize = total_len;
1036 * ip_fw3_ctl_x - extended version of ip_fw3_ctl
1037 * remove the x_header, and adjust the sopt_name,sopt_val and sopt_valsize.
1040 ip_fw3_ctl_x(struct sockopt *sopt)
1042 ip_fw_x_header *x_header;
1043 x_header = (ip_fw_x_header *)(sopt->sopt_val);
1044 sopt->sopt_name = x_header->opcode;
1045 sopt->sopt_valsize -= sizeof(ip_fw_x_header);
1046 bcopy(++x_header, sopt->sopt_val, sopt->sopt_valsize);
1047 return ip_fw3_ctl(sopt);
1052 * {set|get}sockopt parser.
1055 ip_fw3_ctl(struct sockopt *sopt)
1058 switch (sopt->sopt_name) {
1068 case IP_FW_RESETLOG:
1069 error = ip_fw3_ctl_sockopt(sopt);
1072 case IP_FW_SET_MOVE_RULE:
1073 case IP_FW_SET_MOVE_SET:
1074 case IP_FW_SET_SWAP:
1075 case IP_FW_SET_TOGGLE:
1076 error = ip_fw3_ctl_set_sockopt(sopt);
1080 case IP_FW_NAT_FLUSH:
1082 case IP_FW_NAT_GET_RECORD:
1083 if (ip_fw3_ctl_nat_ptr != NULL) {
1084 error = ip_fw3_ctl_nat_ptr(sopt);
1087 case IP_DUMMYNET_GET:
1088 case IP_DUMMYNET_CONFIGURE:
1089 case IP_DUMMYNET_DEL:
1090 case IP_DUMMYNET_FLUSH:
1091 error = ip_dn_sockopt(sopt);
1093 case IP_FW_STATE_ADD:
1094 case IP_FW_STATE_DEL:
1095 case IP_FW_STATE_FLUSH:
1096 case IP_FW_STATE_GET:
1097 if (ip_fw3_ctl_state_ptr != NULL) {
1098 error = ip_fw3_ctl_state_ptr(sopt);
1101 case IP_FW_TABLE_CREATE:
1102 case IP_FW_TABLE_DELETE:
1103 case IP_FW_TABLE_APPEND:
1104 case IP_FW_TABLE_REMOVE:
1105 case IP_FW_TABLE_LIST:
1106 case IP_FW_TABLE_FLUSH:
1107 case IP_FW_TABLE_SHOW:
1108 case IP_FW_TABLE_TEST:
1109 case IP_FW_TABLE_RENAME:
1110 if (ip_fw3_ctl_table_ptr != NULL) {
1111 error = ip_fw3_ctl_table_ptr(sopt);
1114 case IP_FW_SYNC_SHOW_CONF:
1115 case IP_FW_SYNC_SHOW_STATUS:
1116 case IP_FW_SYNC_EDGE_CONF:
1117 case IP_FW_SYNC_EDGE_START:
1118 case IP_FW_SYNC_EDGE_STOP:
1119 case IP_FW_SYNC_EDGE_TEST:
1120 case IP_FW_SYNC_EDGE_CLEAR:
1121 case IP_FW_SYNC_CENTRE_CONF:
1122 case IP_FW_SYNC_CENTRE_START:
1123 case IP_FW_SYNC_CENTRE_STOP:
1124 case IP_FW_SYNC_CENTRE_TEST:
1125 case IP_FW_SYNC_CENTRE_CLEAR:
1126 if (ip_fw3_ctl_sync_ptr != NULL) {
1127 error = ip_fw3_ctl_sync_ptr(sopt);
1131 kprintf("ip_fw3_ctl invalid option %d\n",
1139 ip_fw3_ctl_sockopt(struct sockopt *sopt)
1141 int error = 0, rulenum;
1143 switch (sopt->sopt_name) {
1145 error = ip_fw3_ctl_get_rules(sopt);
1148 error = ip_fw3_ctl_get_modules(sopt);
1151 ip_fw3_ctl_flush_rule(0);
1154 error = ip_fw3_ctl_add_rule(sopt);
1157 error = ip_fw3_ctl_delete_rule(sopt);
1160 case IP_FW_RESETLOG: /* argument is an int, the rule number */
1162 if (sopt->sopt_valsize != 0) {
1163 error = soopt_to_kbuf(sopt, &rulenum,
1164 sizeof(int), sizeof(int));
1169 error = ip_fw3_ctl_zero_entry(rulenum,
1170 sopt->sopt_name == IP_FW_RESETLOG);
1173 kprintf("ip_fw3_ctl invalid option %d\n",
1181 ip_fw3_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1183 struct ip_fw_args args;
1184 struct mbuf *m = *m0;
1186 int tee = 0, error = 0, ret;
1188 if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1189 /* Extract info from dummynet tag */
1190 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1191 KKASSERT(mtag != NULL);
1192 args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1193 KKASSERT(args.rule != NULL);
1195 m_tag_delete(m, mtag);
1196 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1204 ret = ip_fw3_chk(&args);
1221 case IP_FW_DUMMYNET:
1222 /* Send packet to the appropriate pipe */
1223 m = ip_fw3_dummynet_io(m, args.cookie, DN_TO_IP_IN,
1231 * Must clear bridge tag when changing
1233 m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED;
1234 if (ip_divert_p != NULL) {
1235 m = ip_divert_p(m, tee, 1);
1239 /* not sure this is the right error msg */
1248 panic("unknown ipfw3 return value: %d", ret);
1256 ip_fw3_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1258 struct ip_fw_args args;
1259 struct mbuf *m = *m0;
1261 int tee = 0, error = 0, ret;
1263 if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1264 /* Extract info from dummynet tag */
1265 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1266 KKASSERT(mtag != NULL);
1267 args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1268 KKASSERT(args.rule != NULL);
1270 m_tag_delete(m, mtag);
1271 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1279 ret = ip_fw3_chk(&args);
1297 case IP_FW_DUMMYNET:
1298 m = ip_fw3_dummynet_io(m, args.cookie, DN_TO_IP_OUT,
1307 if (ip_divert_p != NULL) {
1308 m = ip_divert_p(m, tee, 0);
1312 /* not sure this is the right error msg */
1322 panic("unknown ipfw3 return value: %d", ret);
1332 struct pfil_head *pfh;
1333 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1335 pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1339 pfil_add_hook(ip_fw3_check_in, NULL, PFIL_IN, pfh);
1340 pfil_add_hook(ip_fw3_check_out, NULL, PFIL_OUT, pfh);
1346 struct pfil_head *pfh;
1348 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1350 pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1354 pfil_remove_hook(ip_fw3_check_in, NULL, PFIL_IN, pfh);
1355 pfil_remove_hook(ip_fw3_check_out, NULL, PFIL_OUT, pfh);
1359 ip_fw3_sysctl_enable_dispatch(netmsg_t nmsg)
1361 struct lwkt_msg *lmsg = &nmsg->lmsg;
1362 int enable = lmsg->u.ms_result;
1364 if (sysctl_var_fw3_enable == enable)
1367 sysctl_var_fw3_enable = enable;
1368 if (sysctl_var_fw3_enable)
1374 lwkt_replymsg(lmsg, 0);
1378 ip_fw3_sysctl_enable(SYSCTL_HANDLER_ARGS)
1380 struct netmsg_base nmsg;
1381 struct lwkt_msg *lmsg;
1384 enable = sysctl_var_fw3_enable;
1385 error = sysctl_handle_int(oidp, &enable, 0, req);
1386 if (error || req->newptr == NULL)
1389 netmsg_init(&nmsg, NULL, &curthread->td_msgport,
1390 0, ip_fw3_sysctl_enable_dispatch);
1392 lmsg->u.ms_result = enable;
1394 return lwkt_domsg(IPFW_CFGPORT, lmsg, 0);
1398 ip_fw3_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS)
1400 return sysctl_int_range(oidp, arg1, arg2, req,
1401 IPFW_AUTOINC_STEP_MIN, IPFW_AUTOINC_STEP_MAX);
1405 ctx_init_dispatch(netmsg_t nmsg)
1407 struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
1408 struct ipfw3_context *ctx;
1409 struct ip_fw *def_rule;
1411 ctx = kmalloc(LEN_FW3_CTX, M_IPFW3, M_WAITOK | M_ZERO);
1412 fw3_ctx[mycpuid] = ctx;
1413 ctx->sets = IPFW_ALL_SETS;
1415 def_rule = kmalloc(LEN_FW3, M_IPFW3, M_WAITOK | M_ZERO);
1416 def_rule->act_ofs = 0;
1417 def_rule->rulenum = IPFW_DEFAULT_RULE;
1418 def_rule->cmd_len = 2;
1419 def_rule->set = IPFW_DEFAULT_SET;
1421 def_rule->cmd[0].len = LEN_OF_IPFWINSN;
1422 def_rule->cmd[0].module = MODULE_BASIC_ID;
1423 #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
1424 def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1426 if (filters_default_to_accept)
1427 def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1429 def_rule->cmd[0].opcode = O_BASIC_DENY;
1432 /* Install the default rule */
1433 ctx->default_rule = def_rule;
1434 ctx->rules = def_rule;
1437 * if sibiling in last CPU is exists,
1438 * then it's sibling should be current rule
1440 if (fwmsg->sibling != NULL) {
1441 fwmsg->sibling->sibling = def_rule;
1443 /* prepare for next CPU */
1444 fwmsg->sibling = def_rule;
1446 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1450 init_dispatch(netmsg_t nmsg)
1452 struct netmsg_ipfw fwmsg;
1455 kprintf("ipfw3 already loaded\n");
1460 bzero(&fwmsg, sizeof(fwmsg));
1461 netmsg_init(&fwmsg.base, NULL, &curthread->td_msgport,
1462 0, ctx_init_dispatch);
1463 netisr_domsg(&fwmsg.base, 0);
1465 ip_fw_chk_ptr = ip_fw3_chk;
1466 ip_fw_ctl_x_ptr = ip_fw3_ctl_x;
1467 ip_fw_dn_io_ptr = ip_fw3_dummynet_io;
1469 kprintf("ipfw3 initialized, default to %s\n",
1470 filters_default_to_accept ? "accept" : "deny");
1473 if (sysctl_var_fw3_enable)
1476 lwkt_replymsg(&nmsg->lmsg, error);
1482 struct netmsg_base smsg;
1486 netmsg_init(&smsg, NULL, &curthread->td_msgport,
1488 error = lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1495 fini_dispatch(netmsg_t nmsg)
1502 netmsg_service_sync();
1503 ip_fw_chk_ptr = NULL;
1504 ip_fw_ctl_x_ptr = NULL;
1505 ip_fw_dn_io_ptr = NULL;
1506 ip_fw3_ctl_flush_rule(1);
1507 /* Free pre-cpu context */
1508 for (cpu = 0; cpu < ncpus; ++cpu) {
1509 if (fw3_ctx[cpu] != NULL) {
1510 kfree(fw3_ctx[cpu], M_IPFW3);
1511 fw3_ctx[cpu] = NULL;
1514 kprintf("ipfw3 unloaded\n");
1516 lwkt_replymsg(&nmsg->lmsg, error);
1522 struct netmsg_base smsg;
1524 netmsg_init(&smsg, NULL, &curthread->td_msgport,
1526 return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1529 #endif /* KLD_MODULE */
1532 ip_fw3_modevent(module_t mod, int type, void *unused)
1538 err = ip_fw3_init();
1544 kprintf("ipfw3 statically compiled, cannot unload\n");
1547 err = ip_fw3_fini();
1556 static moduledata_t ipfw3mod = {
1561 /* ipfw3 must init before ipfw3_basic */
1562 DECLARE_MODULE(ipfw3, ipfw3mod, SI_SUB_PROTO_END, SI_ORDER_FIRST);
1563 MODULE_VERSION(ipfw3, 1);