From: marta Date: Fri, 6 Nov 2009 11:54:02 +0000 (+0000) Subject: Added the code for xid matching. (The code is not yet enabled) X-Git-Tag: ipfw-0.9-5~4 X-Git-Url: http://git.onelab.eu/?p=ipfw.git;a=commitdiff_plain;h=5f337135c613b2ee3cb24ade7617ecaae0a74681 Added the code for xid matching. (The code is not yet enabled) Minor fixes, comments. --- diff --git a/Makefile b/Makefile index 69b6481..a35b722 100644 --- 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: diff --git a/dummynet/Makefile b/dummynet/Makefile index b361cba..ff68e55 100644 --- a/dummynet/Makefile +++ b/dummynet/Makefile @@ -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. diff --git a/dummynet/include/sys/malloc.h b/dummynet/include/sys/malloc.h index d103801..03b9dfb 100644 --- a/dummynet/include/sys/malloc.h +++ b/dummynet/include/sys/malloc.h @@ -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) diff --git a/dummynet/ip_dummynet.c b/dummynet/ip_dummynet.c index a613bbf..b8cbc2e 100644 --- a/dummynet/ip_dummynet.c +++ b/dummynet/ip_dummynet.c @@ -86,6 +86,7 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_dummynet.c,v 1.110.2.4 2008/10/31 12:58:1 #include #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); diff --git a/dummynet/ip_fw2.c b/dummynet/ip_fw2.c index 039e084..39d6ab7 100644 --- a/dummynet/ip_fw2.c +++ b/dummynet/ip_fw2.c @@ -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: diff --git a/dummynet/ip_fw_pfil.c b/dummynet/ip_fw_pfil.c index 9d65e7f..bc1f011 100644 --- a/dummynet/ip_fw_pfil.c +++ b/dummynet/ip_fw_pfil.c @@ -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", diff --git a/dummynet/ipfw2_mod.c b/dummynet/ipfw2_mod.c index 26fb5d9..ebb16b2 100644 --- a/dummynet/ipfw2_mod.c +++ b/dummynet/ipfw2_mod.c @@ -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 }, diff --git a/dummynet/missing.h b/dummynet/missing.h index 76b8153..c47b117 100644 --- a/dummynet/missing.h +++ b/dummynet/missing.h @@ -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 --- 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 #include /* struct in_addr */ -#include /* struct in_addr */ +#include /* struct in6_addr */ #include /* * 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, diff --git a/ipfw/Makefile b/ipfw/Makefile index 5c3ba6a..a8a4f47 100644 --- a/ipfw/Makefile +++ b/ipfw/Makefile @@ -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 += -O0 +EXTRA_CFLAGS += -O1 EXTRA_CFLAGS += -include ../glue.h LDFLAGS=