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