Work on the radix code, added support to compile on OpenWRT,
[ipfw.git] / dummynet / ip_fw_pfil.c
index bc1f011..368192a 100644 (file)
@@ -49,6 +49,9 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_fw_pfil.c,v 1.25.2.2 2008/04/25 10:26:30
 
 #include <net/if.h>
 #include <net/pfil.h>
+#include <net/vnet.h>
+
+#include "missing.h"
 
 #include <netinet/in.h>
 #include <netinet/ip.h>
@@ -61,11 +64,9 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_fw_pfil.c,v 1.25.2.2 2008/04/25 10:26:30
 
 #include <machine/in_cksum.h>
 
-#include "missing.h"
-
-int fw_enable = 1;
+VNET_DEFINE(int, fw_enable) = 1;
 #ifdef INET6
-int fw6_enable = 1;
+VNET_DEFINE(int, fw6_enable) = 1;
 #endif
 
 int ipfw_chg_hook(SYSCTL_HANDLER_ARGS);
@@ -105,6 +106,8 @@ ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
                KASSERT(ng_tag->dir == NG_IPFW_IN,
                    ("ng_ipfw tag with wrong direction"));
                args.rule = ng_tag->rule;
+               args.rule_id = ng_tag->rule_id;
+               args.chain_id = ng_tag->chain_id;
                m_tag_delete(*m0, (struct m_tag *)ng_tag);
        }
 
@@ -115,16 +118,22 @@ again:
 
                dt = (struct dn_pkt_tag *)(dn_tag+1);
                args.rule = dt->rule;
+               args.rule_id = dt->rule_id;
+               args.chain_id = dt->chain_id;
 
                m_tag_delete(*m0, dn_tag);
        }
 
        args.m = *m0;
        args.inp = inp;
-       ipfw = ipfw_chk(&args);
-       *m0 = args.m;   /* args.m can be modified by ipfw_chk */
        tee = 0;
 
+       if (V_fw_one_pass == 0 || args.rule == NULL) {
+               ipfw = ipfw_chk(&args);
+               *m0 = args.m;
+       } else
+               ipfw = IP_FW_PASS;
+
        KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
            __func__));
 
@@ -151,7 +160,6 @@ again:
                goto drop;
                break;                  /* not reached */
 
-       /* here packets come after the ipfw classification */
        case IP_FW_DUMMYNET:
                if (ip_dn_io_ptr == NULL)
                        goto drop;
@@ -231,6 +239,8 @@ ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
                KASSERT(ng_tag->dir == NG_IPFW_OUT,
                    ("ng_ipfw tag with wrong direction"));
                args.rule = ng_tag->rule;
+               args.rule_id = ng_tag->rule_id;
+               args.chain_id = ng_tag->chain_id;
                m_tag_delete(*m0, (struct m_tag *)ng_tag);
        }
 
@@ -241,6 +251,8 @@ again:
 
                dt = (struct dn_pkt_tag *)(dn_tag+1);
                args.rule = dt->rule;
+               args.rule_id = dt->rule_id;
+               args.chain_id = dt->chain_id;
 
                m_tag_delete(*m0, dn_tag);
        }
@@ -248,10 +260,14 @@ again:
        args.m = *m0;
        args.oif = ifp;
        args.inp = inp;
-       ipfw = ipfw_chk(&args);
-       *m0 = args.m;   /* args.m can be modified by ipfw_chk */
        tee = 0;
 
+       if (V_fw_one_pass == 0 || args.rule == NULL) {
+               ipfw = ipfw_chk(&args);
+               *m0 = args.m;
+       } else
+               ipfw = IP_FW_PASS;
+
        KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
            __func__));
 
@@ -423,7 +439,7 @@ nodivert:
        return 1;
 }
 
-static int
+int
 ipfw_hook(void)
 {
        struct pfil_head *pfh_inet;
@@ -432,13 +448,15 @@ ipfw_hook(void)
        if (pfh_inet == NULL)
                return ENOENT;
 
-       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);
+       (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+               pfh_inet);
+       (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+               pfh_inet);
 
        return 0;
 }
 
-static int
+int
 ipfw_unhook(void)
 {
        struct pfil_head *pfh_inet;
@@ -447,14 +465,16 @@ ipfw_unhook(void)
        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);
+       (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+               pfh_inet);
+       (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+               pfh_inet);
 
        return 0;
 }
 
 #ifdef INET6
-static int
+int
 ipfw6_hook(void)
 {
        struct pfil_head *pfh_inet6;
@@ -463,13 +483,15 @@ ipfw6_hook(void)
        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);
+       (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+               pfh_inet6);
+       (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+               pfh_inet6);
 
        return 0;
 }
 
-static int
+int
 ipfw6_unhook(void)
 {
        struct pfil_head *pfh_inet6;
@@ -478,8 +500,10 @@ ipfw6_unhook(void)
        if (pfh_inet6 == NULL)
                return ENOENT;
 
-       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);
+       (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+               pfh_inet6);
+       (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+               pfh_inet6);
 
        return 0;
 }
@@ -488,38 +512,54 @@ ipfw6_unhook(void)
 int
 ipfw_chg_hook(SYSCTL_HANDLER_ARGS)
 {
-       int enable = *(int *)arg1;
+       int enable;
+       int oldenable;
        int error;
 
+       if (arg1 == &VNET_NAME(fw_enable)) {
+               enable = V_fw_enable;
+       }
+#ifdef INET6
+       else if (arg1 == &VNET_NAME(fw6_enable)) {
+               enable = V_fw6_enable;
+       }
+#endif
+       else
+               return (EINVAL);
+
+       oldenable = enable;
+
        error = sysctl_handle_int(oidp, &enable, 0, req);
+
        if (error)
                return (error);
 
        enable = (enable) ? 1 : 0;
 
-       if (enable == *(int *)arg1)
+       if (enable == oldenable)
                return (0);
 
-       if (arg1 == &fw_enable) {
+       if (arg1 == &VNET_NAME(fw_enable)) {
                if (enable)
                        error = ipfw_hook();
                else
                        error = ipfw_unhook();
+               if (error)
+                       return (error);
+               V_fw_enable = enable;
        }
 #ifdef INET6
-       if (arg1 == &fw6_enable) {
+       else if (arg1 == &VNET_NAME(fw6_enable)) {
                if (enable)
                        error = ipfw6_hook();
                else
                        error = ipfw6_unhook();
+               if (error)
+                       return (error);
+               V_fw6_enable = enable;
        }
 #endif
 
-       if (error)
-               return (error);
-
-       *(int *)arg1 = enable;
-
        return (0);
 }