diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 7c561476c8cc..ac08c28c3c9a 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -8,7 +8,7 @@ _randomdev=	randomdev
 
 SUBDIR=	3dfx accf_data accf_http agp aha amr an aue \
 	cam ccd cd9660 coda cue dc fdesc fxp if_disc if_ef \
-	if_ppp if_sl if_tap if_tun ipfilter ipfw ispfw joy kernfs kue \
+	if_ppp if_sl if_tap if_tun ip6fw ipfilter ipfw ispfw joy kernfs kue \
 	md mfs mii mlx msdos ncp netgraph nfs ntfs nullfs \
 	nwfs pcn portal procfs ${_randomdev} \
 	rl rp sf sis sk sn sound ste syscons ti tl twe tx \
diff --git a/sys/modules/ip6fw/Makefile b/sys/modules/ip6fw/Makefile
new file mode 100644
index 000000000000..64fa17ea7f9d
--- /dev/null
+++ b/sys/modules/ip6fw/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+.PATH:	${.CURDIR}/../../netinet6
+KMOD=	ip6fw
+SRCS=	ip6_fw.c
+NOMAN=
+CFLAGS+= -DIPV6FIREWALL
+#
+#If you want it verbose
+#CFLAGS+= -DIPV6FIREWALL_VERBOSE
+#CFLAGS+= -DIPV6FIREWALL_VERBOSE_LIMIT=100
+#
+#If you want it to pass all packets by default
+#CFLAGS+= -DIPV6FIREWALL_DEFAULT_TO_ACCEPT
+#
+
+.include <bsd.kmod.mk>
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index caa38eff1ef5..2664ccbf746d 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -62,9 +62,7 @@
 #include <netkey/key.h>
 #endif /* IPSEC */
 
-#ifdef IPV6FIREWALL
 #include <netinet6/ip6_fw.h>
-#endif
 
 #include <net/net_osdep.h>
 
@@ -415,11 +413,10 @@ ip6_forward(m, srcrt)
 	    (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0)
 		type = ND_REDIRECT;
 
-#ifdef IPV6FIREWALL
 	/*
 	 * Check with the firewall...
 	 */
-	if (ip6_fw_chk_ptr) {
+	if (ip6_fw_enable && ip6_fw_chk_ptr) {
 		u_short port = 0;
 		/* If ipfw says divert, we have to just drop packet */
 		if ((*ip6_fw_chk_ptr)(&ip6, rt->rt_ifp, &port, &m)) {
@@ -429,7 +426,6 @@ ip6_forward(m, srcrt)
 		if (!m)
 			goto freecopy;
 	}
-#endif
 
 	/*
 	 * Fake scoped addresses. Note that even link-local source or
diff --git a/sys/netinet6/ip6_fw.c b/sys/netinet6/ip6_fw.c
index 53c0cc7e475e..f0f710f573f0 100644
--- a/sys/netinet6/ip6_fw.c
+++ b/sys/netinet6/ip6_fw.c
@@ -20,9 +20,11 @@
  * Implement IPv6 packet firewall
  */
 
+#if !defined(KLD_MODULE)
 #include "opt_ip6fw.h"
 #include "opt_inet.h"
 #include "opt_inet6.h"
+#endif
 
 #ifdef IP6DIVERT
 #error "NOT SUPPORTED IPV6 DIVERT"
@@ -84,6 +86,8 @@ LIST_HEAD (ip6_fw_head, ip6_fw_chain) ip6_fw_chain;
 #ifdef SYSCTL_NODE
 SYSCTL_DECL(_net_inet6_ip6);
 SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
+SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, enable, CTLFLAG_RW,
+    &ip6_fw_enable, 0, "Enable ip6fw");
 SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, debug, CTLFLAG_RW, &fw6_debug, 0, "");
 SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, verbose, CTLFLAG_RW, &fw6_verbose, 0, "");
 SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, &fw6_verbose_limit, 0, "");
@@ -1184,3 +1188,48 @@ ip6_fw_init(void)
 		    fw6_verbose_limit);
 #endif
 }
+
+static ip6_fw_chk_t *old_chk_ptr;
+static ip6_fw_ctl_t *old_ctl_ptr;
+
+static int
+ip6fw_modevent(module_t mod, int type, void *unused)
+{
+	int s;
+	
+	switch (type) {
+	case MOD_LOAD:
+		s = splnet();
+
+		old_chk_ptr = ip6_fw_chk_ptr;
+		old_ctl_ptr = ip6_fw_ctl_ptr;
+
+		ip6_fw_init();
+		splx(s);
+		return 0;
+	case MOD_UNLOAD:
+		s = splnet();
+		ip6_fw_chk_ptr =  old_chk_ptr;
+		ip6_fw_ctl_ptr =  old_ctl_ptr;
+		while (LIST_FIRST(&ip6_fw_chain) != NULL) {
+			struct ip6_fw_chain *fcp = LIST_FIRST(&ip6_fw_chain);
+			LIST_REMOVE(LIST_FIRST(&ip6_fw_chain), chain);
+			free(fcp->rule, M_IP6FW);
+			free(fcp, M_IP6FW);
+		}
+	
+		splx(s);
+		printf("IPv6 firewall unloaded\n");
+		return 0;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static moduledata_t ip6fwmod = {
+	"ip6fw",
+	ip6fw_modevent,
+	0
+};
+DECLARE_MODULE(ip6fw, ip6fwmod, SI_SUB_PSEUDO, SI_ORDER_ANY);
diff --git a/sys/netinet6/ip6_fw.h b/sys/netinet6/ip6_fw.h
index 6b4c9221518f..36665641b42d 100644
--- a/sys/netinet6/ip6_fw.h
+++ b/sys/netinet6/ip6_fw.h
@@ -190,6 +190,7 @@ typedef	int ip6_fw_chk_t __P((struct ip6_hdr**, struct ifnet*,
 typedef	int ip6_fw_ctl_t __P((int, struct mbuf**));
 extern	ip6_fw_chk_t *ip6_fw_chk_ptr;
 extern	ip6_fw_ctl_t *ip6_fw_ctl_ptr;
+extern	int ip6_fw_enable;
 
 #endif /* _KERNEL */
 
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 6bcaa057372b..46f0b9ce8c78 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -109,9 +109,7 @@
 #include <netinet6/nd6.h>
 #include <netinet6/in6_prefix.h>
 
-#ifdef IPV6FIREWALL
 #include <netinet6/ip6_fw.h>
-#endif
 
 #include <netinet6/ip6protosw.h>
 
@@ -134,11 +132,10 @@ int ip6_sourcecheck;			/* XXX */
 int ip6_sourcecheck_interval;		/* XXX */
 const int int6intrq_present = 1;
 
-#ifdef IPV6FIREWALL
 /* firewall hooks */
 ip6_fw_chk_t *ip6_fw_chk_ptr;
 ip6_fw_ctl_t *ip6_fw_ctl_ptr;
-#endif
+int ip6_fw_enable = 1;
 
 struct ip6stat ip6stat;
 
@@ -174,9 +171,6 @@ ip6_init()
 	register_netisr(NETISR_IPV6, ip6intr);
 	nd6_init();
 	frag6_init();
-#ifdef IPV6FIREWALL
-	ip6_fw_init();
-#endif
 	/*
 	 * in many cases, random() here does NOT return random number
 	 * as initialization during bootstrap time occur in fixed order.
@@ -325,11 +319,10 @@ ip6_input(m)
 
 	ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
 
-#ifdef IPV6FIREWALL
 	/*
 	 * Check with the firewall...
 	 */
-	if (ip6_fw_chk_ptr) {
+	if (ip6_fw_enable && ip6_fw_chk_ptr) {
 		u_short port = 0;
 		/* If ipfw says divert, we have to just drop packet */
 		/* use port as a dummy argument */
@@ -340,7 +333,6 @@ ip6_input(m)
 		if (!m)
 			return;
 	}
-#endif
 
 	/*
 	 * Scope check
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 64d1bb536d84..c17070ce711a 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -106,9 +106,7 @@
 
 #include <net/net_osdep.h>
 
-#ifdef IPV6FIREWALL
 #include <netinet6/ip6_fw.h>
-#endif
 
 #include <netinet6/ip6protosw.h>
 
@@ -803,11 +801,10 @@ skip_ipsec2:;
 			ip6->ip6_dst.s6_addr16[1] = 0;
 	}
 
-#ifdef IPV6FIREWALL
 	/*
 	 * Check with the firewall...
 	 */
-	if (ip6_fw_chk_ptr) {
+	if (ip6_fw_enable && ip6_fw_chk_ptr) {
 		u_short port = 0;
 		m->m_pkthdr.rcvif = NULL;	/*XXX*/
 		/* If ipfw says divert, we have to just drop packet */
@@ -820,7 +817,6 @@ skip_ipsec2:;
 			goto done;
 		}
 	}
-#endif
 
 	/*
 	 * If the outgoing packet contains a hop-by-hop options header,
@@ -1388,7 +1384,6 @@ ip6_ctloutput(so, sopt)
 				break;
 #endif /* IPSEC */
 
-#ifdef IPV6FIREWALL
 			case IPV6_FW_ADD:
 			case IPV6_FW_DEL:
 			case IPV6_FW_FLUSH:
@@ -1409,7 +1404,6 @@ ip6_ctloutput(so, sopt)
 				m = *mp;
 			    }
 				break;
-#endif
 
 			default:
 				error = ENOPROTOOPT;
@@ -1543,7 +1537,6 @@ ip6_ctloutput(so, sopt)
 			  }
 #endif /* IPSEC */
 
-#ifdef IPV6FIREWALL
 			case IPV6_FW_GET:
 			  {
 				struct mbuf *m;
@@ -1560,7 +1553,6 @@ ip6_ctloutput(so, sopt)
 					m_freem(m);
 			  }
 				break;
-#endif
 
 			default:
 				error = ENOPROTOOPT;