Sync with the new ipfw3 version.
[ipfw.git] / dummynet2 / ipfw2_mod.c
index f59a37c..1ea6e57 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 /*
- * $Id: ipfw2_mod.c 4671 2010-01-04 17:50:51Z luigi $
+ * $Id: ipfw2_mod.c 5797 2010-03-21 16:31:08Z luigi $
  *
  * The main interface to build ipfw+dummynet as a linux module.
  * (and possibly as a windows module as well, though that part
@@ -70,6 +70,9 @@
 #include <netinet/ipfw/ip_fw_private.h>                /* ip_fw_ctl_t, ip_fw_chk_t */
 #include <netinet/ip_dummynet.h>       /* ip_dn_ctl_t, ip_dn_io_t */
 #include <net/pfil.h>                  /* PFIL_IN, PFIL_OUT */
+
+#ifdef __linux__
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
 #warning --- inet_hashtables not present on 2.4
 #include <linux/tcp.h>
@@ -83,6 +86,8 @@ static inline int inet_iif(const struct sk_buff *skb)
 #else
 #include <net/inet_hashtables.h>       /* inet_lookup */
 #endif
+#endif /* __linux__ */
+
 #include <net/route.h>                 /* inet_iif */
 
 /*
@@ -98,6 +103,12 @@ ip_fw_chk_t    *ip_fw_chk_ptr;
 
 void           (*bridge_dn_p)(struct mbuf *, struct ifnet *);
 
+/* Divert hooks. */
+void (*ip_divert_ptr)(struct mbuf *m, int incoming);
+
+/* ng_ipfw hooks. */
+ng_ipfw_input_t *ng_ipfw_input_p = NULL;
+
 /*---
  * Glue code to implement the registration of children with the parent.
  * Each child should call my_mod_register() when linking, so that
@@ -130,8 +141,13 @@ int
 my_mod_register(const char *name, int order,
        struct moduledata *mod, void *init, void *uninit)
 {
-       struct mod_args m = { .name = name, .order = order,
-               .mod = mod, .init = init, .uninit = uninit };
+       struct mod_args m;
+
+       m.name = name;
+       m.order = order;
+       m.mod = mod;
+       m.init = init;
+       m.uninit = uninit;
 
        printf("%s %s called\n", __FUNCTION__, name);
        if (mod_idx < sizeof(mods) / sizeof(mods[0]))
@@ -199,49 +215,42 @@ ipfw_ctl_h(struct sockopt *s, int cmd, int dir, int len, void __user *user)
        memset(&t, 0, sizeof(t));
        s->sopt_td = &t;
        
-       // printf("%s called with cmd %d len %d\n", __FUNCTION__, cmd, len);
+       //printf("%s called with cmd %d len %d sopt %p user %p\n", __FUNCTION__, cmd, len, s, user);
 
-       if (cmd < IP_DUMMYNET_CONFIGURE && ip_fw_ctl_ptr)
+       if (ip_fw_ctl_ptr && cmd != IP_DUMMYNET3 && (cmd == IP_FW3 ||
+           cmd < IP_DUMMYNET_CONFIGURE))
                ret = ip_fw_ctl_ptr(s);
-       else if (cmd >= IP_DUMMYNET_CONFIGURE && ip_dn_ctl_ptr)
+       else if (ip_dn_ctl_ptr && (cmd == IP_DUMMYNET3 ||
+           cmd >= IP_DUMMYNET_CONFIGURE))
                ret = ip_dn_ctl_ptr(s);
-
+       
        return -ret;    /* errors are < 0 on linux */
 }
 
-#ifdef _WIN32
-
-void
-netisr_dispatch(int __unused num, struct mbuf *m)
-{
-}
-
 int
 ip_output(struct mbuf *m, struct mbuf __unused *opt,
        struct route __unused *ro, int __unused flags,
     struct ip_moptions __unused *imo, struct inpcb __unused *inp)
 {
        netisr_dispatch(0, m);
-       return 0;
+        return 0;
 }
 
-#else /* this is the linux glue */
 /*
  * setsockopt hook has no return value other than the error code.
  */
-static int
+int
 do_ipfw_set_ctl(struct sock __unused *sk, int cmd,
        void __user *user, unsigned int len)
 {
        struct sockopt s;       /* pass arguments */
-
        return ipfw_ctl_h(&s, cmd, SOPT_SET, len, user);
 }
 
 /*
  * getsockopt can can return a block of data in response.
  */
-static int
+int
 do_ipfw_get_ctl(struct sock __unused *sk,
        int cmd, void __user *user, int *len)
 {
@@ -252,6 +261,8 @@ do_ipfw_get_ctl(struct sock __unused *sk,
        return ret;
 }
 
+#ifdef __linux__
+
 /*
  * declare our [get|set]sockopt hooks
  */
@@ -405,7 +416,7 @@ ipfw2_queue_handler(QH_ARGS)
        }
 
        m->m_skb = skb;
-       m->m_len = skb->len;            /* len in this skbuf */
+       m->m_len = skb->len;            /* len from ip header to end */
        m->m_pkthdr.len = skb->len;     /* total packet len */
        m->m_pkthdr.rcvif = info->indev;
        m->queue_entry = info;
@@ -463,15 +474,6 @@ netisr_dispatch(int num, struct mbuf *m)
        REINJECT(info, ((num == -1)?NF_DROP:NF_STOP));  /* accept but no more firewall */
 }
 
-int
-ip_output(struct mbuf *m, struct mbuf __unused *opt,
-       struct route __unused *ro, int __unused flags,
-    struct ip_moptions __unused *imo, struct inpcb __unused *inp)
-{
-       netisr_dispatch(0, m);
-        return 0;
-}
-
 /*
  * socket lookup function for linux.
  * This code is used to associate uid, gid, jail/xid to packets,
@@ -674,13 +676,18 @@ static struct nf_hook_ops ipfw_ops[] __read_mostly = {
                SET_MOD_OWNER
         },
 };
-#endif /* !__linux__ */
+#endif /* __linux__ */
 
 /* descriptors for the children, until i find a way for the
  * linker to produce them
  */
 extern moduledata_t *moddesc_ipfw;
 extern moduledata_t *moddesc_dummynet;
+extern moduledata_t *moddesc_dn_fifo;
+extern moduledata_t *moddesc_dn_wf2qp;
+extern moduledata_t *moddesc_dn_rr;
+extern moduledata_t *moddesc_dn_qfq;
+extern moduledata_t *moddesc_dn_prio;
 extern void *sysinit_ipfw_init;
 extern void *sysuninit_ipfw_destroy;
 extern void *sysinit_vnet_ipfw_init;
@@ -689,27 +696,37 @@ extern void *sysuninit_vnet_ipfw_uninit;
 /*
  * Module glue - init and exit function.
  */
-static int __init
+int __init
 ipfw_module_init(void)
 {
        int ret = 0;
-
-       printf("%s in-hook %d svn id %s\n", __FUNCTION__, IPFW_HOOK_IN, "$Id: ipfw2_mod.c 4671 2010-01-04 17:50:51Z luigi $");
+#ifdef _WIN32
+       unsigned long resolution;
+#endif
 
        rn_init(64);
-
        my_mod_register("ipfw",  1, moddesc_ipfw, NULL, NULL);
        my_mod_register("sy_ipfw",  2, NULL,
                sysinit_ipfw_init, sysuninit_ipfw_destroy);
        my_mod_register("sy_Vnet_ipfw",  3, NULL,
                sysinit_vnet_ipfw_init, sysuninit_vnet_ipfw_uninit);
        my_mod_register("dummynet",  4, moddesc_dummynet, NULL, NULL);
+       my_mod_register("dn_fifo",  5, moddesc_dn_fifo, NULL, NULL);
+       my_mod_register("dn_wf2qp",  6, moddesc_dn_wf2qp, NULL, NULL);
+       my_mod_register("dn_rr",  7, moddesc_dn_rr, NULL, NULL);
+       my_mod_register("dn_qfq",  8, moddesc_dn_qfq, NULL, NULL);
+       my_mod_register("dn_prio",  9, moddesc_dn_prio, NULL, NULL);
        init_children();
 
 #ifdef _WIN32
-       return ret;
+       resolution = ExSetTimerResolution(1, TRUE);
+       printf("*** ExSetTimerResolution: resolution set to %d n-sec ***\n",resolution);
+#endif
+#ifdef EMULATE_SYSCTL
+       keinit_GST();
+#endif 
 
-#else  /* linux hook */
+#ifdef __linux__
        /* sockopt register, in order to talk with user space */
        ret = nf_register_sockopt(&ipfw_sockopts);
         if (ret < 0) {
@@ -740,21 +757,26 @@ clean_modules:
        fini_children();
        printf("%s error\n", __FUNCTION__);
 
+#endif /* __linux__ */
        return ret;
-#endif /* linux */
 }
 
 /* module shutdown */
-static void __exit
+void __exit
 ipfw_module_exit(void)
 {
+#ifdef EMULATE_SYSCTL
+       keexit_GST();
+#endif
 #ifdef _WIN32
+       ExSetTimerResolution(0,FALSE);
+
 #else  /* linux hook */
         nf_unregister_hooks(ipfw_ops, ARRAY_SIZE(ipfw_ops));
        /* maybe drain the queue before unregistering ? */
        nf_unregister_queue_handler(PF_INET  UNREG_QH_ARG(ipfw2_queue_handler) );
        nf_unregister_sockopt(&ipfw_sockopts);
-#endif /* linux */
+#endif /* __linux__ */
 
        fini_children();