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/in_cksum.h>
53 #include <sys/systm.h>
55 #include <sys/socket.h>
56 #include <sys/syslog.h>
57 #include <sys/ucred.h>
59 #include <sys/mplock2.h>
62 #include <net/radix.h>
63 #include <net/route.h>
65 #include <net/netmsg2.h>
67 #include <netinet/in.h>
68 #include <netinet/in_systm.h>
69 #include <netinet/in_var.h>
70 #include <netinet/in_pcb.h>
71 #include <netinet/ip.h>
72 #include <netinet/ip_var.h>
73 #include <netinet/ip_icmp.h>
74 #include <netinet/tcp.h>
75 #include <netinet/tcp_timer.h>
76 #include <netinet/tcp_var.h>
77 #include <netinet/tcpip.h>
78 #include <netinet/udp.h>
79 #include <netinet/udp_var.h>
80 #include <netinet/ip_divert.h>
81 #include <netinet/if_ether.h>
83 #include <net/ipfw3/ip_fw.h>
84 #include <net/ipfw3/ip_fw3_set.h>
85 #include <net/ipfw3_basic/ip_fw3_log.h>
86 #include <net/ipfw3_basic/ip_fw3_table.h>
87 #include <net/ipfw3_basic/ip_fw3_sync.h>
88 #include <net/ipfw3_basic/ip_fw3_basic.h>
89 #include <net/ipfw3_basic/ip_fw3_state.h>
90 #include <net/ipfw3_nat/ip_fw3_nat.h>
91 #include <net/dummynet3/ip_dummynet3.h>
93 MALLOC_DEFINE(M_IPFW3, "IPFW3", "ipfw3 module");
96 #define MAX_OPCODE_PER_MODULE 100
98 #define IPFW_AUTOINC_STEP_MIN 1
99 #define IPFW_AUTOINC_STEP_MAX 1000
100 #define IPFW_AUTOINC_STEP_DEF 100
104 struct netmsg_base base;
105 const struct ipfw_ioc_rule *ioc_rule;
107 struct ip_fw *next_rule;
108 struct ip_fw *prev_rule;
109 struct ip_fw *sibling; /* sibling in prevous CPU */
113 struct netmsg_base base;
115 struct ip_fw *start_rule;
116 struct ip_fw *prev_rule;
117 struct ipfw_ioc_state *ioc_state;
125 struct netmsg_base base;
126 struct ip_fw *start_rule;
131 ip_fw_ctl_t *ip_fw3_ctl_nat_ptr = NULL;
132 ip_fw_ctl_t *ip_fw3_ctl_state_ptr = NULL;
133 ip_fw_ctl_t *ip_fw3_ctl_table_ptr = NULL;
134 ip_fw_ctl_t *ip_fw3_ctl_sync_ptr = NULL;
135 ip_fw_log_t *ip_fw3_log_ptr = NULL;
137 extern int ip_fw_loaded;
138 extern struct ipfw3_state_context *fw3_state_ctx[MAXCPU];
139 int sysctl_var_fw3_enable = 1;
140 int sysctl_var_fw3_one_pass = 1;
141 int sysctl_var_fw3_verbose = 0;
142 static int sysctl_var_fw3_flushing;
143 static int sysctl_var_fw3_debug;
144 static int sysctl_var_autoinc_step = IPFW_AUTOINC_STEP_DEF;
146 int ip_fw3_sysctl_enable(SYSCTL_HANDLER_ARGS);
147 int ip_fw3_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS);
149 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw3, CTLFLAG_RW, 0, "Firewall");
150 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, enable, CTLTYPE_INT | CTLFLAG_RW,
151 &sysctl_var_fw3_enable, 0, ip_fw3_sysctl_enable, "I", "Enable ipfw");
152 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, sysctl_var_autoinc_step,
153 CTLTYPE_INT | CTLFLAG_RW, &sysctl_var_autoinc_step, 0,
154 ip_fw3_sysctl_autoinc_step, "I", "Rule number autincrement step");
155 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO,one_pass,CTLFLAG_RW,
156 &sysctl_var_fw3_one_pass, 0,
157 "Only do a single pass through ipfw3 when using dummynet(4)");
158 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, debug, CTLFLAG_RW,
159 &sysctl_var_fw3_debug, 0, "Enable printing of debug ip_fw statements");
160 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, verbose, CTLFLAG_RW,
161 &sysctl_var_fw3_verbose, 0, "Log matches to ipfw3 rules");
164 filter_func filter_funcs[MAX_MODULE][MAX_OPCODE_PER_MODULE];
165 struct ipfw3_module fw3_modules[MAX_MODULE];
166 struct ipfw3_context *fw3_ctx[MAXCPU];
167 struct ipfw3_sync_context fw3_sync_ctx;
171 ip_fw3_register_module(int module_id,char *module_name)
173 struct ipfw3_module *tmp;
177 for (i=0; i < MAX_MODULE; i++) {
178 if (tmp->type == 0) {
181 strncpy(tmp->name, module_name, strlen(module_name));
186 kprintf("ipfw3 module %s loaded\n", module_name);
190 ip_fw3_unregister_module(int module_id)
192 struct ipfw3_module *tmp;
195 int i, len, cmdlen, found;
199 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
201 for (; fw; fw = fw->next) {
202 for (len = fw->cmd_len, cmd = fw->cmd; len > 0;
204 cmd = (ipfw_insn *)((uint32_t *)cmd + cmdlen)) {
206 if (cmd->module == 0 &&
207 (cmd->opcode == 0 || cmd->opcode == 1)) {
208 //action accept or deny
209 } else if (cmd->module == module_id) {
219 for (i = 0; i < MAX_MODULE; i++) {
220 if (tmp->type == 1 && tmp->id == module_id) {
222 kprintf("ipfw3 module %s unloaded\n",
229 for (i = 0; i < MAX_OPCODE_PER_MODULE; i++) {
230 if (module_id == 0) {
231 if (i ==0 || i == 1) {
235 filter_funcs[module_id][i] = NULL;
242 ip_fw3_register_filter_funcs(int module, int opcode, filter_func func)
244 filter_funcs[module][opcode] = func;
248 check_accept(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
249 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
251 *cmd_val = IP_FW_PASS;
252 *cmd_ctl = IP_FW_CTL_DONE;
253 if (cmd->arg3 && ip_fw3_log_ptr != NULL) {
254 ip_fw3_log_ptr((*args)->m, (*args)->eh, cmd->arg1);
259 check_deny(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
260 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
262 *cmd_val = IP_FW_DENY;
263 *cmd_ctl = IP_FW_CTL_DONE;
264 if (cmd->arg3 && ip_fw3_log_ptr != NULL) {
265 ip_fw3_log_ptr((*args)->m, (*args)->eh, cmd->arg1);
272 memset(fw3_modules, 0, sizeof(struct ipfw3_module) * MAX_MODULE);
273 memset(filter_funcs, 0, sizeof(filter_func) *
274 MAX_OPCODE_PER_MODULE * MAX_MODULE);
275 ip_fw3_register_filter_funcs(0, O_BASIC_ACCEPT,
276 (filter_func)check_accept);
277 ip_fw3_register_filter_funcs(0, O_BASIC_DENY, (filter_func)check_deny);
281 ip_fw3_free_rule(struct ip_fw *rule)
283 kfree(rule, M_IPFW3);
288 static struct ip_fw *
289 lookup_next_rule(struct ip_fw *me)
291 struct ip_fw *rule = NULL;
294 /* look for action, in case it is a skipto */
295 cmd = ACTION_PTR(me);
296 if ((int)cmd->module == MODULE_BASIC_ID &&
297 (int)cmd->opcode == O_BASIC_SKIPTO) {
298 for (rule = me->next; rule; rule = rule->next) {
299 if (rule->rulenum >= cmd->arg1)
303 if (rule == NULL) { /* failure or not a skipto */
306 me->next_rule = rule;
311 * rules are stored in ctx->ipfw_rule_chain.
312 * and each rule is combination of multiple cmds.(ipfw_insn)
313 * in each rule, it begin with filter cmds. and end with action cmds.
314 * 'outer/inner loop' are looping the rules/cmds.
315 * it will invoke the cmds relatived function according to the cmd's
316 * module id and opcode id. and process according to return value.
319 ip_fw3_chk(struct ip_fw_args *args)
325 struct mbuf *m = args->m;
326 struct ip *ip = mtod(m, struct ip *);
327 struct ip_fw *f = NULL; /* matching rule */
328 int cmd_val = IP_FW_PASS;
330 struct divert_info *divinfo;
333 * hlen The length of the IPv4 header.
334 * hlen >0 means we have an IPv4 packet.
336 u_int hlen = 0; /* hlen >0 means we have an IP pkt */
339 * offset The offset of a fragment. offset != 0 means that
340 * we have a fragment at this offset of an IPv4 packet.
341 * offset == 0 means that (if this is an IPv4 packet)
342 * this is the first or only fragment.
347 uint16_t src_port = 0, dst_port = 0; /* NOTE: host format */
348 struct in_addr src_ip, dst_ip; /* NOTE: network format */
350 uint8_t prev_module = -1, prev_opcode = -1; /* previous module & opcode */
351 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
353 if (m->m_pkthdr.fw_flags & IPFW_MBUF_GENERATED)
354 return IP_FW_PASS; /* accept */
356 if (args->eh == NULL || /* layer 3 packet */
357 (m->m_pkthdr.len >= sizeof(struct ip) &&
358 ntohs(args->eh->ether_type) == ETHERTYPE_IP))
359 hlen = ip->ip_hl << 2;
362 * Collect parameters into local variables for faster matching.
364 if (hlen == 0) { /* do not grab addresses for non-ip pkts */
365 proto = args->f_id.proto = 0; /* mark f_id invalid */
366 goto after_ip_checks;
369 proto = args->f_id.proto = ip->ip_p;
372 if (args->eh != NULL) { /* layer 2 packets are as on the wire */
373 offset = ntohs(ip->ip_off) & IP_OFFMASK;
374 ip_len = ntohs(ip->ip_len);
376 offset = ip->ip_off & IP_OFFMASK;
380 #define PULLUP_TO(len) \
382 if (m->m_len < (len)) { \
383 args->m = m = m_pullup(m, (len)); \
385 goto pullup_failed; \
386 ip = mtod(m, struct ip *); \
393 PULLUP_TO(hlen + sizeof(struct tcphdr));
394 tcp = L3HDR(struct tcphdr, ip);
395 dst_port = tcp->th_dport;
396 src_port = tcp->th_sport;
397 args->f_id.flags = tcp->th_flags;
400 PULLUP_TO(hlen + sizeof(struct udphdr));
401 udp = L3HDR(struct udphdr, ip);
402 dst_port = udp->uh_dport;
403 src_port = udp->uh_sport;
407 icmp = L3HDR(struct icmp, ip);
408 args->f_id.flags = icmp->icmp_type;
409 dst_port = icmp->icmp_id;
419 args->f_id.src_ip = ntohl(src_ip.s_addr);
420 args->f_id.dst_ip = ntohl(dst_ip.s_addr);
421 args->f_id.src_port = src_port = ntohs(src_port);
422 args->f_id.dst_port = dst_port = ntohs(dst_port);
427 * Packet has already been tagged. Look for the next rule
428 * to restart processing.
430 * If sysctl_var_fw3_one_pass != 0 then just accept it.
431 * XXX should not happen here, but optimized out in
434 if (sysctl_var_fw3_one_pass)
437 /* This rule is being/has been flushed */
438 if (sysctl_var_fw3_flushing)
441 f = args->rule->next_rule;
443 f = lookup_next_rule(args->rule);
446 * Find the starting rule. It can be either the first
447 * one, or the one after divert_rule if asked so.
451 mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
453 divinfo = m_tag_data(mtag);
454 skipto = divinfo->skipto;
460 if (args->eh == NULL && skipto != 0) {
461 /* No skipto during rule flushing */
462 if (sysctl_var_fw3_flushing) {
465 if (skipto >= IPFW_DEFAULT_RULE) {
466 return IP_FW_DENY; /* invalid */
468 while (f && f->rulenum <= skipto) {
471 if (f == NULL) { /* drop packet */
474 } else if (sysctl_var_fw3_flushing) {
475 /* Rules are being flushed; skip to default rule */
476 f = ctx->default_rule;
479 if ((mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL)) != NULL) {
480 m_tag_delete(m, mtag);
484 * Now scan the rules, and parse microinstructions for each rule.
486 int prev_val; /* previous result of 'or' filter */
490 /* foreach rule in chain */
491 for (; f; f = f->next) {
492 again: /* check the rule again*/
493 if (ctx->sets & (1 << f->set)) {
498 /* foreach cmd in rule */
499 for (l = f->cmd_len, cmd = f->cmd; l > 0; l -= cmdlen,
500 cmd = (ipfw_insn *)((uint32_t *)cmd+ cmdlen)) {
503 /* skip 'or' filter when already match */
504 if (cmd->len & F_OR &&
505 cmd->module == prev_module &&
506 cmd->opcode == prev_opcode &&
511 check_body: /* check the body of the rule again.*/
512 (filter_funcs[cmd->module][cmd->opcode])
513 (&cmd_ctl, &cmd_val, &args, &f, cmd, ip_len);
516 if (prev_val == 0) /* but 'or' failed */
519 case IP_FW_CTL_AGAIN:
526 case IP_FW_CTL_CHK_STATE:
527 /* update the cmd and l */
529 l = f->cmd_len - f->act_ofs;
532 if (cmd->len & F_NOT)
535 if (cmd->len & F_OR) { /* has 'or' */
536 if (!cmd_val) { /* not matched */
537 if(prev_val == -1){ /* first 'or' */
539 prev_module = cmd->module;
540 prev_opcode = cmd->opcode;
541 } else if (prev_module == cmd->module &&
542 prev_opcode == cmd->opcode) {
543 /* continuous 'or' filter */
544 } else if (prev_module != cmd->module ||
545 prev_opcode != cmd->opcode) {
546 /* 'or' filter changed */
551 prev_module = cmd->module;
552 prev_opcode = cmd->opcode;
555 } else { /* has 'or' and matched */
557 prev_module = cmd->module;
558 prev_opcode = cmd->opcode;
561 if (!cmd_val) { /* not matched */
565 /* previous 'or' not matched */
573 } /* end of inner for, scan opcodes */
574 next_rule:; /* try next rule */
575 } /* end of outer for, scan rules */
576 kprintf("+++ ipfw: ouch!, skip past end of rules, denying packet\n");
580 /* Update statistics */
583 f->timestamp = time_second;
587 if (sysctl_var_fw3_verbose)
588 kprintf("pullup failed\n");
593 ip_fw3_dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa)
598 const struct ipfw_flow_id *id;
599 struct dn_flow_id *fid;
603 mtag = m_tag_get(PACKET_TAG_DUMMYNET, sizeof(*pkt),
604 M_INTWAIT | M_NULLOK);
609 m_tag_prepend(m, mtag);
611 pkt = m_tag_data(mtag);
612 bzero(pkt, sizeof(*pkt));
614 cmd = (ipfw_insn *)((uint32_t *)fwa->rule->cmd + fwa->rule->act_ofs);
615 KASSERT(cmd->opcode == O_DUMMYNET_PIPE ||
616 cmd->opcode == O_DUMMYNET_QUEUE,
617 ("Rule is not PIPE or QUEUE, opcode %d", cmd->opcode));
620 pkt->dn_flags = (dir & DN_FLAGS_DIR_MASK);
622 pkt->pipe_nr = pipe_nr;
624 pkt->cpuid = mycpuid;
625 pkt->msgport = netisr_curport();
629 fid->fid_dst_ip = id->dst_ip;
630 fid->fid_src_ip = id->src_ip;
631 fid->fid_dst_port = id->dst_port;
632 fid->fid_src_port = id->src_port;
633 fid->fid_proto = id->proto;
634 fid->fid_flags = id->flags;
636 pkt->dn_priv = fwa->rule;
638 if ((int)cmd->opcode == O_DUMMYNET_PIPE)
639 pkt->dn_flags |= DN_FLAGS_IS_PIPE;
641 m->m_pkthdr.fw_flags |= DUMMYNET_MBUF_TAGGED;
647 add_rule_dispatch(netmsg_t nmsg)
649 struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
650 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
651 struct ip_fw *rule, *prev,*next;
652 const struct ipfw_ioc_rule *ioc_rule;
654 ioc_rule = fwmsg->ioc_rule;
655 // create rule by ioc_rule
656 rule = kmalloc(RULESIZE(ioc_rule), M_IPFW3, M_WAITOK | M_ZERO);
657 rule->act_ofs = ioc_rule->act_ofs;
658 rule->cmd_len = ioc_rule->cmd_len;
659 rule->rulenum = ioc_rule->rulenum;
660 rule->set = ioc_rule->set;
661 bcopy(ioc_rule->cmd, rule->cmd, rule->cmd_len * 4);
663 for (prev = NULL, next = ctx->rules;
664 next; prev = next, next = next->next) {
665 if (ioc_rule->insert) {
666 if (next->rulenum >= ioc_rule->rulenum) {
670 if (next->rulenum > ioc_rule->rulenum) {
675 KASSERT(next != NULL, ("no default rule?!"));
678 * Insert rule into the pre-determined position
684 rule->next = ctx->rules;
689 * if sibiling in last CPU is exists,
690 * then it's sibling should be current rule
692 if (fwmsg->sibling != NULL) {
693 fwmsg->sibling->sibling = rule;
695 /* prepare for next CPU */
696 fwmsg->sibling = rule;
698 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
702 * confirm the rulenumber
703 * call dispatch function to add rule into the list
704 * Update the statistic
707 ip_fw3_add_rule(struct ipfw_ioc_rule *ioc_rule)
709 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
710 struct netmsg_ipfw fwmsg;
711 struct netmsg_base *nmsg;
714 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
717 * If rulenum is 0, find highest numbered rule before the
718 * default rule, and add rule number incremental step.
720 if (ioc_rule->rulenum == 0) {
721 int step = sysctl_var_autoinc_step;
723 KKASSERT(step >= IPFW_AUTOINC_STEP_MIN &&
724 step <= IPFW_AUTOINC_STEP_MAX);
727 * Locate the highest numbered rule before default
729 for (f = ctx->rules; f; f = f->next) {
730 if (f->rulenum == IPFW_DEFAULT_RULE)
732 ioc_rule->rulenum = f->rulenum;
734 if (ioc_rule->rulenum < IPFW_DEFAULT_RULE - step)
735 ioc_rule->rulenum += step;
737 KASSERT(ioc_rule->rulenum != IPFW_DEFAULT_RULE &&
738 ioc_rule->rulenum != 0,
739 ("invalid rule num %d", ioc_rule->rulenum));
741 bzero(&fwmsg, sizeof(fwmsg));
743 netmsg_init(nmsg, NULL, &curthread->td_msgport,
744 0, add_rule_dispatch);
745 fwmsg.ioc_rule = ioc_rule;
747 netisr_domsg(nmsg, 0);
749 IPFW3_DEBUG("++ installed rule %d, static count now %d\n",
750 ioc_rule->rulenum, static_count);
754 * Free storage associated with a static rule (including derived
756 * The caller is in charge of clearing rule pointers to avoid
758 * @return a pointer to the next entry.
759 * Arguments are not checked, so they better be correct.
760 * Must be called at splimp().
763 ip_fw3_delete_rule(struct ipfw3_context *ctx,
764 struct ip_fw *prev, struct ip_fw *rule)
767 ctx->rules = rule->next;
769 prev->next = rule->next;
771 kfree(rule, M_IPFW3);
777 flush_rule_dispatch(netmsg_t nmsg)
779 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
780 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
781 struct ip_fw *rule, *the_rule;
782 int kill_default = dmsg->kill_default;
785 while (rule != NULL) {
786 if (rule->rulenum == IPFW_DEFAULT_RULE && kill_default == 0) {
793 kfree(the_rule, M_IPFW3);
796 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
801 * Deletes all rules from a chain (including the default rule
802 * if the second argument is set).
803 * Must be called at splimp().
806 ip_fw3_ctl_flush_rule(int kill_default)
808 struct netmsg_del dmsg;
810 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
813 sysctl_var_fw3_flushing = 1;
814 netmsg_service_sync();
817 * Press the 'flush' button
819 bzero(&dmsg, sizeof(dmsg));
820 netmsg_init(&dmsg.base, NULL, &curthread->td_msgport,
821 0, flush_rule_dispatch);
822 dmsg.kill_default = kill_default;
823 netisr_domsg(&dmsg.base, 0);
826 sysctl_var_fw3_flushing = 0;
830 delete_rule_dispatch(netmsg_t nmsg)
832 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
833 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
834 struct ip_fw *rule, *prev = NULL;
838 if (rule->rulenum == dmsg->rulenum) {
839 ip_fw3_delete_rule(ctx, prev, rule);
846 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
850 ip_fw3_ctl_delete_rule(struct sockopt *sopt)
852 struct netmsg_del dmsg;
853 struct netmsg_base *nmsg;
856 rulenum = (int *) sopt->sopt_val;
860 * Get rid of the rule duplications on all CPUs
862 bzero(&dmsg, sizeof(dmsg));
864 netmsg_init(nmsg, NULL, &curthread->td_msgport,
865 0, delete_rule_dispatch);
866 dmsg.rulenum = *rulenum;
867 netisr_domsg(nmsg, 0);
872 * Clear counters for a specific rule.
875 ip_fw3_clear_counters(struct ip_fw *rule)
877 rule->bcnt = rule->pcnt = 0;
882 ip_fw3_zero_entry_dispatch(netmsg_t nmsg)
884 struct netmsg_zent *zmsg = (struct netmsg_zent *)nmsg;
885 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
888 if (zmsg->rulenum == 0) {
889 for (rule = ctx->rules; rule; rule = rule->next) {
890 ip_fw3_clear_counters(rule);
893 for (rule = ctx->rules; rule; rule = rule->next) {
894 if (rule->rulenum == zmsg->rulenum) {
895 ip_fw3_clear_counters(rule);
899 ip_fw3_clear_counters(ctx->default_rule);
900 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
904 * Reset some or all counters on firewall rules.
905 * @arg frwl is null to clear all entries, or contains a specific
907 * @arg log_only is 1 if we only want to reset logs, zero otherwise.
910 ip_fw3_ctl_zero_entry(int rulenum, int log_only)
912 struct netmsg_zent zmsg;
913 struct netmsg_base *nmsg;
915 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
917 bzero(&zmsg, sizeof(zmsg));
919 netmsg_init(nmsg, NULL, &curthread->td_msgport,
920 0, ip_fw3_zero_entry_dispatch);
921 zmsg.log_only = log_only;
924 msg = log_only ? "ipfw: All logging counts reset.\n"
925 : "ipfw: Accounting cleared.\n";
930 * Locate the first rule with 'rulenum'
932 for (rule = ctx->rules; rule; rule = rule->next) {
933 if (rule->rulenum == rulenum)
936 if (rule == NULL) /* we did not find any matching rules */
938 zmsg.start_rule = rule;
939 zmsg.rulenum = rulenum;
941 msg = log_only ? "ipfw: Entry %d logging count reset.\n"
942 : "ipfw: Entry %d cleared.\n";
944 netisr_domsg(nmsg, 0);
945 KKASSERT(zmsg.start_rule == NULL);
947 if (sysctl_var_fw3_verbose)
948 log(LOG_SECURITY | LOG_NOTICE, msg, rulenum);
953 * Get the ioc_rule from the sopt
954 * call ip_fw3_add_rule to add the rule
957 ip_fw3_ctl_add_rule(struct sockopt *sopt)
959 struct ipfw_ioc_rule *ioc_rule;
962 size = sopt->sopt_valsize;
963 if (size > (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX) ||
964 size < sizeof(*ioc_rule) - sizeof(ipfw_insn)) {
967 if (size != (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX)) {
968 sopt->sopt_val = krealloc(sopt->sopt_val, sizeof(uint32_t) *
969 IPFW_RULE_SIZE_MAX, M_TEMP, M_WAITOK);
971 ioc_rule = sopt->sopt_val;
973 ip_fw3_add_rule(ioc_rule);
978 ip_fw3_ctl_get_modules(struct sockopt *sopt)
981 struct ipfw3_module *mod;
982 char module_str[1024];
983 memset(module_str,0,1024);
984 for (i = 0, mod = fw3_modules; i < MAX_MODULE; i++, mod++) {
985 if (mod->type != 0) {
987 strcat(module_str,",");
988 strcat(module_str,mod->name);
991 bzero(sopt->sopt_val, sopt->sopt_valsize);
992 bcopy(module_str, sopt->sopt_val, strlen(module_str));
993 sopt->sopt_valsize = strlen(module_str);
998 * Copy all static rules and states on all CPU
1001 ip_fw3_ctl_get_rules(struct sockopt *sopt)
1003 struct ipfw3_context *ctx = fw3_ctx[mycpuid];
1005 struct ipfw_ioc_rule *ioc;
1006 const struct ip_fw *sibling;
1009 ioc = (struct ipfw_ioc_rule *)sopt->sopt_val;
1011 for (rule = ctx->rules; rule; rule = rule->next) {
1012 total_len += IOC_RULESIZE(rule);
1013 if (total_len > sopt->sopt_valsize) {
1014 bzero(sopt->sopt_val, sopt->sopt_valsize);
1017 ioc->act_ofs = rule->act_ofs;
1018 ioc->cmd_len = rule->cmd_len;
1019 ioc->rulenum = rule->rulenum;
1020 ioc->set = rule->set;
1022 ioc->sets = fw3_ctx[mycpuid]->sets;
1026 for (sibling = rule; sibling != NULL; sibling = sibling->sibling) {
1027 ioc->pcnt += sibling->pcnt;
1028 ioc->bcnt += sibling->bcnt;
1029 if (sibling->timestamp > ioc->timestamp)
1030 ioc->timestamp = sibling->timestamp;
1032 bcopy(rule->cmd, ioc->cmd, ioc->cmd_len * 4);
1033 ioc = (struct ipfw_ioc_rule *)((uint8_t *)ioc + IOC_RULESIZE(ioc));
1035 sopt->sopt_valsize = total_len;
1041 * ip_fw3_ctl_x - extended version of ip_fw3_ctl
1042 * remove the x_header, and adjust the sopt_name,sopt_val and sopt_valsize.
1045 ip_fw3_ctl_x(struct sockopt *sopt)
1047 ip_fw_x_header *x_header;
1048 x_header = (ip_fw_x_header *)(sopt->sopt_val);
1049 sopt->sopt_name = x_header->opcode;
1050 sopt->sopt_valsize -= sizeof(ip_fw_x_header);
1051 bcopy(++x_header, sopt->sopt_val, sopt->sopt_valsize);
1052 return ip_fw3_ctl(sopt);
1057 * {set|get}sockopt parser.
1060 ip_fw3_ctl(struct sockopt *sopt)
1063 switch (sopt->sopt_name) {
1073 case IP_FW_RESETLOG:
1074 error = ip_fw3_ctl_sockopt(sopt);
1077 case IP_FW_SET_MOVE_RULE:
1078 case IP_FW_SET_MOVE_SET:
1079 case IP_FW_SET_SWAP:
1080 case IP_FW_SET_TOGGLE:
1081 error = ip_fw3_ctl_set_sockopt(sopt);
1085 case IP_FW_NAT_FLUSH:
1087 case IP_FW_NAT_GET_RECORD:
1088 if (ip_fw3_ctl_nat_ptr != NULL) {
1089 error = ip_fw3_ctl_nat_ptr(sopt);
1092 case IP_DUMMYNET_GET:
1093 case IP_DUMMYNET_CONFIGURE:
1094 case IP_DUMMYNET_DEL:
1095 case IP_DUMMYNET_FLUSH:
1096 error = ip_dn_sockopt(sopt);
1098 case IP_FW_STATE_ADD:
1099 case IP_FW_STATE_DEL:
1100 case IP_FW_STATE_FLUSH:
1101 case IP_FW_STATE_GET:
1102 if (ip_fw3_ctl_state_ptr != NULL) {
1103 error = ip_fw3_ctl_state_ptr(sopt);
1106 case IP_FW_TABLE_CREATE:
1107 case IP_FW_TABLE_DELETE:
1108 case IP_FW_TABLE_APPEND:
1109 case IP_FW_TABLE_REMOVE:
1110 case IP_FW_TABLE_LIST:
1111 case IP_FW_TABLE_FLUSH:
1112 case IP_FW_TABLE_SHOW:
1113 case IP_FW_TABLE_TEST:
1114 case IP_FW_TABLE_RENAME:
1115 if (ip_fw3_ctl_table_ptr != NULL) {
1116 error = ip_fw3_ctl_table_ptr(sopt);
1119 case IP_FW_SYNC_SHOW_CONF:
1120 case IP_FW_SYNC_SHOW_STATUS:
1121 case IP_FW_SYNC_EDGE_CONF:
1122 case IP_FW_SYNC_EDGE_START:
1123 case IP_FW_SYNC_EDGE_STOP:
1124 case IP_FW_SYNC_EDGE_TEST:
1125 case IP_FW_SYNC_EDGE_CLEAR:
1126 case IP_FW_SYNC_CENTRE_CONF:
1127 case IP_FW_SYNC_CENTRE_START:
1128 case IP_FW_SYNC_CENTRE_STOP:
1129 case IP_FW_SYNC_CENTRE_TEST:
1130 case IP_FW_SYNC_CENTRE_CLEAR:
1131 if (ip_fw3_ctl_sync_ptr != NULL) {
1132 error = ip_fw3_ctl_sync_ptr(sopt);
1136 kprintf("ip_fw3_ctl invalid option %d\n",
1144 ip_fw3_ctl_sockopt(struct sockopt *sopt)
1146 int error = 0, rulenum;
1148 switch (sopt->sopt_name) {
1150 error = ip_fw3_ctl_get_rules(sopt);
1153 error = ip_fw3_ctl_get_modules(sopt);
1156 ip_fw3_ctl_flush_rule(0);
1159 error = ip_fw3_ctl_add_rule(sopt);
1162 error = ip_fw3_ctl_delete_rule(sopt);
1165 case IP_FW_RESETLOG: /* argument is an int, the rule number */
1167 if (sopt->sopt_valsize != 0) {
1168 error = soopt_to_kbuf(sopt, &rulenum,
1169 sizeof(int), sizeof(int));
1174 error = ip_fw3_ctl_zero_entry(rulenum,
1175 sopt->sopt_name == IP_FW_RESETLOG);
1178 kprintf("ip_fw3_ctl invalid option %d\n",
1186 ip_fw3_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1188 struct ip_fw_args args;
1189 struct mbuf *m = *m0;
1191 int tee = 0, error = 0, ret;
1193 if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1194 /* Extract info from dummynet tag */
1195 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1196 KKASSERT(mtag != NULL);
1197 args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1198 KKASSERT(args.rule != NULL);
1200 m_tag_delete(m, mtag);
1201 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1209 ret = ip_fw3_chk(&args);
1226 case IP_FW_DUMMYNET:
1227 /* Send packet to the appropriate pipe */
1228 m = ip_fw3_dummynet_io(m, args.cookie, DN_TO_IP_IN,
1236 * Must clear bridge tag when changing
1238 m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED;
1239 if (ip_divert_p != NULL) {
1240 m = ip_divert_p(m, tee, 1);
1244 /* not sure this is the right error msg */
1253 panic("unknown ipfw3 return value: %d", ret);
1261 ip_fw3_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1263 struct ip_fw_args args;
1264 struct mbuf *m = *m0;
1266 int tee = 0, error = 0, ret;
1268 if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1269 /* Extract info from dummynet tag */
1270 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1271 KKASSERT(mtag != NULL);
1272 args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1273 KKASSERT(args.rule != NULL);
1275 m_tag_delete(m, mtag);
1276 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1284 ret = ip_fw3_chk(&args);
1302 case IP_FW_DUMMYNET:
1303 m = ip_fw3_dummynet_io(m, args.cookie, DN_TO_IP_OUT,
1312 if (ip_divert_p != NULL) {
1313 m = ip_divert_p(m, tee, 0);
1317 /* not sure this is the right error msg */
1327 panic("unknown ipfw3 return value: %d", ret);
1337 struct pfil_head *pfh;
1338 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1340 pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1344 pfil_add_hook(ip_fw3_check_in, NULL, PFIL_IN, pfh);
1345 pfil_add_hook(ip_fw3_check_out, NULL, PFIL_OUT, pfh);
1351 struct pfil_head *pfh;
1353 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1355 pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1359 pfil_remove_hook(ip_fw3_check_in, NULL, PFIL_IN, pfh);
1360 pfil_remove_hook(ip_fw3_check_out, NULL, PFIL_OUT, pfh);
1364 ip_fw3_sysctl_enable_dispatch(netmsg_t nmsg)
1366 struct lwkt_msg *lmsg = &nmsg->lmsg;
1367 int enable = lmsg->u.ms_result;
1369 if (sysctl_var_fw3_enable == enable)
1372 sysctl_var_fw3_enable = enable;
1373 if (sysctl_var_fw3_enable)
1379 lwkt_replymsg(lmsg, 0);
1383 ip_fw3_sysctl_enable(SYSCTL_HANDLER_ARGS)
1385 struct netmsg_base nmsg;
1386 struct lwkt_msg *lmsg;
1389 enable = sysctl_var_fw3_enable;
1390 error = sysctl_handle_int(oidp, &enable, 0, req);
1391 if (error || req->newptr == NULL)
1394 netmsg_init(&nmsg, NULL, &curthread->td_msgport,
1395 0, ip_fw3_sysctl_enable_dispatch);
1397 lmsg->u.ms_result = enable;
1399 return lwkt_domsg(IPFW_CFGPORT, lmsg, 0);
1403 ip_fw3_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS)
1405 return sysctl_int_range(oidp, arg1, arg2, req,
1406 IPFW_AUTOINC_STEP_MIN, IPFW_AUTOINC_STEP_MAX);
1410 ctx_init_dispatch(netmsg_t nmsg)
1412 struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
1413 struct ipfw3_context *ctx;
1414 struct ip_fw *def_rule;
1416 ctx = kmalloc(LEN_FW3_CTX, M_IPFW3, M_WAITOK | M_ZERO);
1417 fw3_ctx[mycpuid] = ctx;
1418 ctx->sets = IPFW_ALL_SETS;
1420 def_rule = kmalloc(LEN_FW3, M_IPFW3, M_WAITOK | M_ZERO);
1421 def_rule->act_ofs = 0;
1422 def_rule->rulenum = IPFW_DEFAULT_RULE;
1423 def_rule->cmd_len = 2;
1424 def_rule->set = IPFW_DEFAULT_SET;
1426 def_rule->cmd[0].len = LEN_OF_IPFWINSN;
1427 def_rule->cmd[0].module = MODULE_BASIC_ID;
1428 #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
1429 def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1431 if (filters_default_to_accept)
1432 def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1434 def_rule->cmd[0].opcode = O_BASIC_DENY;
1437 /* Install the default rule */
1438 ctx->default_rule = def_rule;
1439 ctx->rules = def_rule;
1442 * if sibiling in last CPU is exists,
1443 * then it's sibling should be current rule
1445 if (fwmsg->sibling != NULL) {
1446 fwmsg->sibling->sibling = def_rule;
1448 /* prepare for next CPU */
1449 fwmsg->sibling = def_rule;
1451 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1455 init_dispatch(netmsg_t nmsg)
1457 struct netmsg_ipfw fwmsg;
1460 kprintf("ipfw3 already loaded\n");
1465 bzero(&fwmsg, sizeof(fwmsg));
1466 netmsg_init(&fwmsg.base, NULL, &curthread->td_msgport,
1467 0, ctx_init_dispatch);
1468 netisr_domsg(&fwmsg.base, 0);
1470 ip_fw_chk_ptr = ip_fw3_chk;
1471 ip_fw_ctl_x_ptr = ip_fw3_ctl_x;
1472 ip_fw_dn_io_ptr = ip_fw3_dummynet_io;
1474 kprintf("ipfw3 initialized, default to %s\n",
1475 filters_default_to_accept ? "accept" : "deny");
1478 if (sysctl_var_fw3_enable)
1481 lwkt_replymsg(&nmsg->lmsg, error);
1487 struct netmsg_base smsg;
1491 netmsg_init(&smsg, NULL, &curthread->td_msgport,
1493 error = lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1500 fini_dispatch(netmsg_t nmsg)
1507 netmsg_service_sync();
1508 ip_fw_chk_ptr = NULL;
1509 ip_fw_ctl_x_ptr = NULL;
1510 ip_fw_dn_io_ptr = NULL;
1511 ip_fw3_ctl_flush_rule(1);
1512 /* Free pre-cpu context */
1513 for (cpu = 0; cpu < ncpus; ++cpu) {
1514 if (fw3_ctx[cpu] != NULL) {
1515 kfree(fw3_ctx[cpu], M_IPFW3);
1516 fw3_ctx[cpu] = NULL;
1519 kprintf("ipfw3 unloaded\n");
1521 lwkt_replymsg(&nmsg->lmsg, error);
1527 struct netmsg_base smsg;
1529 netmsg_init(&smsg, NULL, &curthread->td_msgport,
1531 return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1534 #endif /* KLD_MODULE */
1537 ip_fw3_modevent(module_t mod, int type, void *unused)
1543 err = ip_fw3_init();
1549 kprintf("ipfw3 statically compiled, cannot unload\n");
1552 err = ip_fw3_fini();
1561 static moduledata_t ipfw3mod = {
1566 /* ipfw3 must init before ipfw3_basic */
1567 DECLARE_MODULE(ipfw3, ipfw3mod, SI_SUB_PROTO_END, SI_ORDER_FIRST);
1568 MODULE_VERSION(ipfw3, 1);