Minor fixes, comments.
# 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:
(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:
# $(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)
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
$(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
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.
*/
#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; \
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)
#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)
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);
}
#endif
-#if 0
+#ifndef linux /* FreeBSD */
static void
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;
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:
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",
goto drop;
break; /* not reached */
+ /* here packets come after the ipfw classification */
case IP_FW_DUMMYNET:
if (ip_dn_io_ptr == NULL)
goto drop;
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",
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);
#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
#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);
{
struct sock *sk;
int ret = -1; /* default return value */
+ int uid = -1; /* user id */
+ int st = -1; /* state */
if (proto != IPPROTO_TCP)
return -1;
/*
* 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.
*/
#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;
}
{
.hook = call_ipfw,
.pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
+ .hooknum = IPFW_HOOK_IN,
.priority = NF_IP_PRI_FILTER,
SET_MOD_OWNER
},
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_ */
* 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
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 */
IP_FW_FLUSH,
IP_FW_ZERO,
IP_FW_GET,
+ IP_FW_DYN_GET,
IP_FW_RESETLOG,
IP_FW_NAT_CFG,
# 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=