Move ipfw(4) code for ip_{input,output}() into ip_fw2.c to create in/out
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 13 Sep 2008 12:57:07 +0000 (12:57 +0000)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 13 Sep 2008 12:57:07 +0000 (12:57 +0000)
pfil hooks for AF_INET pfil head.

During ipfw(4) module loading, ipfw(4) pfil hooks will be added to AF_INET
pfil head, only if fw_enable is 1.  ipfw(4) pfil hooks could be added and
deleted from AF_INET pfil head dynamicly by setting net.inet.ip.fw.enable
(1 to add, 0 to delete)

sys/net/ipfw/ip_fw2.c
sys/netinet/ip_input.c
sys/netinet/ip_output.c

index ee861c0..2f25eae 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/netinet/ip_fw2.c,v 1.6.2.12 2003/04/08 10:42:32 maxim Exp $
- * $DragonFly: src/sys/net/ipfw/ip_fw2.c,v 1.82 2008/09/13 10:47:23 sephe Exp $
+ * $DragonFly: src/sys/net/ipfw/ip_fw2.c,v 1.83 2008/09/13 12:57:07 sephe Exp $
  */
 
 #define        DEB(x)
@@ -57,6 +57,7 @@
 #include <net/if.h>
 #include <net/route.h>
 #include <net/netmsg2.h>
+#include <net/pfil.h>
 
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -4034,14 +4035,190 @@ done:
                      ipfw_tick, NULL);
 }
 
+static int
+ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
+{
+       struct ip_fw_args args;
+       struct mbuf *m = *m0;
+       struct m_tag *mtag;
+       int tee = 0, error = 0, i;
+
+       if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
+               /* Extract info from dummynet tag */
+               mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
+               KKASSERT(mtag != NULL);
+               args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
+               KKASSERT(args.rule != NULL);
+
+               m_tag_delete(m, mtag);
+               m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
+       } else {
+               args.rule = NULL;
+       }
+
+       args.eh = NULL;
+       args.oif = NULL;
+       args.m = m;
+       i = ipfw_chk(&args);
+       m = args.m;
+
+       if (m == NULL) {
+               error = EACCES;
+               goto back;
+       }
+
+       switch (i) {
+       case IP_FW_PASS:
+               break;
+
+       case IP_FW_DENY:
+               m_freem(m);
+               m = NULL;
+               error = EACCES;
+               break;
+
+       case IP_FW_DUMMYNET:
+               /* Send packet to the appropriate pipe */
+               ipfw_dummynet_io(m, args.cookie, DN_TO_IP_IN, &args);
+               break;
+
+       case IP_FW_TEE:
+               tee = 1;
+               /* FALL THROUGH */
+
+       case IP_FW_DIVERT:
+               if (ip_divert_p != NULL) {
+                       m = ip_divert_p(m, tee, 1);
+               } else {
+                       m_freem(m);
+                       m = NULL;
+                       /* not sure this is the right error msg */
+                       error = EACCES;
+               }
+               break;
+
+       default:
+               panic("unknown ipfw return value: %d\n", i);
+       }
+back:
+       *m0 = m;
+       return error;
+}
+
+static int
+ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
+{
+       struct ip_fw_args args;
+       struct mbuf *m = *m0;
+       struct m_tag *mtag;
+       int tee = 0, error = 0, off;
+
+       if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
+               /* Extract info from dummynet tag */
+               mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
+               KKASSERT(mtag != NULL);
+               args.rule = ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
+               KKASSERT(args.rule != NULL);
+
+               m_tag_delete(m, mtag);
+               m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
+       } else {
+               args.rule = NULL;
+       }
+
+       args.eh = NULL;
+       args.m = m;
+       args.oif = ifp;
+       off = ipfw_chk(&args);
+       m = args.m;
+
+       if (m == NULL) {
+               error = EACCES;
+               goto back;
+       }
+
+       switch (off) {
+       case IP_FW_PASS:
+               break;
+
+       case IP_FW_DENY:
+               m_freem(m);
+               m = NULL;
+               error = EACCES;
+               break;
+
+       case IP_FW_DUMMYNET:
+               ipfw_dummynet_io(m, args.cookie, DN_TO_IP_OUT, &args);
+               break;
+
+       case IP_FW_TEE:
+               tee = 1;
+               /* FALL THROUGH */
+
+       case IP_FW_DIVERT:
+               if (ip_divert_p != NULL) {
+                       m = ip_divert_p(m, tee, 0);
+               } else {
+                       m_freem(m);
+                       m = NULL;
+                       /* not sure this is the right error msg */
+                       error = EACCES;
+               }
+               break;
+
+       default:
+               panic("unknown ipfw return value: %d\n", off);
+       }
+back:
+       *m0 = m;
+       return error;
+}
+
+static void
+ipfw_hook(void)
+{
+       struct pfil_head *pfh;
+
+       IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
+
+       pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+       if (pfh == NULL)
+               return;
+
+       pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh);
+       pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh);
+}
+
+static void
+ipfw_dehook(void)
+{
+       struct pfil_head *pfh;
+
+       IPFW_ASSERT_CFGPORT(&curthread->td_msgport);
+
+       pfh = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+       if (pfh == NULL)
+               return;
+
+       pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh);
+       pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh);
+}
+
 static void
 ipfw_sysctl_enable_dispatch(struct netmsg *nmsg)
 {
        struct lwkt_msg *lmsg = &nmsg->nm_lmsg;
        int enable = lmsg->u.ms_result;
 
-       fw_enable = enable;
+       if (fw_enable == enable)
+               goto reply;
 
+       fw_enable = enable;
+       if (fw_enable)
+               ipfw_hook();
+       else
+               ipfw_dehook();
+reply:
        lwkt_replymsg(lmsg, 0);
 }
 
@@ -4203,6 +4380,9 @@ ipfw_init_dispatch(struct netmsg *nmsg)
 
        ip_fw_loaded = 1;
        callout_reset(&ipfw_timeout_h, hz, ipfw_tick, NULL);
+
+       if (fw_enable)
+               ipfw_hook();
 reply:
        crit_exit();
        lwkt_replymsg(&nmsg->nm_lmsg, error);
@@ -4231,6 +4411,8 @@ ipfw_fini_dispatch(struct netmsg *nmsg)
                goto reply;
        }
 
+       ipfw_dehook();
+
        callout_stop(&ipfw_timeout_h);
 
        ip_fw_loaded = 0;
index f680ad8..56e5878 100644 (file)
@@ -65,7 +65,7 @@
  *
  *     @(#)ip_input.c  8.2 (Berkeley) 1/4/94
  * $FreeBSD: src/sys/netinet/ip_input.c,v 1.130.2.52 2003/03/07 07:01:28 silby Exp $
- * $DragonFly: src/sys/netinet/ip_input.c,v 1.105 2008/09/13 10:23:39 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_input.c,v 1.106 2008/09/13 12:57:07 sephe Exp $
  */
 
 #define        _IP_VHL
@@ -410,7 +410,7 @@ ip_input(struct mbuf *m)
        struct ip *ip;
        struct in_ifaddr *ia = NULL;
        struct in_ifaddr_container *iac;
-       int i, hlen, checkif;
+       int hlen, checkif;
        u_short sum;
        struct in_addr pkt_dst;
        boolean_t using_srcrt = FALSE;          /* forward (by PFIL_HOOKS) */
@@ -561,69 +561,6 @@ iphack:
                using_srcrt = (odst.s_addr != ip->ip_dst.s_addr);
        }
 
-       if (fw_enable && IPFW_LOADED) {
-               struct ip_fw_args args;
-               int tee = 0;
-
-               if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
-                       /* Extract info from dummynet tag */
-                       mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
-                       KKASSERT(mtag != NULL);
-                       args.rule =
-                       ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
-                       KKASSERT(args.rule != NULL);
-
-                       m_tag_delete(m, mtag);
-                       m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
-               } else {
-                       args.rule = NULL;
-               }
-
-               args.eh = NULL;
-               args.oif = NULL;
-               args.m = m;
-               i = ip_fw_chk_ptr(&args);
-               m = args.m;
-
-               if (m == NULL)
-                       return;
-               ip = mtod(m, struct ip *);      /* just in case m changed */
-
-               switch (i) {
-               case IP_FW_PASS:
-                       goto pass;
-
-               case IP_FW_DENY:
-                       m_freem(m);
-                       return;
-
-               case IP_FW_DUMMYNET:
-                       /* Send packet to the appropriate pipe */
-                       ip_fw_dn_io_ptr(m, args.cookie, DN_TO_IP_IN, &args);
-                       goto pass;
-
-               case IP_FW_TEE:
-                       tee = 1;
-                       /* FALL THROUGH */
-
-               case IP_FW_DIVERT:
-                       if (ip_divert_p != NULL) {
-                               m = ip_divert_p(m, tee, 1);
-                               if (m == NULL)
-                                       return;
-                               ip = mtod(m, struct ip *);
-                               hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-                               goto pass;
-                       } else {
-                               m_freem(m);
-                               return;
-                       }
-
-               default:
-                       panic("unknown ipfw return value: %d\n", i);
-               }
-       }
-pass:
        if (m->m_pkthdr.fw_flags & IPFORWARD_MBUF_TAGGED) {
                mtag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
                KKASSERT(mtag != NULL);
@@ -638,6 +575,9 @@ pass:
                m->m_pkthdr.fw_flags &= ~FW_MBUF_REDISPATCH;
        }
 
+#if defined(IPSEC) && !defined(IPSEC_FILTERGIF)
+pass:
+#endif
        /*
         * Process options and, if not destined for us,
         * ship it on.  ip_dooptions returns 1 when an
index d1889d9..5b06c9d 100644 (file)
@@ -28,7 +28,7 @@
  *
  *     @(#)ip_output.c 8.3 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/netinet/ip_output.c,v 1.99.2.37 2003/04/15 06:44:45 silby Exp $
- * $DragonFly: src/sys/netinet/ip_output.c,v 1.62 2008/09/13 08:48:42 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_output.c,v 1.63 2008/09/13 12:57:07 sephe Exp $
  */
 
 #define _IP_VHL
@@ -65,7 +65,6 @@
 #include <netinet/in_pcb.h>
 #include <netinet/in_var.h>
 #include <netinet/ip_var.h>
-#include <netinet/ip_divert.h>
 
 #include <netproto/mpls/mpls_var.h>
 
@@ -180,7 +179,7 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
        struct ifnet *ifp = NULL;       /* keep compiler happy */
        struct mbuf *m;
        int hlen = sizeof(struct ip);
-       int len, off, error = 0;
+       int len, error = 0;
        struct sockaddr_in *dst = NULL; /* keep compiler happy */
        struct in_ifaddr *ia = NULL;
        int isbroadcast, sw_csum;
@@ -789,76 +788,6 @@ spd_done:
                ip = mtod(m, struct ip *);
        }
 
-       /*
-        * Check with the firewall...
-        */
-       if (fw_enable && IPFW_LOADED) {
-               struct ip_fw_args args;
-               int tee = 0;
-
-               if (m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED) {
-                       /* Extract info from dummynet tag */
-                       mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
-                       KKASSERT(mtag != NULL);
-                       args.rule =
-                       ((struct dn_pkt *)m_tag_data(mtag))->dn_priv;
-                       KKASSERT(args.rule != NULL);
-
-                       m_tag_delete(m, mtag);
-                       m->m_pkthdr.fw_flags &= ~DUMMYNET_MBUF_TAGGED;
-               } else {
-                       args.rule = NULL;
-               }
-
-               args.eh = NULL;
-               args.m = m;
-               args.oif = ifp;
-               off = ip_fw_chk_ptr(&args);
-               m = args.m;
-
-               if (m == NULL) {
-                       error = EACCES;
-                       goto done;
-               }
-               ip = mtod(m, struct ip *);
-
-               switch (off) {
-               case IP_FW_PASS:
-                       break;
-
-               case IP_FW_DENY:
-                       m_freem(m);
-                       error = EACCES;
-                       goto done;
-
-               case IP_FW_DUMMYNET:
-                       error = 0;
-                       ip_fw_dn_io_ptr(m, args.cookie, DN_TO_IP_OUT, &args);
-                       break;
-
-               case IP_FW_TEE:
-                       tee = 1;
-                       /* FALL THROUGH */
-
-               case IP_FW_DIVERT:
-                       if (ip_divert_p != NULL) {
-                               m = ip_divert_p(m, tee, 0);
-                               if (m == NULL)
-                                       goto done;
-                               ip = mtod(m, struct ip *);
-                               break;
-                       } else {
-                               m_freem(m);
-                               /* not sure this is the right error msg */
-                               error = EACCES;
-                               goto done;
-                       }
-
-               default:
-                       panic("unknown ipfw return value: %d\n", off);
-               }
-       }
-
        if (m->m_pkthdr.fw_flags & IPFORWARD_MBUF_TAGGED) {
                /*
                 * Check dst to make sure it is directly reachable on the