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