e53964cacc8aca96b7dccfc53317d50d9adb6ba1
[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/thread2.h>
53 #include <sys/in_cksum.h>
54 #include <sys/systm.h>
55 #include <sys/proc.h>
56 #include <sys/socket.h>
57 #include <sys/syslog.h>
58 #include <sys/ucred.h>
59 #include <sys/lock.h>
60 #include <sys/mplock2.h>
61
62 #include <net/if.h>
63 #include <net/radix.h>
64 #include <net/route.h>
65 #include <net/pfil.h>
66 #include <net/netmsg2.h>
67
68 #include <netinet/in.h>
69 #include <netinet/in_systm.h>
70 #include <netinet/in_var.h>
71 #include <netinet/in_pcb.h>
72 #include <netinet/ip.h>
73 #include <netinet/ip_var.h>
74 #include <netinet/ip_icmp.h>
75 #include <netinet/tcp.h>
76 #include <netinet/tcp_timer.h>
77 #include <netinet/tcp_var.h>
78 #include <netinet/tcpip.h>
79 #include <netinet/udp.h>
80 #include <netinet/udp_var.h>
81 #include <netinet/ip_divert.h>
82 #include <netinet/if_ether.h>
83
84 #include <net/ipfw3/ip_fw.h>
85 #include <net/ipfw3/ip_fw3_set.h>
86 #include <net/ipfw3_basic/ip_fw3_log.h>
87 #include <net/ipfw3_basic/ip_fw3_table.h>
88 #include <net/ipfw3_basic/ip_fw3_sync.h>
89 #include <net/ipfw3_basic/ip_fw3_basic.h>
90 #include <net/ipfw3_basic/ip_fw3_state.h>
91 #include <net/ipfw3_nat/ip_fw3_nat.h>
92 #include <net/dummynet3/ip_dummynet3.h>
93
94 MALLOC_DEFINE(M_IPFW3, "IPFW3", "ipfw3 module");
95
96 #define MAX_MODULE              10
97 #define MAX_OPCODE_PER_MODULE   100
98
99 #define IPFW_AUTOINC_STEP_MIN   1
100 #define IPFW_AUTOINC_STEP_MAX   1000
101 #define IPFW_AUTOINC_STEP_DEF   100
102
103
104 struct netmsg_ipfw {
105         struct netmsg_base base;
106         const struct ipfw_ioc_rule *ioc_rule;
107         struct ip_fw    *rule;
108         struct ip_fw    *next_rule;
109         struct ip_fw    *prev_rule;
110         struct ip_fw    *sibling;       /* sibling in prevous CPU */
111 };
112
113 struct netmsg_del {
114         struct netmsg_base base;
115         struct ip_fw    *rule;
116         struct ip_fw    *start_rule;
117         struct ip_fw    *prev_rule;
118         struct ipfw_ioc_state *ioc_state;
119         uint16_t        rulenum;
120         uint8_t         set_from;
121         uint8_t         set_to;
122         int             kill_default;
123 };
124
125 struct netmsg_zent {
126         struct netmsg_base base;
127         struct ip_fw    *start_rule;
128         uint16_t        rulenum;
129         uint16_t        log_only;
130 };
131
132 ip_fw_ctl_t     *ip_fw3_ctl_nat_ptr = NULL;
133 ip_fw_ctl_t     *ip_fw3_ctl_state_ptr = NULL;
134 ip_fw_ctl_t     *ip_fw3_ctl_table_ptr = NULL;
135 ip_fw_ctl_t     *ip_fw3_ctl_sync_ptr = NULL;
136 ip_fw_log_t     *ip_fw3_log_ptr = NULL;
137
138 extern int ip_fw_loaded;
139 extern struct ipfw3_state_context       *fw3_state_ctx[MAXCPU];
140 int                     sysctl_var_fw3_enable = 1;
141 int                     sysctl_var_fw3_one_pass = 1;
142 int                     sysctl_var_fw3_verbose = 0;
143 static int              sysctl_var_fw3_flushing;
144 static int              sysctl_var_fw3_debug;
145 static int              sysctl_var_autoinc_step = IPFW_AUTOINC_STEP_DEF;
146
147 int     ip_fw3_sysctl_enable(SYSCTL_HANDLER_ARGS);
148 int     ip_fw3_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS);
149
150 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw3, CTLFLAG_RW, 0, "Firewall");
151 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, enable, CTLTYPE_INT | CTLFLAG_RW,
152         &sysctl_var_fw3_enable, 0, ip_fw3_sysctl_enable, "I", "Enable ipfw");
153 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, sysctl_var_autoinc_step,
154         CTLTYPE_INT | CTLFLAG_RW, &sysctl_var_autoinc_step, 0,
155         ip_fw3_sysctl_autoinc_step, "I", "Rule number autincrement step");
156 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO,one_pass,CTLFLAG_RW,
157         &sysctl_var_fw3_one_pass, 0,
158         "Only do a single pass through ipfw3 when using dummynet(4)");
159 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, debug, CTLFLAG_RW,
160         &sysctl_var_fw3_debug, 0, "Enable printing of debug ip_fw statements");
161 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, verbose, CTLFLAG_RW,
162         &sysctl_var_fw3_verbose, 0, "Log matches to ipfw3 rules");
163
164
165 filter_func                     filter_funcs[MAX_MODULE][MAX_OPCODE_PER_MODULE];
166 struct ipfw3_module             fw3_modules[MAX_MODULE];
167 struct ipfw3_context            *fw3_ctx[MAXCPU];
168 struct ipfw3_sync_context       fw3_sync_ctx;
169
170
171 void
172 ip_fw3_register_module(int module_id,char *module_name)
173 {
174         struct ipfw3_module *tmp;
175         int i;
176
177         tmp = fw3_modules;
178         for (i=0; i < MAX_MODULE; i++) {
179                 if (tmp->type == 0) {
180                         tmp->type = 1;
181                         tmp->id = module_id;
182                         strncpy(tmp->name, module_name, strlen(module_name));
183                         break;
184                 }
185                 tmp++;
186         }
187         kprintf("ipfw3 module %s loaded\n", module_name);
188 }
189
190 int
191 ip_fw3_unregister_module(int module_id)
192 {
193         struct ipfw3_module *tmp;
194         struct ip_fw *fw;
195         ipfw_insn *cmd;
196         int i, len, cmdlen, found;
197
198         found = 0;
199         tmp = fw3_modules;
200         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
201         fw = ctx->rules;
202         for (; fw; fw = fw->next) {
203                 for (len = fw->cmd_len, cmd = fw->cmd; len > 0;
204                         len -= cmdlen,
205                         cmd = (ipfw_insn *)((uint32_t *)cmd + cmdlen)) {
206                         cmdlen = F_LEN(cmd);
207                         if (cmd->module == 0 &&
208                                 (cmd->opcode == 0 || cmd->opcode == 1)) {
209                                 //action accept or deny
210                         } else if (cmd->module == module_id) {
211                                 found = 1;
212                                 goto decide;
213                         }
214                 }
215         }
216 decide:
217         if (found) {
218                 return 1;
219         } else {
220                 for (i = 0; i < MAX_MODULE; i++) {
221                         if (tmp->type == 1 && tmp->id == module_id) {
222                                 tmp->type = 0;
223                                 kprintf("ipfw3 module %s unloaded\n",
224                                                 tmp->name);
225                                 break;
226                         }
227                         tmp++;
228                 }
229
230                 for (i = 0; i < MAX_OPCODE_PER_MODULE; i++) {
231                         if (module_id == 0) {
232                                 if (i ==0 || i == 1) {
233                                         continue;
234                                 }
235                         }
236                         filter_funcs[module_id][i] = NULL;
237                 }
238                 return 0;
239         }
240 }
241
242 void
243 ip_fw3_register_filter_funcs(int module, int opcode, filter_func func)
244 {
245         filter_funcs[module][opcode] = func;
246 }
247
248 void
249 check_accept(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
250                 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
251 {
252         *cmd_val = IP_FW_PASS;
253         *cmd_ctl = IP_FW_CTL_DONE;
254         if (cmd->arg3 && ip_fw3_log_ptr != NULL) {
255                 ip_fw3_log_ptr((*args)->m, (*args)->eh, cmd->arg1);
256         }
257 }
258
259 void
260 check_deny(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
261                 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
262 {
263         *cmd_val = IP_FW_DENY;
264         *cmd_ctl = IP_FW_CTL_DONE;
265         if (cmd->arg3 && ip_fw3_log_ptr != NULL) {
266                 ip_fw3_log_ptr((*args)->m, (*args)->eh, cmd->arg1);
267         }
268 }
269
270 void
271 init_module(void)
272 {
273         memset(fw3_modules, 0, sizeof(struct ipfw3_module) * MAX_MODULE);
274         memset(filter_funcs, 0, sizeof(filter_func) *
275                         MAX_OPCODE_PER_MODULE * MAX_MODULE);
276         ip_fw3_register_filter_funcs(0, O_BASIC_ACCEPT,
277                         (filter_func)check_accept);
278         ip_fw3_register_filter_funcs(0, O_BASIC_DENY, (filter_func)check_deny);
279 }
280
281 int
282 ip_fw3_free_rule(struct ip_fw *rule)
283 {
284         kfree(rule, M_IPFW3);
285         rule = NULL;
286         return 1;
287 }
288
289 static struct ip_fw *
290 lookup_next_rule(struct ip_fw *me)
291 {
292         struct ip_fw *rule = NULL;
293         ipfw_insn *cmd;
294
295         /* look for action, in case it is a skipto */
296         cmd = ACTION_PTR(me);
297         if ((int)cmd->module == MODULE_BASIC_ID &&
298                 (int)cmd->opcode == O_BASIC_SKIPTO) {
299                 for (rule = me->next; rule; rule = rule->next) {
300                         if (rule->rulenum >= cmd->arg1)
301                                 break;
302                 }
303         }
304         if (rule == NULL) {     /* failure or not a skipto */
305                 rule = me->next;
306         }
307         me->next_rule = rule;
308         return rule;
309 }
310
311 /*
312  * rules are stored in ctx->ipfw_rule_chain.
313  * and each rule is combination of multiple cmds.(ipfw_insn)
314  * in each rule, it begin with filter cmds. and end with action cmds.
315  * 'outer/inner loop' are looping the rules/cmds.
316  * it will invoke the cmds relatived function according to the cmd's
317  * module id and opcode id. and process according to return value.
318  */
319 int
320 ip_fw3_chk(struct ip_fw_args *args)
321 {
322         struct tcphdr *tcp;
323         struct udphdr *udp;
324         struct icmp *icmp;
325
326         struct mbuf *m = args->m;
327         struct ip *ip = mtod(m, struct ip *);
328         struct ip_fw *f = NULL;         /* matching rule */
329         int cmd_val = IP_FW_PASS;
330         struct m_tag *mtag;
331         struct divert_info *divinfo;
332
333         /*
334          * hlen The length of the IPv4 header.
335          *      hlen >0 means we have an IPv4 packet.
336          */
337         u_int hlen = 0;         /* hlen >0 means we have an IP pkt */
338
339         /*
340          * offset       The offset of a fragment. offset != 0 means that
341          *      we have a fragment at this offset of an IPv4 packet.
342          *      offset == 0 means that (if this is an IPv4 packet)
343          *      this is the first or only fragment.
344          */
345         u_short offset = 0;
346
347         uint8_t proto;
348         uint16_t src_port = 0, dst_port = 0;    /* NOTE: host format    */
349         struct in_addr src_ip, dst_ip;          /* NOTE: network format */
350         uint16_t ip_len = 0;
351         uint8_t prev_module = -1, prev_opcode = -1; /* previous module & opcode */
352         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
353
354         if (m->m_pkthdr.fw_flags & IPFW_MBUF_GENERATED)
355                 return IP_FW_PASS;      /* accept */
356
357         if (args->eh == NULL ||         /* layer 3 packet */
358                 (m->m_pkthdr.len >= sizeof(struct ip) &&
359                  ntohs(args->eh->ether_type) == ETHERTYPE_IP))
360                 hlen = ip->ip_hl << 2;
361
362         /*
363          * Collect parameters into local variables for faster matching.
364          */
365         if (hlen == 0) {        /* do not grab addresses for non-ip pkts */
366                 proto = args->f_id.proto = 0;   /* mark f_id invalid */
367                 goto after_ip_checks;
368         }
369
370         proto = args->f_id.proto = ip->ip_p;
371         src_ip = ip->ip_src;
372         dst_ip = ip->ip_dst;
373         if (args->eh != NULL) { /* layer 2 packets are as on the wire */
374                 offset = ntohs(ip->ip_off) & IP_OFFMASK;
375                 ip_len = ntohs(ip->ip_len);
376         } else {
377                 offset = ip->ip_off & IP_OFFMASK;
378                 ip_len = ip->ip_len;
379         }
380
381 #define PULLUP_TO(len)                                  \
382 do {                                                    \
383         if (m->m_len < (len)) {                         \
384                 args->m = m = m_pullup(m, (len));       \
385                         if (m == NULL)                  \
386                                 goto pullup_failed;     \
387                 ip = mtod(m, struct ip *);              \
388         }                                               \
389 } while (0)
390
391         if (offset == 0) {
392                 switch (proto) {
393                         case IPPROTO_TCP:
394                                 PULLUP_TO(hlen + sizeof(struct tcphdr));
395                                 tcp = L3HDR(struct tcphdr, ip);
396                                 dst_port = tcp->th_dport;
397                                 src_port = tcp->th_sport;
398                                 args->f_id.flags = tcp->th_flags;
399                                 break;
400                         case IPPROTO_UDP:
401                                 PULLUP_TO(hlen + sizeof(struct udphdr));
402                                 udp = L3HDR(struct udphdr, ip);
403                                 dst_port = udp->uh_dport;
404                                 src_port = udp->uh_sport;
405                                 break;
406                         case IPPROTO_ICMP:
407                                 PULLUP_TO(hlen + 4);
408                                 icmp = L3HDR(struct icmp, ip);
409                                 args->f_id.flags = icmp->icmp_type;
410                                 dst_port = icmp->icmp_id;
411                                 src_port = dst_port;
412                                 break;
413                         default:
414                                 break;
415                 }
416         }
417
418 #undef PULLUP_TO
419
420         args->f_id.src_ip = ntohl(src_ip.s_addr);
421         args->f_id.dst_ip = ntohl(dst_ip.s_addr);
422         args->f_id.src_port = src_port = ntohs(src_port);
423         args->f_id.dst_port = dst_port = ntohs(dst_port);
424
425 after_ip_checks:
426         if (args->rule) {
427                 /*
428                  * Packet has already been tagged. Look for the next rule
429                  * to restart processing.
430                  *
431                  * If sysctl_var_fw3_one_pass != 0 then just accept it.
432                  * XXX should not happen here, but optimized out in
433                  * the caller.
434                  */
435                 if (sysctl_var_fw3_one_pass)
436                         return IP_FW_PASS;
437
438                 /* This rule is being/has been flushed */
439                 if (sysctl_var_fw3_flushing)
440                         return IP_FW_DENY;
441
442                 f = args->rule->next_rule;
443                 if (f == NULL)
444                         f = lookup_next_rule(args->rule);
445         } else {
446                 /*
447                  * Find the starting rule. It can be either the first
448                  * one, or the one after divert_rule if asked so.
449                  */
450                 int skipto;
451
452                 mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
453                 if (mtag != NULL) {
454                         divinfo = m_tag_data(mtag);
455                         skipto = divinfo->skipto;
456                 } else {
457                         skipto = 0;
458                 }
459
460                 f = ctx->rules;
461                 if (args->eh == NULL && skipto != 0) {
462                         /* No skipto during rule flushing */
463                         if (sysctl_var_fw3_flushing) {
464                                 return IP_FW_DENY;
465                         }
466                         if (skipto >= IPFW_DEFAULT_RULE) {
467                                 return IP_FW_DENY; /* invalid */
468                         }
469                         while (f && f->rulenum <= skipto) {
470                                 f = f->next;
471                         }
472                         if (f == NULL) {        /* drop packet */
473                                 return IP_FW_DENY;
474                         }
475                 } else if (sysctl_var_fw3_flushing) {
476                         /* Rules are being flushed; skip to default rule */
477                         f = ctx->default_rule;
478                 }
479         }
480         if ((mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL)) != NULL) {
481                 m_tag_delete(m, mtag);
482         }
483
484         /*
485          * Now scan the rules, and parse microinstructions for each rule.
486          */
487         int prev_val;   /*  previous result of 'or' filter */
488         int l, cmdlen;
489         ipfw_insn *cmd;
490         int cmd_ctl;
491         /* foreach rule in chain */
492         for (; f; f = f->next) {
493 again:  /* check the rule again*/
494                 if (ctx->sets & (1 << f->set)) {
495                         continue;
496                 }
497
498                 prev_val = -1;
499                  /* foreach cmd in rule */
500                 for (l = f->cmd_len, cmd = f->cmd; l > 0; l -= cmdlen,
501                         cmd = (ipfw_insn *)((uint32_t *)cmd+ cmdlen)) {
502                         cmdlen = F_LEN(cmd);
503
504                         /* skip 'or' filter when already match */
505                         if (cmd->len & F_OR &&
506                                 cmd->module == prev_module &&
507                                 cmd->opcode == prev_opcode &&
508                                 prev_val == 1) {
509                                 goto next_cmd;
510                         }
511
512 check_body: /* check the body of the rule again.*/
513                         (filter_funcs[cmd->module][cmd->opcode])
514                                 (&cmd_ctl, &cmd_val, &args, &f, cmd, ip_len);
515                         switch(cmd_ctl) {
516                                 case IP_FW_CTL_DONE:
517                                         if (prev_val == 0) /* but 'or' failed */
518                                                 goto next_rule;
519                                         goto done;
520                                 case IP_FW_CTL_AGAIN:
521                                         goto again;
522                                 case IP_FW_CTL_NEXT:
523                                         goto next_rule;
524                                 case IP_FW_CTL_NAT:
525                                         args->rule=f;
526                                         goto done;
527                                 case IP_FW_CTL_CHK_STATE:
528                                         /* update the cmd and l */
529                                         cmd = ACTION_PTR(f);
530                                         l = f->cmd_len - f->act_ofs;
531                                         goto check_body;
532                         }
533                         if (cmd->len & F_NOT)
534                                 cmd_val= !cmd_val;
535
536                         if (cmd->len & F_OR) {  /* has 'or' */
537                                 if (!cmd_val) { /* not matched */
538                                         if(prev_val == -1){     /* first 'or' */
539                                                 prev_val = 0;
540                                                 prev_module = cmd->module;
541                                                 prev_opcode = cmd->opcode;
542                                         } else if (prev_module == cmd->module &&
543                                                 prev_opcode == cmd->opcode) {
544                                                 /* continuous 'or' filter */
545                                         } else if (prev_module != cmd->module ||
546                                                 prev_opcode != cmd->opcode) {
547                                                 /* 'or' filter changed */
548                                                 if(prev_val == 0){
549                                                         goto next_rule;
550                                                 } else {
551                                                         prev_val = 0;
552                                                         prev_module = cmd->module;
553                                                         prev_opcode = cmd->opcode;
554                                                 }
555                                         }
556                                 } else { /* has 'or' and matched */
557                                         prev_val = 1;
558                                         prev_module = cmd->module;
559                                         prev_opcode = cmd->opcode;
560                                 }
561                         } else { /* no or */
562                                 if (!cmd_val) { /* not matched */
563                                         goto next_rule;
564                                 } else {
565                                         if (prev_val == 0) {
566                                                 /* previous 'or' not matched */
567                                                 goto next_rule;
568                                         } else {
569                                                 prev_val = -1;
570                                         }
571                                 }
572                         }
573 next_cmd:;
574                 }       /* end of inner for, scan opcodes */
575 next_rule:;             /* try next rule                */
576         }               /* end of outer for, scan rules */
577         kprintf("+++ ipfw: ouch!, skip past end of rules, denying packet\n");
578         return IP_FW_DENY;
579
580 done:
581         /* Update statistics */
582         f->pcnt++;
583         f->bcnt += ip_len;
584         f->timestamp = time_second;
585         return cmd_val;
586
587 pullup_failed:
588         if (sysctl_var_fw3_verbose)
589                 kprintf("pullup failed\n");
590         return IP_FW_DENY;
591 }
592
593 struct mbuf *
594 ip_fw3_dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa)
595 {
596         struct m_tag *mtag;
597         struct dn_pkt *pkt;
598         ipfw_insn *cmd;
599         const struct ipfw_flow_id *id;
600         struct dn_flow_id *fid;
601
602         M_ASSERTPKTHDR(m);
603
604         mtag = m_tag_get(PACKET_TAG_DUMMYNET, sizeof(*pkt),
605             M_INTWAIT | M_NULLOK);
606         if (mtag == NULL) {
607                 m_freem(m);
608                 return (NULL);
609         }
610         m_tag_prepend(m, mtag);
611
612         pkt = m_tag_data(mtag);
613         bzero(pkt, sizeof(*pkt));
614
615         cmd = (ipfw_insn *)((uint32_t *)fwa->rule->cmd + fwa->rule->act_ofs);
616         KASSERT(cmd->opcode == O_DUMMYNET_PIPE ||
617                         cmd->opcode == O_DUMMYNET_QUEUE,
618                         ("Rule is not PIPE or QUEUE, opcode %d", cmd->opcode));
619
620         pkt->dn_m = m;
621         pkt->dn_flags = (dir & DN_FLAGS_DIR_MASK);
622         pkt->ifp = fwa->oif;
623         pkt->pipe_nr = pipe_nr;
624
625         pkt->cpuid = mycpuid;
626         pkt->msgport = netisr_curport();
627
628         id = &fwa->f_id;
629         fid = &pkt->id;
630         fid->fid_dst_ip = id->dst_ip;
631         fid->fid_src_ip = id->src_ip;
632         fid->fid_dst_port = id->dst_port;
633         fid->fid_src_port = id->src_port;
634         fid->fid_proto = id->proto;
635         fid->fid_flags = id->flags;
636
637         pkt->dn_priv = fwa->rule;
638
639         if ((int)cmd->opcode == O_DUMMYNET_PIPE)
640                 pkt->dn_flags |= DN_FLAGS_IS_PIPE;
641
642         m->m_pkthdr.fw_flags |= DUMMYNET_MBUF_TAGGED;
643         return (m);
644 }
645
646
647 void
648 add_rule_dispatch(netmsg_t nmsg)
649 {
650         struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
651         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
652         struct ip_fw *rule, *prev,*next;
653         const struct ipfw_ioc_rule *ioc_rule;
654
655         ioc_rule = fwmsg->ioc_rule;
656          // create rule by ioc_rule
657         rule = kmalloc(RULESIZE(ioc_rule), M_IPFW3, M_WAITOK | M_ZERO);
658         rule->act_ofs = ioc_rule->act_ofs;
659         rule->cmd_len = ioc_rule->cmd_len;
660         rule->rulenum = ioc_rule->rulenum;
661         rule->set = ioc_rule->set;
662         bcopy(ioc_rule->cmd, rule->cmd, rule->cmd_len * 4);
663
664         for (prev = NULL, next = ctx->rules;
665                 next; prev = next, next = next->next) {
666                 if (next->rulenum > ioc_rule->rulenum) {
667                         break;
668                 }
669         }
670         KASSERT(next != NULL, ("no default rule?!"));
671
672         /*
673          * Insert rule into the pre-determined position
674          */
675         if (prev != NULL) {
676                 rule->next = next;
677                 prev->next = rule;
678         } else {
679                 rule->next = ctx->rules;
680                 ctx->rules = rule;
681         }
682
683         /*
684          * if sibiling in last CPU is exists,
685          * then it's sibling should be current rule
686          */
687         if (fwmsg->sibling != NULL) {
688                 fwmsg->sibling->sibling = rule;
689         }
690         /* prepare for next CPU */
691         fwmsg->sibling = rule;
692
693         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
694 }
695
696 /*
697  * confirm the rulenumber
698  * call dispatch function to add rule into the list
699  * Update the statistic
700  */
701 void
702 ip_fw3_add_rule(struct ipfw_ioc_rule *ioc_rule)
703 {
704         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
705         struct netmsg_ipfw fwmsg;
706         struct netmsg_base *nmsg;
707         struct ip_fw *f;
708
709         IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
710
711         /*
712          * If rulenum is 0, find highest numbered rule before the
713          * default rule, and add rule number incremental step.
714          */
715         if (ioc_rule->rulenum == 0) {
716                 int step = sysctl_var_autoinc_step;
717
718                 KKASSERT(step >= IPFW_AUTOINC_STEP_MIN &&
719                                 step <= IPFW_AUTOINC_STEP_MAX);
720
721                 /*
722                  * Locate the highest numbered rule before default
723                  */
724                 for (f = ctx->rules; f; f = f->next) {
725                         if (f->rulenum == IPFW_DEFAULT_RULE)
726                                 break;
727                         ioc_rule->rulenum = f->rulenum;
728                 }
729                 if (ioc_rule->rulenum < IPFW_DEFAULT_RULE - step)
730                         ioc_rule->rulenum += step;
731         }
732         KASSERT(ioc_rule->rulenum != IPFW_DEFAULT_RULE &&
733                         ioc_rule->rulenum != 0,
734                         ("invalid rule num %d", ioc_rule->rulenum));
735
736         bzero(&fwmsg, sizeof(fwmsg));
737         nmsg = &fwmsg.base;
738         netmsg_init(nmsg, NULL, &curthread->td_msgport,
739                         0, add_rule_dispatch);
740         fwmsg.ioc_rule = ioc_rule;
741
742         netisr_domsg(nmsg, 0);
743
744         IPFW3_DEBUG("++ installed rule %d, static count now %d\n",
745                         ioc_rule->rulenum, static_count);
746 }
747
748 /**
749  * Free storage associated with a static rule (including derived
750  * dynamic rules).
751  * The caller is in charge of clearing rule pointers to avoid
752  * dangling pointers.
753  * @return a pointer to the next entry.
754  * Arguments are not checked, so they better be correct.
755  * Must be called at splimp().
756  */
757 struct ip_fw *
758 ip_fw3_delete_rule(struct ipfw3_context *ctx,
759                  struct ip_fw *prev, struct ip_fw *rule)
760 {
761         if (prev == NULL)
762                 ctx->rules = rule->next;
763         else
764                 prev->next = rule->next;
765
766         kfree(rule, M_IPFW3);
767         rule = NULL;
768         return NULL;
769 }
770
771 void
772 flush_rule_dispatch(netmsg_t nmsg)
773 {
774         struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
775         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
776         struct ip_fw *rule, *the_rule;
777         int kill_default = dmsg->kill_default;
778
779         rule = ctx->rules;
780         while (rule != NULL) {
781                 if (rule->rulenum == IPFW_DEFAULT_RULE && kill_default == 0) {
782                         ctx->rules = rule;
783                         break;
784                 }
785                 the_rule = rule;
786                 rule = rule->next;
787
788                 kfree(the_rule, M_IPFW3);
789         }
790
791         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
792 }
793
794
795 /*
796  * Deletes all rules from a chain (including the default rule
797  * if the second argument is set).
798  * Must be called at splimp().
799  */
800 void
801 ip_fw3_ctl_flush_rule(int kill_default)
802 {
803         struct netmsg_del dmsg;
804
805         IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
806
807         if (!kill_default) {
808                 sysctl_var_fw3_flushing = 1;
809                 netmsg_service_sync();
810         }
811         /*
812          * Press the 'flush' button
813          */
814         bzero(&dmsg, sizeof(dmsg));
815         netmsg_init(&dmsg.base, NULL, &curthread->td_msgport,
816                         0, flush_rule_dispatch);
817         dmsg.kill_default = kill_default;
818         netisr_domsg(&dmsg.base, 0);
819
820         /* Flush is done */
821         sysctl_var_fw3_flushing = 0;
822 }
823
824 void
825 delete_rule_dispatch(netmsg_t nmsg)
826 {
827         struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
828         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
829         struct ip_fw *rule, *prev = NULL;
830
831         rule = ctx->rules;
832         while (rule!=NULL) {
833                 if (rule->rulenum == dmsg->rulenum) {
834                         ip_fw3_delete_rule(ctx, prev, rule);
835                         break;
836                 }
837                 prev = rule;
838                 rule = rule->next;
839         }
840
841         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
842 }
843
844 int
845 ip_fw3_ctl_delete_rule(struct sockopt *sopt)
846 {
847         struct netmsg_del dmsg;
848         struct netmsg_base *nmsg;
849         int *rulenum;
850
851         rulenum = (int *) sopt->sopt_val;
852
853
854         /*
855          * Get rid of the rule duplications on all CPUs
856          */
857         bzero(&dmsg, sizeof(dmsg));
858         nmsg = &dmsg.base;
859         netmsg_init(nmsg, NULL, &curthread->td_msgport,
860                         0, delete_rule_dispatch);
861         dmsg.rulenum = *rulenum;
862         netisr_domsg(nmsg, 0);
863         return 0;
864 }
865
866 /*
867  * Clear counters for a specific rule.
868  */
869 void
870 ip_fw3_clear_counters(struct ip_fw *rule)
871 {
872         rule->bcnt = rule->pcnt = 0;
873         rule->timestamp = 0;
874 }
875
876 void
877 ip_fw3_zero_entry_dispatch(netmsg_t nmsg)
878 {
879         struct netmsg_zent *zmsg = (struct netmsg_zent *)nmsg;
880         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
881         struct ip_fw *rule;
882
883         if (zmsg->rulenum == 0) {
884                 for (rule = ctx->rules; rule; rule = rule->next) {
885                         ip_fw3_clear_counters(rule);
886                 }
887         } else {
888                 for (rule = ctx->rules; rule; rule = rule->next) {
889                         if (rule->rulenum == zmsg->rulenum) {
890                                 ip_fw3_clear_counters(rule);
891                         }
892                 }
893         }
894         ip_fw3_clear_counters(ctx->default_rule);
895         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
896 }
897
898 /**
899  * Reset some or all counters on firewall rules.
900  * @arg frwl is null to clear all entries, or contains a specific
901  * rule number.
902  * @arg log_only is 1 if we only want to reset logs, zero otherwise.
903  */
904 int
905 ip_fw3_ctl_zero_entry(int rulenum, int log_only)
906 {
907         struct netmsg_zent zmsg;
908         struct netmsg_base *nmsg;
909         const char *msg;
910         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
911
912         bzero(&zmsg, sizeof(zmsg));
913         nmsg = &zmsg.base;
914         netmsg_init(nmsg, NULL, &curthread->td_msgport,
915                         0, ip_fw3_zero_entry_dispatch);
916         zmsg.log_only = log_only;
917
918         if (rulenum == 0) {
919                 msg = log_only ? "ipfw: All logging counts reset.\n"
920                                    : "ipfw: Accounting cleared.\n";
921         } else {
922                 struct ip_fw *rule;
923
924                 /*
925                  * Locate the first rule with 'rulenum'
926                  */
927                 for (rule = ctx->rules; rule; rule = rule->next) {
928                         if (rule->rulenum == rulenum)
929                                 break;
930                 }
931                 if (rule == NULL) /* we did not find any matching rules */
932                         return (EINVAL);
933                 zmsg.start_rule = rule;
934                 zmsg.rulenum = rulenum;
935
936                 msg = log_only ? "ipfw: Entry %d logging count reset.\n"
937                                    : "ipfw: Entry %d cleared.\n";
938         }
939         netisr_domsg(nmsg, 0);
940         KKASSERT(zmsg.start_rule == NULL);
941
942         if (sysctl_var_fw3_verbose)
943                 log(LOG_SECURITY | LOG_NOTICE, msg, rulenum);
944         return (0);
945 }
946
947 /*
948  * Get the ioc_rule from the sopt
949  * call ip_fw3_add_rule to add the rule
950  */
951 int
952 ip_fw3_ctl_add_rule(struct sockopt *sopt)
953 {
954         struct ipfw_ioc_rule *ioc_rule;
955         size_t size;
956
957         size = sopt->sopt_valsize;
958         if (size > (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX) ||
959                         size < sizeof(*ioc_rule)) {
960                 return EINVAL;
961         }
962         if (size != (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX)) {
963                 sopt->sopt_val = krealloc(sopt->sopt_val, sizeof(uint32_t) *
964                                 IPFW_RULE_SIZE_MAX, M_TEMP, M_WAITOK);
965         }
966         ioc_rule = sopt->sopt_val;
967
968         ip_fw3_add_rule(ioc_rule);
969         return 0;
970 }
971
972 int
973 ip_fw3_ctl_get_modules(struct sockopt *sopt)
974 {
975         int i;
976         struct ipfw3_module *mod;
977         char module_str[1024];
978         memset(module_str,0,1024);
979         for (i = 0, mod = fw3_modules; i < MAX_MODULE; i++, mod++) {
980                 if (mod->type != 0) {
981                         if (i > 0)
982                                 strcat(module_str,",");
983                         strcat(module_str,mod->name);
984                 }
985         }
986         bzero(sopt->sopt_val, sopt->sopt_valsize);
987         bcopy(module_str, sopt->sopt_val, strlen(module_str));
988         sopt->sopt_valsize = strlen(module_str);
989         return 0;
990 }
991
992 /*
993  * Copy all static rules and states on all CPU
994  */
995 int
996 ip_fw3_ctl_get_rules(struct sockopt *sopt)
997 {
998         struct ipfw3_context *ctx = fw3_ctx[mycpuid];
999         struct ip_fw *rule;
1000         struct ipfw_ioc_rule *ioc;
1001         const struct ip_fw *sibling;
1002         int total_len = 0;
1003
1004         ioc = (struct ipfw_ioc_rule *)sopt->sopt_val;
1005
1006         for (rule = ctx->rules; rule; rule = rule->next) {
1007                 total_len += IOC_RULESIZE(rule);
1008                 if (total_len > sopt->sopt_valsize) {
1009                         bzero(sopt->sopt_val, sopt->sopt_valsize);
1010                         return 0;
1011                 }
1012                 ioc->act_ofs = rule->act_ofs;
1013                 ioc->cmd_len = rule->cmd_len;
1014                 ioc->rulenum = rule->rulenum;
1015                 ioc->set = rule->set;
1016
1017                 ioc->sets = fw3_ctx[mycpuid]->sets;
1018                 ioc->pcnt = 0;
1019                 ioc->bcnt = 0;
1020                 ioc->timestamp = 0;
1021                 for (sibling = rule; sibling != NULL; sibling = sibling->sibling) {
1022                         ioc->pcnt += sibling->pcnt;
1023                         ioc->bcnt += sibling->bcnt;
1024                         if (sibling->timestamp > ioc->timestamp)
1025                                 ioc->timestamp = sibling->timestamp;
1026                 }
1027                 bcopy(rule->cmd, ioc->cmd, ioc->cmd_len * 4);
1028                 ioc = (struct ipfw_ioc_rule *)((uint8_t *)ioc + IOC_RULESIZE(ioc));
1029         }
1030         sopt->sopt_valsize = total_len;
1031         return 0;
1032 }
1033
1034
1035 /*
1036  * ip_fw3_ctl_x - extended version of ip_fw3_ctl
1037  * remove the x_header, and adjust the sopt_name,sopt_val and sopt_valsize.
1038  */
1039 int
1040 ip_fw3_ctl_x(struct sockopt *sopt)
1041 {
1042         ip_fw_x_header *x_header;
1043         x_header = (ip_fw_x_header *)(sopt->sopt_val);
1044         sopt->sopt_name = x_header->opcode;
1045         sopt->sopt_valsize -= sizeof(ip_fw_x_header);
1046         bcopy(++x_header, sopt->sopt_val, sopt->sopt_valsize);
1047         return ip_fw3_ctl(sopt);
1048 }
1049
1050
1051 /**
1052  * {set|get}sockopt parser.
1053  */
1054 int
1055 ip_fw3_ctl(struct sockopt *sopt)
1056 {
1057         int error = 0;
1058         switch (sopt->sopt_name) {
1059                 case IP_FW_X:
1060                         ip_fw3_ctl_x(sopt);
1061                         break;
1062                 case IP_FW_GET:
1063                 case IP_FW_MODULE:
1064                 case IP_FW_FLUSH:
1065                 case IP_FW_ADD:
1066                 case IP_FW_DEL:
1067                 case IP_FW_ZERO:
1068                 case IP_FW_RESETLOG:
1069                         error = ip_fw3_ctl_sockopt(sopt);
1070                         break;
1071                 case IP_FW_SET_GET:
1072                 case IP_FW_SET_MOVE_RULE:
1073                 case IP_FW_SET_MOVE_SET:
1074                 case IP_FW_SET_SWAP:
1075                 case IP_FW_SET_TOGGLE:
1076                         error = ip_fw3_ctl_set_sockopt(sopt);
1077                         break;
1078                 case IP_FW_NAT_ADD:
1079                 case IP_FW_NAT_DEL:
1080                 case IP_FW_NAT_FLUSH:
1081                 case IP_FW_NAT_GET:
1082                 case IP_FW_NAT_GET_RECORD:
1083                         if (ip_fw3_ctl_nat_ptr != NULL) {
1084                                 error = ip_fw3_ctl_nat_ptr(sopt);
1085                         }
1086                         break;
1087                 case IP_DUMMYNET_GET:
1088                 case IP_DUMMYNET_CONFIGURE:
1089                 case IP_DUMMYNET_DEL:
1090                 case IP_DUMMYNET_FLUSH:
1091                         error = ip_dn_sockopt(sopt);
1092                         break;
1093                 case IP_FW_STATE_ADD:
1094                 case IP_FW_STATE_DEL:
1095                 case IP_FW_STATE_FLUSH:
1096                 case IP_FW_STATE_GET:
1097                         if (ip_fw3_ctl_state_ptr != NULL) {
1098                                 error = ip_fw3_ctl_state_ptr(sopt);
1099                         }
1100                         break;
1101                 case IP_FW_TABLE_CREATE:
1102                 case IP_FW_TABLE_DELETE:
1103                 case IP_FW_TABLE_APPEND:
1104                 case IP_FW_TABLE_REMOVE:
1105                 case IP_FW_TABLE_LIST:
1106                 case IP_FW_TABLE_FLUSH:
1107                 case IP_FW_TABLE_SHOW:
1108                 case IP_FW_TABLE_TEST:
1109                 case IP_FW_TABLE_RENAME:
1110                         if (ip_fw3_ctl_table_ptr != NULL) {
1111                                 error = ip_fw3_ctl_table_ptr(sopt);
1112                         }
1113                         break;
1114                 case IP_FW_SYNC_SHOW_CONF:
1115                 case IP_FW_SYNC_SHOW_STATUS:
1116                 case IP_FW_SYNC_EDGE_CONF:
1117                 case IP_FW_SYNC_EDGE_START:
1118                 case IP_FW_SYNC_EDGE_STOP:
1119                 case IP_FW_SYNC_EDGE_TEST:
1120                 case IP_FW_SYNC_EDGE_CLEAR:
1121                 case IP_FW_SYNC_CENTRE_CONF:
1122                 case IP_FW_SYNC_CENTRE_START:
1123                 case IP_FW_SYNC_CENTRE_STOP:
1124                 case IP_FW_SYNC_CENTRE_TEST:
1125                 case IP_FW_SYNC_CENTRE_CLEAR:
1126                         if (ip_fw3_ctl_sync_ptr != NULL) {
1127                                 error = ip_fw3_ctl_sync_ptr(sopt);
1128                         }
1129                         break;
1130                 default:
1131                         kprintf("ip_fw3_ctl invalid option %d\n",
1132                                 sopt->sopt_name);
1133                         error = EINVAL;
1134         }
1135         return error;
1136 }
1137
1138 int
1139 ip_fw3_ctl_sockopt(struct sockopt *sopt)
1140 {
1141         int error = 0, rulenum;
1142
1143         switch (sopt->sopt_name) {
1144                 case IP_FW_GET:
1145                         error = ip_fw3_ctl_get_rules(sopt);
1146                         break;
1147                 case IP_FW_MODULE:
1148                         error = ip_fw3_ctl_get_modules(sopt);
1149                         break;
1150                 case IP_FW_FLUSH:
1151                         ip_fw3_ctl_flush_rule(0);
1152                         break;
1153                 case IP_FW_ADD:
1154                         error = ip_fw3_ctl_add_rule(sopt);
1155                         break;
1156                 case IP_FW_DEL:
1157                         error = ip_fw3_ctl_delete_rule(sopt);
1158                         break;
1159                 case IP_FW_ZERO:
1160                 case IP_FW_RESETLOG: /* argument is an int, the rule number */
1161                         rulenum = 0;
1162                         if (sopt->sopt_valsize != 0) {
1163                                 error = soopt_to_kbuf(sopt, &rulenum,
1164                                                 sizeof(int), sizeof(int));
1165                                 if (error) {
1166                                         break;
1167                                 }
1168                         }
1169                         error = ip_fw3_ctl_zero_entry(rulenum,
1170                                         sopt->sopt_name == IP_FW_RESETLOG);
1171                         break;
1172                 default:
1173                         kprintf("ip_fw3_ctl invalid option %d\n",
1174                                 sopt->sopt_name);
1175                         error = EINVAL;
1176         }
1177         return error;
1178 }
1179
1180 int
1181 ip_fw3_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1182 {
1183         struct ip_fw_args args;
1184         struct mbuf *m = *m0;
1185         struct m_tag *mtag;
1186         int tee = 0, error = 0, ret;
1187         // again:
1188         if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1189                 /* Extract info from dummynet tag */
1190                 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1191                 KKASSERT(mtag != NULL);
1192                 args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1193                 KKASSERT(args.rule != NULL);
1194
1195                 m_tag_delete(m, mtag);
1196                 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1197         } else {
1198                 args.rule = NULL;
1199         }
1200
1201         args.eh = NULL;
1202         args.oif = NULL;
1203         args.m = m;
1204         ret = ip_fw3_chk(&args);
1205         m = args.m;
1206
1207         if (m == NULL) {
1208                 error = EACCES;
1209                 goto back;
1210         }
1211         switch (ret) {
1212                 case IP_FW_PASS:
1213                         break;
1214
1215                 case IP_FW_DENY:
1216                         m_freem(m);
1217                         m = NULL;
1218                         error = EACCES;
1219                         break;
1220
1221                 case IP_FW_DUMMYNET:
1222                         /* Send packet to the appropriate pipe */
1223                         m = ip_fw3_dummynet_io(m, args.cookie, DN_TO_IP_IN,
1224                             &args);
1225                         break;
1226                 case IP_FW_TEE:
1227                         tee = 1;
1228                         /* FALL THROUGH */
1229                 case IP_FW_DIVERT:
1230                         /*
1231                          * Must clear bridge tag when changing
1232                          */
1233                         m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED;
1234                         if (ip_divert_p != NULL) {
1235                                 m = ip_divert_p(m, tee, 1);
1236                         } else {
1237                                 m_freem(m);
1238                                 m = NULL;
1239                                 /* not sure this is the right error msg */
1240                                 error = EACCES;
1241                         }
1242                         break;
1243                 case IP_FW_NAT:
1244                         break;
1245                 case IP_FW_ROUTE:
1246                         break;
1247                 default:
1248                         panic("unknown ipfw3 return value: %d", ret);
1249         }
1250 back:
1251         *m0 = m;
1252         return error;
1253 }
1254
1255 int
1256 ip_fw3_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1257 {
1258         struct ip_fw_args args;
1259         struct mbuf *m = *m0;
1260         struct m_tag *mtag;
1261         int tee = 0, error = 0, ret;
1262         // again:
1263         if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1264                 /* Extract info from dummynet tag */
1265                 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1266                 KKASSERT(mtag != NULL);
1267                 args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1268                 KKASSERT(args.rule != NULL);
1269
1270                 m_tag_delete(m, mtag);
1271                 m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1272         } else {
1273                 args.rule = NULL;
1274         }
1275
1276         args.eh = NULL;
1277         args.m = m;
1278         args.oif = ifp;
1279         ret = ip_fw3_chk(&args);
1280         m = args.m;
1281
1282         if (m == NULL) {
1283                 error = EACCES;
1284                 goto back;
1285         }
1286
1287         switch (ret) {
1288                 case IP_FW_PASS:
1289                         break;
1290
1291                 case IP_FW_DENY:
1292                         m_freem(m);
1293                         m = NULL;
1294                         error = EACCES;
1295                         break;
1296
1297                 case IP_FW_DUMMYNET:
1298                         m = ip_fw3_dummynet_io(m, args.cookie, DN_TO_IP_OUT,
1299                             &args);
1300                         break;
1301
1302                 case IP_FW_TEE:
1303                         tee = 1;
1304                         /* FALL THROUGH */
1305
1306                 case IP_FW_DIVERT:
1307                         if (ip_divert_p != NULL) {
1308                                 m = ip_divert_p(m, tee, 0);
1309                         } else {
1310                                 m_freem(m);
1311                                 m = NULL;
1312                                 /* not sure this is the right error msg */
1313                                 error = EACCES;
1314                         }
1315                         break;
1316
1317                 case IP_FW_NAT:
1318                         break;
1319                 case IP_FW_ROUTE:
1320                         break;
1321                 default:
1322                         panic("unknown ipfw3 return value: %d", ret);
1323         }
1324 back:
1325         *m0 = m;
1326         return error;
1327 }
1328
1329 void
1330 ip_fw3_hook(void)
1331 {
1332         struct pfil_head *pfh;
1333         IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1334
1335         pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1336         if (pfh == NULL)
1337                 return;
1338
1339         pfil_add_hook(ip_fw3_check_in, NULL, PFIL_IN, pfh);
1340         pfil_add_hook(ip_fw3_check_out, NULL, PFIL_OUT, pfh);
1341 }
1342
1343 void
1344 ip_fw3_dehook(void)
1345 {
1346         struct pfil_head *pfh;
1347
1348         IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1349
1350         pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1351         if (pfh == NULL)
1352                 return;
1353
1354         pfil_remove_hook(ip_fw3_check_in, NULL, PFIL_IN, pfh);
1355         pfil_remove_hook(ip_fw3_check_out, NULL, PFIL_OUT, pfh);
1356 }
1357
1358 void
1359 ip_fw3_sysctl_enable_dispatch(netmsg_t nmsg)
1360 {
1361         struct lwkt_msg *lmsg = &nmsg->lmsg;
1362         int enable = lmsg->u.ms_result;
1363
1364         if (sysctl_var_fw3_enable == enable)
1365                 goto reply;
1366
1367         sysctl_var_fw3_enable = enable;
1368         if (sysctl_var_fw3_enable)
1369                 ip_fw3_hook();
1370         else
1371                 ip_fw3_dehook();
1372
1373 reply:
1374         lwkt_replymsg(lmsg, 0);
1375 }
1376
1377 int
1378 ip_fw3_sysctl_enable(SYSCTL_HANDLER_ARGS)
1379 {
1380         struct netmsg_base nmsg;
1381         struct lwkt_msg *lmsg;
1382         int enable, error;
1383
1384         enable = sysctl_var_fw3_enable;
1385         error = sysctl_handle_int(oidp, &enable, 0, req);
1386         if (error || req->newptr == NULL)
1387                 return error;
1388
1389         netmsg_init(&nmsg, NULL, &curthread->td_msgport,
1390                         0, ip_fw3_sysctl_enable_dispatch);
1391         lmsg = &nmsg.lmsg;
1392         lmsg->u.ms_result = enable;
1393
1394         return lwkt_domsg(IPFW_CFGPORT, lmsg, 0);
1395 }
1396
1397 int
1398 ip_fw3_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS)
1399 {
1400         return sysctl_int_range(oidp, arg1, arg2, req,
1401                         IPFW_AUTOINC_STEP_MIN, IPFW_AUTOINC_STEP_MAX);
1402 }
1403
1404 void
1405 ctx_init_dispatch(netmsg_t nmsg)
1406 {
1407         struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
1408         struct ipfw3_context *ctx;
1409         struct ip_fw *def_rule;
1410
1411         ctx = kmalloc(LEN_FW3_CTX, M_IPFW3, M_WAITOK | M_ZERO);
1412         fw3_ctx[mycpuid] = ctx;
1413         ctx->sets = IPFW_ALL_SETS;
1414
1415         def_rule = kmalloc(LEN_FW3, M_IPFW3, M_WAITOK | M_ZERO);
1416         def_rule->act_ofs = 0;
1417         def_rule->rulenum = IPFW_DEFAULT_RULE;
1418         def_rule->cmd_len = 2;
1419         def_rule->set = IPFW_DEFAULT_SET;
1420
1421         def_rule->cmd[0].len = LEN_OF_IPFWINSN;
1422         def_rule->cmd[0].module = MODULE_BASIC_ID;
1423 #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
1424         def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1425 #else
1426         if (filters_default_to_accept)
1427                 def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1428         else
1429                 def_rule->cmd[0].opcode = O_BASIC_DENY;
1430 #endif
1431
1432         /* Install the default rule */
1433         ctx->default_rule = def_rule;
1434         ctx->rules = def_rule;
1435
1436         /*
1437          * if sibiling in last CPU is exists,
1438          * then it's sibling should be current rule
1439          */
1440         if (fwmsg->sibling != NULL) {
1441                 fwmsg->sibling->sibling = def_rule;
1442         }
1443         /* prepare for next CPU */
1444         fwmsg->sibling = def_rule;
1445
1446         netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
1447 }
1448
1449 void
1450 init_dispatch(netmsg_t nmsg)
1451 {
1452         struct netmsg_ipfw fwmsg;
1453         int error = 0;
1454         if (IPFW3_LOADED) {
1455                 kprintf("ipfw3 already loaded\n");
1456                 error = EEXIST;
1457                 goto reply;
1458         }
1459
1460         bzero(&fwmsg, sizeof(fwmsg));
1461         netmsg_init(&fwmsg.base, NULL, &curthread->td_msgport,
1462                         0, ctx_init_dispatch);
1463         netisr_domsg(&fwmsg.base, 0);
1464
1465         ip_fw_chk_ptr = ip_fw3_chk;
1466         ip_fw_ctl_x_ptr = ip_fw3_ctl_x;
1467         ip_fw_dn_io_ptr = ip_fw3_dummynet_io;
1468
1469         kprintf("ipfw3 initialized, default to %s\n",
1470                         filters_default_to_accept ? "accept" : "deny");
1471
1472         ip_fw3_loaded = 1;
1473         if (sysctl_var_fw3_enable)
1474                 ip_fw3_hook();
1475 reply:
1476         lwkt_replymsg(&nmsg->lmsg, error);
1477 }
1478
1479 int
1480 ip_fw3_init(void)
1481 {
1482         struct netmsg_base smsg;
1483         int error;
1484
1485         init_module();
1486         netmsg_init(&smsg, NULL, &curthread->td_msgport,
1487                         0, init_dispatch);
1488         error = lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1489         return error;
1490 }
1491
1492 #ifdef KLD_MODULE
1493
1494 void
1495 fini_dispatch(netmsg_t nmsg)
1496 {
1497         int error = 0, cpu;
1498
1499         ip_fw3_loaded = 0;
1500
1501         ip_fw3_dehook();
1502         netmsg_service_sync();
1503         ip_fw_chk_ptr = NULL;
1504         ip_fw_ctl_x_ptr = NULL;
1505         ip_fw_dn_io_ptr = NULL;
1506         ip_fw3_ctl_flush_rule(1);
1507         /* Free pre-cpu context */
1508         for (cpu = 0; cpu < ncpus; ++cpu) {
1509                 if (fw3_ctx[cpu] != NULL) {
1510                         kfree(fw3_ctx[cpu], M_IPFW3);
1511                         fw3_ctx[cpu] = NULL;
1512                 }
1513         }
1514         kprintf("ipfw3 unloaded\n");
1515
1516         lwkt_replymsg(&nmsg->lmsg, error);
1517 }
1518
1519 int
1520 ip_fw3_fini(void)
1521 {
1522         struct netmsg_base smsg;
1523
1524         netmsg_init(&smsg, NULL, &curthread->td_msgport,
1525                         0, fini_dispatch);
1526         return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1527 }
1528
1529 #endif  /* KLD_MODULE */
1530
1531 static int
1532 ip_fw3_modevent(module_t mod, int type, void *unused)
1533 {
1534         int err = 0;
1535
1536         switch (type) {
1537                 case MOD_LOAD:
1538                         err = ip_fw3_init();
1539                         break;
1540
1541                 case MOD_UNLOAD:
1542
1543 #ifndef KLD_MODULE
1544                         kprintf("ipfw3 statically compiled, cannot unload\n");
1545                         err = EBUSY;
1546 #else
1547                         err = ip_fw3_fini();
1548 #endif
1549                         break;
1550                 default:
1551                         break;
1552         }
1553         return err;
1554 }
1555
1556 static moduledata_t ipfw3mod = {
1557         "ipfw3",
1558         ip_fw3_modevent,
1559         0
1560 };
1561 /* ipfw3 must init before ipfw3_basic */
1562 DECLARE_MODULE(ipfw3, ipfw3mod, SI_SUB_PROTO_END, SI_ORDER_FIRST);
1563 MODULE_VERSION(ipfw3, 1);