1 /*
2  * Copyright (c) 2014 - 2017 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Bill Yuan <bycn82@dragonflybsd.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/mbuf.h>
39 #include <sys/socketvar.h>
40 #include <sys/sysctl.h>
41 #include <sys/syslog.h>
42 #include <sys/systimer.h>
43 #include <sys/thread2.h>
44 #include <sys/in_cksum.h>
45 
46 #include <net/if.h>
47 #include <net/ethernet.h>
48 #include <net/netmsg2.h>
49 #include <net/netisr2.h>
50 #include <net/route.h>
51 
52 #include <netinet/ip.h>
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/in_var.h>
56 #include <netinet/in_pcb.h>
57 #include <netinet/ip_var.h>
58 #include <netinet/ip_icmp.h>
59 #include <netinet/tcp.h>
60 #include <netinet/tcp_timer.h>
61 #include <netinet/tcp_var.h>
62 #include <netinet/tcpip.h>
63 #include <netinet/udp.h>
64 #include <netinet/udp_var.h>
65 #include <netinet/ip_divert.h>
66 #include <netinet/if_ether.h>
67 
68 #include <net/ipfw3/ip_fw.h>
69 #include <net/ipfw3/ip_fw3_table.h>
70 #include <net/ipfw3/ip_fw3_sync.h>
71 
72 #include "ip_fw3_basic.h"
73 
74 extern struct ipfw_context		*ipfw_ctx[MAXCPU];
75 extern struct ipfw_sync_context 	sync_ctx;
76 extern int 				fw_verbose;
77 extern ipfw_basic_delete_state_t 	*ipfw_basic_flush_state_prt;
78 extern ipfw_basic_append_state_t 	*ipfw_basic_append_state_prt;
79 extern ipfw_sync_send_state_t 		*ipfw_sync_send_state_prt;
80 extern ipfw_sync_install_state_t 	*ipfw_sync_install_state_prt;
81 
82 static struct netmsg_base 	ipfw_timeout_netmsg; /* schedule ipfw timeout */
83 static struct callout 		ipfw_tick_callout;
84 static int 	ip_fw_basic_loaded;
85 static int 	state_lifetime = 20;
86 static int	state_expiry_check_interval = 10;
87 static int 	state_count_max = 4096;
88 static int 	state_hash_size_old = 0;
89 static int 	state_hash_size = 4096;
90 
91 
92 static int ipfw_sysctl_adjust_hash_size(SYSCTL_HANDLER_ARGS);
93 void adjust_hash_size_dispatch(netmsg_t nmsg);
94 
95 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw_basic,
96 		CTLFLAG_RW, 0, "Firewall Basic");
97 SYSCTL_PROC(_net_inet_ip_fw_basic, OID_AUTO, state_hash_size,
98 		CTLTYPE_INT | CTLFLAG_RW, &state_hash_size, 0,
99 		ipfw_sysctl_adjust_hash_size, "I", "Adjust hash size");
100 
101 SYSCTL_INT(_net_inet_ip_fw_basic, OID_AUTO, state_lifetime, CTLFLAG_RW,
102 		&state_lifetime, 0, "default life time");
103 SYSCTL_INT(_net_inet_ip_fw_basic, OID_AUTO,
104 		state_expiry_check_interval, CTLFLAG_RW,
105 		&state_expiry_check_interval, 0,
106 		"default state expiry check interval");
107 SYSCTL_INT(_net_inet_ip_fw_basic, OID_AUTO, state_count_max, CTLFLAG_RW,
108 		&state_count_max, 0, "maximum of state");
109 
110 static struct ip_fw *lookup_next_rule(struct ip_fw *me);
111 static int iface_match(struct ifnet *ifp, ipfw_insn_if *cmd);
112 static __inline int hash_packet(struct ipfw_flow_id *id);
113 
114 static int
115 ipfw_sysctl_adjust_hash_size(SYSCTL_HANDLER_ARGS)
116 {
117 	int error, value = 0;
118 
119 	state_hash_size_old = state_hash_size;
120 	value = state_hash_size;
121 	error = sysctl_handle_int(oidp, &value, 0, req);
122 	if (error || !req->newptr) {
123 		goto back;
124 	}
125 	/*
126 	 * Make sure we have a power of 2 and
127 	 * do not allow more than 64k entries.
128 	 */
129 	error = EINVAL;
130 	if (value <= 1 || value > 65536) {
131 		goto back;
132 	}
133 	if ((value & (value - 1)) != 0) {
134 		goto back;
135 	}
136 
137 	error = 0;
138 	if (state_hash_size != value) {
139 		state_hash_size = value;
140 
141 		struct netmsg_base *msg, the_msg;
142 		msg = &the_msg;
143 		bzero(msg,sizeof(struct netmsg_base));
144 
145 		netmsg_init(msg, NULL, &curthread->td_msgport,
146 				0, adjust_hash_size_dispatch);
147 		netisr_domsg(msg, 0);
148 	}
149 back:
150 	return error;
151 }
152 
153 void
154 adjust_hash_size_dispatch(netmsg_t nmsg)
155 {
156 	struct ipfw_state_context *state_ctx;
157 	struct ip_fw_state *the_state, *state;
158 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
159 	int i;
160 
161 	for (i = 0; i < state_hash_size_old; i++) {
162 		state_ctx = &ctx->state_ctx[i];
163 		if (state_ctx != NULL) {
164 			state = state_ctx->state;
165 			while (state != NULL) {
166 				the_state = state;
167 				state = state->next;
168 				kfree(the_state, M_IPFW3_BASIC);
169 				the_state = NULL;
170 			}
171 		}
172 	}
173 	kfree(ctx->state_ctx,M_IPFW3_BASIC);
174 	ctx->state_ctx = kmalloc(state_hash_size *
175 				sizeof(struct ipfw_state_context),
176 				M_IPFW3_BASIC, M_WAITOK | M_ZERO);
177 	ctx->state_hash_size = state_hash_size;
178 	netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
179 }
180 
181 static __inline int
182 hash_packet(struct ipfw_flow_id *id)
183 {
184 	uint32_t i;
185 	i = (id->proto) ^ (id->dst_ip) ^ (id->src_ip) ^
186 		(id->dst_port) ^ (id->src_port);
187 	i &= state_hash_size - 1;
188 	return i;
189 }
190 
191 static struct ip_fw *
192 lookup_next_rule(struct ip_fw *me)
193 {
194 	struct ip_fw *rule = NULL;
195 	ipfw_insn *cmd;
196 
197 	/* look for action, in case it is a skipto */
198 	cmd = ACTION_PTR(me);
199 	if ((int)cmd->module == MODULE_BASIC_ID &&
200 		(int)cmd->opcode == O_BASIC_SKIPTO) {
201 		for (rule = me->next; rule; rule = rule->next) {
202 			if (rule->rulenum >= cmd->arg1)
203 				break;
204 		}
205 	}
206 	if (rule == NULL) /* failure or not a skipto */
207 		rule = me->next;
208 
209 	me->next_rule = rule;
210 	return rule;
211 }
212 
213 /*
214  * return value
215  * 0 : not match  1: same direction 2: reverse direction
216  */
217 int
218 match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid, struct ip_fw_state *state)
219 {
220 	 if (fid->src_ip == state->flow_id.src_ip &&
221 		 fid->dst_ip == state->flow_id.dst_ip &&
222 		 (fid->src_port == state->flow_id.src_port ||
223 				 state->flow_id.src_port == 0) &&
224 		 (fid->dst_port == state->flow_id.dst_port ||
225 				 state->flow_id.dst_port == 0)) {
226 		 return 1;
227 	 }
228 	 if (fid->src_ip == state->flow_id.dst_ip &&
229 		 fid->dst_ip == state->flow_id.src_ip &&
230 		 (fid->src_port == state->flow_id.dst_port ||
231 				 state->flow_id.dst_port == 0) &&
232 		 (fid->dst_port == state->flow_id.src_port ||
233 				 state->flow_id.src_port == 0)) {
234 		 return 2;
235 	 }
236 	 return 0;
237 }
238 
239 /*
240  * return 1 when more states than limit
241  * arg3: limit type (1=src ip, 2=src port, 3=dst ip, 4=dst port)
242  * arg1: limit
243  */
244 int
245 count_match_state(ipfw_insn *cmd, struct ipfw_flow_id *fid,
246 	struct ip_fw_state *state, int *count)
247 {
248 	 if ((cmd->arg3 == 1 && fid->src_ip == state->flow_id.src_ip) ||
249 		 (cmd->arg3 == 2 && fid->src_port == state->flow_id.src_port) ||
250 		 (cmd->arg3 == 3 && fid->dst_ip == state->flow_id.dst_ip) ||
251 		 (cmd->arg3 == 4 && fid->dst_port == state->flow_id.dst_port)) {
252 		 *count = *count + 1;
253 		 if (*count >= cmd->arg1)
254 			 return 1;
255 	 }
256 	  return 0;
257 }
258 
259 /*
260  * when all = 1, it will check all the state_ctx
261  * all = 1 during keep-state
262  * all = 0 during check-state
263  *
264  * in the cmd of keep_state
265  * arg3=type arg1=limit
266  */
267 static struct ip_fw_state *
268 lookup_state(struct ip_fw_args *args, ipfw_insn *cmd, int *limited, int all)
269 {
270 	struct ip_fw_state *state = NULL;
271 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
272 	struct ipfw_state_context *state_ctx;
273 	int start, end, i, count = 0;
274 
275 	if (all && cmd->arg1) {
276 		start = 0;
277 		end = state_hash_size - 1;
278 	} else {
279 		start = hash_packet(&args->f_id);
280 		end = hash_packet(&args->f_id);
281 	}
282 
283 	for (i = start; i <= end; i++) {
284 		state_ctx = &ctx->state_ctx[i];
285 		if (state_ctx != NULL) {
286 			state = state_ctx->state;
287 			struct ipfw_flow_id	*fid = &args->f_id;
288 			while (state != NULL) {
289 				/* has limit and already exceed the limit */
290 				if (cmd->arg1 &&
291 					count_match_state(cmd, fid,
292 							state, &count) != 0) {
293 					*limited = 1;
294 					 goto done;
295 				 }
296 
297 				if (fid->proto == state->flow_id.proto &&
298 						 match_state(cmd, fid, state) != 0)
299 					 goto done;
300 
301 				state = state->next;
302 			}
303 		}
304 	}
305 done:
306 	return state;
307 }
308 
309 static struct ip_fw_state *
310 install_state(struct ip_fw *rule, ipfw_insn *cmd, struct ip_fw_args *args)
311 {
312 	struct ip_fw_state *state;
313 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
314 	struct ipfw_state_context *state_ctx;
315 	int hash = hash_packet(&args->f_id);
316 	state_ctx = &ctx->state_ctx[hash];
317 	state = kmalloc(sizeof(struct ip_fw_state),
318 			M_IPFW3_BASIC, M_NOWAIT | M_ZERO);
319 	if (state == NULL) {
320 		return NULL;
321 	}
322 	state->stub = rule;
323 	state->lifetime = cmd->arg2 == 0 ? state_lifetime : cmd->arg2 ;
324 	state->timestamp = time_second;
325 	state->expiry = 0;
326 	bcopy(&args->f_id,&state->flow_id,sizeof(struct ipfw_flow_id));
327 	//append the state into the state chian
328 	if (state_ctx->last != NULL)
329 		state_ctx->last->next = state;
330 	else
331 		state_ctx->state = state;
332 	state_ctx->last = state;
333 	state_ctx->count++;
334 
335 	if (sync_ctx.running & 2) {
336 		ipfw_sync_send_state_prt(state, mycpuid, hash);
337 	}
338 	return state;
339 }
340 
341 void
342 ipfw_sync_install_state(struct cmd_send_state *cmd)
343 {
344         struct ip_fw_state *state;
345         struct ipfw_context *ctx = ipfw_ctx[cmd->cpu];
346         struct ipfw_state_context *state_ctx;
347         struct ip_fw *rule;
348 
349         state_ctx = &ctx->state_ctx[cmd->hash];
350         state = kmalloc(sizeof(struct ip_fw_state),
351                         M_IPFW3_BASIC, M_NOWAIT | M_ZERO);
352         if (state == NULL) {
353                 return;
354         }
355         for (rule = ctx->ipfw_rule_chain; rule; rule = rule->next) {
356                 if (rule->rulenum == cmd->rulenum) {
357                         goto found;
358                 }
359         }
360         return;
361 found:
362         state->stub = rule;
363         state->lifetime = cmd->lifetime;
364         state->timestamp = time_second;
365         state->expiry = 0;
366         bcopy(&cmd->flow, &state->flow_id, sizeof(struct ipfw_flow_id));
367         //append the state into the state chian
368         if (state_ctx->last != NULL)
369                 state_ctx->last->next = state;
370         else
371                 state_ctx->state = state;
372         state_ctx->last = state;
373         state_ctx->count++;
374 }
375 
376 static int
377 iface_match(struct ifnet *ifp, ipfw_insn_if *cmd)
378 {
379 	if (ifp == NULL)	/* no iface with this packet, match fails */
380 		return 0;
381 
382 	/* Check by name or by IP address */
383 	if (cmd->name[0] != '\0') { /* match by name */
384 		/* Check name */
385 		if (cmd->p.glob) {
386 			if (kfnmatch(cmd->name, ifp->if_xname, 0) == 0)
387 				return(1);
388 		} else {
389 			if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0)
390 				return(1);
391 		}
392 	} else {
393 		struct ifaddr_container *ifac;
394 
395 		TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) {
396 			struct ifaddr *ia = ifac->ifa;
397 
398 			if (ia->ifa_addr == NULL)
399 				continue;
400 			if (ia->ifa_addr->sa_family != AF_INET)
401 				continue;
402 			if (cmd->p.ip.s_addr ==
403 				((struct sockaddr_in *)
404 				(ia->ifa_addr))->sin_addr.s_addr)
405 					return(1);	/* match */
406 
407 		}
408 	}
409 	return 0;	/* no match, fail ... */
410 }
411 
412 /* implimentation of the checker functions */
413 void
414 check_count(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
415 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
416 {
417 	(*f)->pcnt++;
418 	(*f)->bcnt += ip_len;
419 	(*f)->timestamp = time_second;
420 	*cmd_ctl = IP_FW_CTL_NEXT;
421 }
422 
423 void
424 check_skipto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
425 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
426 {
427 	(*f)->pcnt++;
428 	(*f)->bcnt += ip_len;
429 	(*f)->timestamp = time_second;
430 	if ((*f)->next_rule == NULL)
431 		lookup_next_rule(*f);
432 	*f = (*f)->next_rule;
433 	*cmd_ctl = IP_FW_CTL_AGAIN;
434 }
435 
436 void
437 check_forward(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
438 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
439 {
440 	struct sockaddr_in *sin, *sa;
441 	struct m_tag *mtag;
442 
443 	if ((*args)->eh) {	/* not valid on layer2 pkts */
444 		*cmd_ctl=IP_FW_CTL_NEXT;
445 		return;
446 	}
447 
448 	(*f)->pcnt++;
449 	(*f)->bcnt += ip_len;
450 	(*f)->timestamp = time_second;
451 	if ((*f)->next_rule == NULL)
452 		lookup_next_rule(*f);
453 
454 	mtag = m_tag_get(PACKET_TAG_IPFORWARD,
455 			sizeof(*sin), M_INTWAIT | M_NULLOK);
456 	if (mtag == NULL) {
457 		*cmd_val = IP_FW_DENY;
458 		*cmd_ctl = IP_FW_CTL_DONE;
459 		return;
460 	}
461 	sin = m_tag_data(mtag);
462 	sa = &((ipfw_insn_sa *)cmd)->sa;
463 	/* arg3: count of the dest, arg1: type of fwd */
464 	int i = 0;
465 	if(cmd->arg3 > 1) {
466 		if (cmd->arg1 == 0) {		/* type: random */
467 			i = krandom() % cmd->arg3;
468 		} else if (cmd->arg1 == 1) {	/* type: round-robin */
469 			i = cmd->arg2++ % cmd->arg3;
470 		} else if (cmd->arg1 == 2) {	/* type: sticky */
471 			struct ip *ip = mtod((*args)->m, struct ip *);
472 			i = ip->ip_src.s_addr & (cmd->arg3 - 1);
473 		}
474 		sa += i;
475 	}
476 	*sin = *sa;	/* apply the destination */
477 	m_tag_prepend((*args)->m, mtag);
478 	(*args)->m->m_pkthdr.fw_flags |= IPFORWARD_MBUF_TAGGED;
479 	(*args)->m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED;
480 	*cmd_ctl = IP_FW_CTL_DONE;
481 	*cmd_val = IP_FW_PASS;
482 }
483 
484 void
485 check_check_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
486 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
487 {
488 	struct ip_fw_state *state=NULL;
489 	int limited = 0 ;
490 	state = lookup_state(*args, cmd, &limited, 0);
491 	if (state != NULL) {
492 		state->pcnt++;
493 		state->bcnt += ip_len;
494 		state->timestamp = time_second;
495 		(*f)->pcnt++;
496 		(*f)->bcnt += ip_len;
497 		(*f)->timestamp = time_second;
498 		*f = state->stub;
499 		*cmd_ctl = IP_FW_CTL_CHK_STATE;
500 	} else {
501 		*cmd_ctl = IP_FW_CTL_NEXT;
502 	}
503 }
504 
505 void
506 check_in(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
507 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
508 {
509 	*cmd_ctl = IP_FW_CTL_NO;
510 	*cmd_val = ((*args)->oif == NULL);
511 }
512 
513 void
514 check_out(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
515 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
516 {
517 	*cmd_ctl = IP_FW_CTL_NO;
518 	*cmd_val = ((*args)->oif != NULL);
519 }
520 
521 void
522 check_via(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
523 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
524 {
525 	*cmd_ctl = IP_FW_CTL_NO;
526 	*cmd_val = iface_match((*args)->oif ?
527 			(*args)->oif : (*args)->m->m_pkthdr.rcvif,
528 			(ipfw_insn_if *)cmd);
529 }
530 
531 void
532 check_proto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
533 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
534 {
535 	*cmd_ctl = IP_FW_CTL_NO;
536 	*cmd_val = ((*args)->f_id.proto == cmd->arg1);
537 }
538 
539 void
540 check_prob(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
541 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
542 {
543 	*cmd_ctl = IP_FW_CTL_NO;
544 	*cmd_val = (krandom() % 100) < cmd->arg1;
545 }
546 
547 void
548 check_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
549 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
550 {
551 	u_int hlen = 0;
552 	struct mbuf *m = (*args)->m;
553 	struct ip *ip = mtod(m, struct ip *);
554 	struct in_addr src_ip = ip->ip_src;
555 
556 	if ((*args)->eh == NULL ||
557 		(m->m_pkthdr.len >= sizeof(struct ip) &&
558 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
559 		hlen = ip->ip_hl << 2;
560 	}
561 	*cmd_val = (hlen > 0 &&
562 			((ipfw_insn_ip *)cmd)->addr.s_addr == src_ip.s_addr);
563 	*cmd_ctl = IP_FW_CTL_NO;
564 }
565 
566 void
567 check_from_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
568 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
569 {
570 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
571 	struct ipfw_table_context *table_ctx;
572 	struct radix_node_head *rnh;
573 	struct sockaddr_in sa;
574 
575 	struct mbuf *m = (*args)->m;
576 	struct ip *ip = mtod(m, struct ip *);
577 	struct in_addr src_ip = ip->ip_src;
578 
579 	*cmd_val = IP_FW_NOT_MATCH;
580 
581 	table_ctx = ctx->table_ctx;
582 	table_ctx += cmd->arg1;
583 
584         if (table_ctx->type != 0) {
585                 rnh = table_ctx->node;
586                 sa.sin_len = 8;
587                 sa.sin_addr.s_addr = src_ip.s_addr;
588                 if(rnh->rnh_lookup((char *)&sa, NULL, rnh) != NULL)
589                         *cmd_val = IP_FW_MATCH;
590         }
591 	*cmd_ctl = IP_FW_CTL_NO;
592 }
593 
594 void
595 check_from_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
596 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
597 {
598 	u_int hlen = 0;
599 	struct mbuf *m = (*args)->m;
600 	struct ip *ip = mtod(m, struct ip *);
601 	struct in_addr src_ip = ip->ip_src;
602 
603 	if ((*args)->eh == NULL ||
604 		(m->m_pkthdr.len >= sizeof(struct ip) &&
605 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
606 		hlen = ip->ip_hl << 2;
607 	}
608 	*cmd_ctl = IP_FW_CTL_NO;
609 	if (hlen > 0) {
610 		struct ifnet *tif;
611 		tif = INADDR_TO_IFP(&src_ip);
612 		*cmd_val = (tif != NULL);
613 	} else {
614 		*cmd_val = IP_FW_NOT_MATCH;
615 	}
616 }
617 
618 void
619 check_from_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
620 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
621 {
622 	u_int hlen = 0;
623 	struct mbuf *m = (*args)->m;
624 	struct ip *ip = mtod(m, struct ip *);
625 	struct in_addr src_ip = ip->ip_src;
626 
627 	if ((*args)->eh == NULL ||
628 		(m->m_pkthdr.len >= sizeof(struct ip) &&
629 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
630 		hlen = ip->ip_hl << 2;
631 	}
632 
633 	*cmd_ctl = IP_FW_CTL_NO;
634 	*cmd_val = (hlen > 0 &&
635 			((ipfw_insn_ip *)cmd)->addr.s_addr ==
636 			(src_ip.s_addr &
637 			((ipfw_insn_ip *)cmd)->mask.s_addr));
638 }
639 
640 void
641 check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
642 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
643 {
644 	u_int hlen = 0;
645 	struct mbuf *m = (*args)->m;
646 	struct ip *ip = mtod(m, struct ip *);
647 	struct in_addr dst_ip = ip->ip_dst;
648 
649 	if ((*args)->eh == NULL ||
650 		(m->m_pkthdr.len >= sizeof(struct ip) &&
651 		 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
652 		hlen = ip->ip_hl << 2;
653 	}
654 	*cmd_val = (hlen > 0 &&
655 			((ipfw_insn_ip *)cmd)->addr.s_addr == dst_ip.s_addr);
656 	*cmd_ctl = IP_FW_CTL_NO;
657 }
658 
659 void
660 check_to_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
661 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
662 {
663 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
664 	struct ipfw_table_context *table_ctx;
665 	struct radix_node_head *rnh;
666 	struct sockaddr_in sa;
667 
668 	struct mbuf *m = (*args)->m;
669 	struct ip *ip = mtod(m, struct ip *);
670 	struct in_addr dst_ip = ip->ip_dst;
671 
672 	*cmd_val = IP_FW_NOT_MATCH;
673 
674 	table_ctx = ctx->table_ctx;
675 	table_ctx += cmd->arg1;
676 
677         if (table_ctx->type != 0) {
678                 rnh = table_ctx->node;
679                 sa.sin_len = 8;
680                 sa.sin_addr.s_addr = dst_ip.s_addr;
681                 if(rnh->rnh_lookup((char *)&sa, NULL, rnh) != NULL)
682                         *cmd_val = IP_FW_MATCH;
683         }
684 	*cmd_ctl = IP_FW_CTL_NO;
685 }
686 
687 void
688 check_to_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
689 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
690 {
691 	u_int hlen = 0;
692 	struct mbuf *m = (*args)->m;
693 	struct ip *ip = mtod(m, struct ip *);
694 	struct in_addr dst_ip = ip->ip_dst;
695 
696 	if ((*args)->eh == NULL ||
697 		(m->m_pkthdr.len >= sizeof(struct ip) &&
698 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
699 		hlen = ip->ip_hl << 2;
700 	}
701 	*cmd_ctl = IP_FW_CTL_NO;
702 	if (hlen > 0) {
703 		struct ifnet *tif;
704 		tif = INADDR_TO_IFP(&dst_ip);
705 		*cmd_val = (tif != NULL);
706 	} else {
707 		*cmd_val = IP_FW_NOT_MATCH;
708 	}
709 }
710 
711 void
712 check_to_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
713 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
714 {
715 	u_int hlen = 0;
716 	struct mbuf *m = (*args)->m;
717 	struct ip *ip = mtod(m, struct ip *);
718 	struct in_addr dst_ip = ip->ip_dst;
719 
720 	if ((*args)->eh == NULL ||
721 		(m->m_pkthdr.len >= sizeof(struct ip) &&
722 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
723 		hlen = ip->ip_hl << 2;
724 	}
725 
726 	*cmd_ctl = IP_FW_CTL_NO;
727 	*cmd_val = (hlen > 0 &&
728 			((ipfw_insn_ip *)cmd)->addr.s_addr ==
729 			(dst_ip.s_addr &
730 			((ipfw_insn_ip *)cmd)->mask.s_addr));
731 }
732 
733 void
734 check_keep_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
735 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
736 {
737 	struct ip_fw_state *state;
738 	int limited = 0;
739 
740 	*cmd_ctl = IP_FW_CTL_NO;
741 	*cmd_val = IP_FW_MATCH;
742 	state = lookup_state(*args, cmd, &limited, 1);
743 	if (limited != 1) {
744 		if (state == NULL)
745 			state = install_state(*f, cmd, *args);
746 
747 		if (state != NULL) {
748 			state->pcnt++;
749 			state->bcnt += ip_len;
750 			state->timestamp = time_second;
751 		}
752 	}
753 }
754 
755 void
756 check_tag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
757 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
758 {
759 	struct m_tag *mtag = m_tag_locate((*args)->m,
760 			MTAG_IPFW, cmd->arg1, NULL);
761 	if (mtag == NULL) {
762 		mtag = m_tag_alloc(MTAG_IPFW,cmd->arg1, 0, M_NOWAIT);
763 		if (mtag != NULL)
764 			m_tag_prepend((*args)->m, mtag);
765 
766 	}
767 	(*f)->pcnt++;
768 	(*f)->bcnt += ip_len;
769 	(*f)->timestamp = time_second;
770 	*cmd_ctl = IP_FW_CTL_NEXT;
771 }
772 
773 void
774 check_untag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
775 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
776 {
777 	struct m_tag *mtag = m_tag_locate((*args)->m,
778 			MTAG_IPFW, cmd->arg1, NULL);
779 	if (mtag != NULL)
780 		m_tag_delete((*args)->m, mtag);
781 
782 	(*f)->pcnt++;
783 	(*f)->bcnt += ip_len;
784 	(*f)->timestamp = time_second;
785 	*cmd_ctl = IP_FW_CTL_NEXT;
786 }
787 
788 void
789 check_tagged(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
790 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
791 {
792 	*cmd_ctl = IP_FW_CTL_NO;
793 	if (m_tag_locate( (*args)->m, MTAG_IPFW,cmd->arg1, NULL) != NULL )
794 		*cmd_val = IP_FW_MATCH;
795 	else
796 		*cmd_val = IP_FW_NOT_MATCH;
797 }
798 
799 void
800 check_src_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
801         struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
802 {
803         *cmd_ctl = IP_FW_CTL_NO;
804         if ((*args)->f_id.src_port == cmd->arg1)
805                 *cmd_val = IP_FW_MATCH;
806         else
807                 *cmd_val = IP_FW_NOT_MATCH;
808 }
809 
810 void
811 check_dst_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
812         struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
813 {
814         *cmd_ctl = IP_FW_CTL_NO;
815         if ((*args)->f_id.dst_port == cmd->arg1)
816                 *cmd_val = IP_FW_MATCH;
817         else
818                 *cmd_val = IP_FW_NOT_MATCH;
819 }
820 
821 void
822 check_src_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
823 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
824 {
825 	struct in_addr src_ip;
826 	u_int hlen = 0;
827 	struct mbuf *m = (*args)->m;
828 	struct ip *ip = mtod(m, struct ip *);
829 	src_ip = ip->ip_src;
830 	if ((*args)->eh == NULL ||
831 		(m->m_pkthdr.len >= sizeof(struct ip) &&
832 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
833 		hlen = ip->ip_hl << 2;
834 	}
835 	*cmd_val = (hlen > 0 && ((ipfw_insn_ip *)cmd)->addr.s_addr == src_ip.s_addr);
836 	*cmd_ctl = IP_FW_CTL_NO;
837 	if (*cmd_val && (*args)->f_id.src_port == cmd->arg1)
838 		*cmd_val = IP_FW_MATCH;
839 	else
840 		*cmd_val = IP_FW_NOT_MATCH;
841 }
842 
843 void
844 check_dst_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
845 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
846 {
847 	struct in_addr dst_ip;
848 	u_int hlen = 0;
849 	struct mbuf *m = (*args)->m;
850 	struct ip *ip = mtod(m, struct ip *);
851 	dst_ip = ip->ip_dst;
852 	if ((*args)->eh == NULL ||
853 		(m->m_pkthdr.len >= sizeof(struct ip) &&
854 		 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
855 		hlen = ip->ip_hl << 2;
856 	}
857 	*cmd_val = (hlen > 0 && ((ipfw_insn_ip *)cmd)->addr.s_addr == dst_ip.s_addr);
858 	*cmd_ctl = IP_FW_CTL_NO;
859 	if (*cmd_val && (*args)->f_id.dst_port == cmd->arg1)
860 		*cmd_val = IP_FW_MATCH;
861 	else
862 		*cmd_val = IP_FW_NOT_MATCH;
863 }
864 
865 
866 
867 static void
868 ipfw_basic_add_state(struct ipfw_ioc_state *ioc_state)
869 {
870 	struct ip_fw_state *state;
871 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
872 	struct ipfw_state_context *state_ctx;
873 	state_ctx = &ctx->state_ctx[hash_packet(&(ioc_state->flow_id))];
874 	state = kmalloc(sizeof(struct ip_fw_state),
875 			M_IPFW3_BASIC, M_WAITOK | M_ZERO);
876 	struct ip_fw *rule = ctx->ipfw_rule_chain;
877 	while (rule != NULL) {
878 		if (rule->rulenum == ioc_state->rulenum) {
879 			break;
880 		}
881 		rule = rule->next;
882 	}
883 	if (rule == NULL)
884 		return;
885 
886 	state->stub = rule;
887 
888 	state->lifetime = ioc_state->lifetime == 0 ?
889 		state_lifetime : ioc_state->lifetime ;
890 	state->timestamp = time_second;
891 	state->expiry = ioc_state->expiry;
892 	bcopy(&ioc_state->flow_id, &state->flow_id,
893 			sizeof(struct ipfw_flow_id));
894 	//append the state into the state chian
895 	if (state_ctx->last != NULL)
896 		state_ctx->last->next = state;
897 	else
898 		state_ctx->state = state;
899 
900 	state_ctx->last = state;
901 	state_ctx->count++;
902 }
903 
904 /*
905  * if rule is NULL
906  * 		flush all states
907  * else
908  * 		flush states which stub is the rule
909  */
910 static void
911 ipfw_basic_flush_state(struct ip_fw *rule)
912 {
913 	struct ipfw_state_context *state_ctx;
914 	struct ip_fw_state *state,*the_state, *prev_state;
915 	struct ipfw_context *ctx;
916 	int i;
917 
918 	ctx = ipfw_ctx[mycpuid];
919 	for (i = 0; i < state_hash_size; i++) {
920 		state_ctx = &ctx->state_ctx[i];
921 		if (state_ctx != NULL) {
922 			state = state_ctx->state;
923 			prev_state = NULL;
924 			while (state != NULL) {
925 				if (rule != NULL && state->stub != rule) {
926 					prev_state = state;
927 					state = state->next;
928 				} else {
929 					if (prev_state == NULL)
930 						state_ctx->state = state->next;
931 					else
932 						prev_state->next = state->next;
933 
934 					the_state = state;
935 					state = state->next;
936 					kfree(the_state, M_IPFW3_BASIC);
937 					state_ctx->count--;
938 					if (state == NULL)
939 						state_ctx->last = prev_state;
940 
941 				}
942 			}
943 		}
944 	}
945 }
946 
947 /*
948  * clean up expired state in every tick
949  */
950 static void
951 ipfw_cleanup_expired_state(netmsg_t nmsg)
952 {
953 	struct ip_fw_state *state,*the_state,*prev_state;
954 	struct ipfw_context *ctx = ipfw_ctx[mycpuid];
955 	struct ipfw_state_context *state_ctx;
956 	int i;
957 
958 	for (i = 0; i < state_hash_size; i++) {
959 		prev_state = NULL;
960 		state_ctx = &(ctx->state_ctx[i]);
961 		if (ctx->state_ctx != NULL) {
962 			state = state_ctx->state;
963 			while (state != NULL) {
964 				if (IS_EXPIRED(state)) {
965 					if (prev_state == NULL)
966 						state_ctx->state = state->next;
967 					else
968 						prev_state->next = state->next;
969 
970 					the_state =state;
971 					state = state->next;
972 
973 					if (the_state == state_ctx->last)
974 						state_ctx->last = NULL;
975 
976 
977 					kfree(the_state, M_IPFW3_BASIC);
978 					state_ctx->count--;
979 				} else {
980 					prev_state = state;
981 					state = state->next;
982 				}
983 			}
984 		}
985 	}
986 	netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
987 }
988 
989 static void
990 ipfw_tick(void *dummy __unused)
991 {
992 	struct lwkt_msg *lmsg = &ipfw_timeout_netmsg.lmsg;
993 	KKASSERT(mycpuid == IPFW_CFGCPUID);
994 
995 	crit_enter();
996 	KKASSERT(lmsg->ms_flags & MSGF_DONE);
997 	if (IPFW_BASIC_LOADED) {
998 		lwkt_sendmsg_oncpu(IPFW_CFGPORT, lmsg);
999 		/* ipfw_timeout_netmsg's handler reset this callout */
1000 	}
1001 	crit_exit();
1002 }
1003 
1004 static void
1005 ipfw_tick_dispatch(netmsg_t nmsg)
1006 {
1007 	IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1008 	KKASSERT(IPFW_BASIC_LOADED);
1009 
1010 	/* Reply ASAP */
1011 	crit_enter();
1012 	lwkt_replymsg(&nmsg->lmsg, 0);
1013 	crit_exit();
1014 
1015 	callout_reset(&ipfw_tick_callout,
1016 			state_expiry_check_interval * hz, ipfw_tick, NULL);
1017 
1018 	struct netmsg_base msg;
1019 	netmsg_init(&msg, NULL, &curthread->td_msgport, 0,
1020 			ipfw_cleanup_expired_state);
1021 	netisr_domsg(&msg, 0);
1022 }
1023 
1024 static void
1025 ipfw_basic_init_dispatch(netmsg_t nmsg)
1026 {
1027 	IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1028 	KKASSERT(IPFW3_LOADED);
1029 
1030 	int error = 0;
1031 	callout_init_mp(&ipfw_tick_callout);
1032 	netmsg_init(&ipfw_timeout_netmsg, NULL, &netisr_adone_rport,
1033 			MSGF_DROPABLE | MSGF_PRIORITY, ipfw_tick_dispatch);
1034 	callout_reset(&ipfw_tick_callout,
1035 			state_expiry_check_interval * hz, ipfw_tick, NULL);
1036 	lwkt_replymsg(&nmsg->lmsg, error);
1037 	ip_fw_basic_loaded=1;
1038 }
1039 
1040 static int
1041 ipfw_basic_init(void)
1042 {
1043 	ipfw_basic_flush_state_prt = ipfw_basic_flush_state;
1044 	ipfw_basic_append_state_prt = ipfw_basic_add_state;
1045 	ipfw_sync_install_state_prt = ipfw_sync_install_state;
1046 
1047 	register_ipfw_module(MODULE_BASIC_ID, MODULE_BASIC_NAME);
1048 	register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_COUNT,
1049 			(filter_func)check_count);
1050 	register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_SKIPTO,
1051 			(filter_func)check_skipto);
1052 	register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_FORWARD,
1053 			(filter_func)check_forward);
1054 	register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_KEEP_STATE,
1055 			(filter_func)check_keep_state);
1056 	register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_CHECK_STATE,
1057 			(filter_func)check_check_state);
1058 
1059 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1060 			O_BASIC_IN, (filter_func)check_in);
1061 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1062 			O_BASIC_OUT, (filter_func)check_out);
1063 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1064 			O_BASIC_VIA, (filter_func)check_via);
1065 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1066 			O_BASIC_XMIT, (filter_func)check_via);
1067 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1068 			O_BASIC_RECV, (filter_func)check_via);
1069 
1070 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1071 			O_BASIC_PROTO, (filter_func)check_proto);
1072 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1073 			O_BASIC_PROB, (filter_func)check_prob);
1074 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1075 			O_BASIC_IP_SRC, (filter_func)check_from);
1076 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1077 			O_BASIC_IP_SRC_LOOKUP, (filter_func)check_from_lookup);
1078 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1079 			O_BASIC_IP_SRC_ME, (filter_func)check_from_me);
1080 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1081 			O_BASIC_IP_SRC_MASK, (filter_func)check_from_mask);
1082 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1083 			O_BASIC_IP_DST, (filter_func)check_to);
1084 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1085 			O_BASIC_IP_DST_LOOKUP, (filter_func)check_to_lookup);
1086 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1087 			O_BASIC_IP_DST_ME, (filter_func)check_to_me);
1088 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1089 			O_BASIC_IP_DST_MASK, (filter_func)check_to_mask);
1090 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1091 			O_BASIC_TAG, (filter_func)check_tag);
1092 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1093 			O_BASIC_UNTAG, (filter_func)check_untag);
1094 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1095 			O_BASIC_TAGGED, (filter_func)check_tagged);
1096 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1097 			O_BASIC_IP_SRCPORT, (filter_func)check_src_port);
1098 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1099 			O_BASIC_IP_DSTPORT, (filter_func)check_dst_port);
1100 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1101 			O_BASIC_IP_SRC_N_PORT, (filter_func)check_src_n_port);
1102 	register_ipfw_filter_funcs(MODULE_BASIC_ID,
1103 			O_BASIC_IP_DST_N_PORT, (filter_func)check_dst_n_port);
1104 
1105 	int cpu;
1106 	struct ipfw_context *ctx;
1107 
1108 	for (cpu = 0; cpu < ncpus; cpu++) {
1109 		ctx = ipfw_ctx[cpu];
1110 		if (ctx != NULL) {
1111 			ctx->state_ctx = kmalloc(state_hash_size *
1112 					sizeof(struct ipfw_state_context),
1113 					M_IPFW3_BASIC, M_WAITOK | M_ZERO);
1114 			ctx->state_hash_size = state_hash_size;
1115 		}
1116 	}
1117 
1118 	struct netmsg_base smsg;
1119 	netmsg_init(&smsg, NULL, &curthread->td_msgport,
1120 			0, ipfw_basic_init_dispatch);
1121 	lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1122 	return 0;
1123 }
1124 
1125 static void
1126 ipfw_basic_stop_dispatch(netmsg_t nmsg)
1127 {
1128 	IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
1129 	KKASSERT(IPFW3_LOADED);
1130 	int error = 0;
1131 	callout_stop(&ipfw_tick_callout);
1132 	netmsg_service_sync();
1133 	crit_enter();
1134 	lwkt_dropmsg(&ipfw_timeout_netmsg.lmsg);
1135 	crit_exit();
1136 	lwkt_replymsg(&nmsg->lmsg, error);
1137 	ip_fw_basic_loaded=0;
1138 }
1139 
1140 static int
1141 ipfw_basic_stop(void)
1142 {
1143 	int cpu,i;
1144 	struct ipfw_state_context *state_ctx;
1145 	struct ip_fw_state *state,*the_state;
1146 	struct ipfw_context *ctx;
1147 	if (unregister_ipfw_module(MODULE_BASIC_ID) ==0 ) {
1148 		ipfw_basic_flush_state_prt = NULL;
1149 		ipfw_basic_append_state_prt = NULL;
1150 
1151 		for (cpu = 0; cpu < ncpus; cpu++) {
1152 			ctx = ipfw_ctx[cpu];
1153 			if (ctx != NULL) {
1154 				for (i = 0; i < state_hash_size; i++) {
1155 					state_ctx = &ctx->state_ctx[i];
1156 					if (state_ctx != NULL) {
1157 						state = state_ctx->state;
1158 						while (state != NULL) {
1159 							the_state = state;
1160 							state = state->next;
1161 							if (the_state ==
1162 								state_ctx->last)
1163 							state_ctx->last = NULL;
1164 
1165 							kfree(the_state,
1166 								M_IPFW3_BASIC);
1167 						}
1168 					}
1169 				}
1170 				ctx->state_hash_size = 0;
1171 				kfree(ctx->state_ctx, M_IPFW3_BASIC);
1172 				ctx->state_ctx = NULL;
1173 			}
1174 		}
1175 		struct netmsg_base smsg;
1176 		netmsg_init(&smsg, NULL, &curthread->td_msgport,
1177 				0, ipfw_basic_stop_dispatch);
1178 		return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0);
1179 	}
1180 	return 1;
1181 }
1182 
1183 
1184 static int
1185 ipfw3_basic_modevent(module_t mod, int type, void *data)
1186 {
1187 	int err;
1188 	switch (type) {
1189 		case MOD_LOAD:
1190 			err = ipfw_basic_init();
1191 			break;
1192 		case MOD_UNLOAD:
1193 			err = ipfw_basic_stop();
1194 			break;
1195 		default:
1196 			err = 1;
1197 	}
1198 	return err;
1199 }
1200 
1201 static moduledata_t ipfw3_basic_mod = {
1202 	"ipfw3_basic",
1203 	ipfw3_basic_modevent,
1204 	NULL
1205 };
1206 DECLARE_MODULE(ipfw3_basic, ipfw3_basic_mod, SI_SUB_PROTO_END, SI_ORDER_ANY);
1207 MODULE_DEPEND(ipfw3_basic, ipfw3, 1, 1, 1);
1208 MODULE_VERSION(ipfw3_basic, 1);
1209