Added the code for xid matching. (The code is not yet enabled)
[ipfw.git] / dummynet / ipfw2_mod.c
index 26fb5d9..ebb16b2 100644 (file)
@@ -180,7 +180,7 @@ 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\n", __FUNCTION__, cmd, len);
 
        if (cmd < IP_DUMMYNET_CONFIGURE && ip_fw_ctl_ptr)
                ret = ip_fw_ctl_ptr(s);
@@ -281,6 +281,19 @@ static struct nf_sockopt_ops ipfw_sockopts = {
 #define NF_IP_POST_ROUTING     NF_INET_POST_ROUTING
 #endif
 
+/*
+ * ipfw hooks the POST_ROUTING and the PRE_ROUTING chain.
+ * PlanetLab tags the xid in the LOCAL_INPUT and in the
+ * POST_ROUTING chain, so if we want to intercept the
+ * traffic by using the id we need to hook the LOCAL_INPUT
+ * chain instead of the PRE_ROUTING.
+ */
+#ifdef IPFW_PLANETLAB
+#define IPFW_HOOK_IN NF_IP_LOCAL_IN
+#else
+#define IPFW_HOOK_IN NF_IP_PRE_ROUTING
+#endif
+
 /*
  * The main netfilter hook.
  * To make life simple, we queue everything and then do all the
@@ -383,7 +396,7 @@ ipfw2_queue_handler(QH_ARGS)
 #endif
 
        /* XXX add the interface */
-       if (info->hook == NF_IP_PRE_ROUTING) {
+       if (info->hook == IPFW_HOOK_IN) {
                ret = ipfw_check_in(NULL, &m, info->indev, PFIL_IN, NULL);
        } else {
                ret = ipfw_check_out(NULL, &m, info->outdev, PFIL_OUT, NULL);
@@ -460,6 +473,8 @@ linux_lookup(const int proto, const __be32 saddr, const __be16 sport,
 {
        struct sock *sk;
        int ret = -1;   /* default return value */
+       int uid = -1;   /* user id */
+       int st = -1;    /* state */
 
        if (proto != IPPROTO_TCP)
                return -1;
@@ -495,10 +510,13 @@ linux_lookup(const int proto, const __be32 saddr, const __be16 sport,
 
        /*
         * On a match, sk is returned with a refcount.
-        * In tcp states less that TCP_TIME_WAIT sk references a struct sock
-        * which is what we want,
-        * otherwise it references a struct inet_timewait_sock which does
-        * not point to credentials.
+        * In tcp some states reference a valid struct sock
+        * which is what we want, otherwise the struct sock
+        * referenced can be invalid, as in the case of the
+        * TCP_TIME_WAIT state, when it references a
+        * struct inet_timewait_sock which does not point to credentials.
+        * To be safe we exclude TCP_CLOSE and TCP_LAST_ACK states too.
+        *
         * Once again we need conditional code because the UID and GID
         * location changes between the two kernels.
         */
@@ -511,15 +529,18 @@ linux_lookup(const int proto, const __be32 saddr, const __be16 sport,
 #define _CURR_UID f_cred->fsuid
 #define _CURR_GID f_cred->fsgid
 #endif
-       if (sk->sk_state < TCP_TIME_WAIT && sk->sk_socket && sk->sk_socket->file) {
+       st = sk->sk_state;
+       if (st != TCP_TIME_WAIT && st != TCP_CLOSE && st != TCP_LAST_ACK &&
+                       sk->sk_socket && sk->sk_socket->file) {
                ugp->fw_uid = sk->sk_socket->file->_CURR_UID;
+               uid = ugp->fw_uid;
                ret = 1;
        }
        sock_put(sk);
 #undef _CURR_UID
 #undef _CURR_GID
 
-       //printf("%s dir %d skb->dst %p skb->dev %p ret %d\n", __FUNCTION__, dir, skb->dst, skb->dev, ret);
+       //printf("%s dir %d sb>dst %p sb>dev %p ret %d id %d st%d\n", __FUNCTION__, dir, skb->dst, skb->dev, ret, uid, st);
        return ret;
 }
 
@@ -577,7 +598,7 @@ static struct nf_hook_ops ipfw_ops[] __read_mostly = {
         {
                 .hook           = call_ipfw,
                 .pf             = PF_INET,
-                .hooknum        = NF_IP_PRE_ROUTING,
+                .hooknum        = IPFW_HOOK_IN,
                 .priority       = NF_IP_PRI_FILTER,
                 SET_MOD_OWNER
         },