patch-2.3.99-pre2 linux/net/ipv4/netfilter/ipt_owner.c

Next file: linux/net/ipv4/netfilter/ipt_state.c
Previous file: linux/net/ipv4/netfilter/ipt_multiport.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre1/linux/net/ipv4/netfilter/ipt_owner.c linux/net/ipv4/netfilter/ipt_owner.c
@@ -0,0 +1,136 @@
+/* Kernel module to match various things tied to sockets associated with
+   locally generated outgoing packets.
+
+   (C)2000 Marc Boucher
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/file.h>
+#include <net/sock.h>
+
+#include <linux/netfilter_ipv4/ipt_owner.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+EXPORT_NO_SYMBOLS;
+
+static int
+match_pid(const struct sk_buff *skb, pid_t pid)
+{
+	struct task_struct *p;
+	int i;
+
+	read_lock(&tasklist_lock);
+	p = find_task_by_pid(pid);
+	if(p && p->files) {
+		for (i=0; i < p->files->max_fds; i++) {
+			if (fcheck_task(p, i) == skb->sk->socket->file) {
+				read_unlock(&tasklist_lock);
+				return 1;
+			}
+        	}
+	}
+	read_unlock(&tasklist_lock);
+	return 0;
+}
+
+static int
+match_sid(const struct sk_buff *skb, pid_t sid)
+{
+	struct task_struct *p;
+	int i, found=0;
+
+	read_lock(&tasklist_lock);
+	for_each_task(p) {
+		if ((p->session != sid) || !p->files)
+			continue;
+
+		for (i=0; i < p->files->max_fds; i++) {
+			if (fcheck_task(p, i) == skb->sk->socket->file) {
+				found = 1;
+				break;
+			}
+		}
+		if(found)
+			break;
+	}
+	read_unlock(&tasklist_lock);
+
+	return found;
+}
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      const void *hdr,
+      u_int16_t datalen,
+      int *hotdrop)
+{
+	const struct ipt_owner_info *info = matchinfo;
+
+	if (!skb->sk || !skb->sk->socket || !skb->sk->socket->file)
+		return 0;
+
+	if(info->match & IPT_OWNER_UID) {
+		if((skb->sk->socket->file->f_uid != info->uid) ^
+		    !!(info->invert & IPT_OWNER_UID))
+			return 0;
+	}
+
+	if(info->match & IPT_OWNER_GID) {
+		if((skb->sk->socket->file->f_gid != info->gid) ^
+		    !!(info->invert & IPT_OWNER_GID))
+			return 0;
+	}
+
+	if(info->match & IPT_OWNER_PID) {
+		if (!match_pid(skb, info->pid) ^
+		    !!(info->invert & IPT_OWNER_PID))
+			return 0;
+	}
+
+	if(info->match & IPT_OWNER_SID) {
+		if (!match_sid(skb, info->sid) ^
+		    !!(info->invert & IPT_OWNER_SID))
+			return 0;
+	}
+
+	return 1;
+}
+
+static int
+checkentry(const char *tablename,
+           const struct ipt_ip *ip,
+           void *matchinfo,
+           unsigned int matchsize,
+           unsigned int hook_mask)
+{
+        if (hook_mask
+            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
+                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
+                return 0;
+        }
+
+	if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info)))
+		return 0;
+
+	return 1;
+}
+
+static struct ipt_match owner_match
+= { { NULL, NULL }, "owner", &match, &checkentry, THIS_MODULE };
+
+static int __init init(void)
+{
+	return ipt_register_match(&owner_match);
+}
+
+static void __exit fini(void)
+{
+	ipt_unregister_match(&owner_match);
+}
+
+module_init(init);
+module_exit(fini);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)