2 * Copyright (c) 2014 - 2017 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Bill Yuan <bycn82@dragonflybsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.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>
47 #include <net/ethernet.h>
48 #include <net/netmsg2.h>
49 #include <net/netisr2.h>
50 #include <net/route.h>
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>
68 #include <net/ipfw3/ip_fw.h>
69 #include <net/ipfw3/ip_fw3_table.h>
70 #include <net/ipfw3/ip_fw3_sync.h>
72 #include "ip_fw3_basic.h"
74 #define TIME_LEQ(a, b) ((int)((a) - (b)) <= 0)
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
;
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;
94 static int ipfw_sysctl_adjust_hash_size(SYSCTL_HANDLER_ARGS
);
95 void adjust_hash_size_dispatch(netmsg_t nmsg
);
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");
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");
113 ipfw_sysctl_adjust_hash_size(SYSCTL_HANDLER_ARGS
)
115 int error
, value
= 0;
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
) {
124 * Make sure we have a power of 2 and
125 * do not allow more than 64k entries.
128 if (value
<= 1 || value
> 65536) {
131 if ((value
& (value
- 1)) != 0) {
136 if (state_hash_size
!= value
) {
137 state_hash_size
= value
;
139 struct netmsg_base
*msg
, the_msg
;
141 bzero(msg
,sizeof(struct netmsg_base
));
143 netmsg_init(msg
, NULL
, &curthread
->td_msgport
,
144 0, adjust_hash_size_dispatch
);
145 netisr_domsg(msg
, 0);
152 adjust_hash_size_dispatch(netmsg_t nmsg
)
154 struct ipfw_state_context
*state_ctx
;
155 struct ip_fw_state
*the_state
, *state
;
156 struct ipfw_context
*ctx
= ipfw_ctx
[mycpuid
];
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
) {
166 kfree(the_state
, M_IPFW3_BASIC
);
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_all(&nmsg
->base
, mycpuid
+ 1);
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
);
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
);
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
);
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
);
244 hash_packet(struct ipfw_flow_id
*id
)
247 i
= (id
->proto
) ^ (id
->dst_ip
) ^ (id
->src_ip
) ^
248 (id
->dst_port
) ^ (id
->src_port
);
249 i
&= state_hash_size
- 1;
253 static struct ip_fw
*
254 lookup_next_rule(struct ip_fw
*me
)
256 struct ip_fw
*rule
= NULL
;
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
)
268 if (rule
== NULL
) /* failure or not a skipto */
271 me
->next_rule
= rule
;
277 * 0 : not match 1: same direction 2: reverse direction
280 match_state(ipfw_insn
*cmd
, struct ipfw_flow_id
*fid
, struct ip_fw_state
*state
)
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)) {
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)) {
302 * return 1 when more states than limit
303 * arg3: limit type (1=src ip, 2=src port, 3=dst ip, 4=dst port)
307 count_match_state(ipfw_insn
*cmd
, struct ipfw_flow_id
*fid
,
308 struct ip_fw_state
*state
, int *count
)
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
)) {
315 if (*count
>= cmd
->arg1
)
322 * when all = 1, it will check all the state_ctx
323 * all = 1 during keep-state
324 * all = 0 during check-state
326 * in the cmd of keep_state
327 * arg3=type arg1=limit
329 static struct ip_fw_state
*
330 lookup_state(struct ip_fw_args
*args
, ipfw_insn
*cmd
, int *limited
, int all
)
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;
337 if (all
&& cmd
->arg1
) {
339 end
= state_hash_size
- 1;
341 start
= hash_packet(&args
->f_id
);
342 end
= hash_packet(&args
->f_id
);
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 */
353 count_match_state(cmd
, fid
,
354 state
, &count
) != 0) {
359 if (fid
->proto
== state
->flow_id
.proto
&&
360 match_state(cmd
, fid
, state
) != 0)
371 static struct ip_fw_state
*
372 install_state(struct ip_fw
*rule
, ipfw_insn
*cmd
, struct ip_fw_args
*args
)
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
);
385 state
->lifetime
= cmd
->arg2
== 0 ? state_lifetime
: cmd
->arg2
;
386 state
->timestamp
= time_second
;
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
;
393 state_ctx
->state
= state
;
394 state_ctx
->last
= state
;
397 if (sync_ctx
.running
& 2) {
398 ipfw_sync_send_state_prt(state
, mycpuid
, hash
);
404 ipfw_sync_install_state(struct cmd_send_state
*cmd
)
406 struct ip_fw_state
*state
;
407 struct ipfw_context
*ctx
= ipfw_ctx
[cmd
->cpu
];
408 struct ipfw_state_context
*state_ctx
;
411 state_ctx
= &ctx
->state_ctx
[cmd
->hash
];
412 state
= kmalloc(sizeof(struct ip_fw_state
),
413 M_IPFW3_BASIC
, M_NOWAIT
| M_ZERO
);
417 for (rule
= ctx
->ipfw_rule_chain
; rule
; rule
= rule
->next
) {
418 if (rule
->rulenum
== cmd
->rulenum
) {
425 state
->lifetime
= cmd
->lifetime
;
426 state
->timestamp
= time_second
;
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
;
433 state_ctx
->state
= state
;
434 state_ctx
->last
= state
;
439 iface_match(struct ifnet
*ifp
, ipfw_insn_if
*cmd
)
441 if (ifp
== NULL
) /* no iface with this packet, match fails */
444 /* Check by name or by IP address */
445 if (cmd
->name
[0] != '\0') { /* match by name */
448 if (kfnmatch(cmd
->name
, ifp
->if_xname
, 0) == 0)
451 if (strncmp(ifp
->if_xname
, cmd
->name
, IFNAMSIZ
) == 0)
455 struct ifaddr_container
*ifac
;
457 TAILQ_FOREACH(ifac
, &ifp
->if_addrheads
[mycpuid
], ifa_link
) {
458 struct ifaddr
*ia
= ifac
->ifa
;
460 if (ia
->ifa_addr
== NULL
)
462 if (ia
->ifa_addr
->sa_family
!= AF_INET
)
464 if (cmd
->p
.ip
.s_addr
==
465 ((struct sockaddr_in
*)
466 (ia
->ifa_addr
))->sin_addr
.s_addr
)
467 return(1); /* match */
471 return 0; /* no match, fail ... */
474 /* implimentation of the checker functions */
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
)
480 (*f
)->bcnt
+= ip_len
;
481 (*f
)->timestamp
= time_second
;
482 *cmd_ctl
= IP_FW_CTL_NEXT
;
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
)
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
;
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
)
502 struct sockaddr_in
*sin
, *sa
;
505 if ((*args
)->eh
) { /* not valid on layer2 pkts */
506 *cmd_ctl
=IP_FW_CTL_NEXT
;
511 (*f
)->bcnt
+= ip_len
;
512 (*f
)->timestamp
= time_second
;
513 if ((*f
)->next_rule
== NULL
)
514 lookup_next_rule(*f
);
516 mtag
= m_tag_get(PACKET_TAG_IPFORWARD
,
517 sizeof(*sin
), M_NOWAIT
);
519 *cmd_val
= IP_FW_DENY
;
520 *cmd_ctl
= IP_FW_CTL_DONE
;
523 sin
= m_tag_data(mtag
);
524 sa
= &((ipfw_insn_sa
*)cmd
)->sa
;
525 /* arg3: count of the dest, arg1: type of fwd */
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);
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
;
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
)
550 struct ip_fw_state
*state
=NULL
;
552 state
= lookup_state(*args
, cmd
, &limited
, 0);
555 state
->bcnt
+= ip_len
;
556 state
->timestamp
= time_second
;
558 (*f
)->bcnt
+= ip_len
;
559 (*f
)->timestamp
= time_second
;
561 *cmd_ctl
= IP_FW_CTL_CHK_STATE
;
563 *cmd_ctl
= IP_FW_CTL_NEXT
;
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
)
571 *cmd_ctl
= IP_FW_CTL_NO
;
572 *cmd_val
= ((*args
)->oif
== NULL
);
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
)
579 *cmd_ctl
= IP_FW_CTL_NO
;
580 *cmd_val
= ((*args
)->oif
!= NULL
);
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
)
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
);
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
)
597 *cmd_ctl
= IP_FW_CTL_NO
;
598 *cmd_val
= ((*args
)->f_id
.proto
== cmd
->arg1
);
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
)
605 *cmd_ctl
= IP_FW_CTL_NO
;
606 *cmd_val
= (krandom() % 100) < cmd
->arg1
;
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
)
613 struct in_addr src_ip
;
615 struct mbuf
*m
= (*args
)->m
;
616 struct ip
*ip
= mtod(m
, struct ip
*);
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;
623 *cmd_val
= (hlen
> 0 &&
624 ((ipfw_insn_ip
*)cmd
)->addr
.s_addr
== src_ip
.s_addr
);
625 *cmd_ctl
= IP_FW_CTL_NO
;
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
)
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
;
637 struct mbuf
*m
= (*args
)->m
;
638 struct ip
*ip
= mtod(m
, struct ip
*);
639 struct in_addr src_ip
= ip
->ip_src
;
641 *cmd_val
= IP_FW_NOT_MATCH
;
643 table_ctx
= ctx
->table_ctx
;
644 table_ctx
+= cmd
->arg1
;
646 if (table_ctx
->type
!= 0) {
647 rnh
= table_ctx
->node
;
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
;
653 *cmd_ctl
= IP_FW_CTL_NO
;
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
)
660 struct in_addr src_ip
;
662 struct mbuf
*m
= (*args
)->m
;
663 struct ip
*ip
= mtod(m
, struct ip
*);
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;
670 *cmd_ctl
= IP_FW_CTL_NO
;
673 tif
= INADDR_TO_IFP(&src_ip
);
674 *cmd_val
= (tif
!= NULL
);
676 *cmd_val
= IP_FW_NOT_MATCH
;
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
)
684 struct in_addr src_ip
;
686 struct mbuf
*m
= (*args
)->m
;
687 struct ip
*ip
= mtod(m
, struct ip
*);
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;
695 *cmd_ctl
= IP_FW_CTL_NO
;
696 *cmd_val
= (hlen
> 0 &&
697 ((ipfw_insn_ip
*)cmd
)->addr
.s_addr
==
699 ((ipfw_insn_ip
*)cmd
)->mask
.s_addr
));
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
)
706 struct in_addr dst_ip
;
708 struct mbuf
*m
= (*args
)->m
;
709 struct ip
*ip
= mtod(m
, struct ip
*);
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;
716 *cmd_val
= (hlen
> 0 &&
717 ((ipfw_insn_ip
*)cmd
)->addr
.s_addr
== dst_ip
.s_addr
);
718 *cmd_ctl
= IP_FW_CTL_NO
;
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
)
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
;
730 struct mbuf
*m
= (*args
)->m
;
731 struct ip
*ip
= mtod(m
, struct ip
*);
732 struct in_addr dst_ip
= ip
->ip_dst
;
734 *cmd_val
= IP_FW_NOT_MATCH
;
736 table_ctx
= ctx
->table_ctx
;
737 table_ctx
+= cmd
->arg1
;
739 if (table_ctx
->type
!= 0) {
740 rnh
= table_ctx
->node
;
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
;
746 *cmd_ctl
= IP_FW_CTL_NO
;
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
)
753 struct in_addr dst_ip
;
755 struct mbuf
*m
= (*args
)->m
;
756 struct ip
*ip
= mtod(m
, struct ip
*);
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;
763 *cmd_ctl
= IP_FW_CTL_NO
;
766 tif
= INADDR_TO_IFP(&dst_ip
);
767 *cmd_val
= (tif
!= NULL
);
769 *cmd_val
= IP_FW_NOT_MATCH
;
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
)
777 struct in_addr dst_ip
;
779 struct mbuf
*m
= (*args
)->m
;
780 struct ip
*ip
= mtod(m
, struct ip
*);
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;
788 *cmd_ctl
= IP_FW_CTL_NO
;
789 *cmd_val
= (hlen
> 0 &&
790 ((ipfw_insn_ip
*)cmd
)->addr
.s_addr
==
792 ((ipfw_insn_ip
*)cmd
)->mask
.s_addr
));
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
)
799 struct ip_fw_state
*state
;
802 *cmd_ctl
= IP_FW_CTL_NO
;
803 *cmd_val
= IP_FW_MATCH
;
804 state
= lookup_state(*args
, cmd
, &limited
, 1);
807 state
= install_state(*f
, cmd
, *args
);
811 state
->bcnt
+= ip_len
;
812 state
->timestamp
= time_second
;
818 check_tag(int *cmd_ctl
, int *cmd_val
, struct ip_fw_args
**args
,
819 struct ip_fw
**f
, ipfw_insn
*cmd
, uint16_t ip_len
)
821 struct m_tag
*mtag
= m_tag_locate((*args
)->m
,
822 MTAG_IPFW
, cmd
->arg1
, NULL
);
824 mtag
= m_tag_alloc(MTAG_IPFW
,cmd
->arg1
, 0, M_NOWAIT
);
826 m_tag_prepend((*args
)->m
, mtag
);
830 (*f
)->bcnt
+= ip_len
;
831 (*f
)->timestamp
= time_second
;
832 *cmd_ctl
= IP_FW_CTL_NEXT
;
836 check_untag(int *cmd_ctl
, int *cmd_val
, struct ip_fw_args
**args
,
837 struct ip_fw
**f
, ipfw_insn
*cmd
, uint16_t ip_len
)
839 struct m_tag
*mtag
= m_tag_locate((*args
)->m
,
840 MTAG_IPFW
, cmd
->arg1
, NULL
);
842 m_tag_delete((*args
)->m
, mtag
);
845 (*f
)->bcnt
+= ip_len
;
846 (*f
)->timestamp
= time_second
;
847 *cmd_ctl
= IP_FW_CTL_NEXT
;
851 check_tagged(int *cmd_ctl
, int *cmd_val
, struct ip_fw_args
**args
,
852 struct ip_fw
**f
, ipfw_insn
*cmd
, uint16_t ip_len
)
854 *cmd_ctl
= IP_FW_CTL_NO
;
855 if (m_tag_locate( (*args
)->m
, MTAG_IPFW
,cmd
->arg1
, NULL
) != NULL
)
856 *cmd_val
= IP_FW_MATCH
;
858 *cmd_val
= IP_FW_NOT_MATCH
;
862 check_src_port(int *cmd_ctl
, int *cmd_val
, struct ip_fw_args
**args
,
863 struct ip_fw
**f
, ipfw_insn
*cmd
, uint16_t ip_len
)
865 *cmd_ctl
= IP_FW_CTL_NO
;
866 if ((*args
)->f_id
.src_port
== cmd
->arg1
)
867 *cmd_val
= IP_FW_MATCH
;
869 *cmd_val
= IP_FW_NOT_MATCH
;
873 check_dst_port(int *cmd_ctl
, int *cmd_val
, struct ip_fw_args
**args
,
874 struct ip_fw
**f
, ipfw_insn
*cmd
, uint16_t ip_len
)
876 *cmd_ctl
= IP_FW_CTL_NO
;
877 if ((*args
)->f_id
.dst_port
== cmd
->arg1
)
878 *cmd_val
= IP_FW_MATCH
;
880 *cmd_val
= IP_FW_NOT_MATCH
;
884 check_src_n_port(int *cmd_ctl
, int *cmd_val
, struct ip_fw_args
**args
,
885 struct ip_fw
**f
, ipfw_insn
*cmd
, uint16_t ip_len
)
887 struct in_addr src_ip
;
889 struct mbuf
*m
= (*args
)->m
;
890 struct ip
*ip
= mtod(m
, struct ip
*);
892 if ((*args
)->eh
== NULL
||
893 (m
->m_pkthdr
.len
>= sizeof(struct ip
) &&
894 ntohs((*args
)->eh
->ether_type
) == ETHERTYPE_IP
)) {
895 hlen
= ip
->ip_hl
<< 2;
897 *cmd_val
= (hlen
> 0 && ((ipfw_insn_ip
*)cmd
)->addr
.s_addr
== src_ip
.s_addr
);
898 *cmd_ctl
= IP_FW_CTL_NO
;
899 if (*cmd_val
&& (*args
)->f_id
.src_port
== cmd
->arg1
)
900 *cmd_val
= IP_FW_MATCH
;
902 *cmd_val
= IP_FW_NOT_MATCH
;
906 check_dst_n_port(int *cmd_ctl
, int *cmd_val
, struct ip_fw_args
**args
,
907 struct ip_fw
**f
, ipfw_insn
*cmd
, uint16_t ip_len
)
909 struct in_addr dst_ip
;
911 struct mbuf
*m
= (*args
)->m
;
912 struct ip
*ip
= mtod(m
, struct ip
*);
914 if ((*args
)->eh
== NULL
||
915 (m
->m_pkthdr
.len
>= sizeof(struct ip
) &&
916 ntohs((*args
)->eh
->ether_type
) == ETHERTYPE_IP
)) {
917 hlen
= ip
->ip_hl
<< 2;
919 *cmd_val
= (hlen
> 0 && ((ipfw_insn_ip
*)cmd
)->addr
.s_addr
== dst_ip
.s_addr
);
920 *cmd_ctl
= IP_FW_CTL_NO
;
921 if (*cmd_val
&& (*args
)->f_id
.dst_port
== cmd
->arg1
)
922 *cmd_val
= IP_FW_MATCH
;
924 *cmd_val
= IP_FW_NOT_MATCH
;
930 ipfw_basic_add_state(struct ipfw_ioc_state
*ioc_state
)
932 struct ip_fw_state
*state
;
933 struct ipfw_context
*ctx
= ipfw_ctx
[mycpuid
];
934 struct ipfw_state_context
*state_ctx
;
935 state_ctx
= &ctx
->state_ctx
[hash_packet(&(ioc_state
->flow_id
))];
936 state
= kmalloc(sizeof(struct ip_fw_state
),
937 M_IPFW3_BASIC
, M_WAITOK
| M_ZERO
);
938 struct ip_fw
*rule
= ctx
->ipfw_rule_chain
;
939 while (rule
!= NULL
) {
940 if (rule
->rulenum
== ioc_state
->rulenum
) {
950 state
->lifetime
= ioc_state
->lifetime
== 0 ?
951 state_lifetime
: ioc_state
->lifetime
;
952 state
->timestamp
= time_second
;
953 state
->expiry
= ioc_state
->expiry
;
954 bcopy(&ioc_state
->flow_id
, &state
->flow_id
,
955 sizeof(struct ipfw_flow_id
));
956 //append the state into the state chian
957 if (state_ctx
->last
!= NULL
)
958 state_ctx
->last
->next
= state
;
960 state_ctx
->state
= state
;
962 state_ctx
->last
= state
;
970 * flush states which stub is the rule
973 ipfw_basic_flush_state(struct ip_fw
*rule
)
975 struct ipfw_state_context
*state_ctx
;
976 struct ip_fw_state
*state
,*the_state
, *prev_state
;
977 struct ipfw_context
*ctx
;
980 ctx
= ipfw_ctx
[mycpuid
];
981 for (i
= 0; i
< state_hash_size
; i
++) {
982 state_ctx
= &ctx
->state_ctx
[i
];
983 if (state_ctx
!= NULL
) {
984 state
= state_ctx
->state
;
986 while (state
!= NULL
) {
987 if (rule
!= NULL
&& state
->stub
!= rule
) {
991 if (prev_state
== NULL
)
992 state_ctx
->state
= state
->next
;
994 prev_state
->next
= state
->next
;
998 kfree(the_state
, M_IPFW3_BASIC
);
1001 state_ctx
->last
= prev_state
;
1010 * clean up expired state in every tick
1013 ipfw_cleanup_expired_state(netmsg_t nmsg
)
1015 struct ip_fw_state
*state
,*the_state
,*prev_state
;
1016 struct ipfw_context
*ctx
= ipfw_ctx
[mycpuid
];
1017 struct ipfw_state_context
*state_ctx
;
1020 for (i
= 0; i
< state_hash_size
; i
++) {
1022 state_ctx
= &(ctx
->state_ctx
[i
]);
1023 if (ctx
->state_ctx
!= NULL
) {
1024 state
= state_ctx
->state
;
1025 while (state
!= NULL
) {
1026 if (IS_EXPIRED(state
)) {
1027 if (prev_state
== NULL
)
1028 state_ctx
->state
= state
->next
;
1030 prev_state
->next
= state
->next
;
1033 state
= state
->next
;
1035 if (the_state
== state_ctx
->last
)
1036 state_ctx
->last
= NULL
;
1039 kfree(the_state
, M_IPFW3_BASIC
);
1043 state
= state
->next
;
1048 netisr_forwardmsg_all(&nmsg
->base
, mycpuid
+ 1);
1052 ipfw_tick(void *dummy __unused
)
1054 struct lwkt_msg
*lmsg
= &ipfw_timeout_netmsg
.lmsg
;
1055 KKASSERT(mycpuid
== IPFW_CFGCPUID
);
1058 KKASSERT(lmsg
->ms_flags
& MSGF_DONE
);
1059 if (IPFW_BASIC_LOADED
) {
1060 lwkt_sendmsg_oncpu(IPFW_CFGPORT
, lmsg
);
1061 /* ipfw_timeout_netmsg's handler reset this callout */
1067 ipfw_tick_dispatch(netmsg_t nmsg
)
1069 IPFW_ASSERT_CFGPORT(&curthread
->td_msgport
);
1070 KKASSERT(IPFW_BASIC_LOADED
);
1074 lwkt_replymsg(&nmsg
->lmsg
, 0);
1077 callout_reset(&ipfw_tick_callout
,
1078 state_expiry_check_interval
* hz
, ipfw_tick
, NULL
);
1080 struct netmsg_base msg
;
1081 netmsg_init(&msg
, NULL
, &curthread
->td_msgport
, 0,
1082 ipfw_cleanup_expired_state
);
1083 netisr_domsg(&msg
, 0);
1087 ipfw_basic_init_dispatch(netmsg_t nmsg
)
1089 IPFW_ASSERT_CFGPORT(&curthread
->td_msgport
);
1090 KKASSERT(IPFW3_LOADED
);
1093 callout_init_mp(&ipfw_tick_callout
);
1094 netmsg_init(&ipfw_timeout_netmsg
, NULL
, &netisr_adone_rport
,
1095 MSGF_DROPABLE
| MSGF_PRIORITY
, ipfw_tick_dispatch
);
1096 callout_reset(&ipfw_tick_callout
,
1097 state_expiry_check_interval
* hz
, ipfw_tick
, NULL
);
1098 lwkt_replymsg(&nmsg
->lmsg
, error
);
1099 ip_fw_basic_loaded
=1;
1103 ipfw_basic_init(void)
1105 ipfw_basic_flush_state_prt
= ipfw_basic_flush_state
;
1106 ipfw_basic_append_state_prt
= ipfw_basic_add_state
;
1107 ipfw_sync_install_state_prt
= ipfw_sync_install_state
;
1109 register_ipfw_module(MODULE_BASIC_ID
, MODULE_BASIC_NAME
);
1110 register_ipfw_filter_funcs(MODULE_BASIC_ID
, O_BASIC_COUNT
,
1111 (filter_func
)check_count
);
1112 register_ipfw_filter_funcs(MODULE_BASIC_ID
, O_BASIC_SKIPTO
,
1113 (filter_func
)check_skipto
);
1114 register_ipfw_filter_funcs(MODULE_BASIC_ID
, O_BASIC_FORWARD
,
1115 (filter_func
)check_forward
);
1116 register_ipfw_filter_funcs(MODULE_BASIC_ID
, O_BASIC_KEEP_STATE
,
1117 (filter_func
)check_keep_state
);
1118 register_ipfw_filter_funcs(MODULE_BASIC_ID
, O_BASIC_CHECK_STATE
,
1119 (filter_func
)check_check_state
);
1121 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1122 O_BASIC_IN
, (filter_func
)check_in
);
1123 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1124 O_BASIC_OUT
, (filter_func
)check_out
);
1125 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1126 O_BASIC_VIA
, (filter_func
)check_via
);
1127 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1128 O_BASIC_XMIT
, (filter_func
)check_via
);
1129 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1130 O_BASIC_RECV
, (filter_func
)check_via
);
1132 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1133 O_BASIC_PROTO
, (filter_func
)check_proto
);
1134 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1135 O_BASIC_PROB
, (filter_func
)check_prob
);
1136 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1137 O_BASIC_IP_SRC
, (filter_func
)check_from
);
1138 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1139 O_BASIC_IP_SRC_LOOKUP
, (filter_func
)check_from_lookup
);
1140 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1141 O_BASIC_IP_SRC_ME
, (filter_func
)check_from_me
);
1142 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1143 O_BASIC_IP_SRC_MASK
, (filter_func
)check_from_mask
);
1144 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1145 O_BASIC_IP_DST
, (filter_func
)check_to
);
1146 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1147 O_BASIC_IP_DST_LOOKUP
, (filter_func
)check_to_lookup
);
1148 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1149 O_BASIC_IP_DST_ME
, (filter_func
)check_to_me
);
1150 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1151 O_BASIC_IP_DST_MASK
, (filter_func
)check_to_mask
);
1152 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1153 O_BASIC_TAG
, (filter_func
)check_tag
);
1154 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1155 O_BASIC_UNTAG
, (filter_func
)check_untag
);
1156 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1157 O_BASIC_TAGGED
, (filter_func
)check_tagged
);
1158 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1159 O_BASIC_IP_SRCPORT
, (filter_func
)check_src_port
);
1160 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1161 O_BASIC_IP_DSTPORT
, (filter_func
)check_dst_port
);
1162 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1163 O_BASIC_IP_SRC_N_PORT
, (filter_func
)check_src_n_port
);
1164 register_ipfw_filter_funcs(MODULE_BASIC_ID
,
1165 O_BASIC_IP_DST_N_PORT
, (filter_func
)check_dst_n_port
);
1168 struct ipfw_context
*ctx
;
1170 for (cpu
= 0; cpu
< ncpus
; cpu
++) {
1171 ctx
= ipfw_ctx
[cpu
];
1173 ctx
->state_ctx
= kmalloc(state_hash_size
*
1174 sizeof(struct ipfw_state_context
),
1175 M_IPFW3_BASIC
, M_WAITOK
| M_ZERO
);
1176 ctx
->state_hash_size
= state_hash_size
;
1180 struct netmsg_base smsg
;
1181 netmsg_init(&smsg
, NULL
, &curthread
->td_msgport
,
1182 0, ipfw_basic_init_dispatch
);
1183 lwkt_domsg(IPFW_CFGPORT
, &smsg
.lmsg
, 0);
1188 ipfw_basic_stop_dispatch(netmsg_t nmsg
)
1190 IPFW_ASSERT_CFGPORT(&curthread
->td_msgport
);
1191 KKASSERT(IPFW3_LOADED
);
1193 callout_stop(&ipfw_tick_callout
);
1194 netmsg_service_sync();
1196 lwkt_dropmsg(&ipfw_timeout_netmsg
.lmsg
);
1198 lwkt_replymsg(&nmsg
->lmsg
, error
);
1199 ip_fw_basic_loaded
=0;
1203 ipfw_basic_stop(void)
1206 struct ipfw_state_context
*state_ctx
;
1207 struct ip_fw_state
*state
,*the_state
;
1208 struct ipfw_context
*ctx
;
1209 if (unregister_ipfw_module(MODULE_BASIC_ID
) ==0 ) {
1210 ipfw_basic_flush_state_prt
= NULL
;
1211 ipfw_basic_append_state_prt
= NULL
;
1213 for (cpu
= 0; cpu
< ncpus
; cpu
++) {
1214 ctx
= ipfw_ctx
[cpu
];
1216 for (i
= 0; i
< state_hash_size
; i
++) {
1217 state_ctx
= &ctx
->state_ctx
[i
];
1218 if (state_ctx
!= NULL
) {
1219 state
= state_ctx
->state
;
1220 while (state
!= NULL
) {
1222 state
= state
->next
;
1225 state_ctx
->last
= NULL
;
1232 ctx
->state_hash_size
= 0;
1233 kfree(ctx
->state_ctx
, M_IPFW3_BASIC
);
1234 ctx
->state_ctx
= NULL
;
1237 struct netmsg_base smsg
;
1238 netmsg_init(&smsg
, NULL
, &curthread
->td_msgport
,
1239 0, ipfw_basic_stop_dispatch
);
1240 return lwkt_domsg(IPFW_CFGPORT
, &smsg
.lmsg
, 0);
1247 ipfw3_basic_modevent(module_t mod
, int type
, void *data
)
1252 err
= ipfw_basic_init();
1255 err
= ipfw_basic_stop();
1263 static moduledata_t ipfw3_basic_mod
= {
1265 ipfw3_basic_modevent
,
1268 DECLARE_MODULE(ipfw3_basic
, ipfw3_basic_mod
, SI_SUB_PROTO_END
, SI_ORDER_ANY
);
1269 MODULE_DEPEND(ipfw3_basic
, ipfw3
, 1, 1, 1);
1270 MODULE_VERSION(ipfw3_basic
, 1);