mtree(8): Fix crc() prototype.
[dragonfly.git] / sys / net / ipfw3 / ip_fw3.c
blob26e799dfdd53ae25be4a995c4869d2108ecf6b53
1 /*
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) 2015 - 2016 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
12 * are met:
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
19 * distribution.
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
35 * SUCH DAMAGE.
39 #include "opt_ipfw.h"
40 #include "opt_inet.h"
41 #ifndef INET
42 #error IPFIREWALL3 requires INET.
43 #endif /* INET */
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/malloc.h>
48 #include <sys/mbuf.h>
49 #include <sys/kernel.h>
50 #include <sys/proc.h>
51 #include <sys/socket.h>
52 #include <sys/socketvar.h>
53 #include <sys/sysctl.h>
54 #include <sys/syslog.h>
55 #include <sys/ucred.h>
56 #include <sys/in_cksum.h>
57 #include <sys/lock.h>
58 #include <sys/thread2.h>
59 #include <sys/mplock2.h>
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/in_var.h>
64 #include <netinet/in_pcb.h>
65 #include <netinet/ip.h>
66 #include <netinet/ip_var.h>
67 #include <netinet/ip_icmp.h>
68 #include <netinet/tcp.h>
69 #include <netinet/tcp_timer.h>
70 #include <netinet/tcp_var.h>
71 #include <netinet/tcpip.h>
72 #include <netinet/udp.h>
73 #include <netinet/udp_var.h>
74 #include <netinet/ip_divert.h>
75 #include <netinet/if_ether.h>
77 #include <net/if.h>
78 #include <net/radix.h>
79 #include <net/route.h>
80 #include <net/pfil.h>
81 #include <net/netmsg2.h>
83 #include <net/ipfw3/ip_fw.h>
84 #include <net/ipfw3/ip_fw3_log.h>
85 #include <net/ipfw3/ip_fw3_table.h>
86 #include <net/ipfw3/ip_fw3_sync.h>
87 #include <net/ipfw3_basic/ip_fw3_basic.h>
88 #include <net/ipfw3_nat/ip_fw3_nat.h>
89 #include <net/dummynet3/ip_dummynet3.h>
91 MALLOC_DEFINE(M_IPFW3, "IPFW3", "ip_fw3 default module");
93 #ifdef IPFIREWALL_DEBUG
94 #define DPRINTF(fmt, ...) \
95 do { \
96 if (fw_debug > 0) \
97 kprintf(fmt, __VA_ARGS__); \
98 } while (0)
99 #else
100 #define DPRINTF(fmt, ...) ((void)0)
101 #endif
103 #define MAX_MODULE 10
104 #define MAX_OPCODE_PER_MODULE 100
106 #define IPFW_AUTOINC_STEP_MIN 1
107 #define IPFW_AUTOINC_STEP_MAX 1000
108 #define IPFW_AUTOINC_STEP_DEF 100
111 struct netmsg_ipfw {
112 struct netmsg_base base;
113 const struct ipfw_ioc_rule *ioc_rule;
114 struct ip_fw *rule;
115 struct ip_fw *next_rule;
116 struct ip_fw *prev_rule;
117 struct ip_fw *sibling; /* sibling in prevous CPU */
120 struct netmsg_del {
121 struct netmsg_base base;
122 struct ip_fw *rule;
123 struct ip_fw *start_rule;
124 struct ip_fw *prev_rule;
125 struct ipfw_ioc_state *ioc_state;
126 uint16_t rulenum;
127 uint8_t from_set;
128 uint8_t to_set;
131 struct netmsg_zent {
132 struct netmsg_base base;
133 struct ip_fw *start_rule;
134 uint16_t rulenum;
135 uint16_t log_only;
138 ip_fw_ctl_t *ipfw_ctl_nat_ptr = NULL;
140 /* handlers which implemented in ipfw_basic module */
141 ipfw_basic_delete_state_t *ipfw_basic_flush_state_prt = NULL;
142 ipfw_basic_append_state_t *ipfw_basic_append_state_prt = NULL;
144 extern int ip_fw_loaded;
145 static uint32_t static_count; /* # of static rules */
146 static uint32_t static_ioc_len; /* bytes of static rules */
147 static int ipfw_flushing;
148 int fw_verbose = 0;
149 static int fw_debug;
150 static int autoinc_step = IPFW_AUTOINC_STEP_DEF;
152 static int ipfw_sysctl_enable(SYSCTL_HANDLER_ARGS);
153 static int ipfw_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS);
155 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw3, CTLFLAG_RW, 0, "Firewall");
156 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, enable, CTLTYPE_INT | CTLFLAG_RW,
157 &fw3_enable, 0, ipfw_sysctl_enable, "I", "Enable ipfw");
158 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, autoinc_step, CTLTYPE_INT | CTLFLAG_RW,
159 &autoinc_step, 0, ipfw_sysctl_autoinc_step, "I",
160 "Rule number autincrement step");
161 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO,one_pass,CTLFLAG_RW,
162 &fw3_one_pass, 0,
163 "Only do a single pass through ipfw when using dummynet(4)");
164 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, debug, CTLFLAG_RW,
165 &fw_debug, 0, "Enable printing of debug ip_fw statements");
166 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, verbose, CTLFLAG_RW,
167 &fw_verbose, 0, "Log matches to ipfw rules");
168 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, static_count, CTLFLAG_RD,
169 &static_count, 0, "Number of static rules");
171 filter_func filter_funcs[MAX_MODULE][MAX_OPCODE_PER_MODULE];
172 struct ipfw_module ipfw_modules[MAX_MODULE];
173 struct ipfw_context *ipfw_ctx[MAXCPU];
174 struct ipfw_sync_context sync_ctx;
175 static int ipfw_ctl(struct sockopt *sopt);
178 void
179 check_accept(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
180 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len);
181 void
182 check_deny(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
183 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len);
184 void init_module(void);
187 void
188 register_ipfw_module(int module_id,char *module_name)
190 struct ipfw_module *tmp;
191 int i;
193 tmp = ipfw_modules;
194 for (i=0; i < MAX_MODULE; i++) {
195 if (tmp->type == 0) {
196 tmp->type = 1;
197 tmp->id = module_id;
198 strncpy(tmp->name, module_name, strlen(module_name));
199 break;
201 tmp++;
203 kprintf("ipfw3 module %s loaded\n", module_name);
207 unregister_ipfw_module(int module_id)
209 struct ipfw_module *tmp;
210 struct ip_fw *fw;
211 ipfw_insn *cmd;
212 int i, len, cmdlen, found;
214 found = 0;
215 tmp = ipfw_modules;
216 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
217 fw = ctx->ipfw_rule_chain;
218 for (; fw; fw = fw->next) {
219 for (len = fw->cmd_len, cmd = fw->cmd; len > 0;
220 len -= cmdlen,
221 cmd = (ipfw_insn *)((uint32_t *)cmd + cmdlen)) {
222 cmdlen = F_LEN(cmd);
223 if (cmd->module == 0 &&
224 (cmd->opcode == 0 || cmd->opcode == 1)) {
225 //action accept or deny
226 } else if (cmd->module == module_id) {
227 found = 1;
228 goto decide;
232 decide:
233 if (found) {
234 return 1;
235 } else {
236 for (i = 0; i < MAX_MODULE; i++) {
237 if (tmp->type == 1 && tmp->id == module_id) {
238 tmp->type = 0;
239 kprintf("ipfw3 module %s unloaded\n",
240 tmp->name);
241 break;
243 tmp++;
246 for (i = 0; i < MAX_OPCODE_PER_MODULE; i++) {
247 if (module_id == 0) {
248 if (i ==0 || i == 1) {
249 continue;
252 filter_funcs[module_id][i] = NULL;
254 return 0;
258 void
259 register_ipfw_filter_funcs(int module, int opcode, filter_func func)
261 filter_funcs[module][opcode] = func;
264 void
265 check_accept(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
266 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
268 *cmd_val = IP_FW_PASS;
269 *cmd_ctl = IP_FW_CTL_DONE;
270 if (cmd->arg3) {
271 ipfw_log((*args)->m, (*args)->eh, cmd->arg1);
275 void
276 check_deny(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
277 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
279 *cmd_val = IP_FW_DENY;
280 *cmd_ctl = IP_FW_CTL_DONE;
281 if (cmd->arg3) {
282 ipfw_log((*args)->m, (*args)->eh, cmd->arg1);
286 void
287 init_module(void)
289 memset(ipfw_modules, 0, sizeof(struct ipfw_module) * MAX_MODULE);
290 memset(filter_funcs, 0, sizeof(filter_func) *
291 MAX_OPCODE_PER_MODULE * MAX_MODULE);
292 register_ipfw_filter_funcs(0, O_BASIC_ACCEPT,
293 (filter_func)check_accept);
294 register_ipfw_filter_funcs(0, O_BASIC_DENY, (filter_func)check_deny);
297 static __inline int
298 ipfw_free_rule(struct ip_fw *rule)
300 kfree(rule, M_IPFW3);
301 rule = NULL;
302 return 1;
305 static struct ip_fw *
306 lookup_next_rule(struct ip_fw *me)
308 struct ip_fw *rule = NULL;
309 ipfw_insn *cmd;
311 /* look for action, in case it is a skipto */
312 cmd = ACTION_PTR(me);
313 if ((int)cmd->module == MODULE_BASIC_ID &&
314 (int)cmd->opcode == O_BASIC_SKIPTO) {
315 for (rule = me->next; rule; rule = rule->next) {
316 if (rule->rulenum >= cmd->arg1)
317 break;
320 if (rule == NULL) { /* failure or not a skipto */
321 rule = me->next;
323 me->next_rule = rule;
324 return rule;
328 * rules are stored in ctx->ipfw_rule_chain.
329 * and each rule is combination of multiple cmds.(ipfw_insn)
330 * in each rule, it begin with filter cmds. and end with action cmds.
331 * 'outer/inner loop' are looping the rules/cmds.
332 * it will invoke the cmds relatived function according to the cmd's
333 * module id and opcode id. and process according to return value.
335 static int
336 ipfw_chk(struct ip_fw_args *args)
338 struct mbuf *m = args->m;
339 struct ip *ip = mtod(m, struct ip *);
340 struct ip_fw *f = NULL; /* matching rule */
341 int cmd_val = IP_FW_PASS;
342 struct m_tag *mtag;
343 struct divert_info *divinfo;
346 * hlen The length of the IPv4 header.
347 * hlen >0 means we have an IPv4 packet.
349 u_int hlen = 0; /* hlen >0 means we have an IP pkt */
352 * offset The offset of a fragment. offset != 0 means that
353 * we have a fragment at this offset of an IPv4 packet.
354 * offset == 0 means that (if this is an IPv4 packet)
355 * this is the first or only fragment.
357 u_short offset = 0;
359 uint8_t proto;
360 uint16_t src_port = 0, dst_port = 0; /* NOTE: host format */
361 struct in_addr src_ip, dst_ip; /* NOTE: network format */
362 uint16_t ip_len = 0;
363 uint8_t prev_module = -1, prev_opcode = -1; /* previous module & opcode */
364 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
366 if (m->m_pkthdr.fw_flags & IPFW_MBUF_GENERATED)
367 return IP_FW_PASS; /* accept */
369 if (args->eh == NULL || /* layer 3 packet */
370 (m->m_pkthdr.len >= sizeof(struct ip) &&
371 ntohs(args->eh->ether_type) == ETHERTYPE_IP))
372 hlen = ip->ip_hl << 2;
375 * Collect parameters into local variables for faster matching.
377 if (hlen == 0) { /* do not grab addresses for non-ip pkts */
378 proto = args->f_id.proto = 0; /* mark f_id invalid */
379 goto after_ip_checks;
382 proto = args->f_id.proto = ip->ip_p;
383 src_ip = ip->ip_src;
384 dst_ip = ip->ip_dst;
385 if (args->eh != NULL) { /* layer 2 packets are as on the wire */
386 offset = ntohs(ip->ip_off) & IP_OFFMASK;
387 ip_len = ntohs(ip->ip_len);
388 } else {
389 offset = ip->ip_off & IP_OFFMASK;
390 ip_len = ip->ip_len;
393 #define PULLUP_TO(len) \
394 do { \
395 if (m->m_len < (len)) { \
396 args->m = m = m_pullup(m, (len)); \
397 if (m == NULL) \
398 goto pullup_failed; \
399 ip = mtod(m, struct ip *); \
401 } while (0)
403 if (offset == 0) {
404 switch (proto) {
405 case IPPROTO_TCP:
407 struct tcphdr *tcp;
409 PULLUP_TO(hlen + sizeof(struct tcphdr));
410 tcp = L3HDR(struct tcphdr, ip);
411 dst_port = tcp->th_dport;
412 src_port = tcp->th_sport;
413 args->f_id.flags = tcp->th_flags;
415 break;
417 case IPPROTO_UDP:
419 struct udphdr *udp;
421 PULLUP_TO(hlen + sizeof(struct udphdr));
422 udp = L3HDR(struct udphdr, ip);
423 dst_port = udp->uh_dport;
424 src_port = udp->uh_sport;
426 break;
428 case IPPROTO_ICMP:
429 PULLUP_TO(hlen + 4);
430 args->f_id.flags =
431 L3HDR(struct icmp, ip)->icmp_type;
432 break;
434 default:
435 break;
439 #undef PULLUP_TO
441 args->f_id.src_ip = ntohl(src_ip.s_addr);
442 args->f_id.dst_ip = ntohl(dst_ip.s_addr);
443 args->f_id.src_port = src_port = ntohs(src_port);
444 args->f_id.dst_port = dst_port = ntohs(dst_port);
446 after_ip_checks:
447 if (args->rule) {
449 * Packet has already been tagged. Look for the next rule
450 * to restart processing.
452 * If fw3_one_pass != 0 then just accept it.
453 * XXX should not happen here, but optimized out in
454 * the caller.
456 if (fw3_one_pass)
457 return IP_FW_PASS;
459 /* This rule is being/has been flushed */
460 if (ipfw_flushing)
461 return IP_FW_DENY;
463 f = args->rule->next_rule;
464 if (f == NULL)
465 f = lookup_next_rule(args->rule);
466 } else {
468 * Find the starting rule. It can be either the first
469 * one, or the one after divert_rule if asked so.
471 int skipto;
473 mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
474 if (mtag != NULL) {
475 divinfo = m_tag_data(mtag);
476 skipto = divinfo->skipto;
477 } else {
478 skipto = 0;
481 f = ctx->ipfw_rule_chain;
482 if (args->eh == NULL && skipto != 0) {
483 /* No skipto during rule flushing */
484 if (ipfw_flushing) {
485 return IP_FW_DENY;
487 if (skipto >= IPFW_DEFAULT_RULE) {
488 return IP_FW_DENY; /* invalid */
490 while (f && f->rulenum <= skipto) {
491 f = f->next;
493 if (f == NULL) { /* drop packet */
494 return IP_FW_DENY;
496 } else if (ipfw_flushing) {
497 /* Rules are being flushed; skip to default rule */
498 f = ctx->ipfw_default_rule;
501 if ((mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL)) != NULL) {
502 m_tag_delete(m, mtag);
506 * Now scan the rules, and parse microinstructions for each rule.
508 int prev_val; /* previous result of 'or' filter */
509 int l, cmdlen;
510 ipfw_insn *cmd;
511 int cmd_ctl;
512 /* foreach rule in chain */
513 for (; f; f = f->next) {
514 again: /* check the rule again*/
515 if (ctx->ipfw_set_disable & (1 << f->set)) {
516 continue;
519 prev_val = -1;
520 /* foreach cmd in rule */
521 for (l = f->cmd_len, cmd = f->cmd; l > 0; l -= cmdlen,
522 cmd = (ipfw_insn *)((uint32_t *)cmd+ cmdlen)) {
523 cmdlen = F_LEN(cmd);
525 /* skip 'or' filter when already match */
526 if (cmd->len & F_OR &&
527 cmd->module == prev_module &&
528 cmd->opcode == prev_opcode &&
529 prev_val == 1) {
530 goto next_cmd;
533 check_body: /* check the body of the rule again.*/
534 (filter_funcs[cmd->module][cmd->opcode])
535 (&cmd_ctl, &cmd_val, &args, &f, cmd, ip_len);
536 switch(cmd_ctl) {
537 case IP_FW_CTL_DONE:
538 if (prev_val == 0) /* but 'or' failed */
539 goto next_rule;
540 goto done;
541 case IP_FW_CTL_AGAIN:
542 goto again;
543 case IP_FW_CTL_NEXT:
544 goto next_rule;
545 case IP_FW_CTL_NAT:
546 args->rule=f;
547 goto done;
548 case IP_FW_CTL_CHK_STATE:
549 /* update the cmd and l */
550 cmd = ACTION_PTR(f);
551 l = f->cmd_len - f->act_ofs;
552 goto check_body;
554 if (cmd->len & F_NOT)
555 cmd_val= !cmd_val;
557 if (cmd->len & F_OR) { /* has 'or' */
558 if (!cmd_val) { /* not matched */
559 if(prev_val == -1){ /* first 'or' */
560 prev_val = 0;
561 prev_module = cmd->module;
562 prev_opcode = cmd->opcode;
563 } else if (prev_module == cmd->module &&
564 prev_opcode == cmd->opcode) {
565 /* continuous 'or' filter */
566 } else if (prev_module != cmd->module ||
567 prev_opcode != cmd->opcode) {
568 /* 'or' filter changed */
569 if(prev_val == 0){
570 goto next_rule;
571 } else {
572 prev_val = 0;
573 prev_module = cmd->module;
574 prev_opcode = cmd->opcode;
577 } else { /* has 'or' and matched */
578 prev_val = 1;
579 prev_module = cmd->module;
580 prev_opcode = cmd->opcode;
582 } else { /* no or */
583 if (!cmd_val) { /* not matched */
584 goto next_rule;
585 } else {
586 if (prev_val == 0) {
587 /* previous 'or' not matched */
588 goto next_rule;
589 } else {
590 prev_val = -1;
594 next_cmd:;
595 } /* end of inner for, scan opcodes */
596 next_rule:; /* try next rule */
597 } /* end of outer for, scan rules */
598 kprintf("+++ ipfw: ouch!, skip past end of rules, denying packet\n");
599 return IP_FW_DENY;
601 done:
602 /* Update statistics */
603 f->pcnt++;
604 f->bcnt += ip_len;
605 f->timestamp = time_second;
606 return cmd_val;
608 pullup_failed:
609 if (fw_verbose)
610 kprintf("pullup failed\n");
611 return IP_FW_DENY;
614 static struct mbuf *
615 ipfw_dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa)
617 struct m_tag *mtag;
618 struct dn_pkt *pkt;
619 ipfw_insn *cmd;
620 const struct ipfw_flow_id *id;
621 struct dn_flow_id *fid;
623 M_ASSERTPKTHDR(m);
625 mtag = m_tag_get(PACKET_TAG_DUMMYNET, sizeof(*pkt),
626 M_INTWAIT | M_NULLOK);
627 if (mtag == NULL) {
628 m_freem(m);
629 return (NULL);
631 m_tag_prepend(m, mtag);
633 pkt = m_tag_data(mtag);
634 bzero(pkt, sizeof(*pkt));
636 cmd = (ipfw_insn *)((uint32_t *)fwa->rule->cmd + fwa->rule->act_ofs);
637 KASSERT(cmd->opcode == O_DUMMYNET_PIPE ||
638 cmd->opcode == O_DUMMYNET_QUEUE,
639 ("Rule is not PIPE or QUEUE, opcode %d", cmd->opcode));
641 pkt->dn_m = m;
642 pkt->dn_flags = (dir & DN_FLAGS_DIR_MASK);
643 pkt->ifp = fwa->oif;
644 pkt->pipe_nr = pipe_nr;
646 pkt->cpuid = mycpuid;
647 pkt->msgport = netisr_curport();
649 id = &fwa->f_id;
650 fid = &pkt->id;
651 fid->fid_dst_ip = id->dst_ip;
652 fid->fid_src_ip = id->src_ip;
653 fid->fid_dst_port = id->dst_port;
654 fid->fid_src_port = id->src_port;
655 fid->fid_proto = id->proto;
656 fid->fid_flags = id->flags;
658 pkt->dn_priv = fwa->rule;
660 if ((int)cmd->opcode == O_DUMMYNET_PIPE)
661 pkt->dn_flags |= DN_FLAGS_IS_PIPE;
663 m->m_pkthdr.fw_flags |= DUMMYNET_MBUF_TAGGED;
664 return (m);
667 static __inline void
668 ipfw_inc_static_count(struct ip_fw *rule)
670 /* Static rule's counts are updated only on CPU0 */
671 KKASSERT(mycpuid == 0);
673 static_count++;
674 static_ioc_len += IOC_RULESIZE(rule);
677 static __inline void
678 ipfw_dec_static_count(struct ip_fw *rule)
680 int l = IOC_RULESIZE(rule);
682 /* Static rule's counts are updated only on CPU0 */
683 KKASSERT(mycpuid == 0);
685 KASSERT(static_count > 0, ("invalid static count %u", static_count));
686 static_count--;
688 KASSERT(static_ioc_len >= l,
689 ("invalid static len %u", static_ioc_len));
690 static_ioc_len -= l;
693 static void
694 ipfw_add_rule_dispatch(netmsg_t nmsg)
696 struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
697 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
698 struct ip_fw *rule, *prev,*next;
699 const struct ipfw_ioc_rule *ioc_rule;
701 ioc_rule = fwmsg->ioc_rule;
702 // create rule by ioc_rule
703 rule = kmalloc(RULESIZE(ioc_rule), M_IPFW3, M_WAITOK | M_ZERO);
704 rule->act_ofs = ioc_rule->act_ofs;
705 rule->cmd_len = ioc_rule->cmd_len;
706 rule->rulenum = ioc_rule->rulenum;
707 rule->set = ioc_rule->set;
708 bcopy(ioc_rule->cmd, rule->cmd, rule->cmd_len * 4);
710 for (prev = NULL, next = ctx->ipfw_rule_chain;
711 next; prev = next, next = next->next) {
712 if (next->rulenum > ioc_rule->rulenum) {
713 break;
716 KASSERT(next != NULL, ("no default rule?!"));
719 * Insert rule into the pre-determined position
721 if (prev != NULL) {
722 rule->next = next;
723 prev->next = rule;
724 } else {
725 rule->next = ctx->ipfw_rule_chain;
726 ctx->ipfw_rule_chain = rule;
730 * if sibiling in last CPU is exists,
731 * then it's sibling should be current rule
733 if (fwmsg->sibling != NULL) {
734 fwmsg->sibling->sibling = rule;
736 /* prepare for next CPU */
737 fwmsg->sibling = rule;
739 if (mycpuid == 0) {
740 /* Statistics only need to be updated once */
741 ipfw_inc_static_count(rule);
743 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
747 * confirm the rulenumber
748 * call dispatch function to add rule into the list
749 * Update the statistic
751 static void
752 ipfw_add_rule(struct ipfw_ioc_rule *ioc_rule)
754 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
755 struct netmsg_ipfw fwmsg;
756 struct netmsg_base *nmsg;
757 struct ip_fw *f;
759 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
762 * If rulenum is 0, find highest numbered rule before the
763 * default rule, and add rule number incremental step.
765 if (ioc_rule->rulenum == 0) {
766 int step = autoinc_step;
768 KKASSERT(step >= IPFW_AUTOINC_STEP_MIN &&
769 step <= IPFW_AUTOINC_STEP_MAX);
772 * Locate the highest numbered rule before default
774 for (f = ctx->ipfw_rule_chain; f; f = f->next) {
775 if (f->rulenum == IPFW_DEFAULT_RULE)
776 break;
777 ioc_rule->rulenum = f->rulenum;
779 if (ioc_rule->rulenum < IPFW_DEFAULT_RULE - step)
780 ioc_rule->rulenum += step;
782 KASSERT(ioc_rule->rulenum != IPFW_DEFAULT_RULE &&
783 ioc_rule->rulenum != 0,
784 ("invalid rule num %d", ioc_rule->rulenum));
786 bzero(&fwmsg, sizeof(fwmsg));
787 nmsg = &fwmsg.base;
788 netmsg_init(nmsg, NULL, &curthread->td_msgport,
789 0, ipfw_add_rule_dispatch);
790 fwmsg.ioc_rule = ioc_rule;
792 netisr_domsg(nmsg, 0);
794 DPRINTF("++ installed rule %d, static count now %d\n",
795 ioc_rule->rulenum, static_count);
799 * Free storage associated with a static rule (including derived
800 * dynamic rules).
801 * The caller is in charge of clearing rule pointers to avoid
802 * dangling pointers.
803 * @return a pointer to the next entry.
804 * Arguments are not checked, so they better be correct.
805 * Must be called at splimp().
807 static struct ip_fw *
808 ipfw_delete_rule(struct ipfw_context *ctx,
809 struct ip_fw *prev, struct ip_fw *rule)
811 if (prev == NULL)
812 ctx->ipfw_rule_chain = rule->next;
813 else
814 prev->next = rule->next;
816 if (mycpuid == IPFW_CFGCPUID)
817 ipfw_dec_static_count(rule);
819 kfree(rule, M_IPFW3);
820 rule = NULL;
821 return NULL;
824 static void
825 ipfw_flush_rule_dispatch(netmsg_t nmsg)
827 struct lwkt_msg *lmsg = &nmsg->lmsg;
828 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
829 struct ip_fw *rule, *the_rule;
830 int kill_default = lmsg->u.ms_result;
832 rule = ctx->ipfw_rule_chain;
833 while (rule != NULL) {
834 if (rule->rulenum == IPFW_DEFAULT_RULE && kill_default == 0) {
835 ctx->ipfw_rule_chain = rule;
836 break;
838 the_rule = rule;
839 rule = rule->next;
840 if (mycpuid == IPFW_CFGCPUID)
841 ipfw_dec_static_count(the_rule);
843 kfree(the_rule, M_IPFW3);
846 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
849 static void
850 ipfw_append_state_dispatch(netmsg_t nmsg)
852 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
853 struct ipfw_ioc_state *ioc_state = dmsg->ioc_state;
854 (*ipfw_basic_append_state_prt)(ioc_state);
855 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
858 static void
859 ipfw_delete_state_dispatch(netmsg_t nmsg)
861 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
862 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
863 struct ip_fw *rule = ctx->ipfw_rule_chain;
864 while (rule != NULL) {
865 if (rule->rulenum == dmsg->rulenum) {
866 break;
868 rule = rule->next;
871 (*ipfw_basic_flush_state_prt)(rule);
872 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
876 * Deletes all rules from a chain (including the default rule
877 * if the second argument is set).
878 * Must be called at splimp().
880 static void
881 ipfw_ctl_flush_rule(int kill_default)
883 struct netmsg_del dmsg;
884 struct netmsg_base nmsg;
885 struct lwkt_msg *lmsg;
887 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
890 * If 'kill_default' then caller has done the necessary
891 * msgport syncing; unnecessary to do it again.
893 if (!kill_default) {
895 * Let ipfw_chk() know the rules are going to
896 * be flushed, so it could jump directly to
897 * the default rule.
899 ipfw_flushing = 1;
900 netmsg_service_sync();
904 * if ipfw_basic_flush_state_prt
905 * flush all states in all CPU
907 if (ipfw_basic_flush_state_prt != NULL) {
908 bzero(&dmsg, sizeof(dmsg));
909 netmsg_init(&dmsg.base, NULL, &curthread->td_msgport,
910 0, ipfw_delete_state_dispatch);
911 netisr_domsg(&dmsg.base, 0);
914 * Press the 'flush' button
916 bzero(&nmsg, sizeof(nmsg));
917 netmsg_init(&nmsg, NULL, &curthread->td_msgport,
918 0, ipfw_flush_rule_dispatch);
919 lmsg = &nmsg.lmsg;
920 lmsg->u.ms_result = kill_default;
921 netisr_domsg(&nmsg, 0);
923 if (kill_default) {
924 KASSERT(static_count == 0,
925 ("%u static rules remain", static_count));
926 KASSERT(static_ioc_len == 0,
927 ("%u bytes of static rules remain", static_ioc_len));
930 /* Flush is done */
931 ipfw_flushing = 0;
934 static void
935 ipfw_delete_rule_dispatch(netmsg_t nmsg)
937 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
938 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
939 struct ip_fw *rule, *prev = NULL;
941 rule = ctx->ipfw_rule_chain;
942 while (rule!=NULL) {
943 if (rule->rulenum == dmsg->rulenum) {
944 ipfw_delete_rule(ctx, prev, rule);
945 break;
947 prev = rule;
948 rule = rule->next;
951 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
954 static int
955 ipfw_alt_delete_rule(uint16_t rulenum)
957 struct netmsg_del dmsg;
958 struct netmsg_base *nmsg;
961 * delete the state which stub is the rule
962 * which belongs to the CPU and the rulenum
964 bzero(&dmsg, sizeof(dmsg));
965 nmsg = &dmsg.base;
966 netmsg_init(nmsg, NULL, &curthread->td_msgport,
967 0, ipfw_delete_state_dispatch);
968 dmsg.rulenum = rulenum;
969 netisr_domsg(nmsg, 0);
972 * Get rid of the rule duplications on all CPUs
974 bzero(&dmsg, sizeof(dmsg));
975 nmsg = &dmsg.base;
976 netmsg_init(nmsg, NULL, &curthread->td_msgport,
977 0, ipfw_delete_rule_dispatch);
978 dmsg.rulenum = rulenum;
979 netisr_domsg(nmsg, 0);
980 return 0;
983 static void
984 ipfw_alt_delete_ruleset_dispatch(netmsg_t nmsg)
986 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
987 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
988 struct ip_fw *prev, *rule;
989 #ifdef INVARIANTS
990 int del = 0;
991 #endif
993 prev = NULL;
994 rule = ctx->ipfw_rule_chain;
995 while (rule != NULL) {
996 if (rule->set == dmsg->from_set) {
997 rule = ipfw_delete_rule(ctx, prev, rule);
998 #ifdef INVARIANTS
999 del = 1;
1000 #endif
1001 } else {
1002 prev = rule;
1003 rule = rule->next;
1006 KASSERT(del, ("no match set?!"));
1008 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1011 static void
1012 ipfw_disable_ruleset_state_dispatch(netmsg_t nmsg)
1014 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
1015 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1016 struct ip_fw *rule;
1017 #ifdef INVARIANTS
1018 int cleared = 0;
1019 #endif
1021 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1022 if (rule->set == dmsg->from_set) {
1023 #ifdef INVARIANTS
1024 cleared = 1;
1025 #endif
1028 KASSERT(cleared, ("no match set?!"));
1030 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1033 static int
1034 ipfw_alt_delete_ruleset(uint8_t set)
1036 struct netmsg_del dmsg;
1037 struct netmsg_base *nmsg;
1038 int state, del;
1039 struct ip_fw *rule;
1040 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1043 * Check whether the 'set' exists. If it exists,
1044 * then check whether any rules within the set will
1045 * try to create states.
1047 state = 0;
1048 del = 0;
1049 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1050 if (rule->set == set) {
1051 del = 1;
1054 if (!del)
1055 return 0; /* XXX EINVAL? */
1057 if (state) {
1059 * Clear the STATE flag, so no more states will be
1060 * created based the rules in this set.
1062 bzero(&dmsg, sizeof(dmsg));
1063 nmsg = &dmsg.base;
1064 netmsg_init(nmsg, NULL, &curthread->td_msgport,
1065 0, ipfw_disable_ruleset_state_dispatch);
1066 dmsg.from_set = set;
1068 netisr_domsg(nmsg, 0);
1072 * Delete this set
1074 bzero(&dmsg, sizeof(dmsg));
1075 nmsg = &dmsg.base;
1076 netmsg_init(nmsg, NULL, &curthread->td_msgport,
1077 0, ipfw_alt_delete_ruleset_dispatch);
1078 dmsg.from_set = set;
1080 netisr_domsg(nmsg, 0);
1081 return 0;
1084 static void
1085 ipfw_alt_move_rule_dispatch(netmsg_t nmsg)
1087 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
1088 struct ip_fw *rule;
1090 rule = dmsg->start_rule;
1093 * Move to the position on the next CPU
1094 * before the msg is forwarded.
1097 while (rule && rule->rulenum <= dmsg->rulenum) {
1098 if (rule->rulenum == dmsg->rulenum)
1099 rule->set = dmsg->to_set;
1100 rule = rule->next;
1102 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1105 static int
1106 ipfw_alt_move_rule(uint16_t rulenum, uint8_t set)
1108 struct netmsg_del dmsg;
1109 struct netmsg_base *nmsg;
1110 struct ip_fw *rule;
1111 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1114 * Locate first rule to move
1116 for (rule = ctx->ipfw_rule_chain;
1117 rule && rule->rulenum <= rulenum; rule = rule->next) {
1118 if (rule->rulenum == rulenum && rule->set != set)
1119 break;
1121 if (rule == NULL || rule->rulenum > rulenum)
1122 return 0; /* XXX error? */
1124 bzero(&dmsg, sizeof(dmsg));
1125 nmsg = &dmsg.base;
1126 netmsg_init(nmsg, NULL, &curthread->td_msgport,
1127 0, ipfw_alt_move_rule_dispatch);
1128 dmsg.start_rule = rule;
1129 dmsg.rulenum = rulenum;
1130 dmsg.to_set = set;
1132 netisr_domsg(nmsg, 0);
1133 KKASSERT(dmsg.start_rule == NULL);
1134 return 0;
1137 static void
1138 ipfw_alt_move_ruleset_dispatch(netmsg_t nmsg)
1140 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
1141 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1142 struct ip_fw *rule;
1144 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1145 if (rule->set == dmsg->from_set)
1146 rule->set = dmsg->to_set;
1148 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1151 static int
1152 ipfw_alt_move_ruleset(uint8_t from_set, uint8_t to_set)
1154 struct netmsg_del dmsg;
1155 struct netmsg_base *nmsg;
1157 bzero(&dmsg, sizeof(dmsg));
1158 nmsg = &dmsg.base;
1159 netmsg_init(nmsg, NULL, &curthread->td_msgport,
1160 0, ipfw_alt_move_ruleset_dispatch);
1161 dmsg.from_set = from_set;
1162 dmsg.to_set = to_set;
1164 netisr_domsg(nmsg, 0);
1165 return 0;
1168 static void
1169 ipfw_alt_swap_ruleset_dispatch(netmsg_t nmsg)
1171 struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
1172 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1173 struct ip_fw *rule;
1175 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1176 if (rule->set == dmsg->from_set)
1177 rule->set = dmsg->to_set;
1178 else if (rule->set == dmsg->to_set)
1179 rule->set = dmsg->from_set;
1181 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1184 static int
1185 ipfw_alt_swap_ruleset(uint8_t set1, uint8_t set2)
1187 struct netmsg_del dmsg;
1188 struct netmsg_base *nmsg;
1190 bzero(&dmsg, sizeof(dmsg));
1191 nmsg = &dmsg.base;
1192 netmsg_init(nmsg, NULL, &curthread->td_msgport,
1193 0, ipfw_alt_swap_ruleset_dispatch);
1194 dmsg.from_set = set1;
1195 dmsg.to_set = set2;
1197 netisr_domsg(nmsg, 0);
1198 return 0;
1202 static int
1203 ipfw_ctl_alter(uint32_t arg)
1205 uint16_t rulenum;
1206 uint8_t cmd, new_set;
1207 int error = 0;
1209 rulenum = arg & 0xffff;
1210 cmd = (arg >> 24) & 0xff;
1211 new_set = (arg >> 16) & 0xff;
1213 if (cmd > 4)
1214 return EINVAL;
1215 if (new_set >= IPFW_DEFAULT_SET)
1216 return EINVAL;
1217 if (cmd == 0 || cmd == 2) {
1218 if (rulenum == IPFW_DEFAULT_RULE)
1219 return EINVAL;
1220 } else {
1221 if (rulenum >= IPFW_DEFAULT_SET)
1222 return EINVAL;
1225 switch (cmd) {
1226 case 0: /* delete rules with given number */
1227 error = ipfw_alt_delete_rule(rulenum);
1228 break;
1230 case 1: /* delete all rules with given set number */
1231 error = ipfw_alt_delete_ruleset(rulenum);
1232 break;
1234 case 2: /* move rules with given number to new set */
1235 error = ipfw_alt_move_rule(rulenum, new_set);
1236 break;
1238 case 3: /* move rules with given set number to new set */
1239 error = ipfw_alt_move_ruleset(rulenum, new_set);
1240 break;
1242 case 4: /* swap two sets */
1243 error = ipfw_alt_swap_ruleset(rulenum, new_set);
1244 break;
1246 return error;
1250 * Clear counters for a specific rule.
1252 static void
1253 clear_counters(struct ip_fw *rule)
1255 rule->bcnt = rule->pcnt = 0;
1256 rule->timestamp = 0;
1259 static void
1260 ipfw_zero_entry_dispatch(netmsg_t nmsg)
1262 struct netmsg_zent *zmsg = (struct netmsg_zent *)nmsg;
1263 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1264 struct ip_fw *rule;
1266 if (zmsg->rulenum == 0) {
1267 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1268 clear_counters(rule);
1270 } else {
1271 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1272 if (rule->rulenum == zmsg->rulenum) {
1273 clear_counters(rule);
1277 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1281 * Reset some or all counters on firewall rules.
1282 * @arg frwl is null to clear all entries, or contains a specific
1283 * rule number.
1284 * @arg log_only is 1 if we only want to reset logs, zero otherwise.
1286 static int
1287 ipfw_ctl_zero_entry(int rulenum, int log_only)
1289 struct netmsg_zent zmsg;
1290 struct netmsg_base *nmsg;
1291 const char *msg;
1292 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1294 bzero(&zmsg, sizeof(zmsg));
1295 nmsg = &zmsg.base;
1296 netmsg_init(nmsg, NULL, &curthread->td_msgport,
1297 0, ipfw_zero_entry_dispatch);
1298 zmsg.log_only = log_only;
1300 if (rulenum == 0) {
1301 msg = log_only ? "ipfw: All logging counts reset.\n"
1302 : "ipfw: Accounting cleared.\n";
1303 } else {
1304 struct ip_fw *rule;
1307 * Locate the first rule with 'rulenum'
1309 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1310 if (rule->rulenum == rulenum)
1311 break;
1313 if (rule == NULL) /* we did not find any matching rules */
1314 return (EINVAL);
1315 zmsg.start_rule = rule;
1316 zmsg.rulenum = rulenum;
1318 msg = log_only ? "ipfw: Entry %d logging count reset.\n"
1319 : "ipfw: Entry %d cleared.\n";
1321 netisr_domsg(nmsg, 0);
1322 KKASSERT(zmsg.start_rule == NULL);
1324 if (fw_verbose)
1325 log(LOG_SECURITY | LOG_NOTICE, msg, rulenum);
1326 return (0);
1329 static int
1330 ipfw_ctl_add_state(struct sockopt *sopt)
1332 struct ipfw_ioc_state *ioc_state;
1333 ioc_state = sopt->sopt_val;
1334 if (ipfw_basic_append_state_prt != NULL) {
1335 struct netmsg_del dmsg;
1336 bzero(&dmsg, sizeof(dmsg));
1337 netmsg_init(&dmsg.base, NULL, &curthread->td_msgport,
1338 0, ipfw_append_state_dispatch);
1339 (&dmsg)->ioc_state = ioc_state;
1340 netisr_domsg(&dmsg.base, 0);
1342 return 0;
1345 static int
1346 ipfw_ctl_delete_state(struct sockopt *sopt)
1348 int rulenum = 0, error;
1349 if (sopt->sopt_valsize != 0) {
1350 error = soopt_to_kbuf(sopt, &rulenum, sizeof(int), sizeof(int));
1351 if (error) {
1352 return -1;
1355 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1356 struct ip_fw *rule = ctx->ipfw_rule_chain;
1358 while (rule!=NULL) {
1359 if (rule->rulenum == rulenum) {
1360 break;
1362 rule = rule->next;
1364 if (rule == NULL) {
1365 return -1;
1368 struct netmsg_del dmsg;
1369 struct netmsg_base *nmsg;
1371 * delete the state which stub is the rule
1372 * which belongs to the CPU and the rulenum
1374 bzero(&dmsg, sizeof(dmsg));
1375 nmsg = &dmsg.base;
1376 netmsg_init(nmsg, NULL, &curthread->td_msgport,
1377 0, ipfw_delete_state_dispatch);
1378 dmsg.rulenum = rulenum;
1379 netisr_domsg(nmsg, 0);
1380 return 0;
1383 static int
1384 ipfw_ctl_flush_state(struct sockopt *sopt)
1386 struct netmsg_del dmsg;
1387 struct netmsg_base *nmsg;
1389 * delete the state which stub is the rule
1390 * which belongs to the CPU and the rulenum
1392 bzero(&dmsg, sizeof(dmsg));
1393 nmsg = &dmsg.base;
1394 netmsg_init(nmsg, NULL, &curthread->td_msgport,
1395 0, ipfw_delete_state_dispatch);
1396 dmsg.rulenum = 0;
1397 netisr_domsg(nmsg, 0);
1398 return 0;
1402 * Get the ioc_rule from the sopt
1403 * call ipfw_add_rule to add the rule
1405 static int
1406 ipfw_ctl_add_rule(struct sockopt *sopt)
1408 struct ipfw_ioc_rule *ioc_rule;
1409 size_t size;
1411 size = sopt->sopt_valsize;
1412 if (size > (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX) ||
1413 size < sizeof(*ioc_rule)) {
1414 return EINVAL;
1416 if (size != (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX)) {
1417 sopt->sopt_val = krealloc(sopt->sopt_val, sizeof(uint32_t) *
1418 IPFW_RULE_SIZE_MAX, M_TEMP, M_WAITOK);
1420 ioc_rule = sopt->sopt_val;
1422 ipfw_add_rule(ioc_rule);
1423 return 0;
1426 static void *
1427 ipfw_copy_state(struct ip_fw_state *state, struct ipfw_ioc_state *ioc_state, int cpuid)
1429 ioc_state->pcnt = state->pcnt;
1430 ioc_state->bcnt = state->bcnt;
1431 ioc_state->lifetime = state->lifetime;
1432 ioc_state->timestamp = state->timestamp;
1433 ioc_state->cpuid = cpuid;
1434 ioc_state->expiry = state->expiry;
1435 ioc_state->rulenum = state->stub->rulenum;
1437 bcopy(&state->flow_id, &ioc_state->flow_id, sizeof(struct ipfw_flow_id));
1438 return ioc_state + 1;
1441 static void *
1442 ipfw_copy_rule(const struct ip_fw *rule, struct ipfw_ioc_rule *ioc_rule)
1444 const struct ip_fw *sibling;
1445 #ifdef INVARIANTS
1446 int i;
1447 #endif
1449 ioc_rule->act_ofs = rule->act_ofs;
1450 ioc_rule->cmd_len = rule->cmd_len;
1451 ioc_rule->rulenum = rule->rulenum;
1452 ioc_rule->set = rule->set;
1454 ioc_rule->set_disable = ipfw_ctx[mycpuid]->ipfw_set_disable;
1455 ioc_rule->static_count = static_count;
1456 ioc_rule->static_len = static_ioc_len;
1458 ioc_rule->pcnt = 1;
1459 ioc_rule->bcnt = 0;
1460 ioc_rule->timestamp = 0;
1462 #ifdef INVARIANTS
1463 i = 0;
1464 #endif
1465 ioc_rule->pcnt = 0;
1466 ioc_rule->bcnt = 0;
1467 ioc_rule->timestamp = 0;
1468 for (sibling = rule; sibling != NULL; sibling = sibling->sibling) {
1469 ioc_rule->pcnt += sibling->pcnt;
1470 ioc_rule->bcnt += sibling->bcnt;
1471 if (sibling->timestamp > ioc_rule->timestamp)
1472 ioc_rule->timestamp = sibling->timestamp;
1473 #ifdef INVARIANTS
1474 ++i;
1475 #endif
1478 KASSERT(i == ncpus, ("static rule is not duplicated on every cpu"));
1480 bcopy(rule->cmd, ioc_rule->cmd, ioc_rule->cmd_len * 4 /* XXX */);
1482 return ((uint8_t *)ioc_rule + IOC_RULESIZE(ioc_rule));
1485 static int
1486 ipfw_ctl_get_modules(struct sockopt *sopt)
1488 int i;
1489 struct ipfw_module *mod;
1490 char module_str[1024];
1491 memset(module_str,0,1024);
1492 for (i = 0, mod = ipfw_modules; i < MAX_MODULE; i++, mod++) {
1493 if (mod->type != 0) {
1494 if (i > 0)
1495 strcat(module_str,",");
1496 strcat(module_str,mod->name);
1499 bzero(sopt->sopt_val, sopt->sopt_valsize);
1500 bcopy(module_str, sopt->sopt_val, strlen(module_str));
1501 sopt->sopt_valsize = strlen(module_str);
1502 return 0;
1506 * Copy all static rules and states on all CPU
1508 static int
1509 ipfw_ctl_get_rules(struct sockopt *sopt)
1511 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1512 struct ipfw_state_context *state_ctx;
1513 struct ip_fw *rule;
1514 struct ip_fw_state *state;
1515 void *bp;
1516 size_t size;
1517 int i, j, state_count = 0;
1519 size = static_ioc_len;
1520 for (i = 0; i < ncpus; i++) {
1521 for (j = 0; j < ctx->state_hash_size; j++) {
1522 state_ctx = &ipfw_ctx[i]->state_ctx[j];
1523 state_count += state_ctx->count;
1526 if (state_count > 0) {
1527 size += state_count * sizeof(struct ipfw_ioc_state);
1530 if (sopt->sopt_valsize < size) {
1531 /* XXX TODO sopt_val is not big enough */
1532 bzero(sopt->sopt_val, sopt->sopt_valsize);
1533 return 0;
1536 sopt->sopt_valsize = size;
1537 bp = sopt->sopt_val;
1539 for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1540 bp = ipfw_copy_rule(rule, bp);
1542 if (state_count > 0 ) {
1543 for (i = 0; i < ncpus; i++) {
1544 for (j = 0; j < ctx->state_hash_size; j++) {
1545 state_ctx = &ipfw_ctx[i]->state_ctx[j];
1546 state = state_ctx->state;
1547 while (state != NULL) {
1548 bp = ipfw_copy_state(state, bp, i);
1549 state = state->next;
1554 return 0;
1557 static void
1558 ipfw_set_disable_dispatch(netmsg_t nmsg)
1560 struct lwkt_msg *lmsg = &nmsg->lmsg;
1561 struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1563 ctx->ipfw_set_disable = lmsg->u.ms_result32;
1565 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1568 static void
1569 ipfw_ctl_set_disable(uint32_t disable, uint32_t enable)
1571 struct netmsg_base nmsg;
1572 struct lwkt_msg *lmsg;
1573 uint32_t set_disable;
1575 /* IPFW_DEFAULT_SET is always enabled */
1576 enable |= (1 << IPFW_DEFAULT_SET);
1577 set_disable = (ipfw_ctx[mycpuid]->ipfw_set_disable | disable) & ~enable;
1579 bzero(&nmsg, sizeof(nmsg));
1580 netmsg_init(&nmsg, NULL, &curthread->td_msgport,
1581 0, ipfw_set_disable_dispatch);
1582 lmsg = &nmsg.lmsg;
1583 lmsg->u.ms_result32 = set_disable;
1585 netisr_domsg(&nmsg, 0);
1590 * ipfw_ctl_x - extended version of ipfw_ctl
1591 * remove the x_header, and adjust the sopt_name,sopt_val and sopt_valsize.
1594 ipfw_ctl_x(struct sockopt *sopt)
1596 ip_fw_x_header *x_header;
1597 x_header = (ip_fw_x_header *)(sopt->sopt_val);
1598 sopt->sopt_name = x_header->opcode;
1599 sopt->sopt_valsize -= sizeof(ip_fw_x_header);
1600 bcopy(++x_header, sopt->sopt_val, sopt->sopt_valsize);
1601 return ipfw_ctl(sopt);
1606 * {set|get}sockopt parser.
1608 static int
1609 ipfw_ctl(struct sockopt *sopt)
1611 int error, rulenum;
1612 uint32_t *masks;
1613 size_t size;
1615 error = 0;
1616 switch (sopt->sopt_name) {
1617 case IP_FW_X:
1618 ipfw_ctl_x(sopt);
1619 break;
1620 case IP_FW_GET:
1621 error = ipfw_ctl_get_rules(sopt);
1622 break;
1623 case IP_FW_MODULE:
1624 error = ipfw_ctl_get_modules(sopt);
1625 break;
1627 case IP_FW_FLUSH:
1628 ipfw_ctl_flush_rule(0);
1629 break;
1631 case IP_FW_ADD:
1632 error = ipfw_ctl_add_rule(sopt);
1633 break;
1635 case IP_FW_DEL:
1637 * IP_FW_DEL is used for deleting single rules or sets,
1638 * and (ab)used to atomically manipulate sets.
1639 * Argument size is used to distinguish between the two:
1640 * sizeof(uint32_t)
1641 * delete single rule or set of rules,
1642 * or reassign rules (or sets) to a different set.
1643 * 2 * sizeof(uint32_t)
1644 * atomic disable/enable sets.
1645 * first uint32_t contains sets to be disabled,
1646 * second uint32_t contains sets to be enabled.
1648 masks = sopt->sopt_val;
1649 size = sopt->sopt_valsize;
1650 if (size == sizeof(*masks)) {
1652 * Delete or reassign static rule
1654 error = ipfw_ctl_alter(masks[0]);
1655 } else if (size == (2 * sizeof(*masks))) {
1657 * Set enable/disable
1659 ipfw_ctl_set_disable(masks[0], masks[1]);
1660 } else {
1661 error = EINVAL;
1663 break;
1664 case IP_FW_ZERO:
1665 case IP_FW_RESETLOG: /* argument is an int, the rule number */
1666 rulenum = 0;
1667 if (sopt->sopt_valsize != 0) {
1668 error = soopt_to_kbuf(sopt, &rulenum,
1669 sizeof(int), sizeof(int));
1670 if (error) {
1671 break;
1674 error = ipfw_ctl_zero_entry(rulenum,
1675 sopt->sopt_name == IP_FW_RESETLOG);
1676 break;
1677 case IP_FW_NAT_ADD:
1678 case IP_FW_NAT_DEL:
1679 case IP_FW_NAT_FLUSH:
1680 case IP_FW_NAT_GET:
1681 case IP_FW_NAT_GET_RECORD:
1682 if (ipfw_ctl_nat_ptr != NULL) {
1683 error = ipfw_ctl_nat_ptr(sopt);
1685 break;
1686 case IP_DUMMYNET_GET:
1687 case IP_DUMMYNET_CONFIGURE:
1688 case IP_DUMMYNET_DEL:
1689 case IP_DUMMYNET_FLUSH:
1690 error = ip_dn_sockopt(sopt);
1691 break;
1692 case IP_FW_STATE_ADD:
1693 error = ipfw_ctl_add_state(sopt);
1694 break;
1695 case IP_FW_STATE_DEL:
1696 error = ipfw_ctl_delete_state(sopt);
1697 break;
1698 case IP_FW_STATE_FLUSH:
1699 error = ipfw_ctl_flush_state(sopt);
1700 break;
1701 case IP_FW_TABLE_CREATE:
1702 case IP_FW_TABLE_DELETE:
1703 case IP_FW_TABLE_APPEND:
1704 case IP_FW_TABLE_REMOVE:
1705 case IP_FW_TABLE_LIST:
1706 case IP_FW_TABLE_FLUSH:
1707 case IP_FW_TABLE_SHOW:
1708 case IP_FW_TABLE_TEST:
1709 case IP_FW_TABLE_RENAME:
1710 error = ipfw_ctl_table_sockopt(sopt);
1711 break;
1712 case IP_FW_SYNC_SHOW_CONF:
1713 case IP_FW_SYNC_SHOW_STATUS:
1714 case IP_FW_SYNC_EDGE_CONF:
1715 case IP_FW_SYNC_EDGE_START:
1716 case IP_FW_SYNC_EDGE_STOP:
1717 case IP_FW_SYNC_EDGE_TEST:
1718 case IP_FW_SYNC_EDGE_CLEAR:
1719 case IP_FW_SYNC_CENTRE_CONF:
1720 case IP_FW_SYNC_CENTRE_START:
1721 case IP_FW_SYNC_CENTRE_STOP:
1722 case IP_FW_SYNC_CENTRE_TEST:
1723 case IP_FW_SYNC_CENTRE_CLEAR:
1724 error = ipfw_ctl_sync_sockopt(sopt);
1725 break;
1726 default:
1727 kprintf("ipfw_ctl invalid option %d\n",
1728 sopt->sopt_name);
1729 error = EINVAL;
1731 return error;
1734 static int
1735 ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1737 struct ip_fw_args args;
1738 struct mbuf *m = *m0;
1739 struct m_tag *mtag;
1740 int tee = 0, error = 0, ret;
1741 // again:
1742 if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1743 /* Extract info from dummynet tag */
1744 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1745 KKASSERT(mtag != NULL);
1746 args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1747 KKASSERT(args.rule != NULL);
1749 m_tag_delete(m, mtag);
1750 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1751 } else {
1752 args.rule = NULL;
1755 args.eh = NULL;
1756 args.oif = NULL;
1757 args.m = m;
1758 ret = ipfw_chk(&args);
1759 m = args.m;
1761 if (m == NULL) {
1762 error = EACCES;
1763 goto back;
1765 switch (ret) {
1766 case IP_FW_PASS:
1767 break;
1769 case IP_FW_DENY:
1770 m_freem(m);
1771 m = NULL;
1772 error = EACCES;
1773 break;
1775 case IP_FW_DUMMYNET:
1776 /* Send packet to the appropriate pipe */
1777 m = ipfw_dummynet_io(m, args.cookie, DN_TO_IP_IN,
1778 &args);
1779 break;
1781 case IP_FW_TEE:
1782 tee = 1;
1783 /* FALL THROUGH */
1785 case IP_FW_DIVERT:
1787 * Must clear bridge tag when changing
1789 m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED;
1790 if (ip_divert_p != NULL) {
1791 m = ip_divert_p(m, tee, 1);
1792 } else {
1793 m_freem(m);
1794 m = NULL;
1795 /* not sure this is the right error msg */
1796 error = EACCES;
1798 break;
1800 case IP_FW_NAT:
1801 break;
1802 case IP_FW_ROUTE:
1803 break;
1804 default:
1805 panic("unknown ipfw return value: %d", ret);
1807 back:
1808 *m0 = m;
1809 return error;
1812 static int
1813 ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1815 struct ip_fw_args args;
1816 struct mbuf *m = *m0;
1817 struct m_tag *mtag;
1818 int tee = 0, error = 0, ret;
1819 // again:
1820 if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1821 /* Extract info from dummynet tag */
1822 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1823 KKASSERT(mtag != NULL);
1824 args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1825 KKASSERT(args.rule != NULL);
1827 m_tag_delete(m, mtag);
1828 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1829 } else {
1830 args.rule = NULL;
1833 args.eh = NULL;
1834 args.m = m;
1835 args.oif = ifp;
1836 ret = ipfw_chk(&args);
1837 m = args.m;
1839 if (m == NULL) {
1840 error = EACCES;
1841 goto back;
1844 switch (ret) {
1845 case IP_FW_PASS:
1846 break;
1848 case IP_FW_DENY:
1849 m_freem(m);
1850 m = NULL;
1851 error = EACCES;
1852 break;
1854 case IP_FW_DUMMYNET:
1855 m = ipfw_dummynet_io(m, args.cookie, DN_TO_IP_OUT,
1856 &args);
1857 break;
1859 case IP_FW_TEE:
1860 tee = 1;
1861 /* FALL THROUGH */
1863 case IP_FW_DIVERT:
1864 if (ip_divert_p != NULL) {
1865 m = ip_divert_p(m, tee, 0);
1866 } else {
1867 m_freem(m);
1868 m = NULL;
1869 /* not sure this is the right error msg */
1870 error = EACCES;
1872 break;
1874 case IP_FW_NAT:
1875 break;
1876 case IP_FW_ROUTE:
1877 break;
1878 default:
1879 panic("unknown ipfw return value: %d", ret);
1881 back:
1882 *m0 = m;
1883 return error;
1886 static void
1887 ipfw_hook(void)
1889 struct pfil_head *pfh;
1890 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1892 pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1893 if (pfh == NULL)
1894 return;
1896 pfil_add_hook(ipfw_check_in, NULL, PFIL_IN, pfh);
1897 pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT, pfh);
1900 static void
1901 ipfw_dehook(void)
1903 struct pfil_head *pfh;
1905 IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1907 pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1908 if (pfh == NULL)
1909 return;
1911 pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN, pfh);
1912 pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT, pfh);
1915 static void
1916 ipfw_sysctl_enable_dispatch(netmsg_t nmsg)
1918 struct lwkt_msg *lmsg = &nmsg->lmsg;
1919 int enable = lmsg->u.ms_result;
1921 if (fw3_enable == enable)
1922 goto reply;
1924 fw3_enable = enable;
1925 if (fw3_enable)
1926 ipfw_hook();
1927 else
1928 ipfw_dehook();
1930 reply:
1931 lwkt_replymsg(lmsg, 0);
1934 static int
1935 ipfw_sysctl_enable(SYSCTL_HANDLER_ARGS)
1937 struct netmsg_base nmsg;
1938 struct lwkt_msg *lmsg;
1939 int enable, error;
1941 enable = fw3_enable;
1942 error = sysctl_handle_int(oidp, &enable, 0, req);
1943 if (error || req->newptr == NULL)
1944 return error;
1946 netmsg_init(&nmsg, NULL, &curthread->td_msgport,
1947 0, ipfw_sysctl_enable_dispatch);
1948 lmsg = &nmsg.lmsg;
1949 lmsg->u.ms_result = enable;
1951 return lwkt_domsg(IPFW_CFGPORT, lmsg, 0);
1954 static int
1955 ipfw_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS)
1957 return sysctl_int_range(oidp, arg1, arg2, req,
1958 IPFW_AUTOINC_STEP_MIN, IPFW_AUTOINC_STEP_MAX);
1962 static void
1963 ipfw_ctx_init_dispatch(netmsg_t nmsg)
1965 struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
1966 struct ipfw_context *ctx;
1967 struct ip_fw *def_rule;
1969 ctx = kmalloc(sizeof(struct ipfw_context), M_IPFW3, M_WAITOK | M_ZERO);
1970 ipfw_ctx[mycpuid] = ctx;
1972 def_rule = kmalloc(sizeof(struct ip_fw), M_IPFW3, M_WAITOK | M_ZERO);
1973 def_rule->act_ofs = 0;
1974 def_rule->rulenum = IPFW_DEFAULT_RULE;
1975 def_rule->cmd_len = 2;
1976 def_rule->set = IPFW_DEFAULT_SET;
1978 def_rule->cmd[0].len = LEN_OF_IPFWINSN;
1979 def_rule->cmd[0].module = MODULE_BASIC_ID;
1980 #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
1981 def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1982 #else
1983 if (filters_default_to_accept)
1984 def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1985 else
1986 def_rule->cmd[0].opcode = O_BASIC_DENY;
1987 #endif
1989 /* Install the default rule */
1990 ctx->ipfw_default_rule = def_rule;
1991 ctx->ipfw_rule_chain = def_rule;
1994 * if sibiling in last CPU is exists,
1995 * then it's sibling should be current rule
1997 if (fwmsg->sibling != NULL) {
1998 fwmsg->sibling->sibling = def_rule;
2000 /* prepare for next CPU */
2001 fwmsg->sibling = def_rule;
2003 /* Statistics only need to be updated once */
2004 if (mycpuid == 0)
2005 ipfw_inc_static_count(def_rule);
2007 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
2010 static void
2011 ipfw_init_dispatch(netmsg_t nmsg)
2013 struct netmsg_ipfw fwmsg;
2014 int error = 0;
2015 if (IPFW3_LOADED) {
2016 kprintf("ipfw3 already loaded\n");
2017 error = EEXIST;
2018 goto reply;
2021 bzero(&fwmsg, sizeof(fwmsg));
2022 netmsg_init(&fwmsg.base, NULL, &curthread->td_msgport,
2023 0, ipfw_ctx_init_dispatch);
2024 netisr_domsg(&fwmsg.base, 0);
2026 ip_fw_chk_ptr = ipfw_chk;
2027 ip_fw_ctl_x_ptr = ipfw_ctl_x;
2028 ip_fw_dn_io_ptr = ipfw_dummynet_io;
2030 kprintf("ipfw3 initialized, default to %s\n",
2031 filters_default_to_accept ? "accept" : "deny");
2033 ip_fw3_loaded = 1;
2034 if (fw3_enable)
2035 ipfw_hook();
2036 reply:
2037 lwkt_replymsg(&nmsg->lmsg, error);
2040 static int
2041 ipfw3_init(void)
2043 struct netmsg_base smsg;
2044 int error;
2046 ipfw3_log_modevent(MOD_LOAD);
2047 ipfw3_sync_modevent(MOD_LOAD);
2049 init_module();
2050 netmsg_init(&smsg, NULL, &curthread->td_msgport,
2051 0, ipfw_init_dispatch);
2052 error = lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
2053 netmsg_init(&smsg, NULL, &curthread->td_msgport,
2054 0, table_init_dispatch);
2055 error = lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
2056 return error;
2059 #ifdef KLD_MODULE
2061 static void
2062 ipfw_fini_dispatch(netmsg_t nmsg)
2064 int error = 0, cpu;
2066 ip_fw3_loaded = 0;
2068 ipfw_dehook();
2069 netmsg_service_sync();
2070 ip_fw_chk_ptr = NULL;
2071 ip_fw_ctl_x_ptr = NULL;
2072 ip_fw_dn_io_ptr = NULL;
2073 ipfw_ctl_flush_rule(1 /* kill default rule */);
2074 table_fini();
2075 /* Free pre-cpu context */
2076 for (cpu = 0; cpu < ncpus; ++cpu) {
2077 if (ipfw_ctx[cpu] != NULL) {
2078 kfree(ipfw_ctx[cpu], M_IPFW3);
2079 ipfw_ctx[cpu] = NULL;
2082 kprintf("ipfw3 unloaded\n");
2084 lwkt_replymsg(&nmsg->lmsg, error);
2087 static int
2088 ipfw3_fini(void)
2090 struct netmsg_base smsg;
2092 ipfw3_log_modevent(MOD_UNLOAD);
2093 ipfw3_sync_modevent(MOD_UNLOAD);
2095 netmsg_init(&smsg, NULL, &curthread->td_msgport,
2096 0, ipfw_fini_dispatch);
2097 return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
2100 #endif /* KLD_MODULE */
2102 static int
2103 ipfw3_modevent(module_t mod, int type, void *unused)
2105 int err = 0;
2107 switch (type) {
2108 case MOD_LOAD:
2109 err = ipfw3_init();
2110 break;
2112 case MOD_UNLOAD:
2114 #ifndef KLD_MODULE
2115 kprintf("ipfw statically compiled, cannot unload\n");
2116 err = EBUSY;
2117 #else
2118 err = ipfw3_fini();
2119 #endif
2120 break;
2121 default:
2122 break;
2124 return err;
2127 static moduledata_t ipfw3mod = {
2128 "ipfw3",
2129 ipfw3_modevent,
2132 /* ipfw3 must init before ipfw3_basic */
2133 DECLARE_MODULE(ipfw3, ipfw3mod, SI_SUB_PROTO_END, SI_ORDER_FIRST);
2134 MODULE_VERSION(ipfw3, 1);