xref: /dragonfly/sys/net/ipfw3/ip_fw3.c (revision 78478697)
1 /*
2  * Copyright (c) 1993 Daniel Boulet
3  * Copyright (c) 1994 Ugen J.S.Antsilevich
4  * Copyright (c) 2002 Luigi Rizzo, Universita` di Pisa
5  * Copyright (c) 2015 The DragonFly Project.  All rights reserved.
6  *
7  * This code is derived from software contributed to The DragonFly Project
8  * by Bill Yuan <bycn82@gmail.com>
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/systm.h>
47 #include <sys/malloc.h>
48 #include <sys/mbuf.h>
49 #include <sys/kernel.h>
50 #include <sys/proc.h>
51 #include <sys/socket.h>
52 #include <sys/socketvar.h>
53 #include <sys/sysctl.h>
54 #include <sys/syslog.h>
55 #include <sys/ucred.h>
56 #include <sys/in_cksum.h>
57 #include <sys/lock.h>
58 #include <sys/thread2.h>
59 #include <sys/mplock2.h>
60 
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/in_var.h>
64 #include <netinet/in_pcb.h>
65 #include <netinet/ip.h>
66 #include <netinet/ip_var.h>
67 #include <netinet/ip_icmp.h>
68 #include <netinet/tcp.h>
69 #include <netinet/tcp_timer.h>
70 #include <netinet/tcp_var.h>
71 #include <netinet/tcpip.h>
72 #include <netinet/udp.h>
73 #include <netinet/udp_var.h>
74 #include <netinet/ip_divert.h>
75 #include <netinet/if_ether.h>
76 
77 #include <net/if.h>
78 #include <net/radix.h>
79 #include <net/route.h>
80 #include <net/pfil.h>
81 #include <net/netmsg2.h>
82 
83 #include <net/ipfw3/ip_fw.h>
84 #include <net/ipfw3/ip_fw3_log.h>
85 #include <net/ipfw3/ip_fw3_table.h>
86 #include <net/ipfw3_basic/ip_fw3_basic.h>
87 #include <net/ipfw3_nat/ip_fw3_nat.h>
88 #include <net/dummynet3/ip_dummynet3.h>
89 
90 MALLOC_DEFINE(M_IPFW3, "IPFW3", "ip_fw3 default module");
91 
92 #ifdef IPFIREWALL_DEBUG
93 #define DPRINTF(fmt, ...)			\
94 do { 						\
95 	if (fw_debug > 0) 			\
96 		kprintf(fmt, __VA_ARGS__); 	\
97 } while (0)
98 #else
99 #define DPRINTF(fmt, ...)	((void)0)
100 #endif
101 
102 #define MAX_MODULE		10
103 #define MAX_OPCODE_PER_MODULE	100
104 
105 #define IPFW_AUTOINC_STEP_MIN	1
106 #define IPFW_AUTOINC_STEP_MAX	1000
107 #define IPFW_AUTOINC_STEP_DEF	100
108 
109 
110 struct netmsg_ipfw {
111 	struct netmsg_base base;
112 	const struct ipfw_ioc_rule *ioc_rule;
113 	struct ip_fw	*rule;
114 	struct ip_fw	*next_rule;
115 	struct ip_fw	*prev_rule;
116 	struct ip_fw	*sibling;	/* sibling in prevous CPU */
117 };
118 
119 struct netmsg_del {
120 	struct netmsg_base base;
121 	struct ip_fw	*rule;
122 	struct ip_fw	*start_rule;
123 	struct ip_fw	*prev_rule;
124 	struct ipfw_ioc_state *ioc_state;
125 	uint16_t	rulenum;
126 	uint8_t		from_set;
127 	uint8_t		to_set;
128 };
129 
130 struct netmsg_zent {
131 	struct netmsg_base base;
132 	struct ip_fw	*start_rule;
133 	uint16_t	rulenum;
134 	uint16_t	log_only;
135 };
136 
137 ipfw_nat_cfg_t *ipfw_nat_cfg_ptr;
138 ipfw_nat_cfg_t *ipfw_nat_del_ptr;
139 ipfw_nat_cfg_t *ipfw_nat_flush_ptr;
140 ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr;
141 ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
142 
143 /* handlers which implemented in ipfw_basic module */
144 ipfw_basic_delete_state_t *ipfw_basic_flush_state_prt = NULL;
145 ipfw_basic_append_state_t *ipfw_basic_append_state_prt = NULL;
146 
147 static struct ipfw_nat_context *ipfw_nat_ctx;
148 
149 extern int ip_fw_loaded;
150 static uint32_t static_count;	/* # of static rules */
151 static uint32_t static_ioc_len;	/* bytes of static rules */
152 static int ipfw_flushing;
153 int fw_verbose = 0;
154 static int fw_debug;
155 static int autoinc_step = IPFW_AUTOINC_STEP_DEF;
156 
157 static int	ipfw_sysctl_enable(SYSCTL_HANDLER_ARGS);
158 static int	ipfw_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS);
159 
160 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw3, CTLFLAG_RW, 0, "Firewall");
161 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, enable, CTLTYPE_INT | CTLFLAG_RW,
162 	&fw3_enable, 0, ipfw_sysctl_enable, "I", "Enable ipfw");
163 SYSCTL_PROC(_net_inet_ip_fw3, OID_AUTO, autoinc_step, CTLTYPE_INT | CTLFLAG_RW,
164 	&autoinc_step, 0, ipfw_sysctl_autoinc_step, "I",
165 	"Rule number autincrement step");
166 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO,one_pass,CTLFLAG_RW,
167 	&fw3_one_pass, 0,
168 	"Only do a single pass through ipfw when using dummynet(4)");
169 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, debug, CTLFLAG_RW,
170 	&fw_debug, 0, "Enable printing of debug ip_fw statements");
171 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, verbose, CTLFLAG_RW,
172 	&fw_verbose, 0, "Log matches to ipfw rules");
173 SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, static_count, CTLFLAG_RD,
174 	&static_count, 0, "Number of static rules");
175 
176 filter_func filter_funcs[MAX_MODULE][MAX_OPCODE_PER_MODULE];
177 struct ipfw_module ipfw_modules[MAX_MODULE];
178 struct ipfw_context *ipfw_ctx[MAXCPU];
179 static int ipfw_ctl(struct sockopt *sopt);
180 
181 
182 void
183 check_accept(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
184 		struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len);
185 void
186 check_deny(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
187 		struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len);
188 void init_module(void);
189 
190 
191 void
192 register_ipfw_module(int module_id,char *module_name)
193 {
194 	struct ipfw_module *tmp;
195 	int i;
196 
197 	tmp = ipfw_modules;
198 	for (i=0; i < MAX_MODULE; i++) {
199 		if (tmp->type == 0) {
200 			tmp->type = 1;
201 			tmp->id = module_id;
202 			strncpy(tmp->name, module_name, strlen(module_name));
203 			break;
204 		}
205 		tmp++;
206 	}
207 	kprintf("ipfw3 module %s loaded ", module_name);
208 }
209 
210 int
211 unregister_ipfw_module(int module_id)
212 {
213 	struct ipfw_module *tmp;
214 	struct ip_fw *fw;
215 	ipfw_insn *cmd;
216 	int i, len, cmdlen, found;
217 
218 	found = 0;
219 	tmp = ipfw_modules;
220 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
221 	fw = ctx->ipfw_rule_chain;
222 	for (; fw; fw = fw->next) {
223 		for (len = fw->cmd_len, cmd = fw->cmd; len > 0;
224 			len -= cmdlen,
225 			cmd = (ipfw_insn *)((uint32_t *)cmd + cmdlen)) {
226 			cmdlen = F_LEN(cmd);
227 			if (cmd->module == 0 &&
228 				(cmd->opcode == 0 || cmd->opcode == 1)) {
229 				//action accept or deny
230 			} else if (cmd->module == module_id) {
231 				found = 1;
232 				goto decide;
233 			}
234 		}
235 	}
236 decide:
237 	if (found) {
238 		return 1;
239 	} else {
240 		for (i = 0; i < MAX_MODULE; i++) {
241 			if (tmp->type == 1 && tmp->id == module_id) {
242 				tmp->type = 0;
243 				kprintf("ipfw3 module %s unloaded ", tmp->name);
244 				break;
245 			}
246 			tmp++;
247 		}
248 
249 		for (i = 0; i < MAX_OPCODE_PER_MODULE; i++) {
250 			if (module_id == 0) {
251 				if (i ==0 || i == 1) {
252 					continue;
253 				}
254 			}
255 			filter_funcs[module_id][i] = NULL;
256 		}
257 		return 0;
258 	}
259 }
260 
261 void
262 register_ipfw_filter_funcs(int module, int opcode, filter_func func)
263 {
264 	filter_funcs[module][opcode] = func;
265 }
266 
267 void
268 check_accept(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
269 		struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
270 {
271 	*cmd_val = IP_FW_PASS;
272 	*cmd_ctl = IP_FW_CTL_DONE;
273 	if (cmd->arg3) {
274 		ipfw_log((*args)->m, (*args)->eh, cmd->arg1);
275 	}
276 }
277 
278 void
279 check_deny(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
280 		struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
281 {
282 	*cmd_val = IP_FW_DENY;
283 	*cmd_ctl = IP_FW_CTL_DONE;
284 	if (cmd->arg3) {
285 		ipfw_log((*args)->m, (*args)->eh, cmd->arg1);
286 	}
287 }
288 
289 void
290 init_module(void)
291 {
292 	memset(ipfw_modules, 0, sizeof(struct ipfw_module) * MAX_MODULE);
293 	memset(filter_funcs, 0, sizeof(filter_func) *
294 			MAX_OPCODE_PER_MODULE * MAX_MODULE);
295 	register_ipfw_filter_funcs(0, O_BASIC_ACCEPT,
296 			(filter_func)check_accept);
297 	register_ipfw_filter_funcs(0, O_BASIC_DENY, (filter_func)check_deny);
298 }
299 
300 static __inline int
301 ipfw_free_rule(struct ip_fw *rule)
302 {
303 	kfree(rule, M_IPFW3);
304 	rule = NULL;
305 	return 1;
306 }
307 
308 static struct ip_fw *
309 lookup_next_rule(struct ip_fw *me)
310 {
311 	struct ip_fw *rule = NULL;
312 	ipfw_insn *cmd;
313 
314 	/* look for action, in case it is a skipto */
315 	cmd = ACTION_PTR(me);
316 	if ((int)cmd->module == MODULE_BASIC_ID &&
317 		(int)cmd->opcode == O_BASIC_SKIPTO) {
318 		for (rule = me->next; rule; rule = rule->next) {
319 			if (rule->rulenum >= cmd->arg1)
320 				break;
321 		}
322 	}
323 	if (rule == NULL) {	/* failure or not a skipto */
324 		rule = me->next;
325 	}
326 	me->next_rule = rule;
327 	return rule;
328 }
329 
330 /*
331  * rules are stored in ctx->ipfw_rule_chain.
332  * and each rule is combination of multiple cmds.(ipfw_insn)
333  * in each rule, it begin with filter cmds. and end with action cmds.
334  * 'outer/inner loop' are looping the rules/cmds.
335  * it will invoke the cmds relatived function according to the cmd's
336  * module id and opcode id. and process according to return value.
337  */
338 static int
339 ipfw_chk(struct ip_fw_args *args)
340 {
341 	struct mbuf *m = args->m;
342 	struct ip *ip = mtod(m, struct ip *);
343 	struct ip_fw *f = NULL;		/* matching rule */
344 	int cmd_val = IP_FW_PASS;
345 	struct m_tag *mtag;
346 	struct divert_info *divinfo;
347 
348 	/*
349 	 * hlen	The length of the IPv4 header.
350 	 *	hlen >0 means we have an IPv4 packet.
351 	 */
352 	u_int hlen = 0;		/* hlen >0 means we have an IP pkt */
353 
354 	/*
355 	 * offset	The offset of a fragment. offset != 0 means that
356 	 *	we have a fragment at this offset of an IPv4 packet.
357 	 *	offset == 0 means that (if this is an IPv4 packet)
358 	 *	this is the first or only fragment.
359 	 */
360 	u_short offset = 0;
361 
362 	uint8_t proto;
363 	uint16_t src_port = 0, dst_port = 0;	/* NOTE: host format	*/
364 	struct in_addr src_ip, dst_ip;		/* NOTE: network format	*/
365 	uint16_t ip_len = 0;
366 	uint8_t prev_module = -1, prev_opcode = -1; /* previous module & opcode */
367 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
368 
369 	if (m->m_pkthdr.fw_flags & IPFW_MBUF_GENERATED)
370 		return IP_FW_PASS;	/* accept */
371 
372 	if (args->eh == NULL ||		/* layer 3 packet */
373 		(m->m_pkthdr.len >= sizeof(struct ip) &&
374 		 ntohs(args->eh->ether_type) == ETHERTYPE_IP))
375 		hlen = ip->ip_hl << 2;
376 
377 	/*
378 	 * Collect parameters into local variables for faster matching.
379 	 */
380 	if (hlen == 0) {	/* do not grab addresses for non-ip pkts */
381 		proto = args->f_id.proto = 0;	/* mark f_id invalid */
382 		goto after_ip_checks;
383 	}
384 
385 	proto = args->f_id.proto = ip->ip_p;
386 	src_ip = ip->ip_src;
387 	dst_ip = ip->ip_dst;
388 	if (args->eh != NULL) { /* layer 2 packets are as on the wire */
389 		offset = ntohs(ip->ip_off) & IP_OFFMASK;
390 		ip_len = ntohs(ip->ip_len);
391 	} else {
392 		offset = ip->ip_off & IP_OFFMASK;
393 		ip_len = ip->ip_len;
394 	}
395 
396 #define PULLUP_TO(len)					\
397 do {							\
398 	if (m->m_len < (len)) {				\
399 		args->m = m = m_pullup(m, (len));	\
400 			if (m == NULL)			\
401 				goto pullup_failed;	\
402 		ip = mtod(m, struct ip *);		\
403 	}						\
404 } while (0)
405 
406 	if (offset == 0) {
407 		switch (proto) {
408 			case IPPROTO_TCP:
409 				{
410 					struct tcphdr *tcp;
411 
412 					PULLUP_TO(hlen + sizeof(struct tcphdr));
413 					tcp = L3HDR(struct tcphdr, ip);
414 					dst_port = tcp->th_dport;
415 					src_port = tcp->th_sport;
416 					args->f_id.flags = tcp->th_flags;
417 				}
418 				break;
419 
420 			case IPPROTO_UDP:
421 				{
422 					struct udphdr *udp;
423 
424 					PULLUP_TO(hlen + sizeof(struct udphdr));
425 					udp = L3HDR(struct udphdr, ip);
426 					dst_port = udp->uh_dport;
427 					src_port = udp->uh_sport;
428 				}
429 				break;
430 
431 			case IPPROTO_ICMP:
432 				PULLUP_TO(hlen + 4);
433 				args->f_id.flags =
434 					L3HDR(struct icmp, ip)->icmp_type;
435 				break;
436 
437 			default:
438 				break;
439 		}
440 	}
441 
442 #undef PULLUP_TO
443 
444 	args->f_id.src_ip = ntohl(src_ip.s_addr);
445 	args->f_id.dst_ip = ntohl(dst_ip.s_addr);
446 	args->f_id.src_port = src_port = ntohs(src_port);
447 	args->f_id.dst_port = dst_port = ntohs(dst_port);
448 
449 after_ip_checks:
450 	if (args->rule) {
451 		/*
452 		 * Packet has already been tagged. Look for the next rule
453 		 * to restart processing.
454 		 *
455 		 * If fw3_one_pass != 0 then just accept it.
456 		 * XXX should not happen here, but optimized out in
457 		 * the caller.
458 		 */
459 		if (fw3_one_pass)
460 			return IP_FW_PASS;
461 
462 		/* This rule is being/has been flushed */
463 		if (ipfw_flushing)
464 			return IP_FW_DENY;
465 
466 		f = args->rule->next_rule;
467 		if (f == NULL)
468 			f = lookup_next_rule(args->rule);
469 	} else {
470 		/*
471 		 * Find the starting rule. It can be either the first
472 		 * one, or the one after divert_rule if asked so.
473 		 */
474 		int skipto;
475 
476 		mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
477 		if (mtag != NULL) {
478 			divinfo = m_tag_data(mtag);
479 			skipto = divinfo->skipto;
480 		} else {
481 			skipto = 0;
482 		}
483 
484 		f = ctx->ipfw_rule_chain;
485 		if (args->eh == NULL && skipto != 0) {
486 			/* No skipto during rule flushing */
487 			if (ipfw_flushing) {
488 				return IP_FW_DENY;
489 			}
490 			if (skipto >= IPFW_DEFAULT_RULE) {
491 				return IP_FW_DENY; /* invalid */
492 			}
493 			while (f && f->rulenum <= skipto) {
494 				f = f->next;
495 			}
496 			if (f == NULL) {	/* drop packet */
497 				return IP_FW_DENY;
498 			}
499 		} else if (ipfw_flushing) {
500 			/* Rules are being flushed; skip to default rule */
501 			f = ctx->ipfw_default_rule;
502 		}
503 	}
504 	if ((mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL)) != NULL) {
505 		m_tag_delete(m, mtag);
506 	}
507 
508 	/*
509 	 * Now scan the rules, and parse microinstructions for each rule.
510 	 */
511 	int prev_val;	/*  previous result of 'or' filter */
512 	int l, cmdlen;
513 	ipfw_insn *cmd;
514 	int cmd_ctl;
515 	/* foreach rule in chain */
516 	for (; f; f = f->next) {
517 again:  /* check the rule again*/
518 		if (ctx->ipfw_set_disable & (1 << f->set)) {
519 			continue;
520 		}
521 
522 		prev_val = -1;
523 		 /* foreach cmd in rule */
524 		for (l = f->cmd_len, cmd = f->cmd; l > 0; l -= cmdlen,
525 			cmd = (ipfw_insn *)((uint32_t *)cmd+ cmdlen)) {
526 			cmdlen = F_LEN(cmd);
527 
528 			/* skip 'or' filter when already match */
529 			if (cmd->len & F_OR &&
530 				cmd->module == prev_module &&
531 				cmd->opcode == prev_opcode &&
532 				prev_val == 1) {
533 				goto next_cmd;
534 			}
535 
536 check_body: /* check the body of the rule again.*/
537 			(filter_funcs[cmd->module][cmd->opcode])
538 				(&cmd_ctl, &cmd_val, &args, &f, cmd, ip_len);
539 			switch(cmd_ctl) {
540 				case IP_FW_CTL_DONE:
541 					if (prev_val == 0) /* but 'or' failed */
542 						goto next_rule;
543 					goto done;
544 				case IP_FW_CTL_AGAIN:
545 					goto again;
546 				case IP_FW_CTL_NEXT:
547 					goto next_rule;
548 				case IP_FW_CTL_NAT:
549 					args->rule=f;
550 					goto done;
551 				case IP_FW_CTL_CHK_STATE:
552 					/* update the cmd and l */
553 					cmd = ACTION_PTR(f);
554 					l = f->cmd_len - f->act_ofs;
555 					goto check_body;
556 			}
557 			if (cmd->len & F_NOT)
558 				cmd_val= !cmd_val;
559 
560 			if (cmd->len & F_OR) {	/* has 'or' */
561 				if (!cmd_val) {	/* not matched */
562 					if(prev_val == -1){	/* first 'or' */
563 						prev_val = 0;
564 						prev_module = cmd->module;
565 						prev_opcode = cmd->opcode;
566 					} else if (prev_module == cmd->module &&
567 						prev_opcode == cmd->opcode) {
568 						/* continuous 'or' filter */
569 					} else if (prev_module != cmd->module ||
570 						prev_opcode != cmd->opcode) {
571 						/* 'or' filter changed */
572 						if(prev_val == 0){
573 							goto next_rule;
574 						} else {
575 							prev_val = 0;
576 							prev_module = cmd->module;
577 							prev_opcode = cmd->opcode;
578 						}
579 					}
580 				} else { /* has 'or' and matched */
581 					prev_val = 1;
582 					prev_module = cmd->module;
583 					prev_opcode = cmd->opcode;
584 				}
585 			} else { /* no or */
586 				if (!cmd_val) {	/* not matched */
587 					goto next_rule;
588 				} else {
589 					if (prev_val == 0) {
590 						/* previous 'or' not matched */
591 						goto next_rule;
592 					} else {
593 						prev_val = -1;
594 					}
595 				}
596 			}
597 next_cmd:;
598 		}	/* end of inner for, scan opcodes */
599 next_rule:;		/* try next rule		*/
600 	}		/* end of outer for, scan rules */
601 	kprintf("+++ ipfw: ouch!, skip past end of rules, denying packet\n");
602 	return IP_FW_DENY;
603 
604 done:
605 	/* Update statistics */
606 	f->pcnt++;
607 	f->bcnt += ip_len;
608 	f->timestamp = time_second;
609 	return cmd_val;
610 
611 pullup_failed:
612 	if (fw_verbose)
613 		kprintf("pullup failed\n");
614 	return IP_FW_DENY;
615 }
616 
617 static void
618 ipfw_dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa)
619 {
620 	struct m_tag *mtag;
621 	struct dn_pkt *pkt;
622 	ipfw_insn *cmd;
623 	const struct ipfw_flow_id *id;
624 	struct dn_flow_id *fid;
625 
626 	M_ASSERTPKTHDR(m);
627 
628 	mtag = m_tag_get(PACKET_TAG_DUMMYNET, sizeof(*pkt), M_NOWAIT);
629 	if (mtag == NULL) {
630 		m_freem(m);
631 		return;
632 	}
633 	m_tag_prepend(m, mtag);
634 
635 	pkt = m_tag_data(mtag);
636 	bzero(pkt, sizeof(*pkt));
637 
638 	cmd = (ipfw_insn *)((uint32_t *)fwa->rule->cmd + fwa->rule->act_ofs);
639 	KASSERT(cmd->opcode == O_DUMMYNET_PIPE ||
640 			cmd->opcode == O_DUMMYNET_QUEUE,
641 			("Rule is not PIPE or QUEUE, opcode %d", cmd->opcode));
642 
643 	pkt->dn_m = m;
644 	pkt->dn_flags = (dir & DN_FLAGS_DIR_MASK);
645 	pkt->ifp = fwa->oif;
646 	pkt->pipe_nr = pipe_nr;
647 
648 	pkt->cpuid = mycpuid;
649 	pkt->msgport = netisr_curport();
650 
651 	id = &fwa->f_id;
652 	fid = &pkt->id;
653 	fid->fid_dst_ip = id->dst_ip;
654 	fid->fid_src_ip = id->src_ip;
655 	fid->fid_dst_port = id->dst_port;
656 	fid->fid_src_port = id->src_port;
657 	fid->fid_proto = id->proto;
658 	fid->fid_flags = id->flags;
659 
660 	pkt->dn_priv = fwa->rule;
661 
662 	if ((int)cmd->opcode == O_DUMMYNET_PIPE)
663 		pkt->dn_flags |= DN_FLAGS_IS_PIPE;
664 
665 	m->m_pkthdr.fw_flags |= DUMMYNET_MBUF_TAGGED;
666 }
667 
668 static __inline void
669 ipfw_inc_static_count(struct ip_fw *rule)
670 {
671 	/* Static rule's counts are updated only on CPU0 */
672 	KKASSERT(mycpuid == 0);
673 
674 	static_count++;
675 	static_ioc_len += IOC_RULESIZE(rule);
676 }
677 
678 static __inline void
679 ipfw_dec_static_count(struct ip_fw *rule)
680 {
681 	int l = IOC_RULESIZE(rule);
682 
683 	/* Static rule's counts are updated only on CPU0 */
684 	KKASSERT(mycpuid == 0);
685 
686 	KASSERT(static_count > 0, ("invalid static count %u", static_count));
687 	static_count--;
688 
689 	KASSERT(static_ioc_len >= l,
690 			("invalid static len %u", static_ioc_len));
691 	static_ioc_len -= l;
692 }
693 
694 static void
695 ipfw_add_rule_dispatch(netmsg_t nmsg)
696 {
697 	struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
698 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
699 	struct ip_fw *rule, *prev,*next;
700 	const struct ipfw_ioc_rule *ioc_rule;
701 
702 	ioc_rule = fwmsg->ioc_rule;
703 	 // create rule by ioc_rule
704 	rule = kmalloc(RULESIZE(ioc_rule), M_IPFW3, M_WAITOK | M_ZERO);
705 	rule->act_ofs = ioc_rule->act_ofs;
706 	rule->cmd_len = ioc_rule->cmd_len;
707 	rule->rulenum = ioc_rule->rulenum;
708 	rule->set = ioc_rule->set;
709 	bcopy(ioc_rule->cmd, rule->cmd, rule->cmd_len * 4);
710 
711 	for (prev = NULL, next = ctx->ipfw_rule_chain;
712 		next; prev = next, next = next->next) {
713 		if (next->rulenum > ioc_rule->rulenum) {
714 			break;
715 		}
716 	}
717 	KASSERT(next != NULL, ("no default rule?!"));
718 
719 	/*
720 	 * Insert rule into the pre-determined position
721 	 */
722 	if (prev != NULL) {
723 		rule->next = next;
724 		prev->next = rule;
725 	} else {
726 		rule->next = ctx->ipfw_rule_chain;
727 		ctx->ipfw_rule_chain = rule;
728 	}
729 
730 	/*
731 	 * if sibiling in last CPU is exists,
732 	 * then it's sibling should be current rule
733 	 */
734 	if (fwmsg->sibling != NULL) {
735 		fwmsg->sibling->sibling = rule;
736 	}
737 	/* prepare for next CPU */
738 	fwmsg->sibling = rule;
739 
740 	if (mycpuid == 0) {
741 		/* Statistics only need to be updated once */
742 		ipfw_inc_static_count(rule);
743 	}
744 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
745 }
746 
747 /*
748  * confirm the rulenumber
749  * call dispatch function to add rule into the list
750  * Update the statistic
751  */
752 static void
753 ipfw_add_rule(struct ipfw_ioc_rule *ioc_rule)
754 {
755 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
756 	struct netmsg_ipfw fwmsg;
757 	struct netmsg_base *nmsg;
758 	struct ip_fw *f;
759 
760 	IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
761 
762 	/*
763 	 * If rulenum is 0, find highest numbered rule before the
764 	 * default rule, and add rule number incremental step.
765 	 */
766 	if (ioc_rule->rulenum == 0) {
767 		int step = autoinc_step;
768 
769 		KKASSERT(step >= IPFW_AUTOINC_STEP_MIN &&
770 				step <= IPFW_AUTOINC_STEP_MAX);
771 
772 		/*
773 		 * Locate the highest numbered rule before default
774 		 */
775 		for (f = ctx->ipfw_rule_chain; f; f = f->next) {
776 			if (f->rulenum == IPFW_DEFAULT_RULE)
777 				break;
778 			ioc_rule->rulenum = f->rulenum;
779 		}
780 		if (ioc_rule->rulenum < IPFW_DEFAULT_RULE - step)
781 			ioc_rule->rulenum += step;
782 	}
783 	KASSERT(ioc_rule->rulenum != IPFW_DEFAULT_RULE &&
784 			ioc_rule->rulenum != 0,
785 			("invalid rule num %d", ioc_rule->rulenum));
786 
787 	bzero(&fwmsg, sizeof(fwmsg));
788 	nmsg = &fwmsg.base;
789 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
790 			0, ipfw_add_rule_dispatch);
791 	fwmsg.ioc_rule = ioc_rule;
792 
793 	ifnet_domsg(&nmsg->lmsg, 0);
794 
795 	DPRINTF("++ installed rule %d, static count now %d\n",
796 			ioc_rule->rulenum, static_count);
797 }
798 
799 /**
800  * Free storage associated with a static rule (including derived
801  * dynamic rules).
802  * The caller is in charge of clearing rule pointers to avoid
803  * dangling pointers.
804  * @return a pointer to the next entry.
805  * Arguments are not checked, so they better be correct.
806  * Must be called at splimp().
807  */
808 static struct ip_fw *
809 ipfw_delete_rule(struct ipfw_context *ctx,
810 		 struct ip_fw *prev, struct ip_fw *rule)
811 {
812 	if (prev == NULL)
813 		ctx->ipfw_rule_chain = rule->next;
814 	else
815 		prev->next = rule->next;
816 
817 	if (mycpuid == IPFW_CFGCPUID)
818 		ipfw_dec_static_count(rule);
819 
820 	kfree(rule, M_IPFW3);
821 	rule = NULL;
822 	return NULL;
823 }
824 
825 static void
826 ipfw_flush_rule_dispatch(netmsg_t nmsg)
827 {
828 	struct lwkt_msg *lmsg = &nmsg->lmsg;
829 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
830 	struct ip_fw *rule, *the_rule;
831 	int kill_default = lmsg->u.ms_result;
832 
833 	rule = ctx->ipfw_rule_chain;
834 	while (rule != NULL) {
835 		if (rule->rulenum == IPFW_DEFAULT_RULE && kill_default == 0) {
836 			ctx->ipfw_rule_chain = rule;
837 			break;
838 		}
839 		the_rule = rule;
840 		rule = rule->next;
841 		if (mycpuid == IPFW_CFGCPUID)
842 			ipfw_dec_static_count(the_rule);
843 
844 		kfree(the_rule, M_IPFW3);
845 	}
846 
847 	ifnet_forwardmsg(lmsg, mycpuid + 1);
848 }
849 
850 static void
851 ipfw_append_state_dispatch(netmsg_t nmsg)
852 {
853 	struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
854 	struct ipfw_ioc_state *ioc_state = dmsg->ioc_state;
855 	(*ipfw_basic_append_state_prt)(ioc_state);
856 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
857 }
858 
859 static void
860 ipfw_delete_state_dispatch(netmsg_t nmsg)
861 {
862 	struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
863 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
864 	struct ip_fw *rule = ctx->ipfw_rule_chain;
865 	while (rule != NULL) {
866 		if (rule->rulenum == dmsg->rulenum) {
867 			break;
868 		}
869 		rule = rule->next;
870 	}
871 
872 	(*ipfw_basic_flush_state_prt)(rule);
873 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
874 }
875 
876 /*
877  * Deletes all rules from a chain (including the default rule
878  * if the second argument is set).
879  * Must be called at splimp().
880  */
881 static void
882 ipfw_ctl_flush_rule(int kill_default)
883 {
884 	struct netmsg_del dmsg;
885 	struct netmsg_base nmsg;
886 	struct lwkt_msg *lmsg;
887 
888 	IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
889 
890 	/*
891 	 * If 'kill_default' then caller has done the necessary
892 	 * msgport syncing; unnecessary to do it again.
893 	 */
894 	if (!kill_default) {
895 		/*
896 		 * Let ipfw_chk() know the rules are going to
897 		 * be flushed, so it could jump directly to
898 		 * the default rule.
899 		 */
900 		ipfw_flushing = 1;
901 		netmsg_service_sync();
902 	}
903 
904 	/*
905 	 * if ipfw_basic_flush_state_prt
906 	 * flush all states in all CPU
907 	 */
908 	if (ipfw_basic_flush_state_prt != NULL) {
909 		bzero(&dmsg, sizeof(dmsg));
910 		netmsg_init(&dmsg.base, NULL, &curthread->td_msgport,
911 				0, ipfw_delete_state_dispatch);
912 		ifnet_domsg(&dmsg.base.lmsg, 0);
913 	}
914 	/*
915 	 * Press the 'flush' button
916 	 */
917 	bzero(&nmsg, sizeof(nmsg));
918 	netmsg_init(&nmsg, NULL, &curthread->td_msgport,
919 			0, ipfw_flush_rule_dispatch);
920 	lmsg = &nmsg.lmsg;
921 	lmsg->u.ms_result = kill_default;
922 	ifnet_domsg(lmsg, 0);
923 
924 	if (kill_default) {
925 		KASSERT(static_count == 0,
926 				("%u static rules remain", static_count));
927 		KASSERT(static_ioc_len == 0,
928 				("%u bytes of static rules remain", static_ioc_len));
929 	}
930 
931 	/* Flush is done */
932 	ipfw_flushing = 0;
933 }
934 
935 static void
936 ipfw_delete_rule_dispatch(netmsg_t nmsg)
937 {
938 	struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
939 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
940 	struct ip_fw *rule, *prev = NULL;
941 
942 	rule = ctx->ipfw_rule_chain;
943 	while (rule!=NULL) {
944 		if (rule->rulenum == dmsg->rulenum) {
945 			ipfw_delete_rule(ctx, prev, rule);
946 			break;
947 		}
948 		prev = rule;
949 		rule = rule->next;
950 	}
951 
952 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
953 }
954 
955 static int
956 ipfw_alt_delete_rule(uint16_t rulenum)
957 {
958 	struct netmsg_del dmsg;
959 	struct netmsg_base *nmsg;
960 
961 	/*
962 	 * delete the state which stub is the rule
963 	 * which belongs to the CPU and the rulenum
964 	 */
965 	bzero(&dmsg, sizeof(dmsg));
966 	nmsg = &dmsg.base;
967 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
968 			0, ipfw_delete_state_dispatch);
969 	dmsg.rulenum = rulenum;
970 	ifnet_domsg(&nmsg->lmsg, 0);
971 
972 	/*
973 	 * Get rid of the rule duplications on all CPUs
974 	 */
975 	bzero(&dmsg, sizeof(dmsg));
976 	nmsg = &dmsg.base;
977 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
978 			0, ipfw_delete_rule_dispatch);
979 	dmsg.rulenum = rulenum;
980 	ifnet_domsg(&nmsg->lmsg, 0);
981 	return 0;
982 }
983 
984 static void
985 ipfw_alt_delete_ruleset_dispatch(netmsg_t nmsg)
986 {
987 	struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
988 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
989 	struct ip_fw *prev, *rule;
990 #ifdef INVARIANTS
991 	int del = 0;
992 #endif
993 
994 	prev = NULL;
995 	rule = ctx->ipfw_rule_chain;
996 	while (rule != NULL) {
997 		if (rule->set == dmsg->from_set) {
998 			rule = ipfw_delete_rule(ctx, prev, rule);
999 #ifdef INVARIANTS
1000 			del = 1;
1001 #endif
1002 		} else {
1003 			prev = rule;
1004 			rule = rule->next;
1005 		}
1006 	}
1007 	KASSERT(del, ("no match set?!"));
1008 
1009 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
1010 }
1011 
1012 static void
1013 ipfw_disable_ruleset_state_dispatch(netmsg_t nmsg)
1014 {
1015 	struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
1016 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1017 	struct ip_fw *rule;
1018 #ifdef INVARIANTS
1019 	int cleared = 0;
1020 #endif
1021 
1022 	for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1023 		if (rule->set == dmsg->from_set) {
1024 #ifdef INVARIANTS
1025 			cleared = 1;
1026 #endif
1027 		}
1028 	}
1029 	KASSERT(cleared, ("no match set?!"));
1030 
1031 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
1032 }
1033 
1034 static int
1035 ipfw_alt_delete_ruleset(uint8_t set)
1036 {
1037 	struct netmsg_del dmsg;
1038 	struct netmsg_base *nmsg;
1039 	int state, del;
1040 	struct ip_fw *rule;
1041 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1042 
1043 	/*
1044 	 * Check whether the 'set' exists.  If it exists,
1045 	 * then check whether any rules within the set will
1046 	 * try to create states.
1047 	 */
1048 	state = 0;
1049 	del = 0;
1050 	for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1051 		if (rule->set == set) {
1052 			del = 1;
1053 		}
1054 	}
1055 	if (!del)
1056 		return 0; /* XXX EINVAL? */
1057 
1058 	if (state) {
1059 		/*
1060 		 * Clear the STATE flag, so no more states will be
1061 		 * created based the rules in this set.
1062 		 */
1063 		bzero(&dmsg, sizeof(dmsg));
1064 		nmsg = &dmsg.base;
1065 		netmsg_init(nmsg, NULL, &curthread->td_msgport,
1066 				0, ipfw_disable_ruleset_state_dispatch);
1067 		dmsg.from_set = set;
1068 
1069 		ifnet_domsg(&nmsg->lmsg, 0);
1070 	}
1071 
1072 	/*
1073 	 * Delete this set
1074 	 */
1075 	bzero(&dmsg, sizeof(dmsg));
1076 	nmsg = &dmsg.base;
1077 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
1078 			0, ipfw_alt_delete_ruleset_dispatch);
1079 	dmsg.from_set = set;
1080 
1081 	ifnet_domsg(&nmsg->lmsg, 0);
1082 	return 0;
1083 }
1084 
1085 static void
1086 ipfw_alt_move_rule_dispatch(netmsg_t nmsg)
1087 {
1088 	struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
1089 	struct ip_fw *rule;
1090 
1091 	rule = dmsg->start_rule;
1092 
1093 	/*
1094 	 * Move to the position on the next CPU
1095 	 * before the msg is forwarded.
1096 	 */
1097 
1098 	while (rule && rule->rulenum <= dmsg->rulenum) {
1099 		if (rule->rulenum == dmsg->rulenum)
1100 			rule->set = dmsg->to_set;
1101 		rule = rule->next;
1102 	}
1103 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
1104 }
1105 
1106 static int
1107 ipfw_alt_move_rule(uint16_t rulenum, uint8_t set)
1108 {
1109 	struct netmsg_del dmsg;
1110 	struct netmsg_base *nmsg;
1111 	struct ip_fw *rule;
1112 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1113 
1114 	/*
1115 	 * Locate first rule to move
1116 	 */
1117 	for (rule = ctx->ipfw_rule_chain;
1118 		rule && rule->rulenum <= rulenum; rule = rule->next) {
1119 		if (rule->rulenum == rulenum && rule->set != set)
1120 			break;
1121 	}
1122 	if (rule == NULL || rule->rulenum > rulenum)
1123 		return 0; /* XXX error? */
1124 
1125 	bzero(&dmsg, sizeof(dmsg));
1126 	nmsg = &dmsg.base;
1127 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
1128 			0, ipfw_alt_move_rule_dispatch);
1129 	dmsg.start_rule = rule;
1130 	dmsg.rulenum = rulenum;
1131 	dmsg.to_set = set;
1132 
1133 	ifnet_domsg(&nmsg->lmsg, 0);
1134 	KKASSERT(dmsg.start_rule == NULL);
1135 	return 0;
1136 }
1137 
1138 static void
1139 ipfw_alt_move_ruleset_dispatch(netmsg_t nmsg)
1140 {
1141 	struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
1142 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1143 	struct ip_fw *rule;
1144 
1145 	for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1146 		if (rule->set == dmsg->from_set)
1147 			rule->set = dmsg->to_set;
1148 	}
1149 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
1150 }
1151 
1152 static int
1153 ipfw_alt_move_ruleset(uint8_t from_set, uint8_t to_set)
1154 {
1155 	struct netmsg_del dmsg;
1156 	struct netmsg_base *nmsg;
1157 
1158 	bzero(&dmsg, sizeof(dmsg));
1159 	nmsg = &dmsg.base;
1160 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
1161 			0, ipfw_alt_move_ruleset_dispatch);
1162 	dmsg.from_set = from_set;
1163 	dmsg.to_set = to_set;
1164 
1165 	ifnet_domsg(&nmsg->lmsg, 0);
1166 	return 0;
1167 }
1168 
1169 static void
1170 ipfw_alt_swap_ruleset_dispatch(netmsg_t nmsg)
1171 {
1172 	struct netmsg_del *dmsg = (struct netmsg_del *)nmsg;
1173 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1174 	struct ip_fw *rule;
1175 
1176 	for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1177 		if (rule->set == dmsg->from_set)
1178 			rule->set = dmsg->to_set;
1179 		else if (rule->set == dmsg->to_set)
1180 			rule->set = dmsg->from_set;
1181 	}
1182 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
1183 }
1184 
1185 static int
1186 ipfw_alt_swap_ruleset(uint8_t set1, uint8_t set2)
1187 {
1188 	struct netmsg_del dmsg;
1189 	struct netmsg_base *nmsg;
1190 
1191 	bzero(&dmsg, sizeof(dmsg));
1192 	nmsg = &dmsg.base;
1193 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
1194 			0, ipfw_alt_swap_ruleset_dispatch);
1195 	dmsg.from_set = set1;
1196 	dmsg.to_set = set2;
1197 
1198 	ifnet_domsg(&nmsg->lmsg, 0);
1199 	return 0;
1200 }
1201 
1202 
1203 static int
1204 ipfw_ctl_alter(uint32_t arg)
1205 {
1206 	uint16_t rulenum;
1207 	uint8_t cmd, new_set;
1208 	int error = 0;
1209 
1210 	rulenum = arg & 0xffff;
1211 	cmd = (arg >> 24) & 0xff;
1212 	new_set = (arg >> 16) & 0xff;
1213 
1214 	if (cmd > 4)
1215 		return EINVAL;
1216 	if (new_set >= IPFW_DEFAULT_SET)
1217 		return EINVAL;
1218 	if (cmd == 0 || cmd == 2) {
1219 		if (rulenum == IPFW_DEFAULT_RULE)
1220 			return EINVAL;
1221 	} else {
1222 		if (rulenum >= IPFW_DEFAULT_SET)
1223 			return EINVAL;
1224 	}
1225 
1226 	switch (cmd) {
1227 	case 0:	/* delete rules with given number */
1228 		error = ipfw_alt_delete_rule(rulenum);
1229 		break;
1230 
1231 	case 1:	/* delete all rules with given set number */
1232 		error = ipfw_alt_delete_ruleset(rulenum);
1233 		break;
1234 
1235 	case 2:	/* move rules with given number to new set */
1236 		error = ipfw_alt_move_rule(rulenum, new_set);
1237 		break;
1238 
1239 	case 3: /* move rules with given set number to new set */
1240 		error = ipfw_alt_move_ruleset(rulenum, new_set);
1241 		break;
1242 
1243 	case 4: /* swap two sets */
1244 		error = ipfw_alt_swap_ruleset(rulenum, new_set);
1245 		break;
1246 	}
1247 	return error;
1248 }
1249 
1250 /*
1251  * Clear counters for a specific rule.
1252  */
1253 static void
1254 clear_counters(struct ip_fw *rule)
1255 {
1256 	rule->bcnt = rule->pcnt = 0;
1257 	rule->timestamp = 0;
1258 }
1259 
1260 static void
1261 ipfw_zero_entry_dispatch(netmsg_t nmsg)
1262 {
1263 	struct netmsg_zent *zmsg = (struct netmsg_zent *)nmsg;
1264 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1265 	struct ip_fw *rule;
1266 
1267 	if (zmsg->rulenum == 0) {
1268 		for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1269 			clear_counters(rule);
1270 		}
1271 	} else {
1272 		for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1273 			if (rule->rulenum == zmsg->rulenum) {
1274 				clear_counters(rule);
1275 			}
1276 		}
1277 	}
1278 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
1279 }
1280 
1281 /**
1282  * Reset some or all counters on firewall rules.
1283  * @arg frwl is null to clear all entries, or contains a specific
1284  * rule number.
1285  * @arg log_only is 1 if we only want to reset logs, zero otherwise.
1286  */
1287 static int
1288 ipfw_ctl_zero_entry(int rulenum, int log_only)
1289 {
1290 	struct netmsg_zent zmsg;
1291 	struct netmsg_base *nmsg;
1292 	const char *msg;
1293 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1294 
1295 	bzero(&zmsg, sizeof(zmsg));
1296 	nmsg = &zmsg.base;
1297 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
1298 			0, ipfw_zero_entry_dispatch);
1299 	zmsg.log_only = log_only;
1300 
1301 	if (rulenum == 0) {
1302 		msg = log_only ? "ipfw: All logging counts reset.\n"
1303 				   : "ipfw: Accounting cleared.\n";
1304 	} else {
1305 		struct ip_fw *rule;
1306 
1307 		/*
1308 		 * Locate the first rule with 'rulenum'
1309 		 */
1310 		for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1311 			if (rule->rulenum == rulenum)
1312 				break;
1313 		}
1314 		if (rule == NULL) /* we did not find any matching rules */
1315 			return (EINVAL);
1316 		zmsg.start_rule = rule;
1317 		zmsg.rulenum = rulenum;
1318 
1319 		msg = log_only ? "ipfw: Entry %d logging count reset.\n"
1320 				   : "ipfw: Entry %d cleared.\n";
1321 	}
1322 	ifnet_domsg(&nmsg->lmsg, 0);
1323 	KKASSERT(zmsg.start_rule == NULL);
1324 
1325 	if (fw_verbose)
1326 		log(LOG_SECURITY | LOG_NOTICE, msg, rulenum);
1327 	return (0);
1328 }
1329 
1330 static int
1331 ipfw_ctl_add_state(struct sockopt *sopt)
1332 {
1333 	struct ipfw_ioc_state *ioc_state;
1334 	ioc_state = sopt->sopt_val;
1335 	if (ipfw_basic_append_state_prt != NULL) {
1336 		struct netmsg_del dmsg;
1337 		bzero(&dmsg, sizeof(dmsg));
1338 		netmsg_init(&dmsg.base, NULL, &curthread->td_msgport,
1339 			0, ipfw_append_state_dispatch);
1340 		(&dmsg)->ioc_state = ioc_state;
1341 		ifnet_domsg(&dmsg.base.lmsg, 0);
1342 	}
1343 	return 0;
1344 }
1345 
1346 static int
1347 ipfw_ctl_delete_state(struct sockopt *sopt)
1348 {
1349 	int rulenum = 0, error;
1350 	if (sopt->sopt_valsize != 0) {
1351 		error = soopt_to_kbuf(sopt, &rulenum, sizeof(int), sizeof(int));
1352 		if (error) {
1353 			return -1;
1354 		}
1355 	}
1356 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1357 	struct ip_fw *rule = ctx->ipfw_rule_chain;
1358 
1359 	while (rule!=NULL) {
1360 		if (rule->rulenum == rulenum) {
1361 			break;
1362 		}
1363 		rule = rule->next;
1364 	}
1365 	if (rule == NULL) {
1366 		return -1;
1367 	}
1368 
1369 	struct netmsg_del dmsg;
1370 	struct netmsg_base *nmsg;
1371 	/*
1372 	 * delete the state which stub is the rule
1373 	 * which belongs to the CPU and the rulenum
1374 	 */
1375 	bzero(&dmsg, sizeof(dmsg));
1376 	nmsg = &dmsg.base;
1377 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
1378 			0, ipfw_delete_state_dispatch);
1379 	dmsg.rulenum = rulenum;
1380 	ifnet_domsg(&nmsg->lmsg, 0);
1381 	return 0;
1382 }
1383 
1384 static int
1385 ipfw_ctl_flush_state(struct sockopt *sopt)
1386 {
1387 	struct netmsg_del dmsg;
1388 	struct netmsg_base *nmsg;
1389 	/*
1390 	 * delete the state which stub is the rule
1391 	 * which belongs to the CPU and the rulenum
1392 	 */
1393 	bzero(&dmsg, sizeof(dmsg));
1394 	nmsg = &dmsg.base;
1395 	netmsg_init(nmsg, NULL, &curthread->td_msgport,
1396 			0, ipfw_delete_state_dispatch);
1397 	dmsg.rulenum = 0;
1398 	ifnet_domsg(&nmsg->lmsg, 0);
1399 	return 0;
1400 }
1401 
1402 /*
1403  * Get the ioc_rule from the sopt
1404  * call ipfw_add_rule to add the rule
1405  */
1406 static int
1407 ipfw_ctl_add_rule(struct sockopt *sopt)
1408 {
1409 	struct ipfw_ioc_rule *ioc_rule;
1410 	size_t size;
1411 
1412 	size = sopt->sopt_valsize;
1413 	if (size > (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX) ||
1414 			size < sizeof(*ioc_rule)) {
1415 		return EINVAL;
1416 	}
1417 	if (size != (sizeof(uint32_t) * IPFW_RULE_SIZE_MAX)) {
1418 		sopt->sopt_val = krealloc(sopt->sopt_val, sizeof(uint32_t) *
1419 				IPFW_RULE_SIZE_MAX, M_TEMP, M_WAITOK);
1420 	}
1421 	ioc_rule = sopt->sopt_val;
1422 
1423 	ipfw_add_rule(ioc_rule);
1424 	return 0;
1425 }
1426 
1427 static void *
1428 ipfw_copy_state(struct ip_fw_state *state, struct ipfw_ioc_state *ioc_state, int cpuid)
1429 {
1430 	ioc_state->pcnt = state->pcnt;
1431 	ioc_state->bcnt = state->bcnt;
1432 	ioc_state->lifetime = state->lifetime;
1433 	ioc_state->timestamp = state->timestamp;
1434 	ioc_state->cpuid = cpuid;
1435 	ioc_state->expiry = state->expiry;
1436 	ioc_state->rulenum = state->stub->rulenum;
1437 
1438 	bcopy(&state->flow_id, &ioc_state->flow_id, sizeof(struct ipfw_flow_id));
1439 	return ioc_state + 1;
1440 }
1441 
1442 static void *
1443 ipfw_copy_rule(const struct ip_fw *rule, struct ipfw_ioc_rule *ioc_rule)
1444 {
1445 	const struct ip_fw *sibling;
1446 #ifdef INVARIANTS
1447 	int i;
1448 #endif
1449 
1450 	ioc_rule->act_ofs = rule->act_ofs;
1451 	ioc_rule->cmd_len = rule->cmd_len;
1452 	ioc_rule->rulenum = rule->rulenum;
1453 	ioc_rule->set = rule->set;
1454 
1455 	ioc_rule->set_disable = ipfw_ctx[mycpuid]->ipfw_set_disable;
1456 	ioc_rule->static_count = static_count;
1457 	ioc_rule->static_len = static_ioc_len;
1458 
1459 	ioc_rule->pcnt = 1;
1460 	ioc_rule->bcnt = 0;
1461 	ioc_rule->timestamp = 0;
1462 
1463 #ifdef INVARIANTS
1464 	i = 0;
1465 #endif
1466 	ioc_rule->pcnt = 0;
1467 	ioc_rule->bcnt = 0;
1468 	ioc_rule->timestamp = 0;
1469 	for (sibling = rule; sibling != NULL; sibling = sibling->sibling) {
1470 		ioc_rule->pcnt += sibling->pcnt;
1471 		ioc_rule->bcnt += sibling->bcnt;
1472 		if (sibling->timestamp > ioc_rule->timestamp)
1473 			ioc_rule->timestamp = sibling->timestamp;
1474 #ifdef INVARIANTS
1475 		++i;
1476 #endif
1477 	}
1478 
1479 	KASSERT(i == ncpus, ("static rule is not duplicated on every cpu"));
1480 
1481 	bcopy(rule->cmd, ioc_rule->cmd, ioc_rule->cmd_len * 4 /* XXX */);
1482 
1483 	return ((uint8_t *)ioc_rule + IOC_RULESIZE(ioc_rule));
1484 }
1485 
1486 static int
1487 ipfw_ctl_get_modules(struct sockopt *sopt)
1488 {
1489 	int i;
1490 	struct ipfw_module *mod;
1491 	char module_str[1024];
1492 	memset(module_str,0,1024);
1493 	for (i = 0, mod = ipfw_modules; i < MAX_MODULE; i++, mod++) {
1494 		if (mod->type != 0) {
1495 			if (i > 0)
1496 				strcat(module_str,",");
1497 			strcat(module_str,mod->name);
1498 		}
1499 	}
1500 	bzero(sopt->sopt_val, sopt->sopt_valsize);
1501 	bcopy(module_str, sopt->sopt_val, strlen(module_str));
1502 	sopt->sopt_valsize = strlen(module_str);
1503 	return 0;
1504 }
1505 
1506 /*
1507  * Copy all static rules and states on all CPU
1508  */
1509 static int
1510 ipfw_ctl_get_rules(struct sockopt *sopt)
1511 {
1512 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1513 	struct ipfw_state_context *state_ctx;
1514 	struct ip_fw *rule;
1515 	struct ip_fw_state *state;
1516 	void *bp;
1517 	size_t size;
1518 	int i, j, state_count = 0;
1519 
1520 	size = static_ioc_len;
1521 	for (i = 0; i < ncpus; i++) {
1522 		for (j = 0; j < ctx->state_hash_size; j++) {
1523 			state_ctx = &ipfw_ctx[i]->state_ctx[j];
1524 			state_count += state_ctx->count;
1525 		}
1526 	}
1527 	if (state_count > 0) {
1528 		size += state_count * sizeof(struct ipfw_ioc_state);
1529 	}
1530 
1531 	if (sopt->sopt_valsize < size) {
1532 		/* XXX TODO sopt_val is not big enough */
1533 		bzero(sopt->sopt_val, sopt->sopt_valsize);
1534 		return 0;
1535 	}
1536 
1537 	sopt->sopt_valsize = size;
1538 	bp = sopt->sopt_val;
1539 
1540 	for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
1541 		bp = ipfw_copy_rule(rule, bp);
1542 	}
1543 	if (state_count > 0 ) {
1544 		for (i = 0; i < ncpus; i++) {
1545 			for (j = 0; j < ctx->state_hash_size; j++) {
1546 				state_ctx = &ipfw_ctx[i]->state_ctx[j];
1547 				state = state_ctx->state;
1548 				while (state != NULL) {
1549 					bp = ipfw_copy_state(state, bp, i);
1550 					state = state->next;
1551 				}
1552 			}
1553 		}
1554 	}
1555 	return 0;
1556 }
1557 
1558 static void
1559 ipfw_set_disable_dispatch(netmsg_t nmsg)
1560 {
1561 	struct lwkt_msg *lmsg = &nmsg->lmsg;
1562 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
1563 
1564 	ctx->ipfw_set_disable = lmsg->u.ms_result32;
1565 
1566 	ifnet_forwardmsg(lmsg, mycpuid + 1);
1567 }
1568 
1569 static void
1570 ipfw_ctl_set_disable(uint32_t disable, uint32_t enable)
1571 {
1572 	struct netmsg_base nmsg;
1573 	struct lwkt_msg *lmsg;
1574 	uint32_t set_disable;
1575 
1576 	/* IPFW_DEFAULT_SET is always enabled */
1577 	enable |= (1 << IPFW_DEFAULT_SET);
1578 	set_disable = (ipfw_ctx[mycpuid]->ipfw_set_disable | disable) & ~enable;
1579 
1580 	bzero(&nmsg, sizeof(nmsg));
1581 	netmsg_init(&nmsg, NULL, &curthread->td_msgport,
1582 			0, ipfw_set_disable_dispatch);
1583 	lmsg = &nmsg.lmsg;
1584 	lmsg->u.ms_result32 = set_disable;
1585 
1586 	ifnet_domsg(lmsg, 0);
1587 }
1588 
1589 
1590 /*
1591  * ipfw_ctl_x - extended version of ipfw_ctl
1592  * remove the x_header, and adjust the sopt_name,sopt_val and sopt_valsize.
1593  */
1594 int
1595 ipfw_ctl_x(struct sockopt *sopt)
1596 {
1597 	ip_fw_x_header *x_header;
1598 	x_header = (ip_fw_x_header *)(sopt->sopt_val);
1599 	sopt->sopt_name = x_header->opcode;
1600 	sopt->sopt_valsize -= sizeof(ip_fw_x_header);
1601 	bcopy(++x_header, sopt->sopt_val, sopt->sopt_valsize);
1602 	return ipfw_ctl(sopt);
1603 }
1604 
1605 
1606 /**
1607  * {set|get}sockopt parser.
1608  */
1609 static int
1610 ipfw_ctl(struct sockopt *sopt)
1611 {
1612 	int error, rulenum;
1613 	uint32_t *masks;
1614 	size_t size;
1615 
1616 	error = 0;
1617 	switch (sopt->sopt_name) {
1618 		case IP_FW_X:
1619 			ipfw_ctl_x(sopt);
1620 			break;
1621 		case IP_FW_GET:
1622 			error = ipfw_ctl_get_rules(sopt);
1623 			break;
1624 		case IP_FW_MODULE:
1625 			error = ipfw_ctl_get_modules(sopt);
1626 			break;
1627 
1628 		case IP_FW_FLUSH:
1629 			ipfw_ctl_flush_rule(0);
1630 			break;
1631 
1632 		case IP_FW_ADD:
1633 			error = ipfw_ctl_add_rule(sopt);
1634 			break;
1635 
1636 		case IP_FW_DEL:
1637 			/*
1638 			 * IP_FW_DEL is used for deleting single rules or sets,
1639 			 * and (ab)used to atomically manipulate sets.
1640 			 * Argument size is used to distinguish between the two:
1641 			 *	sizeof(uint32_t)
1642 			 *	delete single rule or set of rules,
1643 			 *	or reassign rules (or sets) to a different set.
1644 			 *	2 * sizeof(uint32_t)
1645 			 *	atomic disable/enable sets.
1646 			 *	first uint32_t contains sets to be disabled,
1647 			 *	second uint32_t contains sets to be enabled.
1648 			 */
1649 			masks = sopt->sopt_val;
1650 			size = sopt->sopt_valsize;
1651 			if (size == sizeof(*masks)) {
1652 				/*
1653 				 * Delete or reassign static rule
1654 				 */
1655 				error = ipfw_ctl_alter(masks[0]);
1656 			} else if (size == (2 * sizeof(*masks))) {
1657 				/*
1658 				 * Set enable/disable
1659 				 */
1660 				ipfw_ctl_set_disable(masks[0], masks[1]);
1661 			} else {
1662 				error = EINVAL;
1663 			}
1664 			break;
1665 		case IP_FW_ZERO:
1666 		case IP_FW_RESETLOG: /* argument is an int, the rule number */
1667 			rulenum = 0;
1668 			if (sopt->sopt_valsize != 0) {
1669 				error = soopt_to_kbuf(sopt, &rulenum,
1670 						sizeof(int), sizeof(int));
1671 				if (error) {
1672 					break;
1673 				}
1674 			}
1675 			error = ipfw_ctl_zero_entry(rulenum,
1676 					sopt->sopt_name == IP_FW_RESETLOG);
1677 			break;
1678 		case IP_FW_NAT_CFG:
1679 			error = ipfw_nat_cfg_ptr(sopt);
1680 			break;
1681 		case IP_FW_NAT_DEL:
1682 			error = ipfw_nat_del_ptr(sopt);
1683 			break;
1684 		case IP_FW_NAT_FLUSH:
1685 			error = ipfw_nat_flush_ptr(sopt);
1686 			break;
1687 		case IP_FW_NAT_GET:
1688 			error = ipfw_nat_get_cfg_ptr(sopt);
1689 			break;
1690 		case IP_FW_NAT_LOG:
1691 			error = ipfw_nat_get_log_ptr(sopt);
1692 			break;
1693 		case IP_DUMMYNET_GET:
1694 		case IP_DUMMYNET_CONFIGURE:
1695 		case IP_DUMMYNET_DEL:
1696 		case IP_DUMMYNET_FLUSH:
1697 			error = ip_dn_sockopt(sopt);
1698 			break;
1699 		case IP_FW_STATE_ADD:
1700 			error = ipfw_ctl_add_state(sopt);
1701 			break;
1702 		case IP_FW_STATE_DEL:
1703 			error = ipfw_ctl_delete_state(sopt);
1704 			break;
1705 		case IP_FW_STATE_FLUSH:
1706 			error = ipfw_ctl_flush_state(sopt);
1707 			break;
1708 		case IP_FW_TABLE_CREATE:
1709 		case IP_FW_TABLE_DELETE:
1710 		case IP_FW_TABLE_APPEND:
1711 		case IP_FW_TABLE_REMOVE:
1712 		case IP_FW_TABLE_LIST:
1713 		case IP_FW_TABLE_FLUSH:
1714 		case IP_FW_TABLE_SHOW:
1715 		case IP_FW_TABLE_TEST:
1716 		case IP_FW_TABLE_RENAME:
1717 			error = ipfw_ctl_table_sockopt(sopt);
1718 			break;
1719 		default:
1720 			kprintf("ipfw_ctl invalid option %d\n",
1721 				sopt->sopt_name);
1722 			error = EINVAL;
1723 	}
1724 	return error;
1725 }
1726 
1727 static int
1728 ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1729 {
1730 	struct ip_fw_args args;
1731 	struct mbuf *m = *m0;
1732 	struct m_tag *mtag;
1733 	int tee = 0, error = 0, ret;
1734 	// again:
1735 	if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1736 		/* Extract info from dummynet tag */
1737 		mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1738 		KKASSERT(mtag != NULL);
1739 		args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1740 		KKASSERT(args.rule != NULL);
1741 
1742 		m_tag_delete(m, mtag);
1743 		m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1744 	} else {
1745 		args.rule = NULL;
1746 	}
1747 
1748 	args.eh = NULL;
1749 	args.oif = NULL;
1750 	args.m = m;
1751 	ret = ipfw_chk(&args);
1752 	m = args.m;
1753 
1754 	if (m == NULL) {
1755 		error = EACCES;
1756 		goto back;
1757 	}
1758 	switch (ret) {
1759 		case IP_FW_PASS:
1760 			break;
1761 
1762 		case IP_FW_DENY:
1763 			m_freem(m);
1764 			m = NULL;
1765 			error = EACCES;
1766 			break;
1767 
1768 		case IP_FW_DUMMYNET:
1769 			/* Send packet to the appropriate pipe */
1770 			ipfw_dummynet_io(m, args.cookie, DN_TO_IP_IN, &args);
1771 			break;
1772 
1773 		case IP_FW_TEE:
1774 			tee = 1;
1775 			/* FALL THROUGH */
1776 
1777 		case IP_FW_DIVERT:
1778 			/*
1779 			 * Must clear bridge tag when changing
1780 			 */
1781 			m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED;
1782 			if (ip_divert_p != NULL) {
1783 				m = ip_divert_p(m, tee, 1);
1784 			} else {
1785 				m_freem(m);
1786 				m = NULL;
1787 				/* not sure this is the right error msg */
1788 				error = EACCES;
1789 			}
1790 			break;
1791 
1792 		case IP_FW_NAT:
1793 			break;
1794 		case IP_FW_ROUTE:
1795 			break;
1796 		default:
1797 			panic("unknown ipfw return value: %d", ret);
1798 	}
1799 back:
1800 	*m0 = m;
1801 	return error;
1802 }
1803 
1804 static int
1805 ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
1806 {
1807 	struct ip_fw_args args;
1808 	struct mbuf *m = *m0;
1809 	struct m_tag *mtag;
1810 	int tee = 0, error = 0, ret;
1811 	// again:
1812 	if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
1813 		/* Extract info from dummynet tag */
1814 		mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
1815 		KKASSERT(mtag != NULL);
1816 		args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
1817 		KKASSERT(args.rule != NULL);
1818 
1819 		m_tag_delete(m, mtag);
1820 		m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
1821 	} else {
1822 		args.rule = NULL;
1823 	}
1824 
1825 	args.eh = NULL;
1826 	args.m = m;
1827 	args.oif = ifp;
1828 	ret = ipfw_chk(&args);
1829 	m = args.m;
1830 
1831 	if (m == NULL) {
1832 		error = EACCES;
1833 		goto back;
1834 	}
1835 
1836 	switch (ret) {
1837 		case IP_FW_PASS:
1838 			break;
1839 
1840 		case IP_FW_DENY:
1841 			m_freem(m);
1842 			m = NULL;
1843 			error = EACCES;
1844 			break;
1845 
1846 		case IP_FW_DUMMYNET:
1847 			ipfw_dummynet_io(m, args.cookie, DN_TO_IP_OUT, &args);
1848 			break;
1849 
1850 		case IP_FW_TEE:
1851 			tee = 1;
1852 			/* FALL THROUGH */
1853 
1854 		case IP_FW_DIVERT:
1855 			if (ip_divert_p != NULL) {
1856 				m = ip_divert_p(m, tee, 0);
1857 			} else {
1858 				m_freem(m);
1859 				m = NULL;
1860 				/* not sure this is the right error msg */
1861 				error = EACCES;
1862 			}
1863 			break;
1864 
1865 		case IP_FW_NAT:
1866 			break;
1867 		case IP_FW_ROUTE:
1868 			break;
1869 		default:
1870 			panic("unknown ipfw return value: %d", ret);
1871 	}
1872 back:
1873 	*m0 = m;
1874 	return error;
1875 }
1876 
1877 static void
1878 ipfw_hook(void)
1879 {
1880 	struct pfil_head *pfh;
1881 	IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1882 
1883 	pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1884 	if (pfh == NULL)
1885 		return;
1886 
1887 	pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_MPSAFE, pfh);
1888 	pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_MPSAFE, pfh);
1889 }
1890 
1891 static void
1892 ipfw_dehook(void)
1893 {
1894 	struct pfil_head *pfh;
1895 
1896 	IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1897 
1898 	pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1899 	if (pfh == NULL)
1900 		return;
1901 
1902 	pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN, pfh);
1903 	pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT, pfh);
1904 }
1905 
1906 static void
1907 ipfw_sysctl_enable_dispatch(netmsg_t nmsg)
1908 {
1909 	struct lwkt_msg *lmsg = &nmsg->lmsg;
1910 	int enable = lmsg->u.ms_result;
1911 
1912 	if (fw3_enable == enable)
1913 		goto reply;
1914 
1915 	fw3_enable = enable;
1916 	if (fw3_enable)
1917 		ipfw_hook();
1918 	else
1919 		ipfw_dehook();
1920 
1921 reply:
1922 	lwkt_replymsg(lmsg, 0);
1923 }
1924 
1925 static int
1926 ipfw_sysctl_enable(SYSCTL_HANDLER_ARGS)
1927 {
1928 	struct netmsg_base nmsg;
1929 	struct lwkt_msg *lmsg;
1930 	int enable, error;
1931 
1932 	enable = fw3_enable;
1933 	error = sysctl_handle_int(oidp, &enable, 0, req);
1934 	if (error || req->newptr == NULL)
1935 		return error;
1936 
1937 	netmsg_init(&nmsg, NULL, &curthread->td_msgport,
1938 			0, ipfw_sysctl_enable_dispatch);
1939 	lmsg = &nmsg.lmsg;
1940 	lmsg->u.ms_result = enable;
1941 
1942 	return lwkt_domsg(IPFW_CFGPORT, lmsg, 0);
1943 }
1944 
1945 static int
1946 ipfw_sysctl_autoinc_step(SYSCTL_HANDLER_ARGS)
1947 {
1948 	return sysctl_int_range(oidp, arg1, arg2, req,
1949 			IPFW_AUTOINC_STEP_MIN, IPFW_AUTOINC_STEP_MAX);
1950 }
1951 
1952 
1953 static void
1954 ipfw_ctx_init_dispatch(netmsg_t nmsg)
1955 {
1956 	struct netmsg_ipfw *fwmsg = (struct netmsg_ipfw *)nmsg;
1957 	struct ipfw_context *ctx;
1958 	struct ip_fw *def_rule;
1959 
1960 	if (mycpuid == 0 ) {
1961 		ipfw_nat_ctx = kmalloc(sizeof(struct ipfw_nat_context),
1962 				M_IPFW3, M_WAITOK | M_ZERO);
1963 	}
1964 
1965 	ctx = kmalloc(sizeof(struct ipfw_context), M_IPFW3, M_WAITOK | M_ZERO);
1966 	ipfw_ctx[mycpuid] = ctx;
1967 
1968 	def_rule = kmalloc(sizeof(struct ip_fw), M_IPFW3, M_WAITOK | M_ZERO);
1969 	def_rule->act_ofs = 0;
1970 	def_rule->rulenum = IPFW_DEFAULT_RULE;
1971 	def_rule->cmd_len = 2;
1972 	def_rule->set = IPFW_DEFAULT_SET;
1973 
1974 	def_rule->cmd[0].len = LEN_OF_IPFWINSN;
1975 	def_rule->cmd[0].module = MODULE_BASIC_ID;
1976 #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
1977 	def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1978 #else
1979 	if (filters_default_to_accept)
1980 		def_rule->cmd[0].opcode = O_BASIC_ACCEPT;
1981 	else
1982 		def_rule->cmd[0].opcode = O_BASIC_DENY;
1983 #endif
1984 
1985 	/* Install the default rule */
1986 	ctx->ipfw_default_rule = def_rule;
1987 	ctx->ipfw_rule_chain = def_rule;
1988 
1989 	/*
1990 	 * if sibiling in last CPU is exists,
1991 	 * then it's sibling should be current rule
1992 	 */
1993 	if (fwmsg->sibling != NULL) {
1994 		fwmsg->sibling->sibling = def_rule;
1995 	}
1996 	/* prepare for next CPU */
1997 	fwmsg->sibling = def_rule;
1998 
1999 	/* Statistics only need to be updated once */
2000 	if (mycpuid == 0)
2001 		ipfw_inc_static_count(def_rule);
2002 
2003 	ifnet_forwardmsg(&nmsg->lmsg, mycpuid + 1);
2004 }
2005 
2006 static void
2007 ipfw_init_dispatch(netmsg_t nmsg)
2008 {
2009 	struct netmsg_ipfw fwmsg;
2010 	int error = 0;
2011 	if (IPFW3_LOADED) {
2012 		kprintf("IP firewall already loaded\n");
2013 		error = EEXIST;
2014 		goto reply;
2015 	}
2016 
2017 	bzero(&fwmsg, sizeof(fwmsg));
2018 	netmsg_init(&fwmsg.base, NULL, &curthread->td_msgport,
2019 			0, ipfw_ctx_init_dispatch);
2020 	ifnet_domsg(&fwmsg.base.lmsg, 0);
2021 
2022 	ip_fw_chk_ptr = ipfw_chk;
2023 	ip_fw_ctl_x_ptr = ipfw_ctl_x;
2024 	ip_fw_dn_io_ptr = ipfw_dummynet_io;
2025 
2026 	kprintf("ipfw3 initialized, default to %s, logging ",
2027 		(int)(ipfw_ctx[mycpuid]->ipfw_default_rule->cmd[0].opcode) ==
2028 		O_BASIC_ACCEPT ? "accept" : "deny");
2029 
2030 #ifdef IPFIREWALL_VERBOSE
2031 	fw_verbose = 1;
2032 #endif
2033 	if (fw_verbose == 0) {
2034 		kprintf("disabled ");
2035 	}
2036 	kprintf("\n");
2037 	ip_fw3_loaded = 1;
2038 	if (fw3_enable)
2039 		ipfw_hook();
2040 reply:
2041 	lwkt_replymsg(&nmsg->lmsg, error);
2042 }
2043 
2044 static int
2045 ipfw3_init(void)
2046 {
2047 	struct netmsg_base smsg;
2048 	int error;
2049 
2050 	ipfw3_log_modevent(MOD_LOAD);
2051 	init_module();
2052 	netmsg_init(&smsg, NULL, &curthread->td_msgport,
2053 			0, ipfw_init_dispatch);
2054 	error = lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
2055 	netmsg_init(&smsg, NULL, &curthread->td_msgport,
2056 			0, table_init_dispatch);
2057 	error = lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
2058 	return error;
2059 }
2060 
2061 #ifdef KLD_MODULE
2062 
2063 static void
2064 ipfw_fini_dispatch(netmsg_t nmsg)
2065 {
2066 	int error = 0, cpu;
2067 
2068 	ip_fw3_loaded = 0;
2069 
2070 	ipfw_dehook();
2071 	netmsg_service_sync();
2072 	ip_fw_chk_ptr = NULL;
2073 	ip_fw_ctl_x_ptr = NULL;
2074 	ip_fw_dn_io_ptr = NULL;
2075 	ipfw_ctl_flush_rule(1 /* kill default rule */);
2076 	table_fini();
2077 	/* Free pre-cpu context */
2078 	for (cpu = 0; cpu < ncpus; ++cpu) {
2079 		if (ipfw_ctx[cpu] != NULL) {
2080 			kfree(ipfw_ctx[cpu], M_IPFW3);
2081 			ipfw_ctx[cpu] = NULL;
2082 		}
2083 	}
2084 	kfree(ipfw_nat_ctx,M_IPFW3);
2085 	ipfw_nat_ctx = NULL;
2086 	kprintf("IP firewall unloaded\n");
2087 
2088 	lwkt_replymsg(&nmsg->lmsg, error);
2089 }
2090 
2091 static int
2092 ipfw3_fini(void)
2093 {
2094 	struct netmsg_base smsg;
2095 
2096 	ipfw3_log_modevent(MOD_UNLOAD);
2097 	netmsg_init(&smsg, NULL, &curthread->td_msgport,
2098 			0, ipfw_fini_dispatch);
2099 	return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
2100 }
2101 
2102 #endif	/* KLD_MODULE */
2103 
2104 static int
2105 ipfw3_modevent(module_t mod, int type, void *unused)
2106 {
2107 	int err = 0;
2108 
2109 	switch (type) {
2110 		case MOD_LOAD:
2111 			err = ipfw3_init();
2112 			break;
2113 
2114 		case MOD_UNLOAD:
2115 
2116 #ifndef KLD_MODULE
2117 			kprintf("ipfw statically compiled, cannot unload\n");
2118 			err = EBUSY;
2119 #else
2120 			err = ipfw3_fini();
2121 #endif
2122 			break;
2123 		default:
2124 			break;
2125 	}
2126 	return err;
2127 }
2128 
2129 static moduledata_t ipfw3mod = {
2130 	"ipfw3",
2131 	ipfw3_modevent,
2132 	0
2133 };
2134 DECLARE_MODULE(ipfw3, ipfw3mod, SI_SUB_PROTO_END, SI_ORDER_ANY);
2135 MODULE_VERSION(ipfw3, 1);
2136