16a03354eSMatthew Dillon /*
24408d548SBill Yuan  * Copyright (c) 2014 - 2018 The DragonFly Project.  All rights reserved.
36a03354eSMatthew Dillon  *
46a03354eSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
59187b359SBill Yuan  * by Bill Yuan <bycn82@dragonflybsd.org>
66a03354eSMatthew Dillon  *
76a03354eSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
86a03354eSMatthew Dillon  * modification, are permitted provided that the following conditions
96a03354eSMatthew Dillon  * are met:
106a03354eSMatthew Dillon  *
116a03354eSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
126a03354eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
136a03354eSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
146a03354eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
156a03354eSMatthew Dillon  *    the documentation and/or other materials provided with the
166a03354eSMatthew Dillon  *    distribution.
176a03354eSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
186a03354eSMatthew Dillon  *    contributors may be used to endorse or promote products derived
196a03354eSMatthew Dillon  *    from this software without specific, prior written permission.
206a03354eSMatthew Dillon  *
216a03354eSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
226a03354eSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
236a03354eSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
246a03354eSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
256a03354eSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
266a03354eSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
276a03354eSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
286a03354eSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
296a03354eSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
306a03354eSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
316a03354eSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
326a03354eSMatthew Dillon  * SUCH DAMAGE.
336a03354eSMatthew Dillon  */
346a03354eSMatthew Dillon 
354408d548SBill Yuan #include "opt_ipfw.h"
364408d548SBill Yuan #include "opt_inet.h"
374408d548SBill Yuan #ifndef INET
384408d548SBill Yuan #error IPFIREWALL3 requires INET.
394408d548SBill Yuan #endif /* INET */
404408d548SBill Yuan 
416a03354eSMatthew Dillon #include <sys/param.h>
426a03354eSMatthew Dillon #include <sys/kernel.h>
436a03354eSMatthew Dillon #include <sys/malloc.h>
446a03354eSMatthew Dillon #include <sys/mbuf.h>
456a03354eSMatthew Dillon #include <sys/socketvar.h>
466a03354eSMatthew Dillon #include <sys/sysctl.h>
476a03354eSMatthew Dillon #include <sys/systimer.h>
486a03354eSMatthew Dillon #include <sys/in_cksum.h>
494408d548SBill Yuan #include <sys/systm.h>
504408d548SBill Yuan #include <sys/proc.h>
514408d548SBill Yuan #include <sys/socket.h>
524408d548SBill Yuan #include <sys/syslog.h>
534408d548SBill Yuan #include <sys/ucred.h>
544408d548SBill Yuan #include <sys/lock.h>
554408d548SBill Yuan #include <sys/tree.h>
566a03354eSMatthew Dillon 
576a03354eSMatthew Dillon #include <net/if.h>
586a03354eSMatthew Dillon #include <net/ethernet.h>
596a03354eSMatthew Dillon #include <net/netmsg2.h>
606a03354eSMatthew Dillon #include <net/netisr2.h>
616a03354eSMatthew Dillon #include <net/route.h>
626a03354eSMatthew Dillon 
636a03354eSMatthew Dillon #include <netinet/ip.h>
646a03354eSMatthew Dillon #include <netinet/in.h>
656a03354eSMatthew Dillon #include <netinet/in_systm.h>
666a03354eSMatthew Dillon #include <netinet/in_var.h>
676a03354eSMatthew Dillon #include <netinet/in_pcb.h>
686a03354eSMatthew Dillon #include <netinet/ip_var.h>
696a03354eSMatthew Dillon #include <netinet/ip_icmp.h>
706a03354eSMatthew Dillon #include <netinet/tcp.h>
716a03354eSMatthew Dillon #include <netinet/tcp_timer.h>
726a03354eSMatthew Dillon #include <netinet/tcp_var.h>
736a03354eSMatthew Dillon #include <netinet/tcpip.h>
746a03354eSMatthew Dillon #include <netinet/udp.h>
756a03354eSMatthew Dillon #include <netinet/udp_var.h>
766a03354eSMatthew Dillon #include <netinet/ip_divert.h>
776a03354eSMatthew Dillon #include <netinet/if_ether.h>
786a03354eSMatthew Dillon 
796a03354eSMatthew Dillon #include <net/ipfw3/ip_fw.h>
804408d548SBill Yuan #include <net/ipfw3_basic/ip_fw3_table.h>
814408d548SBill Yuan #include <net/ipfw3_basic/ip_fw3_sync.h>
824408d548SBill Yuan #include <net/ipfw3_basic/ip_fw3_basic.h>
834408d548SBill Yuan #include <net/ipfw3_basic/ip_fw3_state.h>
846a03354eSMatthew Dillon 
854408d548SBill Yuan extern struct ipfw3_context		*fw3_ctx[MAXCPU];
864408d548SBill Yuan extern struct ipfw3_sync_context 	fw3_sync_ctx;
874408d548SBill Yuan extern struct ipfw3_state_context 	*fw3_state_ctx[MAXCPU];
884408d548SBill Yuan extern ip_fw_ctl_t 			*ipfw_ctl_basic_ptr;
896a03354eSMatthew Dillon 
904408d548SBill Yuan extern int 				sysctl_var_fw3_verbose;
916a03354eSMatthew Dillon 
924408d548SBill Yuan extern int 			sysctl_var_state_max_tcp_in;
934408d548SBill Yuan extern int 			sysctl_var_state_max_udp_in;
944408d548SBill Yuan extern int 			sysctl_var_state_max_icmp_in;
956a03354eSMatthew Dillon 
964408d548SBill Yuan extern int 			sysctl_var_state_max_tcp_out;
974408d548SBill Yuan extern int 			sysctl_var_state_max_udp_out;
984408d548SBill Yuan extern int 			sysctl_var_state_max_icmp_out;
99e600b76aSBill Yuan 
1004408d548SBill Yuan extern int 			sysctl_var_icmp_timeout;
1014408d548SBill Yuan extern int 			sysctl_var_tcp_timeout;
1024408d548SBill Yuan extern int 			sysctl_var_udp_timeout;
1036a03354eSMatthew Dillon 
1046a03354eSMatthew Dillon static struct ip_fw *
lookup_next_rule(struct ip_fw * me)1056a03354eSMatthew Dillon lookup_next_rule(struct ip_fw *me)
1066a03354eSMatthew Dillon {
1076a03354eSMatthew Dillon 	struct ip_fw *rule = NULL;
1086a03354eSMatthew Dillon 	ipfw_insn *cmd;
1096a03354eSMatthew Dillon 
1106a03354eSMatthew Dillon 	/* look for action, in case it is a skipto */
1116a03354eSMatthew Dillon 	cmd = ACTION_PTR(me);
1126a03354eSMatthew Dillon 	if ((int)cmd->module == MODULE_BASIC_ID &&
1136a03354eSMatthew Dillon 		(int)cmd->opcode == O_BASIC_SKIPTO) {
1146a03354eSMatthew Dillon 		for (rule = me->next; rule; rule = rule->next) {
1156a03354eSMatthew Dillon 			if (rule->rulenum >= cmd->arg1)
1166a03354eSMatthew Dillon 				break;
1176a03354eSMatthew Dillon 		}
1186a03354eSMatthew Dillon 	}
1196a03354eSMatthew Dillon 	if (rule == NULL) /* failure or not a skipto */
1206a03354eSMatthew Dillon 		rule = me->next;
1216a03354eSMatthew Dillon 
1226a03354eSMatthew Dillon 	me->next_rule = rule;
1236a03354eSMatthew Dillon 	return rule;
1246a03354eSMatthew Dillon }
1256a03354eSMatthew Dillon 
1266a03354eSMatthew Dillon 
1276a03354eSMatthew Dillon static int
iface_match(struct ifnet * ifp,ipfw_insn_if * cmd)1286a03354eSMatthew Dillon iface_match(struct ifnet *ifp, ipfw_insn_if *cmd)
1296a03354eSMatthew Dillon {
1306a03354eSMatthew Dillon 	if (ifp == NULL)	/* no iface with this packet, match fails */
1316a03354eSMatthew Dillon 		return 0;
1326a03354eSMatthew Dillon 
1336a03354eSMatthew Dillon 	/* Check by name or by IP address */
1346a03354eSMatthew Dillon 	if (cmd->name[0] != '\0') { /* match by name */
1356a03354eSMatthew Dillon 		/* Check name */
1366a03354eSMatthew Dillon 		if (cmd->p.glob) {
1376a03354eSMatthew Dillon 			if (kfnmatch(cmd->name, ifp->if_xname, 0) == 0)
1386a03354eSMatthew Dillon 				return(1);
1396a03354eSMatthew Dillon 		} else {
1406a03354eSMatthew Dillon 			if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0)
1416a03354eSMatthew Dillon 				return(1);
1426a03354eSMatthew Dillon 		}
1436a03354eSMatthew Dillon 	} else {
1446a03354eSMatthew Dillon 		struct ifaddr_container *ifac;
1456a03354eSMatthew Dillon 
1466a03354eSMatthew Dillon 		TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) {
1476a03354eSMatthew Dillon 			struct ifaddr *ia = ifac->ifa;
1486a03354eSMatthew Dillon 
1496a03354eSMatthew Dillon 			if (ia->ifa_addr == NULL)
1506a03354eSMatthew Dillon 				continue;
1516a03354eSMatthew Dillon 			if (ia->ifa_addr->sa_family != AF_INET)
1526a03354eSMatthew Dillon 				continue;
1536a03354eSMatthew Dillon 			if (cmd->p.ip.s_addr ==
1546a03354eSMatthew Dillon 				((struct sockaddr_in *)
1556a03354eSMatthew Dillon 				(ia->ifa_addr))->sin_addr.s_addr)
1566a03354eSMatthew Dillon 					return(1);	/* match */
1576a03354eSMatthew Dillon 
1586a03354eSMatthew Dillon 		}
1596a03354eSMatthew Dillon 	}
1606a03354eSMatthew Dillon 	return 0;	/* no match, fail ... */
1616a03354eSMatthew Dillon }
1626a03354eSMatthew Dillon 
1636a03354eSMatthew Dillon /* implimentation of the checker functions */
1646a03354eSMatthew Dillon void
check_count(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)1656a03354eSMatthew Dillon check_count(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
1666a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
1676a03354eSMatthew Dillon {
1686a03354eSMatthew Dillon 	(*f)->pcnt++;
1696a03354eSMatthew Dillon 	(*f)->bcnt += ip_len;
1706a03354eSMatthew Dillon 	(*f)->timestamp = time_second;
1716a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NEXT;
1726a03354eSMatthew Dillon }
1736a03354eSMatthew Dillon 
1746a03354eSMatthew Dillon void
check_skipto(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)1756a03354eSMatthew Dillon check_skipto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
1766a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
1776a03354eSMatthew Dillon {
1786a03354eSMatthew Dillon 	(*f)->pcnt++;
1796a03354eSMatthew Dillon 	(*f)->bcnt += ip_len;
1806a03354eSMatthew Dillon 	(*f)->timestamp = time_second;
1816a03354eSMatthew Dillon 	if ((*f)->next_rule == NULL)
1826a03354eSMatthew Dillon 		lookup_next_rule(*f);
183f92842b0SBill Yuan 	*f = (*f)->next_rule;
1846a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_AGAIN;
1856a03354eSMatthew Dillon }
1866a03354eSMatthew Dillon 
1876a03354eSMatthew Dillon void
check_forward(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)1886a03354eSMatthew Dillon check_forward(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
1896a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
1906a03354eSMatthew Dillon {
1916a03354eSMatthew Dillon 	struct sockaddr_in *sin, *sa;
1926a03354eSMatthew Dillon 	struct m_tag *mtag;
1936a03354eSMatthew Dillon 
1946a03354eSMatthew Dillon 	if ((*args)->eh) {	/* not valid on layer2 pkts */
1956a03354eSMatthew Dillon 		*cmd_ctl=IP_FW_CTL_NEXT;
1966a03354eSMatthew Dillon 		return;
1976a03354eSMatthew Dillon 	}
1986a03354eSMatthew Dillon 
1996a03354eSMatthew Dillon 	(*f)->pcnt++;
2006a03354eSMatthew Dillon 	(*f)->bcnt += ip_len;
2016a03354eSMatthew Dillon 	(*f)->timestamp = time_second;
2026a03354eSMatthew Dillon 	if ((*f)->next_rule == NULL)
2036a03354eSMatthew Dillon 		lookup_next_rule(*f);
2046a03354eSMatthew Dillon 
2056a03354eSMatthew Dillon 	mtag = m_tag_get(PACKET_TAG_IPFORWARD,
206aa612e18SSepherosa Ziehau 			sizeof(*sin), M_INTWAIT | M_NULLOK);
2076a03354eSMatthew Dillon 	if (mtag == NULL) {
2086a03354eSMatthew Dillon 		*cmd_val = IP_FW_DENY;
2096a03354eSMatthew Dillon 		*cmd_ctl = IP_FW_CTL_DONE;
2106a03354eSMatthew Dillon 		return;
2116a03354eSMatthew Dillon 	}
2126a03354eSMatthew Dillon 	sin = m_tag_data(mtag);
2136a03354eSMatthew Dillon 	sa = &((ipfw_insn_sa *)cmd)->sa;
2146a03354eSMatthew Dillon 	/* arg3: count of the dest, arg1: type of fwd */
2156a03354eSMatthew Dillon 	int i = 0;
2166a03354eSMatthew Dillon 	if(cmd->arg3 > 1) {
2176a03354eSMatthew Dillon 		if (cmd->arg1 == 0) {		/* type: random */
2186a03354eSMatthew Dillon 			i = krandom() % cmd->arg3;
2196a03354eSMatthew Dillon 		} else if (cmd->arg1 == 1) {	/* type: round-robin */
2206a03354eSMatthew Dillon 			i = cmd->arg2++ % cmd->arg3;
2216a03354eSMatthew Dillon 		} else if (cmd->arg1 == 2) {	/* type: sticky */
2226a03354eSMatthew Dillon 			struct ip *ip = mtod((*args)->m, struct ip *);
2236a03354eSMatthew Dillon 			i = ip->ip_src.s_addr & (cmd->arg3 - 1);
2246a03354eSMatthew Dillon 		}
2256a03354eSMatthew Dillon 		sa += i;
2266a03354eSMatthew Dillon 	}
2276a03354eSMatthew Dillon 	*sin = *sa;	/* apply the destination */
2286a03354eSMatthew Dillon 	m_tag_prepend((*args)->m, mtag);
2296a03354eSMatthew Dillon 	(*args)->m->m_pkthdr.fw_flags |= IPFORWARD_MBUF_TAGGED;
2306a03354eSMatthew Dillon 	(*args)->m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED;
2316a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_DONE;
2326a03354eSMatthew Dillon 	*cmd_val = IP_FW_PASS;
2336a03354eSMatthew Dillon }
2346a03354eSMatthew Dillon 
2356a03354eSMatthew Dillon void
check_in(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)2366a03354eSMatthew Dillon check_in(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
2376a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
2386a03354eSMatthew Dillon {
2396a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NO;
2406a03354eSMatthew Dillon 	*cmd_val = ((*args)->oif == NULL);
2416a03354eSMatthew Dillon }
2426a03354eSMatthew Dillon 
2436a03354eSMatthew Dillon void
check_out(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)2446a03354eSMatthew Dillon check_out(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
2456a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
2466a03354eSMatthew Dillon {
2476a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NO;
2486a03354eSMatthew Dillon 	*cmd_val = ((*args)->oif != NULL);
2496a03354eSMatthew Dillon }
2506a03354eSMatthew Dillon 
2516a03354eSMatthew Dillon void
check_via(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)2526a03354eSMatthew Dillon check_via(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
2536a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
2546a03354eSMatthew Dillon {
2556a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NO;
2566a03354eSMatthew Dillon 	*cmd_val = iface_match((*args)->oif ?
2576a03354eSMatthew Dillon 			(*args)->oif : (*args)->m->m_pkthdr.rcvif,
2586a03354eSMatthew Dillon 			(ipfw_insn_if *)cmd);
2596a03354eSMatthew Dillon }
2606a03354eSMatthew Dillon 
2616a03354eSMatthew Dillon void
check_proto(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)2626a03354eSMatthew Dillon check_proto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
2636a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
2646a03354eSMatthew Dillon {
2656a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NO;
2666a03354eSMatthew Dillon 	*cmd_val = ((*args)->f_id.proto == cmd->arg1);
2676a03354eSMatthew Dillon }
2686a03354eSMatthew Dillon 
2696a03354eSMatthew Dillon void
check_prob(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)2706a03354eSMatthew Dillon check_prob(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
2716a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
2726a03354eSMatthew Dillon {
2736a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NO;
2746a03354eSMatthew Dillon 	*cmd_val = (krandom() % 100) < cmd->arg1;
2756a03354eSMatthew Dillon }
2766a03354eSMatthew Dillon 
2776a03354eSMatthew Dillon void
check_from(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)2786a03354eSMatthew Dillon check_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
2796a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
2806a03354eSMatthew Dillon {
2816a03354eSMatthew Dillon 	u_int hlen = 0;
2826a03354eSMatthew Dillon 	struct mbuf *m = (*args)->m;
2836a03354eSMatthew Dillon 	struct ip *ip = mtod(m, struct ip *);
284e600b76aSBill Yuan 	struct in_addr src_ip = ip->ip_src;
285e600b76aSBill Yuan 
2866a03354eSMatthew Dillon 	if ((*args)->eh == NULL ||
2876a03354eSMatthew Dillon 		(m->m_pkthdr.len >= sizeof(struct ip) &&
2886a03354eSMatthew Dillon 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
2896a03354eSMatthew Dillon 		hlen = ip->ip_hl << 2;
2906a03354eSMatthew Dillon 	}
2916a03354eSMatthew Dillon 	*cmd_val = (hlen > 0 &&
2926a03354eSMatthew Dillon 			((ipfw_insn_ip *)cmd)->addr.s_addr == src_ip.s_addr);
2936a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NO;
2946a03354eSMatthew Dillon }
2956a03354eSMatthew Dillon 
2966a03354eSMatthew Dillon void
check_from_lookup(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)2975284582fSBill Yuan check_from_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
2985284582fSBill Yuan 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
2995284582fSBill Yuan {
3004408d548SBill Yuan 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
3014408d548SBill Yuan 	struct ipfw3_table_context *table_ctx;
3025284582fSBill Yuan 	struct radix_node_head *rnh;
3035284582fSBill Yuan 	struct sockaddr_in sa;
3045284582fSBill Yuan 
3055284582fSBill Yuan 	struct mbuf *m = (*args)->m;
3065284582fSBill Yuan 	struct ip *ip = mtod(m, struct ip *);
3075284582fSBill Yuan 	struct in_addr src_ip = ip->ip_src;
3085284582fSBill Yuan 
3095284582fSBill Yuan 	*cmd_val = IP_FW_NOT_MATCH;
3105284582fSBill Yuan 
3115284582fSBill Yuan 	table_ctx = ctx->table_ctx;
3125284582fSBill Yuan 	table_ctx += cmd->arg1;
3135284582fSBill Yuan 
3145284582fSBill Yuan         if (table_ctx->type != 0) {
3155284582fSBill Yuan                 rnh = table_ctx->node;
3165284582fSBill Yuan                 sa.sin_len = 8;
3175284582fSBill Yuan                 sa.sin_addr.s_addr = src_ip.s_addr;
318*d8449084SAaron LI                 if (rnh->rnh_lookup(&sa, NULL, rnh) != NULL)
3195284582fSBill Yuan                         *cmd_val = IP_FW_MATCH;
3205284582fSBill Yuan         }
3215284582fSBill Yuan 	*cmd_ctl = IP_FW_CTL_NO;
3225284582fSBill Yuan }
3235284582fSBill Yuan 
3245284582fSBill Yuan void
check_from_me(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)32563317b93SBill Yuan check_from_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
32663317b93SBill Yuan 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
32763317b93SBill Yuan {
32863317b93SBill Yuan 	u_int hlen = 0;
32963317b93SBill Yuan 	struct mbuf *m = (*args)->m;
33063317b93SBill Yuan 	struct ip *ip = mtod(m, struct ip *);
331e600b76aSBill Yuan 	struct in_addr src_ip = ip->ip_src;
332e600b76aSBill Yuan 
33363317b93SBill Yuan 	if ((*args)->eh == NULL ||
33463317b93SBill Yuan 		(m->m_pkthdr.len >= sizeof(struct ip) &&
33563317b93SBill Yuan 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
33663317b93SBill Yuan 		hlen = ip->ip_hl << 2;
33763317b93SBill Yuan 	}
33863317b93SBill Yuan 	*cmd_ctl = IP_FW_CTL_NO;
33963317b93SBill Yuan 	if (hlen > 0) {
34063317b93SBill Yuan 		struct ifnet *tif;
34163317b93SBill Yuan 		tif = INADDR_TO_IFP(&src_ip);
34263317b93SBill Yuan 		*cmd_val = (tif != NULL);
34363317b93SBill Yuan 	} else {
34463317b93SBill Yuan 		*cmd_val = IP_FW_NOT_MATCH;
34563317b93SBill Yuan 	}
34663317b93SBill Yuan }
34763317b93SBill Yuan 
34863317b93SBill Yuan void
check_from_mask(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)34963317b93SBill Yuan check_from_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
35063317b93SBill Yuan 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
35163317b93SBill Yuan {
35263317b93SBill Yuan 	u_int hlen = 0;
35363317b93SBill Yuan 	struct mbuf *m = (*args)->m;
35463317b93SBill Yuan 	struct ip *ip = mtod(m, struct ip *);
355e600b76aSBill Yuan 	struct in_addr src_ip = ip->ip_src;
356e600b76aSBill Yuan 
35763317b93SBill Yuan 	if ((*args)->eh == NULL ||
35863317b93SBill Yuan 		(m->m_pkthdr.len >= sizeof(struct ip) &&
35963317b93SBill Yuan 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
36063317b93SBill Yuan 		hlen = ip->ip_hl << 2;
36163317b93SBill Yuan 	}
36263317b93SBill Yuan 
36363317b93SBill Yuan 	*cmd_ctl = IP_FW_CTL_NO;
36463317b93SBill Yuan 	*cmd_val = (hlen > 0 &&
36563317b93SBill Yuan 			((ipfw_insn_ip *)cmd)->addr.s_addr ==
36663317b93SBill Yuan 			(src_ip.s_addr &
36763317b93SBill Yuan 			((ipfw_insn_ip *)cmd)->mask.s_addr));
36863317b93SBill Yuan }
36963317b93SBill Yuan 
37063317b93SBill Yuan void
check_to(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)3716a03354eSMatthew Dillon check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
3726a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
3736a03354eSMatthew Dillon {
3746a03354eSMatthew Dillon 	u_int hlen = 0;
3756a03354eSMatthew Dillon 	struct mbuf *m = (*args)->m;
3766a03354eSMatthew Dillon 	struct ip *ip = mtod(m, struct ip *);
377e600b76aSBill Yuan 	struct in_addr dst_ip = ip->ip_dst;
378e600b76aSBill Yuan 
3796a03354eSMatthew Dillon 	if ((*args)->eh == NULL ||
3806a03354eSMatthew Dillon 		(m->m_pkthdr.len >= sizeof(struct ip) &&
3816a03354eSMatthew Dillon 		 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
3826a03354eSMatthew Dillon 		hlen = ip->ip_hl << 2;
3836a03354eSMatthew Dillon 	}
3846a03354eSMatthew Dillon 	*cmd_val = (hlen > 0 &&
3856a03354eSMatthew Dillon 			((ipfw_insn_ip *)cmd)->addr.s_addr == dst_ip.s_addr);
3866a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NO;
3876a03354eSMatthew Dillon }
3886a03354eSMatthew Dillon 
3896a03354eSMatthew Dillon void
check_to_lookup(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)3905284582fSBill Yuan check_to_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
3915284582fSBill Yuan 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
3925284582fSBill Yuan {
3934408d548SBill Yuan 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
3944408d548SBill Yuan 	struct ipfw3_table_context *table_ctx;
3955284582fSBill Yuan 	struct radix_node_head *rnh;
3965284582fSBill Yuan 	struct sockaddr_in sa;
3975284582fSBill Yuan 
3985284582fSBill Yuan 	struct mbuf *m = (*args)->m;
3995284582fSBill Yuan 	struct ip *ip = mtod(m, struct ip *);
4005284582fSBill Yuan 	struct in_addr dst_ip = ip->ip_dst;
4015284582fSBill Yuan 
4025284582fSBill Yuan 	*cmd_val = IP_FW_NOT_MATCH;
4035284582fSBill Yuan 
4045284582fSBill Yuan 	table_ctx = ctx->table_ctx;
4055284582fSBill Yuan 	table_ctx += cmd->arg1;
4065284582fSBill Yuan 
4075284582fSBill Yuan         if (table_ctx->type != 0) {
4085284582fSBill Yuan                 rnh = table_ctx->node;
4095284582fSBill Yuan                 sa.sin_len = 8;
4105284582fSBill Yuan                 sa.sin_addr.s_addr = dst_ip.s_addr;
411*d8449084SAaron LI                 if (rnh->rnh_lookup(&sa, NULL, rnh) != NULL)
4125284582fSBill Yuan                         *cmd_val = IP_FW_MATCH;
4135284582fSBill Yuan         }
4145284582fSBill Yuan 	*cmd_ctl = IP_FW_CTL_NO;
4155284582fSBill Yuan }
4165284582fSBill Yuan 
4175284582fSBill Yuan void
check_to_me(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)41863317b93SBill Yuan check_to_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
41963317b93SBill Yuan 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
42063317b93SBill Yuan {
42163317b93SBill Yuan 	u_int hlen = 0;
42263317b93SBill Yuan 	struct mbuf *m = (*args)->m;
42363317b93SBill Yuan 	struct ip *ip = mtod(m, struct ip *);
424e600b76aSBill Yuan 	struct in_addr dst_ip = ip->ip_dst;
425e600b76aSBill Yuan 
42663317b93SBill Yuan 	if ((*args)->eh == NULL ||
42763317b93SBill Yuan 		(m->m_pkthdr.len >= sizeof(struct ip) &&
42863317b93SBill Yuan 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
42963317b93SBill Yuan 		hlen = ip->ip_hl << 2;
43063317b93SBill Yuan 	}
43163317b93SBill Yuan 	*cmd_ctl = IP_FW_CTL_NO;
43263317b93SBill Yuan 	if (hlen > 0) {
43363317b93SBill Yuan 		struct ifnet *tif;
43463317b93SBill Yuan 		tif = INADDR_TO_IFP(&dst_ip);
43563317b93SBill Yuan 		*cmd_val = (tif != NULL);
43663317b93SBill Yuan 	} else {
43763317b93SBill Yuan 		*cmd_val = IP_FW_NOT_MATCH;
43863317b93SBill Yuan 	}
43963317b93SBill Yuan }
44063317b93SBill Yuan 
44163317b93SBill Yuan void
check_to_mask(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)44263317b93SBill Yuan check_to_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
44363317b93SBill Yuan 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
44463317b93SBill Yuan {
44563317b93SBill Yuan 	u_int hlen = 0;
44663317b93SBill Yuan 	struct mbuf *m = (*args)->m;
44763317b93SBill Yuan 	struct ip *ip = mtod(m, struct ip *);
448e600b76aSBill Yuan 	struct in_addr dst_ip = ip->ip_dst;
449e600b76aSBill Yuan 
45063317b93SBill Yuan 	if ((*args)->eh == NULL ||
45163317b93SBill Yuan 		(m->m_pkthdr.len >= sizeof(struct ip) &&
45263317b93SBill Yuan 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
45363317b93SBill Yuan 		hlen = ip->ip_hl << 2;
45463317b93SBill Yuan 	}
45563317b93SBill Yuan 
45663317b93SBill Yuan 	*cmd_ctl = IP_FW_CTL_NO;
45763317b93SBill Yuan 	*cmd_val = (hlen > 0 &&
45863317b93SBill Yuan 			((ipfw_insn_ip *)cmd)->addr.s_addr ==
45963317b93SBill Yuan 			(dst_ip.s_addr &
46063317b93SBill Yuan 			((ipfw_insn_ip *)cmd)->mask.s_addr));
46163317b93SBill Yuan }
46263317b93SBill Yuan 
46363317b93SBill Yuan void
check_tag(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)4646a03354eSMatthew Dillon check_tag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
4656a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
4666a03354eSMatthew Dillon {
4676a03354eSMatthew Dillon 	struct m_tag *mtag = m_tag_locate((*args)->m,
4686a03354eSMatthew Dillon 			MTAG_IPFW, cmd->arg1, NULL);
4696a03354eSMatthew Dillon 	if (mtag == NULL) {
4706a03354eSMatthew Dillon 		mtag = m_tag_alloc(MTAG_IPFW,cmd->arg1, 0, M_NOWAIT);
4716a03354eSMatthew Dillon 		if (mtag != NULL)
4726a03354eSMatthew Dillon 			m_tag_prepend((*args)->m, mtag);
4736a03354eSMatthew Dillon 
4746a03354eSMatthew Dillon 	}
4756a03354eSMatthew Dillon 	(*f)->pcnt++;
4766a03354eSMatthew Dillon 	(*f)->bcnt += ip_len;
4776a03354eSMatthew Dillon 	(*f)->timestamp = time_second;
4786a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NEXT;
4796a03354eSMatthew Dillon }
4806a03354eSMatthew Dillon 
4816a03354eSMatthew Dillon void
check_untag(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)4826a03354eSMatthew Dillon check_untag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
4836a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
4846a03354eSMatthew Dillon {
4856a03354eSMatthew Dillon 	struct m_tag *mtag = m_tag_locate((*args)->m,
4866a03354eSMatthew Dillon 			MTAG_IPFW, cmd->arg1, NULL);
4876a03354eSMatthew Dillon 	if (mtag != NULL)
4886a03354eSMatthew Dillon 		m_tag_delete((*args)->m, mtag);
4896a03354eSMatthew Dillon 
4906a03354eSMatthew Dillon 	(*f)->pcnt++;
4916a03354eSMatthew Dillon 	(*f)->bcnt += ip_len;
4926a03354eSMatthew Dillon 	(*f)->timestamp = time_second;
4936a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NEXT;
4946a03354eSMatthew Dillon }
4956a03354eSMatthew Dillon 
4966a03354eSMatthew Dillon void
check_tagged(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)4976a03354eSMatthew Dillon check_tagged(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
4986a03354eSMatthew Dillon 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
4996a03354eSMatthew Dillon {
5006a03354eSMatthew Dillon 	*cmd_ctl = IP_FW_CTL_NO;
5016a03354eSMatthew Dillon 	if (m_tag_locate( (*args)->m, MTAG_IPFW,cmd->arg1, NULL) != NULL )
5026a03354eSMatthew Dillon 		*cmd_val = IP_FW_MATCH;
5036a03354eSMatthew Dillon 	else
5046a03354eSMatthew Dillon 		*cmd_val = IP_FW_NOT_MATCH;
5056a03354eSMatthew Dillon }
5066a03354eSMatthew Dillon 
507c1bde762SBill Yuan void
check_src_port(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)508c1bde762SBill Yuan check_src_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
509c1bde762SBill Yuan         struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
510c1bde762SBill Yuan {
511c1bde762SBill Yuan         *cmd_ctl = IP_FW_CTL_NO;
512c1bde762SBill Yuan         if ((*args)->f_id.src_port == cmd->arg1)
513c1bde762SBill Yuan                 *cmd_val = IP_FW_MATCH;
514c1bde762SBill Yuan         else
515c1bde762SBill Yuan                 *cmd_val = IP_FW_NOT_MATCH;
516c1bde762SBill Yuan }
517c1bde762SBill Yuan 
518c1bde762SBill Yuan void
check_dst_port(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)519c1bde762SBill Yuan check_dst_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
520c1bde762SBill Yuan         struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
521c1bde762SBill Yuan {
522c1bde762SBill Yuan         *cmd_ctl = IP_FW_CTL_NO;
523c1bde762SBill Yuan         if ((*args)->f_id.dst_port == cmd->arg1)
524c1bde762SBill Yuan                 *cmd_val = IP_FW_MATCH;
525c1bde762SBill Yuan         else
526c1bde762SBill Yuan                 *cmd_val = IP_FW_NOT_MATCH;
527c1bde762SBill Yuan }
528c1bde762SBill Yuan 
529c1bde762SBill Yuan void
check_src_n_port(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)530c1bde762SBill Yuan check_src_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
531c1bde762SBill Yuan 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
532c1bde762SBill Yuan {
533c1bde762SBill Yuan 	struct in_addr src_ip;
534c1bde762SBill Yuan 	u_int hlen = 0;
535c1bde762SBill Yuan 	struct mbuf *m = (*args)->m;
536c1bde762SBill Yuan 	struct ip *ip = mtod(m, struct ip *);
537c1bde762SBill Yuan 	src_ip = ip->ip_src;
538c1bde762SBill Yuan 	if ((*args)->eh == NULL ||
539c1bde762SBill Yuan 		(m->m_pkthdr.len >= sizeof(struct ip) &&
540c1bde762SBill Yuan 		ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
541c1bde762SBill Yuan 		hlen = ip->ip_hl << 2;
542c1bde762SBill Yuan 	}
543c1bde762SBill Yuan 	*cmd_val = (hlen > 0 && ((ipfw_insn_ip *)cmd)->addr.s_addr == src_ip.s_addr);
544c1bde762SBill Yuan 	*cmd_ctl = IP_FW_CTL_NO;
545c1bde762SBill Yuan 	if (*cmd_val && (*args)->f_id.src_port == cmd->arg1)
546c1bde762SBill Yuan 		*cmd_val = IP_FW_MATCH;
547c1bde762SBill Yuan 	else
548c1bde762SBill Yuan 		*cmd_val = IP_FW_NOT_MATCH;
549c1bde762SBill Yuan }
550c1bde762SBill Yuan 
551c1bde762SBill Yuan void
check_dst_n_port(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)552c1bde762SBill Yuan check_dst_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
553c1bde762SBill Yuan 	struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
554c1bde762SBill Yuan {
555c1bde762SBill Yuan 	struct in_addr dst_ip;
556c1bde762SBill Yuan 	u_int hlen = 0;
557c1bde762SBill Yuan 	struct mbuf *m = (*args)->m;
558c1bde762SBill Yuan 	struct ip *ip = mtod(m, struct ip *);
559c1bde762SBill Yuan 	dst_ip = ip->ip_dst;
560c1bde762SBill Yuan 	if ((*args)->eh == NULL ||
561c1bde762SBill Yuan 		(m->m_pkthdr.len >= sizeof(struct ip) &&
562c1bde762SBill Yuan 		 ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
563c1bde762SBill Yuan 		hlen = ip->ip_hl << 2;
564c1bde762SBill Yuan 	}
565c1bde762SBill Yuan 	*cmd_val = (hlen > 0 && ((ipfw_insn_ip *)cmd)->addr.s_addr == dst_ip.s_addr);
566c1bde762SBill Yuan 	*cmd_ctl = IP_FW_CTL_NO;
567c1bde762SBill Yuan 	if (*cmd_val && (*args)->f_id.dst_port == cmd->arg1)
568c1bde762SBill Yuan 		*cmd_val = IP_FW_MATCH;
569c1bde762SBill Yuan 	else
570c1bde762SBill Yuan 		*cmd_val = IP_FW_NOT_MATCH;
571c1bde762SBill Yuan }
572c1bde762SBill Yuan 
5734408d548SBill Yuan int
ip_fw3_basic_init(void)5744408d548SBill Yuan ip_fw3_basic_init(void)
5756a03354eSMatthew Dillon {
5764408d548SBill Yuan 	ip_fw3_register_module(MODULE_BASIC_ID, MODULE_BASIC_NAME);
5774408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_COUNT,
5786a03354eSMatthew Dillon 			(filter_func)check_count);
5794408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_SKIPTO,
5806a03354eSMatthew Dillon 			(filter_func)check_skipto);
5814408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_FORWARD,
5826a03354eSMatthew Dillon 			(filter_func)check_forward);
5834408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_KEEP_STATE,
5846a03354eSMatthew Dillon 			(filter_func)check_keep_state);
5854408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_CHECK_STATE,
5866a03354eSMatthew Dillon 			(filter_func)check_check_state);
5876a03354eSMatthew Dillon 
5884408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
5896a03354eSMatthew Dillon 			O_BASIC_IN, (filter_func)check_in);
5904408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
5916a03354eSMatthew Dillon 			O_BASIC_OUT, (filter_func)check_out);
5924408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
5936a03354eSMatthew Dillon 			O_BASIC_VIA, (filter_func)check_via);
5944408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
5956a03354eSMatthew Dillon 			O_BASIC_XMIT, (filter_func)check_via);
5964408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
5976a03354eSMatthew Dillon 			O_BASIC_RECV, (filter_func)check_via);
5986a03354eSMatthew Dillon 
5994408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
6006a03354eSMatthew Dillon 			O_BASIC_PROTO, (filter_func)check_proto);
6014408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
6026a03354eSMatthew Dillon 			O_BASIC_PROB, (filter_func)check_prob);
6034408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
6046a03354eSMatthew Dillon 			O_BASIC_IP_SRC, (filter_func)check_from);
6054408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
6065284582fSBill Yuan 			O_BASIC_IP_SRC_LOOKUP, (filter_func)check_from_lookup);
6074408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
60863317b93SBill Yuan 			O_BASIC_IP_SRC_ME, (filter_func)check_from_me);
6094408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
61063317b93SBill Yuan 			O_BASIC_IP_SRC_MASK, (filter_func)check_from_mask);
6114408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
6126a03354eSMatthew Dillon 			O_BASIC_IP_DST, (filter_func)check_to);
6134408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
6145284582fSBill Yuan 			O_BASIC_IP_DST_LOOKUP, (filter_func)check_to_lookup);
6154408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
61663317b93SBill Yuan 			O_BASIC_IP_DST_ME, (filter_func)check_to_me);
6174408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
61863317b93SBill Yuan 			O_BASIC_IP_DST_MASK, (filter_func)check_to_mask);
6194408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
6206a03354eSMatthew Dillon 			O_BASIC_TAG, (filter_func)check_tag);
6214408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
6226a03354eSMatthew Dillon 			O_BASIC_UNTAG, (filter_func)check_untag);
6234408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
6246a03354eSMatthew Dillon 			O_BASIC_TAGGED, (filter_func)check_tagged);
6254408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
626c1bde762SBill Yuan 			O_BASIC_IP_SRCPORT, (filter_func)check_src_port);
6274408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
628c1bde762SBill Yuan 			O_BASIC_IP_DSTPORT, (filter_func)check_dst_port);
6294408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
630c1bde762SBill Yuan 			O_BASIC_IP_SRC_N_PORT, (filter_func)check_src_n_port);
6314408d548SBill Yuan 	ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
632c1bde762SBill Yuan 			O_BASIC_IP_DST_N_PORT, (filter_func)check_dst_n_port);
6336a03354eSMatthew Dillon 
6346a03354eSMatthew Dillon 	return 0;
6356a03354eSMatthew Dillon }
6366a03354eSMatthew Dillon 
6374408d548SBill Yuan int
ip_fw3_basic_fini(void)6384408d548SBill Yuan ip_fw3_basic_fini(void)
6396a03354eSMatthew Dillon {
6404408d548SBill Yuan 	return ip_fw3_unregister_module(MODULE_BASIC_ID);
6416a03354eSMatthew Dillon }
6426a03354eSMatthew Dillon 
6436a03354eSMatthew Dillon static int
ipfw3_basic_modevent(module_t mod,int type,void * data)6446a03354eSMatthew Dillon ipfw3_basic_modevent(module_t mod, int type, void *data)
6456a03354eSMatthew Dillon {
6466a03354eSMatthew Dillon 	int err;
6476a03354eSMatthew Dillon 	switch (type) {
6486a03354eSMatthew Dillon 		case MOD_LOAD:
6494408d548SBill Yuan 			err = ip_fw3_basic_init();
6506a03354eSMatthew Dillon 			break;
6516a03354eSMatthew Dillon 		case MOD_UNLOAD:
6524408d548SBill Yuan 			err = ip_fw3_basic_fini();
6536a03354eSMatthew Dillon 			break;
6546a03354eSMatthew Dillon 		default:
6556a03354eSMatthew Dillon 			err = 1;
6566a03354eSMatthew Dillon 	}
6574408d548SBill Yuan 	ip_fw3_state_modevent(type);
658de23f38fSBill Yuan 	ip_fw3_table_modevent(type);
6596a03354eSMatthew Dillon 	return err;
6606a03354eSMatthew Dillon }
6616a03354eSMatthew Dillon 
6626a03354eSMatthew Dillon static moduledata_t ipfw3_basic_mod = {
6636a03354eSMatthew Dillon 	"ipfw3_basic",
6646a03354eSMatthew Dillon 	ipfw3_basic_modevent,
6656a03354eSMatthew Dillon 	NULL
6666a03354eSMatthew Dillon };
6676a03354eSMatthew Dillon DECLARE_MODULE(ipfw3_basic, ipfw3_basic_mod, SI_SUB_PROTO_END, SI_ORDER_ANY);
6686a03354eSMatthew Dillon MODULE_DEPEND(ipfw3_basic, ipfw3, 1, 1, 1);
6696a03354eSMatthew Dillon MODULE_VERSION(ipfw3_basic, 1);
670