Added the code for xid matching. (The code is not yet enabled)
authormarta <marta@8c455092-636d-4788-adf5-e71def0336e8>
Fri, 6 Nov 2009 11:54:02 +0000 (11:54 +0000)
committermarta <marta@8c455092-636d-4788-adf5-e71def0336e8>
Fri, 6 Nov 2009 11:54:02 +0000 (11:54 +0000)
Minor fixes, comments.

Makefile
dummynet/Makefile
dummynet/include/sys/malloc.h
dummynet/ip_dummynet.c
dummynet/ip_fw2.c
dummynet/ip_fw_pfil.c
dummynet/ipfw2_mod.c
dummynet/missing.h
glue.h
ipfw/Makefile

index 69b6481..a35b722 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,9 @@
 # You can run it manually or also under the Planetlab build.
 # Planetlab wants also the 'install' target.
 
+DATE ?= $(shell date +%Y%m%d)
+SNAPSHOT_NAME=ipfw_linux-$(DATE)
+
 _all: all
 
 all clean distclean:
@@ -10,4 +13,11 @@ all clean distclean:
        (cd ipfw && $(MAKE) $(@) )
        (cd dummynet && $(MAKE) $(@) )
 
+snapshot:
+       -ln -s `pwd` /tmp/$(SNAPSHOT_NAME)
+       (cd /tmp; tar cvzhf $(SNAPSHOT_NAME).tgz --exclude .svn \
+               --exclude README.openwrt --exclude tags --exclude NOTES \
+               $(SNAPSHOT_NAME) )
+       -rm  /tmp/$(SNAPSHOT_NAME)
+
 install:
index b361cba..ff68e55 100644 (file)
@@ -12,8 +12,8 @@
 #   $(MOD)-y   for each $MOD in obj-m, the list of objects
 #   obj-y      same as above, for openwrt
 #   O_TARGET   the link target, for openwrt
-#    EXTRA_CFLAGS as the name says... in openwrt
-#    EXTRA_CFLAGS are used in 2.6.22 module kernel compilation too
+#   EXTRA_CFLAGS as the name says... in openwrt
+#   EXTRA_CFLAGS is used in 2.6.22 module kernel compilation too
 #---
 
 $(warning including dummynet/Makefile)
@@ -53,6 +53,7 @@ ifneq ($(shell echo $(VER)|grep '2.4'),)
   WARN += -nostdinc -isystem /usr/lib/gcc/i486-linux-gnu/4.2.4/include
   #WARN = -Wp,-MD,/home/luigi/ports-luigi/dummynet-branches/ipfw_mod/dummynet/.ipfw2_mod.o.d
   #WARN += -Iinclude  -include include/linux/autoconf.h
+
   WARN += -Wall -Wundef
   WARN += -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing
   WARN += -fno-common -Werror-implicit-function-declaration
@@ -93,13 +94,15 @@ all: include_e
        $(MAKE) -C $(KERNELDIR) V=1 M=`pwd` modules
 endif
 
-# the list of object use to build the module
+#-- back to the common section of code
+
+# the list of objects used to build the module
 ipfw_mod-y = $(IPFW_SRCS:%.c=%.o)
 
-#      Original ipfw + dummynet + FreeBSD stuff,
+# Original ipfw and dummynet sources + FreeBSD stuff,
 IPFW_SRCS = ip_fw2.c ip_dummynet.c ip_fw_pfil.c in_cksum.c
 
-#      module glue and functions missing in linux
+# Module glue and functions missing in linux
 IPFW_SRCS += ipfw2_mod.c bsd_compat.c
 
 
@@ -122,6 +125,7 @@ clean:
 distclean: clean
        -rm -f .*cmd modules.order opt_*
        -rm -rf .tmp_versions include_e
+       -rm -rf .ip_dummynet.o.d
 
 # support to create empty dirs and files in include_e/
 # EDIRS is the list of directories, EFILES is the list of files.
index d103801..03b9dfb 100644 (file)
@@ -8,11 +8,10 @@
  */
 #ifndef _WIN32 /* this is the linux version */
 
-#ifndef LINUX_24
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
+#if !defined (LINUX_24) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
 #define malloc(_size, type, flags)                     \
        kmalloc(_size, GFP_ATOMIC | __GFP_ZERO)
-#else /* LINUX < 2.6.22 and LINUX_24 */
+#else /* LINUX <= 2.6.22 and LINUX_24 */
 /* linux 2.6.22 does not zero allocated memory */
 #define malloc(_size, type, flags)                     \
        ({ int _s = _size;                              \
@@ -20,8 +19,7 @@
        if (_ret) memset(_ret, 0, _s);                  \
         (_ret);                                                \
         })
-#endif /* !LINUX_24 */
-#endif /* LINUX < 2.6.22 */
+#endif /* LINUX <= 2.6.22 */
 
 #define calloc(_n, _s) malloc((_n * _s), NULL, GFP_ATOMIC | __GFP_ZERO)
 #define free(_var, type) kfree(_var)
index a613bbf..b8cbc2e 100644 (file)
@@ -86,6 +86,7 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_dummynet.c,v 1.110.2.4 2008/10/31 12:58:1
 #include <netinet6/ip6_var.h>
 
 #include "missing.h"
+
 /*
  * We keep a private variable for the simulation time, but we could
  * probably use an existing one ("softticks" in sys/kern/kern_timeout.c)
@@ -959,6 +960,7 @@ dummynet_send(struct mbuf *m)
                        pkt = dn_tag_get(m);
                        dst = pkt->dn_dir;
                }
+
                switch (dst) {
                case DN_TO_IP_OUT:
                        ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
index 039e084..39d6ab7 100644 (file)
@@ -1978,7 +1978,7 @@ dump_table(struct ip_fw_chain *ch, ipfw_table *tbl)
 }
 #endif
 
-#if 0
+#ifndef linux /* FreeBSD */
 static void
 fill_ugid_cache(struct inpcb *inp, struct ip_fw_ugid *ugp)
 {
@@ -1990,57 +1990,45 @@ fill_ugid_cache(struct inpcb *inp, struct ip_fw_ugid *ugp)
        ugp->fw_ngroups = cr->cr_ngroups;
        bcopy(cr->cr_groups, ugp->fw_groups, sizeof(ugp->fw_groups));
 }
-#endif /* no uigid support */
+#endif
 
 static int
 check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
     struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip,
     u_int16_t src_port, struct ip_fw_ugid *ugp, int *ugid_lookupp,
-    struct inpcb *inp, struct sk_buff *skb)
+    struct inpcb *inp)
 {
-#if 1   /* Linux */
-
-       const struct file *filp;
-
-       if (insn->o.opcode == O_JAIL)
-               return 0;
+#ifdef linux
+       int match = 0;
+       struct sk_buff *skb = ((struct mbuf *)inp)->m_skb;
 
-       if (skb->sk == NULL || skb->sk->sk_socket == NULL)
-               return 0;
-
-       filp = skb->sk->sk_socket->file;
-       if (filp == NULL)
-               return 0;
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,28)
-/* use the current's real uid/gid */
-#define UID f_uid
-#define GID f_gid
-#else /* 2.6.29 */
-/* use the current's file access real uid/gid */
-#define UID f_cred->fsuid
-#define GID f_cred->fsgid
+       if (insn->o.opcode == O_JAIL) {
+#ifdef IPFW_PLANETLAB
+               match = (skb->skb_tag == insn->d[0]);
 #endif
-
-       if (insn->o.opcode == O_UID) {
-               if (filp->UID != (uid_t)insn->d[0])
-                       return 0;
+               return match;
        }
 
-       if (insn->o.opcode == O_GID) {
-               if (filp->GID != (gid_t)insn->d[0])
-                       return 0;
-       }
+       if (*ugid_lookupp == 0) {       /* actively lookup and copy in cache */
+
+               /* returns null if any element of the chain up to file is null.
+                * if sk != NULL then we also have a reference
+                */
+               *ugid_lookupp = linux_lookup(proto,
+                       src_ip.s_addr, htons(src_port),
+                       dst_ip.s_addr, htons(dst_port),
+                       skb, oif ? 1 : 0, ugp);
 
-       /* check for slice_id matching */
-       if (insn->o.opcode == O_GID) {
-               if (filp->GID != (gid_t)insn->d[0])
-                       return 0;
        }
+       if (*ugid_lookupp < 0)
+               return 0;
 
-       return 1;
+       if (insn->o.opcode == O_UID)
+               match = (ugp->fw_uid == (uid_t)insn->d[0]);
+       return match;
+
+#else /* FreeBSD */
 
-#else /* FreeBSD original code */
        struct inpcbinfo *pi;
        int wildcard;
        struct inpcb *pcb;
@@ -2650,7 +2638,7 @@ check_body:
                                                    proto, oif,
                                                    dst_ip, dst_port,
                                                    src_ip, src_port, &fw_ugid_cache,
-                                                   &ugid_lookup, args->inp, m->m_skb);
+                                                   &ugid_lookup, (struct inpcb *)args->m);
                                break;
 
                        case O_RECV:
index 9d65e7f..bc1f011 100644 (file)
@@ -122,7 +122,7 @@ again:
        args.m = *m0;
        args.inp = inp;
        ipfw = ipfw_chk(&args);
-       *m0 = args.m;
+       *m0 = args.m;   /* args.m can be modified by ipfw_chk */
        tee = 0;
 
        KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
@@ -151,6 +151,7 @@ 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;
@@ -248,7 +249,7 @@ again:
        args.oif = ifp;
        args.inp = inp;
        ipfw = ipfw_chk(&args);
-       *m0 = args.m;
+       *m0 = args.m;   /* args.m can be modified by ipfw_chk */
        tee = 0;
 
        KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
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
         },
index 76b8153..c47b117 100644 (file)
@@ -415,4 +415,10 @@ int in_localaddr(struct in_addr in);
 
 int fnmatch(const char *pattern, const char *string, int flags);
 
+struct ip_fw_ugid;
+int
+linux_lookup(const int proto, const __be32 saddr, const __be16 sport,
+       const __be32 daddr, const __be16 dport,
+       struct sk_buff *skb, int dir, struct ip_fw_ugid *ugp);
+
 #endif /* !_MISSING_H_ */
diff --git a/glue.h b/glue.h
index d3571a4..ff7ef07 100644 (file)
--- a/glue.h
+++ b/glue.h
@@ -86,7 +86,7 @@ enum sopt_dir { SOPT_GET, SOPT_SET };
                                 * so early include this file (to be solved) */
 #include <linux/list.h>
 #include <linux/in.h>          /* struct in_addr */
-#include <linux/in6.h>         /* struct in_addr */
+#include <linux/in6.h>         /* struct in6_addr */
 #include <linux/icmp.h>
 /*
  * LIST_HEAD in queue.h conflict with linux/list.h
@@ -206,10 +206,13 @@ struct clockinfo {
         int     profhz;         /* profiling clock frequency */
 };
 
-
-/*
- * linux does not have heapsort
+/* 
+ * linux does not have a reentrant version of qsort,
+ * so we the FreeBSD stdlib version.
  */
+void
+qsort_r(void *a, size_t n, size_t es, void *thunk,
+       int cmp_t(void *, const void *, const void *));
 #define heapsort(_a, _b, _c, _d)       qsort(_a, _b, _c, _d)
 
 #define setprogname(x) /* not present in linux */
@@ -260,6 +263,7 @@ enum ipfw_msg_type {
        IP_FW_FLUSH,
        IP_FW_ZERO,
        IP_FW_GET,
+       IP_FW_DYN_GET,
        IP_FW_RESETLOG,
 
        IP_FW_NAT_CFG,
index 5c3ba6a..a8a4f47 100644 (file)
@@ -7,7 +7,7 @@
 # Do not set with = or := so we can inherit from the caller
 $(warning Building userland ipfw for $(VER))
 EXTRA_CFLAGS += 
-EXTRA_CFLAGS += -O
+EXTRA_CFLAGS += -O1
 EXTRA_CFLAGS += -include ../glue.h
 
 LDFLAGS=