Major changes:
[ipfw.git] / dummynet / ipfw2_mod.c
index 3bf836a..b072ab5 100644 (file)
@@ -282,13 +282,14 @@ static struct nf_sockopt_ops ipfw_sockopts = {
 #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.
+ * ipfw hooks into the POST_ROUTING and the PRE_ROUTING chains.
+ * PlanetLab sets skb_tag to the slice id in the LOCAL_INPUT and
+ * POST_ROUTING chains, so if we want to use that information we
+ * need to hook the LOCAL_INPUT chain instead of the PRE_ROUTING.
+ * However at the moment the skb_tag info is not reliable so
+ * we stay with the standard hooks.
  */
-#ifdef IPFW_PLANETLAB
+#if 0 // defined(IPFW_PLANETLAB)
 #define IPFW_HOOK_IN NF_IP_LOCAL_IN
 #else
 #define IPFW_HOOK_IN NF_IP_PRE_ROUTING
@@ -461,8 +462,24 @@ ip_output(struct mbuf *m, struct mbuf __unused *opt,
  *
  * We do this only on selected protocols: TCP, ...
  *
- * Note- for locally generated, outgoing packets we don't need to
- * do a lookup because the sk_buff already points to the socket where
+ * The chain is the following
+ *   sk_buff*  sock*  socket*    file*
+ *     skb  ->  sk ->sk_socket->file ->f_owner    ->pid
+ *     skb  ->  sk ->sk_socket->file ->f_uid (direct)
+ *     skb  ->  sk ->sk_socket->file ->f_cred->fsuid (2.6.29+)
+ *
+ * Related headers:
+ * linux/skbuff.h      struct skbuff
+ * net/sock.h          struct sock
+ * linux/net.h         struct socket
+ * linux/fs.h          struct file
+ *
+ * With vserver we may have sk->sk_xid and sk->sk_nid that
+ * which we store in fw_groups[1] (matches O_JAIL) and fw_groups[2]
+ * (no matches yet)
+ *
+ * Note- for locally generated, outgoing packets we should not need
+ * need a lookup because the sk_buff already points to the socket where
  * the info is.
  */
 extern struct inet_hashinfo tcp_hashinfo;
@@ -491,10 +508,18 @@ linux_lookup(const int proto, const __be32 saddr, const __be16 sport,
         */
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)
 #define _OPT_NET_ARG
-#else   /* 2.6.25 and above */
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+/* there is no dev_net() on 2.6.25 */
+#define _OPT_NET_ARG (skb->dev->nd_net),
+#else  /* 2.6.26 and above */
 #define _OPT_NET_ARG dev_net(skb->dev),
 #endif
+#endif
 
+       if (0 && skb->sk) {
+               sk=skb->sk;
+       } else {
        sk =  (dir) ?
                inet_lookup(_OPT_NET_ARG &tcp_hashinfo,
                        daddr, dport, saddr, sport,     // matches outgoing for server sockets
@@ -502,6 +527,7 @@ linux_lookup(const int proto, const __be32 saddr, const __be16 sport,
                inet_lookup(_OPT_NET_ARG &tcp_hashinfo,
                        saddr, sport, daddr, dport,     // matches incoming for server sockets
                        skb->dev->ifindex);
+       }
 
 #undef _OPT_NET_ARG
        /* no match, nothing to be done */
@@ -534,9 +560,15 @@ linux_lookup(const int proto, const __be32 saddr, const __be16 sport,
                        sk->sk_socket && sk->sk_socket->file) {
                ugp->fw_uid = sk->sk_socket->file->_CURR_UID;
                uid = ugp->fw_uid;
+               ugp->fw_groups[0] = sk->sk_socket->file->_CURR_GID;
+#ifdef CONFIG_VSERVER
+               ugp->fw_groups[1] = sk->sk_xid;
+               ugp->fw_groups[2] = sk->sk_nid;
+#endif
                ret = 1;
        }
-       sock_put(sk);
+       if (1 && !skb->sk) /* the reference came from the lookup */
+               sock_put(sk);
 #undef _CURR_UID
 #undef _CURR_GID