kernel: Remove numerous #include <sys/thread2.h>.
[dragonfly.git] / sys / net / ipfw3 / ip_fw3.c
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) 2014 - 2018 The DragonFly Project.  All rights reserved.
6  *
7  * This code is derived from software contributed to The DragonFly Project
8  * by Bill Yuan <bycn82@dragonflybsd.org>
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
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.
23  *
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.
36  *
37  */
38
39 #include "opt_ipfw.h"
40 #include "opt_inet.h"
41 #ifndef INET
42 #error IPFIREWALL3 requires INET.
43 #endif /* INET */
44
45 #include <sys/param.h>
46 #include <sys/kernel.h>
47 #include <sys/malloc.h>
48 #include <sys/mbuf.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>
54 #include <sys/proc.h>
55 #include <sys/socket.h>
56 #include <sys/syslog.h>
57 #include <sys/ucred.h>
58 #include <sys/lock.h>
59 #include <sys/mplock2.h>
60
61 #include <net/if.h>
62 #include <net/radix.h>
63 #include <net/route.h>
64 #include <net/pfil.h>
65 #include <net/netmsg2.h>
66
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>
82
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>
92
93 MALLOC_DEFINE(M_IPFW3, "IPFW3", "ipfw3 module");
94
95 #define MAX_MODULE              10
96 #define MAX_OPCODE_PER_MODULE   100
97
98 #define IPFW_AUTOINC_STEP_MIN   1
99 #define IPFW_AUTOINC_STEP_MAX   1000
100 #define IPFW_AUTOINC_STEP_DEF   100
101
102
103 struct netmsg_ipfw {
104         struct netmsg_base base;
105         const struct ipfw_ioc_rule *ioc_rule;
106         struct ip_fw    *rule;
107         struct ip_fw    *next_rule;
108         struct ip_fw    *prev_rule;
109         struct ip_fw    *sibling;       /* sibling in prevous CPU */
110 };
111
112 struct netmsg_del {
113         struct netmsg_base base;
114         struct ip_fw    *rule;
115         struct ip_fw    *start_rule;
116         struct ip_fw    *prev_rule;
117         struct ipfw_ioc_state *ioc_state;
118         uint16_t        rulenum;
119         uint8_t         set_from;
120         uint8_t         set_to;
121         int             kill_default;
122 };
123
124 struct netmsg_zent {
125         struct netmsg_base base;
126         struct ip_fw    *start_rule;
127         uint16_t        rulenum;
128         uint16_t        log_only;
129 };
130
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;
136
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;
145
146 int     ip_fw3_sysctl_enable(SYSCTL_HANDLER_ARGS);
147 int     ip_fw3_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS);
148
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");
162
163
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;
168
169
170 void
171 ip_fw3_register_module(int module_id,char *module_name)
172 {
173         struct ipfw3_module *tmp;
174         int i;
175
176         tmp = fw3_modules;
177         for (i=0; i < MAX_MODULE; i++) {
178                 if (tmp->type == 0) {
179                         tmp->type = 1;
180                         tmp->id = module_id;
181                         strncpy(tmp->name, module_name, strlen(module_name));
182                         break;
183                 }
184                 tmp++;
185         }
186         kprintf("ipfw3 module %s loaded\n", module_name);
187 }
188
189 int
190 ip_fw3_unregister_module(int module_id)
191 {
192         struct ipfw3_module *tmp;
193         struct ip_fw *fw;
194         ipfw_insn *cmd;
195         int i, len, cmdlen, found;
196
197         found = 0;
198         tmp = fw3_modules;
199         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
200         fw = ctx->rules;
201         for (; fw; fw = fw->next) {
202                 for (len = fw->cmd_len, cmd = fw->cmd; len > 0;
203                         len -= cmdlen,
204                         cmd = (ipfw_insn *)((uint32_t *)cmd + cmdlen)) {
205                         cmdlen = F_LEN(cmd);
206                         if (cmd->module == 0 &&
207                                 (cmd->opcode == 0 || cmd->opcode == 1)) {
208                                 //action accept or deny
209                         } else if (cmd->module == module_id) {
210                                 found = 1;
211                                 goto decide;
212                         }
213                 }
214         }
215 decide:
216         if (found) {
217                 return 1;
218         } else {
219                 for (i = 0; i < MAX_MODULE; i++) {
220                         if (tmp->type == 1 && tmp->id == module_id) {
221                                 tmp->type = 0;
222                                 kprintf("ipfw3 module %s unloaded\n",
223                                                 tmp->name);
224                                 break;
225                         }
226                         tmp++;
227                 }
228
229                 for (i = 0; i < MAX_OPCODE_PER_MODULE; i++) {
230                         if (module_id == 0) {
231                                 if (i ==0 || i == 1) {
232                                         continue;
233                                 }
234                         }
235                         filter_funcs[module_id][i] = NULL;
236                 }
237                 return 0;
238         }
239 }
240
241 void
242 ip_fw3_register_filter_funcs(int module, int opcode, filter_func func)
243 {
244         filter_funcs[module][opcode] = func;
245 }
246
247 void
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)
250 {
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);
255         }
256 }
257
258 void
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)
261 {
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);
266         }
267 }
268
269 void
270 init_module(void)
271 {
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);
278 }
279
280 int
281 ip_fw3_free_rule(struct ip_fw *rule)
282 {
283         kfree(rule, M_IPFW3);
284         rule = NULL;
285         return 1;
286 }
287
288 static struct ip_fw *
289 lookup_next_rule(struct ip_fw *me)
290 {
291         struct ip_fw *rule = NULL;
292         ipfw_insn *cmd;
293
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)
300                                 break;
301                 }
302         }
303         if (rule == NULL) {     /* failure or not a skipto */
304                 rule = me->next;
305         }
306         me->next_rule = rule;
307         return rule;
308 }
309
310 /*
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.
317  */
318 int
319 ip_fw3_chk(struct ip_fw_args *args)
320 {
321         struct tcphdr *tcp;
322         struct udphdr *udp;
323         struct icmp *icmp;
324
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;
329         struct m_tag *mtag;
330         struct divert_info *divinfo;
331
332         /*
333          * hlen The length of the IPv4 header.
334          *      hlen >0 means we have an IPv4 packet.
335          */
336         u_int hlen = 0;         /* hlen >0 means we have an IP pkt */
337
338         /*
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.
343          */
344         u_short offset = 0;
345
346         uint8_t proto;
347         uint16_t src_port = 0, dst_port = 0;    /* NOTE: host format    */
348         struct in_addr src_ip, dst_ip;          /* NOTE: network format */
349         uint16_t ip_len = 0;
350         uint8_t prev_module = -1, prev_opcode = -1; /* previous module & opcode */
351         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
352
353         if (m->m_pkthdr.fw_flags & IPFW_MBUF_GENERATED)
354                 return IP_FW_PASS;      /* accept */
355
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;
360
361         /*
362          * Collect parameters into local variables for faster matching.
363          */
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;
367         }
368
369         proto = args->f_id.proto = ip->ip_p;
370         src_ip = ip->ip_src;
371         dst_ip = ip->ip_dst;
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);
375         } else {
376                 offset = ip->ip_off & IP_OFFMASK;
377                 ip_len = ip->ip_len;
378         }
379
380 #define PULLUP_TO(len)                                  \
381 do {                                                    \
382         if (m->m_len < (len)) {                         \
383                 args->m = m = m_pullup(m, (len));       \
384                         if (m == NULL)                  \
385                                 goto pullup_failed;     \
386                 ip = mtod(m, struct ip *);              \
387         }                                               \
388 } while (0)
389
390         if (offset == 0) {
391                 switch (proto) {
392                         case IPPROTO_TCP:
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;
398                                 break;
399                         case IPPROTO_UDP:
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;
404                                 break;
405                         case IPPROTO_ICMP:
406                                 PULLUP_TO(hlen + 4);
407                                 icmp = L3HDR(struct icmp, ip);
408                                 args->f_id.flags = icmp->icmp_type;
409                                 dst_port = icmp->icmp_id;
410                                 src_port = dst_port;
411                                 break;
412                         default:
413                                 break;
414                 }
415         }
416
417 #undef PULLUP_TO
418
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);
423
424 after_ip_checks:
425         if (args->rule) {
426                 /*
427                  * Packet has already been tagged. Look for the next rule
428                  * to restart processing.
429                  *
430                  * If sysctl_var_fw3_one_pass != 0 then just accept it.
431                  * XXX should not happen here, but optimized out in
432                  * the caller.
433                  */
434                 if (sysctl_var_fw3_one_pass)
435                         return IP_FW_PASS;
436
437                 /* This rule is being/has been flushed */
438                 if (sysctl_var_fw3_flushing)
439                         return IP_FW_DENY;
440
441                 f = args->rule->next_rule;
442                 if (f == NULL)
443                         f = lookup_next_rule(args->rule);
444         } else {
445                 /*
446                  * Find the starting rule. It can be either the first
447                  * one, or the one after divert_rule if asked so.
448                  */
449                 int skipto;
450
451                 mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
452                 if (mtag != NULL) {
453                         divinfo = m_tag_data(mtag);
454                         skipto = divinfo->skipto;
455                 } else {
456                         skipto = 0;
457                 }
458
459                 f = ctx->rules;
460                 if (args->eh == NULL && skipto != 0) {
461                         /* No skipto during rule flushing */
462                         if (sysctl_var_fw3_flushing) {
463                                 return IP_FW_DENY;
464                         }
465                         if (skipto >= IPFW_DEFAULT_RULE) {
466                                 return IP_FW_DENY; /* invalid */
467                         }
468                         while (f && f->rulenum <= skipto) {
469                                 f = f->next;
470                         }
471                         if (f == NULL) {        /* drop packet */
472                                 return IP_FW_DENY;
473                         }
474                 } else if (sysctl_var_fw3_flushing) {
475                         /* Rules are being flushed; skip to default rule */
476                         f = ctx->default_rule;
477                 }
478         }
479         if ((mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL)) != NULL) {
480                 m_tag_delete(m, mtag);
481         }
482
483         /*
484          * Now scan the rules, and parse microinstructions for each rule.
485          */
486         int prev_val;   /*  previous result of 'or' filter */
487         int l, cmdlen;
488         ipfw_insn *cmd;
489         int cmd_ctl;
490         /* foreach rule in chain */
491         for (; f; f = f->next) {
492 again:  /* check the rule again*/
493                 if (ctx->sets & (1 << f->set)) {
494                         continue;
495                 }
496
497                 prev_val = -1;
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)) {
501                         cmdlen = F_LEN(cmd);
502
503                         /* skip 'or' filter when already match */
504                         if (cmd->len & F_OR &&
505                                 cmd->module == prev_module &&
506                                 cmd->opcode == prev_opcode &&
507                                 prev_val == 1) {
508                                 goto next_cmd;
509                         }
510
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);
514                         switch(cmd_ctl) {
515                                 case IP_FW_CTL_DONE:
516                                         if (prev_val == 0) /* but 'or' failed */
517                                                 goto next_rule;
518                                         goto done;
519                                 case IP_FW_CTL_AGAIN:
520                                         goto again;
521                                 case IP_FW_CTL_NEXT:
522                                         goto next_rule;
523                                 case IP_FW_CTL_NAT:
524                                         args->rule=f;
525                                         goto done;
526                                 case IP_FW_CTL_CHK_STATE:
527                                         /* update the cmd and l */
528                                         cmd = ACTION_PTR(f);
529                                         l = f->cmd_len - f->act_ofs;
530                                         goto check_body;
531                         }
532                         if (cmd->len & F_NOT)
533                                 cmd_val= !cmd_val;
534
535                         if (cmd->len & F_OR) {  /* has 'or' */
536                                 if (!cmd_val) { /* not matched */
537                                         if(prev_val == -1){     /* first 'or' */
538                                                 prev_val = 0;
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 */
547                                                 if(prev_val == 0){
548                                                         goto next_rule;
549                                                 } else {
550                                                         prev_val = 0;
551                                                         prev_module = cmd->module;
552                                                         prev_opcode = cmd->opcode;
553                                                 }
554                                         }
555                                 } else { /* has 'or' and matched */
556                                         prev_val = 1;
557                                         prev_module = cmd->module;
558                                         prev_opcode = cmd->opcode;
559                                 }
560                         } else { /* no or */
561                                 if (!cmd_val) { /* not matched */
562                                         goto next_rule;
563                                 } else {
564                                         if (prev_val == 0) {
565                                                 /* previous 'or' not matched */
566                                                 goto next_rule;
567                                         } else {
568                                                 prev_val = -1;
569                                         }
570                                 }
571                         }
572 next_cmd:;
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");
577         return IP_FW_DENY;
578
579 done:
580         /* Update statistics */
581         f->pcnt++;
582         f->bcnt += ip_len;
583         f->timestamp = time_second;
584         return cmd_val;
585
586 pullup_failed:
587         if (sysctl_var_fw3_verbose)
588                 kprintf("pullup failed\n");
589         return IP_FW_DENY;
590 }
591
592 struct mbuf *
593 ip_fw3_dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa)
594 {
595         struct m_tag *mtag;
596         struct dn_pkt *pkt;
597         ipfw_insn *cmd;
598         const struct ipfw_flow_id *id;
599         struct dn_flow_id *fid;
600
601         M_ASSERTPKTHDR(m);
602
603         mtag = m_tag_get(PACKET_TAG_DUMMYNET, sizeof(*pkt),
604             M_INTWAIT | M_NULLOK);
605         if (mtag == NULL) {
606                 m_freem(m);
607                 return (NULL);
608         }
609         m_tag_prepend(m, mtag);
610
611         pkt = m_tag_data(mtag);
612         bzero(pkt, sizeof(*pkt));
613
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));
618
619         pkt->dn_m = m;
620         pkt->dn_flags = (dir & DN_FLAGS_DIR_MASK);
621         pkt->ifp = fwa->oif;
622         pkt->pipe_nr = pipe_nr;
623
624         pkt->cpuid = mycpuid;
625         pkt->msgport = netisr_curport();
626
627         id = &fwa->f_id;
628         fid = &pkt->id;
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;
635
636         pkt->dn_priv = fwa->rule;
637
638         if ((int)cmd->opcode == O_DUMMYNET_PIPE)
639                 pkt->dn_flags |= DN_FLAGS_IS_PIPE;
640
641         m->m_pkthdr.fw_flags |= DUMMYNET_MBUF_TAGGED;
642         return (m);
643 }
644
645
646 void
647 add_rule_dispatch(netmsg_t nmsg)
648 {
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;
653
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);
662
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) {
667                                 break;
668                         }
669                 } else {
670                         if (next->rulenum > ioc_rule->rulenum) {
671                                 break;
672                         }
673                 }
674         }
675         KASSERT(next != NULL, ("no default rule?!"));
676
677         /*
678          * Insert rule into the pre-determined position
679          */
680         if (prev != NULL) {
681                 rule->next = next;
682                 prev->next = rule;
683         } else {
684                 rule->next = ctx->rules;
685                 ctx->rules = rule;
686         }
687
688         /*
689          * if sibiling in last CPU is exists,
690          * then it's sibling should be current rule
691          */
692         if (fwmsg->sibling != NULL) {
693                 fwmsg->sibling->sibling = rule;
694         }
695         /* prepare for next CPU */
696         fwmsg->sibling = rule;
697
698         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
699 }
700
701 /*
702  * confirm the rulenumber
703  * call dispatch function to add rule into the list
704  * Update the statistic
705  */
706 void
707 ip_fw3_add_rule(struct ipfw_ioc_rule *ioc_rule)
708 {
709         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
710         struct netmsg_ipfw fwmsg;
711         struct netmsg_base *nmsg;
712         struct ip_fw *f;
713
714         IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
715
716         /*
717          * If rulenum is 0, find highest numbered rule before the
718          * default rule, and add rule number incremental step.
719          */
720         if (ioc_rule->rulenum == 0) {
721                 int step = sysctl_var_autoinc_step;
722
723                 KKASSERT(step >= IPFW_AUTOINC_STEP_MIN &&
724                                 step <= IPFW_AUTOINC_STEP_MAX);
725
726                 /*
727                  * Locate the highest numbered rule before default
728                  */
729                 for (f = ctx->rules; f; f = f->next) {
730                         if (f->rulenum == IPFW_DEFAULT_RULE)
731                                 break;
732                         ioc_rule->rulenum = f->rulenum;
733                 }
734                 if (ioc_rule->rulenum < IPFW_DEFAULT_RULE - step)
735                         ioc_rule->rulenum += step;
736         }
737         KASSERT(ioc_rule->rulenum != IPFW_DEFAULT_RULE &&
738                         ioc_rule->rulenum != 0,
739                         ("invalid rule num %d", ioc_rule->rulenum));
740
741         bzero(&fwmsg, sizeof(fwmsg));
742         nmsg = &fwmsg.base;
743         netmsg_init(nmsg, NULL, &curthread->td_msgport,
744                         0, add_rule_dispatch);
745         fwmsg.ioc_rule = ioc_rule;
746
747         netisr_domsg(nmsg, 0);
748
749         IPFW3_DEBUG("++ installed rule %d, static count now %d\n",
750                         ioc_rule->rulenum, static_count);
751 }
752
753 /**
754  * Free storage associated with a static rule (including derived
755  * dynamic rules).
756  * The caller is in charge of clearing rule pointers to avoid
757  * dangling pointers.
758  * @return a pointer to the next entry.
759  * Arguments are not checked, so they better be correct.
760  * Must be called at splimp().
761  */
762 struct ip_fw *
763 ip_fw3_delete_rule(struct ipfw3_context *ctx,
764                  struct ip_fw *prev, struct ip_fw *rule)
765 {
766         if (prev == NULL)
767                 ctx->rules = rule->next;
768         else
769                 prev->next = rule->next;
770
771         kfree(rule, M_IPFW3);
772         rule = NULL;
773         return NULL;
774 }
775
776 void
777 flush_rule_dispatch(netmsg_t nmsg)
778 {
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;
783
784         rule = ctx->rules;
785         while (rule != NULL) {
786                 if (rule->rulenum == IPFW_DEFAULT_RULE && kill_default == 0) {
787                         ctx->rules = rule;
788                         break;
789                 }
790                 the_rule = rule;
791                 rule = rule->next;
792
793                 kfree(the_rule, M_IPFW3);
794         }
795
796         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
797 }
798
799
800 /*
801  * Deletes all rules from a chain (including the default rule
802  * if the second argument is set).
803  * Must be called at splimp().
804  */
805 void
806 ip_fw3_ctl_flush_rule(int kill_default)
807 {
808         struct netmsg_del dmsg;
809
810         IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
811
812         if (!kill_default) {
813                 sysctl_var_fw3_flushing = 1;
814                 netmsg_service_sync();
815         }
816         /*
817          * Press the 'flush' button
818          */
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);
824
825         /* Flush is done */
826         sysctl_var_fw3_flushing = 0;
827 }
828
829 void
830 delete_rule_dispatch(netmsg_t nmsg)
831 {
832         struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
833         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
834         struct ip_fw *rule, *prev = NULL;
835
836         rule = ctx->rules;
837         while (rule!=NULL) {
838                 if (rule->rulenum == dmsg->rulenum) {
839                         ip_fw3_delete_rule(ctx, prev, rule);
840                         break;
841                 }
842                 prev = rule;
843                 rule = rule->next;
844         }
845
846         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
847 }
848
849 int
850 ip_fw3_ctl_delete_rule(struct sockopt *sopt)
851 {
852         struct netmsg_del dmsg;
853         struct netmsg_base *nmsg;
854         int *rulenum;
855
856         rulenum = (int *) sopt->sopt_val;
857
858
859         /*
860          * Get rid of the rule duplications on all CPUs
861          */
862         bzero(&dmsg, sizeof(dmsg));
863         nmsg = &dmsg.base;
864         netmsg_init(nmsg, NULL, &curthread->td_msgport,
865                         0, delete_rule_dispatch);
866         dmsg.rulenum = *rulenum;
867         netisr_domsg(nmsg, 0);
868         return 0;
869 }
870
871 /*
872  * Clear counters for a specific rule.
873  */
874 void
875 ip_fw3_clear_counters(struct ip_fw *rule)
876 {
877         rule->bcnt = rule->pcnt = 0;
878         rule->timestamp = 0;
879 }
880
881 void
882 ip_fw3_zero_entry_dispatch(netmsg_t nmsg)
883 {
884         struct netmsg_zent *zmsg = (struct netmsg_zent *)nmsg;
885         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
886         struct ip_fw *rule;
887
888         if (zmsg->rulenum == 0) {
889                 for (rule = ctx->rules; rule; rule = rule->next) {
890                         ip_fw3_clear_counters(rule);
891                 }
892         } else {
893                 for (rule = ctx->rules; rule; rule = rule->next) {
894                         if (rule->rulenum == zmsg->rulenum) {
895                                 ip_fw3_clear_counters(rule);
896                         }
897                 }
898         }
899         ip_fw3_clear_counters(ctx->default_rule);
900         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
901 }
902
903 /**
904  * Reset some or all counters on firewall rules.
905  * @arg frwl is null to clear all entries, or contains a specific
906  * rule number.
907  * @arg log_only is 1 if we only want to reset logs, zero otherwise.
908  */
909 int
910 ip_fw3_ctl_zero_entry(int rulenum, int log_only)
911 {
912         struct netmsg_zent zmsg;
913         struct netmsg_base *nmsg;
914         const char *msg;
915         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
916
917         bzero(&zmsg, sizeof(zmsg));
918         nmsg = &zmsg.base;
919         netmsg_init(nmsg, NULL, &curthread->td_msgport,
920                         0, ip_fw3_zero_entry_dispatch);
921         zmsg.log_only = log_only;
922
923         if (rulenum == 0) {
924                 msg = log_only ? "ipfw: All logging counts reset.\n"
925                                    : "ipfw: Accounting cleared.\n";
926         } else {
927                 struct ip_fw *rule;
928
929                 /*
930                  * Locate the first rule with 'rulenum'
931                  */
932                 for (rule = ctx->rules; rule; rule = rule->next) {
933                         if (rule->rulenum == rulenum)
934                                 break;
935                 }
936                 if (rule == NULL) /* we did not find any matching rules */
937                         return (EINVAL);
938                 zmsg.start_rule = rule;
939                 zmsg.rulenum = rulenum;
940
941                 msg = log_only ? "ipfw: Entry %d logging count reset.\n"
942                                    : "ipfw: Entry %d cleared.\n";
943         }
944         netisr_domsg(nmsg, 0);
945         KKASSERT(zmsg.start_rule == NULL);
946
947         if (sysctl_var_fw3_verbose)
948                 log(LOG_SECURITY | LOG_NOTICE, msg, rulenum);
949         return (0);
950 }
951
952 /*
953  * Get the ioc_rule from the sopt
954  * call ip_fw3_add_rule to add the rule
955  */
956 int
957 ip_fw3_ctl_add_rule(struct sockopt *sopt)
958 {
959         struct ipfw_ioc_rule *ioc_rule;
960         size_t size;
961
962         size = sopt->sopt_valsize;
963         if (size > (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX) ||
964                         size < sizeof(*ioc_rule) - sizeof(ipfw_insn)) {
965                 return EINVAL;
966         }
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);
970         }
971         ioc_rule = sopt->sopt_val;
972
973         ip_fw3_add_rule(ioc_rule);
974         return 0;
975 }
976
977 int
978 ip_fw3_ctl_get_modules(struct sockopt *sopt)
979 {
980         int i;
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) {
986                         if (i > 0)
987                                 strcat(module_str,",");
988                         strcat(module_str,mod->name);
989                 }
990         }
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);
994         return 0;
995 }
996
997 /*
998  * Copy all static rules and states on all CPU
999  */
1000 int
1001 ip_fw3_ctl_get_rules(struct sockopt *sopt)
1002 {
1003         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
1004         struct ip_fw *rule;
1005         struct ipfw_ioc_rule *ioc;
1006         const struct ip_fw *sibling;
1007         int total_len = 0;
1008
1009         ioc = (struct ipfw_ioc_rule *)sopt->sopt_val;
1010
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);
1015                         return 0;
1016                 }
1017                 ioc->act_ofs = rule->act_ofs;
1018                 ioc->cmd_len = rule->cmd_len;
1019                 ioc->rulenum = rule->rulenum;
1020                 ioc->set = rule->set;
1021
1022                 ioc->sets = fw3_ctx[mycpuid]->sets;
1023                 ioc->pcnt = 0;
1024                 ioc->bcnt = 0;
1025                 ioc->timestamp = 0;
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;
1031                 }
1032                 bcopy(rule->cmd, ioc->cmd, ioc->cmd_len * 4);
1033                 ioc = (struct ipfw_ioc_rule *)((uint8_t *)ioc + IOC_RULESIZE(ioc));
1034         }
1035         sopt->sopt_valsize = total_len;
1036         return 0;
1037 }
1038
1039
1040 /*
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.
1043  */
1044 int
1045 ip_fw3_ctl_x(struct sockopt *sopt)
1046 {
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);
1053 }
1054
1055
1056 /**
1057  * {set|get}sockopt parser.
1058  */
1059 int
1060 ip_fw3_ctl(struct sockopt *sopt)
1061 {
1062         int error = 0;
1063         switch (sopt->sopt_name) {
1064                 case IP_FW_X:
1065                         ip_fw3_ctl_x(sopt);
1066                         break;
1067                 case IP_FW_GET:
1068                 case IP_FW_MODULE:
1069                 case IP_FW_FLUSH:
1070                 case IP_FW_ADD:
1071                 case IP_FW_DEL:
1072                 case IP_FW_ZERO:
1073                 case IP_FW_RESETLOG:
1074                         error = ip_fw3_ctl_sockopt(sopt);
1075                         break;
1076                 case IP_FW_SET_GET:
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);
1082                         break;
1083                 case IP_FW_NAT_ADD:
1084                 case IP_FW_NAT_DEL:
1085                 case IP_FW_NAT_FLUSH:
1086                 case IP_FW_NAT_GET:
1087                 case IP_FW_NAT_GET_RECORD:
1088                         if (ip_fw3_ctl_nat_ptr != NULL) {
1089                                 error = ip_fw3_ctl_nat_ptr(sopt);
1090                         }
1091                         break;
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);
1097                         break;
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);
1104                         }
1105                         break;
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);
1117                         }
1118                         break;
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);
1133                         }
1134                         break;
1135                 default:
1136                         kprintf("ip_fw3_ctl invalid option %d\n",
1137                                 sopt->sopt_name);
1138                         error = EINVAL;
1139         }
1140         return error;
1141 }
1142
1143 int
1144 ip_fw3_ctl_sockopt(struct sockopt *sopt)
1145 {
1146         int error = 0, rulenum;
1147
1148         switch (sopt->sopt_name) {
1149                 case IP_FW_GET:
1150                         error = ip_fw3_ctl_get_rules(sopt);
1151                         break;
1152                 case IP_FW_MODULE:
1153                         error = ip_fw3_ctl_get_modules(sopt);
1154                         break;
1155                 case IP_FW_FLUSH:
1156                         ip_fw3_ctl_flush_rule(0);
1157                         break;
1158                 case IP_FW_ADD:
1159                         error = ip_fw3_ctl_add_rule(sopt);
1160                         break;
1161                 case IP_FW_DEL:
1162                         error = ip_fw3_ctl_delete_rule(sopt);
1163                         break;
1164                 case IP_FW_ZERO:
1165                 case IP_FW_RESETLOG: /* argument is an int, the rule number */
1166                         rulenum = 0;
1167                         if (sopt->sopt_valsize != 0) {
1168                                 error = soopt_to_kbuf(sopt, &rulenum,
1169                                                 sizeof(int), sizeof(int));
1170                                 if (error) {
1171                                         break;
1172                                 }
1173                         }
1174                         error = ip_fw3_ctl_zero_entry(rulenum,
1175                                         sopt->sopt_name == IP_FW_RESETLOG);
1176                         break;
1177                 default:
1178                         kprintf("ip_fw3_ctl invalid option %d\n",
1179                                 sopt->sopt_name);
1180                         error = EINVAL;
1181         }
1182         return error;
1183 }
1184
1185 int
1186 ip_fw3_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1187 {
1188         struct ip_fw_args args;
1189         struct mbuf *m = *m0;
1190         struct m_tag *mtag;
1191         int tee = 0, error = 0, ret;
1192         // again:
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);
1199
1200                 m_tag_delete(m, mtag);
1201                 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1202         } else {
1203                 args.rule = NULL;
1204         }
1205
1206         args.eh = NULL;
1207         args.oif = NULL;
1208         args.m = m;
1209         ret = ip_fw3_chk(&args);
1210         m = args.m;
1211
1212         if (m == NULL) {
1213                 error = EACCES;
1214                 goto back;
1215         }
1216         switch (ret) {
1217                 case IP_FW_PASS:
1218                         break;
1219
1220                 case IP_FW_DENY:
1221                         m_freem(m);
1222                         m = NULL;
1223                         error = EACCES;
1224                         break;
1225
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,
1229                             &args);
1230                         break;
1231                 case IP_FW_TEE:
1232                         tee = 1;
1233                         /* FALL THROUGH */
1234                 case IP_FW_DIVERT:
1235                         /*
1236                          * Must clear bridge tag when changing
1237                          */
1238                         m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED;
1239                         if (ip_divert_p != NULL) {
1240                                 m = ip_divert_p(m, tee, 1);
1241                         } else {
1242                                 m_freem(m);
1243                                 m = NULL;
1244                                 /* not sure this is the right error msg */
1245                                 error = EACCES;
1246                         }
1247                         break;
1248                 case IP_FW_NAT:
1249                         break;
1250                 case IP_FW_ROUTE:
1251                         break;
1252                 default:
1253                         panic("unknown ipfw3 return value: %d", ret);
1254         }
1255 back:
1256         *m0 = m;
1257         return error;
1258 }
1259
1260 int
1261 ip_fw3_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1262 {
1263         struct ip_fw_args args;
1264         struct mbuf *m = *m0;
1265         struct m_tag *mtag;
1266         int tee = 0, error = 0, ret;
1267         // again:
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);
1274
1275                 m_tag_delete(m, mtag);
1276                 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1277         } else {
1278                 args.rule = NULL;
1279         }
1280
1281         args.eh = NULL;
1282         args.m = m;
1283         args.oif = ifp;
1284         ret = ip_fw3_chk(&args);
1285         m = args.m;
1286
1287         if (m == NULL) {
1288                 error = EACCES;
1289                 goto back;
1290         }
1291
1292         switch (ret) {
1293                 case IP_FW_PASS:
1294                         break;
1295
1296                 case IP_FW_DENY:
1297                         m_freem(m);
1298                         m = NULL;
1299                         error = EACCES;
1300                         break;
1301
1302                 case IP_FW_DUMMYNET:
1303                         m = ip_fw3_dummynet_io(m, args.cookie, DN_TO_IP_OUT,
1304                             &args);
1305                         break;
1306
1307                 case IP_FW_TEE:
1308                         tee = 1;
1309                         /* FALL THROUGH */
1310
1311                 case IP_FW_DIVERT:
1312                         if (ip_divert_p != NULL) {
1313                                 m = ip_divert_p(m, tee, 0);
1314                         } else {
1315                                 m_freem(m);
1316                                 m = NULL;
1317                                 /* not sure this is the right error msg */
1318                                 error = EACCES;
1319                         }
1320                         break;
1321
1322                 case IP_FW_NAT:
1323                         break;
1324                 case IP_FW_ROUTE:
1325                         break;
1326                 default:
1327                         panic("unknown ipfw3 return value: %d", ret);
1328         }
1329 back:
1330         *m0 = m;
1331         return error;
1332 }
1333
1334 void
1335 ip_fw3_hook(void)
1336 {
1337         struct pfil_head *pfh;
1338         IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1339
1340         pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1341         if (pfh == NULL)
1342                 return;
1343
1344         pfil_add_hook(ip_fw3_check_in, NULL, PFIL_IN, pfh);
1345         pfil_add_hook(ip_fw3_check_out, NULL, PFIL_OUT, pfh);
1346 }
1347
1348 void
1349 ip_fw3_dehook(void)
1350 {
1351         struct pfil_head *pfh;
1352
1353         IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1354
1355         pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1356         if (pfh == NULL)
1357                 return;
1358
1359         pfil_remove_hook(ip_fw3_check_in, NULL, PFIL_IN, pfh);
1360         pfil_remove_hook(ip_fw3_check_out, NULL, PFIL_OUT, pfh);
1361 }
1362
1363 void
1364 ip_fw3_sysctl_enable_dispatch(netmsg_t nmsg)
1365 {
1366         struct lwkt_msg *lmsg = &nmsg->lmsg;
1367         int enable = lmsg->u.ms_result;
1368
1369         if (sysctl_var_fw3_enable == enable)
1370                 goto reply;
1371
1372         sysctl_var_fw3_enable = enable;
1373         if (sysctl_var_fw3_enable)
1374                 ip_fw3_hook();
1375         else
1376                 ip_fw3_dehook();
1377
1378 reply:
1379         lwkt_replymsg(lmsg, 0);
1380 }
1381
1382 int
1383 ip_fw3_sysctl_enable(SYSCTL_HANDLER_ARGS)
1384 {
1385         struct netmsg_base nmsg;
1386         struct lwkt_msg *lmsg;
1387         int enable, error;
1388
1389         enable = sysctl_var_fw3_enable;
1390         error = sysctl_handle_int(oidp, &enable, 0, req);
1391         if (error || req->newptr == NULL)
1392                 return error;
1393
1394         netmsg_init(&nmsg, NULL, &curthread->td_msgport,
1395                         0, ip_fw3_sysctl_enable_dispatch);
1396         lmsg = &nmsg.lmsg;
1397         lmsg->u.ms_result = enable;
1398
1399         return lwkt_domsg(IPFW_CFGPORT, lmsg, 0);
1400 }
1401
1402 int
1403 ip_fw3_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS)
1404 {
1405         return sysctl_int_range(oidp, arg1, arg2, req,
1406                         IPFW_AUTOINC_STEP_MIN, IPFW_AUTOINC_STEP_MAX);
1407 }
1408
1409 void
1410 ctx_init_dispatch(netmsg_t nmsg)
1411 {
1412         struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
1413         struct ipfw3_context *ctx;
1414         struct ip_fw *def_rule;
1415
1416         ctx = kmalloc(LEN_FW3_CTX, M_IPFW3, M_WAITOK | M_ZERO);
1417         fw3_ctx[mycpuid] = ctx;
1418         ctx->sets = IPFW_ALL_SETS;
1419
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;
1425
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;
1430 #else
1431         if (filters_default_to_accept)
1432                 def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1433         else
1434                 def_rule->cmd[0].opcode = O_BASIC_DENY;
1435 #endif
1436
1437         /* Install the default rule */
1438         ctx->default_rule = def_rule;
1439         ctx->rules = def_rule;
1440
1441         /*
1442          * if sibiling in last CPU is exists,
1443          * then it's sibling should be current rule
1444          */
1445         if (fwmsg->sibling != NULL) {
1446                 fwmsg->sibling->sibling = def_rule;
1447         }
1448         /* prepare for next CPU */
1449         fwmsg->sibling = def_rule;
1450
1451         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1452 }
1453
1454 void
1455 init_dispatch(netmsg_t nmsg)
1456 {
1457         struct netmsg_ipfw fwmsg;
1458         int error = 0;
1459         if (IPFW3_LOADED) {
1460                 kprintf("ipfw3 already loaded\n");
1461                 error = EEXIST;
1462                 goto reply;
1463         }
1464
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);
1469
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;
1473
1474         kprintf("ipfw3 initialized, default to %s\n",
1475                         filters_default_to_accept ? "accept" : "deny");
1476
1477         ip_fw3_loaded = 1;
1478         if (sysctl_var_fw3_enable)
1479                 ip_fw3_hook();
1480 reply:
1481         lwkt_replymsg(&nmsg->lmsg, error);
1482 }
1483
1484 int
1485 ip_fw3_init(void)
1486 {
1487         struct netmsg_base smsg;
1488         int error;
1489
1490         init_module();
1491         netmsg_init(&smsg, NULL, &curthread->td_msgport,
1492                         0, init_dispatch);
1493         error = lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1494         return error;
1495 }
1496
1497 #ifdef KLD_MODULE
1498
1499 void
1500 fini_dispatch(netmsg_t nmsg)
1501 {
1502         int error = 0, cpu;
1503
1504         ip_fw3_loaded = 0;
1505
1506         ip_fw3_dehook();
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;
1517                 }
1518         }
1519         kprintf("ipfw3 unloaded\n");
1520
1521         lwkt_replymsg(&nmsg->lmsg, error);
1522 }
1523
1524 int
1525 ip_fw3_fini(void)
1526 {
1527         struct netmsg_base smsg;
1528
1529         netmsg_init(&smsg, NULL, &curthread->td_msgport,
1530                         0, fini_dispatch);
1531         return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1532 }
1533
1534 #endif  /* KLD_MODULE */
1535
1536 static int
1537 ip_fw3_modevent(module_t mod, int type, void *unused)
1538 {
1539         int err = 0;
1540
1541         switch (type) {
1542                 case MOD_LOAD:
1543                         err = ip_fw3_init();
1544                         break;
1545
1546                 case MOD_UNLOAD:
1547
1548 #ifndef KLD_MODULE
1549                         kprintf("ipfw3 statically compiled, cannot unload\n");
1550                         err = EBUSY;
1551 #else
1552                         err = ip_fw3_fini();
1553 #endif
1554                         break;
1555                 default:
1556                         break;
1557         }
1558         return err;
1559 }
1560
1561 static moduledata_t ipfw3mod = {
1562         "ipfw3",
1563         ip_fw3_modevent,
1564         0
1565 };
1566 /* ipfw3 must init before ipfw3_basic */
1567 DECLARE_MODULE(ipfw3, ipfw3mod, SI_SUB_PROTO_END, SI_ORDER_FIRST);
1568 MODULE_VERSION(ipfw3, 1);