diff options
-rw-r--r-- | sys/netinet/ip_fw.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_fw2.c | 21 | ||||
-rw-r--r-- | sys/netinet/ip_fw_pfil.c | 146 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 1 |
4 files changed, 108 insertions, 63 deletions
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 05d8b7d..0893e46 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -537,6 +537,9 @@ typedef int ip_fw_ctl_t(struct sockopt *); extern ip_fw_ctl_t *ip_fw_ctl_ptr; extern int fw_one_pass; extern int fw_enable; +#ifdef INET6 +extern int fw6_enable; +#endif /* For kernel ipfw_ether and ipfw_bridge. */ typedef int ip_fw_chk_t(struct ip_fw_args *args); diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 49be308..dacaa57 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -165,11 +165,13 @@ struct table_entry { static int fw_debug = 1; static int autoinc_step = 100; /* bounded to 1..1000 in add_rule() */ +extern int ipfw_chg_hook(SYSCTL_HANDLER_ARGS); + #ifdef SYSCTL_NODE SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, enable, - CTLFLAG_RW | CTLFLAG_SECURE3, - &fw_enable, 0, "Enable ipfw"); +SYSCTL_PROC(_net_inet_ip_fw, OID_AUTO, enable, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &fw_enable, 0, + ipfw_chg_hook, "I", "Enable ipfw"); SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step, CTLFLAG_RW, &autoinc_step, 0, "Rule number autincrement step"); SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, one_pass, @@ -4112,12 +4114,15 @@ ipfw_init(void) /* Setup IPv6 fw sysctl tree. */ sysctl_ctx_init(&ip6_fw_sysctl_ctx); ip6_fw_sysctl_tree = SYSCTL_ADD_NODE(&ip6_fw_sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_net_inet6_ip6), OID_AUTO, "fw", - CTLFLAG_RW | CTLFLAG_SECURE, 0, "Firewall"); + SYSCTL_STATIC_CHILDREN(_net_inet6_ip6), OID_AUTO, "fw", + CTLFLAG_RW | CTLFLAG_SECURE, 0, "Firewall"); + SYSCTL_ADD_PROC(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree), + OID_AUTO, "enable", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, + &fw6_enable, 0, ipfw_chg_hook, "I", "Enable ipfw+6"); SYSCTL_ADD_INT(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree), - OID_AUTO, "deny_unknown_exthdrs", CTLFLAG_RW | CTLFLAG_SECURE, - &fw_deny_unknown_exthdrs, 0, - "Deny packets with unknown IPv6 Extension Headers"); + OID_AUTO, "deny_unknown_exthdrs", CTLFLAG_RW | CTLFLAG_SECURE, + &fw_deny_unknown_exthdrs, 0, + "Deny packets with unknown IPv6 Extension Headers"); #endif layer3_chain.rules = NULL; diff --git a/sys/netinet/ip_fw_pfil.c b/sys/netinet/ip_fw_pfil.c index 65fbf82..a58f96f 100644 --- a/sys/netinet/ip_fw_pfil.c +++ b/sys/netinet/ip_fw_pfil.c @@ -64,7 +64,12 @@ #include <machine/in_cksum.h> -static int ipfw_pfil_hooked = 0; +int fw_enable = 1; +#ifdef INET6 +int fw6_enable = 1; +#endif + +int ipfw_chg_hook(SYSCTL_HANDLER_ARGS); /* Dummynet hooks. */ ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL; @@ -96,9 +101,6 @@ ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, KASSERT(dir == PFIL_IN, ("ipfw_check_in wrong direction!")); - if (!fw_enable) - goto pass; - bzero(&args, sizeof(args)); dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); @@ -217,9 +219,6 @@ ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, KASSERT(dir == PFIL_OUT, ("ipfw_check_out wrong direction!")); - if (!fw_enable) - goto pass; - bzero(&args, sizeof(args)); dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); @@ -417,28 +416,13 @@ static int ipfw_hook(void) { struct pfil_head *pfh_inet; -#ifdef INET6 - struct pfil_head *pfh_inet6; -#endif - - if (ipfw_pfil_hooked) - return EEXIST; pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); if (pfh_inet == NULL) return ENOENT; -#ifdef INET6 - pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); - if (pfh_inet6 == NULL) - return ENOENT; -#endif pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet); pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet); -#ifdef INET6 - pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6); - pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6); -#endif return 0; } @@ -447,31 +431,86 @@ static int ipfw_unhook(void) { struct pfil_head *pfh_inet; -#ifdef INET6 - struct pfil_head *pfh_inet6; -#endif - - if (!ipfw_pfil_hooked) - return ENOENT; pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); if (pfh_inet == NULL) return ENOENT; + + pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet); + pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet); + + return 0; +} + #ifdef INET6 +static int +ipfw6_hook(void) +{ + struct pfil_head *pfh_inet6; + + pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); + if (pfh_inet6 == NULL) + return ENOENT; + + pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6); + pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6); + + return 0; +} + +static int +ipfw6_unhook(void) +{ + struct pfil_head *pfh_inet6; + pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); if (pfh_inet6 == NULL) return ENOENT; -#endif - pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet); - pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet); -#ifdef INET6 pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6); pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6); -#endif return 0; } +#endif /* INET6 */ + +int +ipfw_chg_hook(SYSCTL_HANDLER_ARGS) +{ + int enable = *(int *)arg1; + int error; + + error = sysctl_handle_int(oidp, &enable, 0, req); + if (error) + return (error); + + enable = (enable) ? 1 : 0; + + if (enable == *(int *)arg1) + return (0); + + if (arg1 == &fw_enable) { + if (enable) + error = ipfw_hook(); + else + error = ipfw_unhook(); + } +#ifdef INET6 + if (arg1 == &fw6_enable) { + if (enable) + error = ipfw6_hook(); + else + error = ipfw6_unhook(); + } +#endif + + if (error) + return (error); + + *(int *)arg1 = enable; + + return (0); +} static int ipfw_modevent(module_t mod, int type, void *unused) @@ -480,31 +519,30 @@ ipfw_modevent(module_t mod, int type, void *unused) switch (type) { case MOD_LOAD: - if (ipfw_pfil_hooked) { - printf("IP firewall already loaded\n"); - err = EEXIST; - } else { - if ((err = ipfw_init()) != 0) { - printf("ipfw_init() error\n"); - break; - } - if ((err = ipfw_hook()) != 0) { - printf("ipfw_hook() error\n"); - break; - } - ipfw_pfil_hooked = 1; + if ((err = ipfw_init()) != 0) { + printf("ipfw_init() error\n"); + break; + } + if ((err = ipfw_hook()) != 0) { + printf("ipfw_hook() error\n"); + break; } +#ifdef INET6 + if ((err = ipfw6_hook()) != 0) { + printf("ipfw_hook() error\n"); + break; + } +#endif break; case MOD_UNLOAD: - if (ipfw_pfil_hooked) { - if ((err = ipfw_unhook()) > 0) - break; - ipfw_destroy(); - ipfw_pfil_hooked = 0; - } else { - printf("IP firewall already unloaded\n"); - } + if ((err = ipfw_unhook()) > 0) + break; +#ifdef INET6 + if ((err = ipfw6_unhook()) > 0) + break; +#endif + ipfw_destroy(); break; default: diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index f3e477f..a860074 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -198,7 +198,6 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, stealth, CTLFLAG_RW, */ ip_fw_chk_t *ip_fw_chk_ptr = NULL; ip_dn_io_t *ip_dn_io_ptr = NULL; -int fw_enable = 1; int fw_one_pass = 1; static void ip_freef(struct ipqhead *, struct ipq *); |