port more changes to make PCI work
[linux-2.4.git] / net / ipv6 / netfilter / ip6t_owner.c
1 /* Kernel module to match various things tied to sockets associated with
2    locally generated outgoing packets.
3
4    Copyright (C) 2000,2001 Marc Boucher
5  */
6 #include <linux/module.h>
7 #include <linux/skbuff.h>
8 #include <linux/file.h>
9 #include <net/sock.h>
10
11 #include <linux/netfilter_ipv6/ip6t_owner.h>
12 #include <linux/netfilter_ipv6/ip6_tables.h>
13
14 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
15 MODULE_DESCRIPTION("IP6 tables owner matching module");
16 MODULE_LICENSE("GPL");
17
18 static int
19 match_pid(const struct sk_buff *skb, pid_t pid)
20 {
21         struct task_struct *p;
22         struct files_struct *files;
23         int i;
24
25         read_lock(&tasklist_lock);
26         p = find_task_by_pid(pid);
27         if (!p)
28                 goto out;
29         task_lock(p);
30         files = p->files;
31         if(files) {
32                 read_lock(&files->file_lock);
33                 for (i=0; i < files->max_fds; i++) {
34                         if (fcheck_files(files, i) == skb->sk->socket->file) {
35                                 read_unlock(&files->file_lock);
36                                 task_unlock(p);
37                                 read_unlock(&tasklist_lock);
38                                 return 1;
39                         }
40                 }
41                 read_unlock(&files->file_lock);
42         }
43         task_unlock(p);
44 out:
45         read_unlock(&tasklist_lock);
46         return 0;
47 }
48
49 static int
50 match_sid(const struct sk_buff *skb, pid_t sid)
51 {
52         struct task_struct *p;
53         struct file *file = skb->sk->socket->file;
54         int i, found=0;
55
56         read_lock(&tasklist_lock);
57         for_each_task(p) {
58                 struct files_struct *files;
59                 if (p->session != sid)
60                         continue;
61
62                 task_lock(p);
63                 files = p->files;
64                 if (files) {
65                         read_lock(&files->file_lock);
66                         for (i=0; i < files->max_fds; i++) {
67                                 if (fcheck_files(files, i) == file) {
68                                         found = 1;
69                                         break;
70                                 }
71                         }
72                         read_unlock(&files->file_lock);
73                 }
74                 task_unlock(p);
75                 if(found)
76                         break;
77         }
78         read_unlock(&tasklist_lock);
79
80         return found;
81 }
82
83 static int
84 match(const struct sk_buff *skb,
85       const struct net_device *in,
86       const struct net_device *out,
87       const void *matchinfo,
88       int offset,
89       const void *hdr,
90       u_int16_t datalen,
91       int *hotdrop)
92 {
93         const struct ip6t_owner_info *info = matchinfo;
94
95         if (!skb->sk || !skb->sk->socket || !skb->sk->socket->file)
96                 return 0;
97
98         if(info->match & IP6T_OWNER_UID) {
99                 if((skb->sk->socket->file->f_uid != info->uid) ^
100                     !!(info->invert & IP6T_OWNER_UID))
101                         return 0;
102         }
103
104         if(info->match & IP6T_OWNER_GID) {
105                 if((skb->sk->socket->file->f_gid != info->gid) ^
106                     !!(info->invert & IP6T_OWNER_GID))
107                         return 0;
108         }
109
110         if(info->match & IP6T_OWNER_PID) {
111                 if (!match_pid(skb, info->pid) ^
112                     !!(info->invert & IP6T_OWNER_PID))
113                         return 0;
114         }
115
116         if(info->match & IP6T_OWNER_SID) {
117                 if (!match_sid(skb, info->sid) ^
118                     !!(info->invert & IP6T_OWNER_SID))
119                         return 0;
120         }
121
122         return 1;
123 }
124
125 static int
126 checkentry(const char *tablename,
127            const struct ip6t_ip6 *ip,
128            void *matchinfo,
129            unsigned int matchsize,
130            unsigned int hook_mask)
131 {
132         if (hook_mask
133             & ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) {
134                 printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
135                 return 0;
136         }
137
138         if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info)))
139                 return 0;
140 #ifdef CONFIG_SMP
141         /* files->file_lock can not be used in a BH */
142         if (((struct ip6t_owner_info *)matchinfo)->match
143             & (IP6T_OWNER_PID|IP6T_OWNER_SID)) {
144                 printk("ip6t_owner: pid and sid matching is broken on SMP.\n");
145                 return 0;
146         }
147 #endif
148         return 1;
149 }
150
151 static struct ip6t_match owner_match
152 = { { NULL, NULL }, "owner", &match, &checkentry, NULL, THIS_MODULE };
153
154 static int __init init(void)
155 {
156         return ip6t_register_match(&owner_match);
157 }
158
159 static void __exit fini(void)
160 {
161         ip6t_unregister_match(&owner_match);
162 }
163
164 module_init(init);
165 module_exit(fini);