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