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 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.
+ */
+#if 0 // defined(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);
*
* 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;
{
struct sock *sk;
int ret = -1; /* default return value */
+ int uid = -1; /* user id */
+ int st = -1; /* state */
if (proto != IPPROTO_TCP)
return -1;
*/
#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
- net_iif(skb)) :
+ inet_iif(skb)) :
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 */
/*
* 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;
+ 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
- //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 ret = 0;
- printf("%s called\n", __FUNCTION__);
+ printf("%s in-hook %d svn id %s\n", __FUNCTION__, IPFW_HOOK_IN, "$Id$");
my_mod_register(moddesc_ipfw, "ipfw", 1);
my_mod_register(moddesc_dummynet, "dummynet", 2);