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