at v2.6.14-rc2 343 lines 7.8 kB view raw
1#include <linux/config.h> 2#include <linux/kernel.h> 3#include <linux/init.h> 4#include <linux/module.h> 5#include <linux/proc_fs.h> 6#include <linux/skbuff.h> 7#include <linux/netfilter.h> 8#include <linux/seq_file.h> 9#include <net/protocol.h> 10 11#include "nf_internals.h" 12 13/* 14 * A queue handler may be registered for each protocol. Each is protected by 15 * long term mutex. The handler must provide an an outfn() to accept packets 16 * for queueing and must reinject all packets it receives, no matter what. 17 */ 18static struct nf_queue_handler *queue_handler[NPROTO]; 19static struct nf_queue_rerouter *queue_rerouter; 20 21static DEFINE_RWLOCK(queue_handler_lock); 22 23/* return EBUSY when somebody else is registered, return EEXIST if the 24 * same handler is registered, return 0 in case of success. */ 25int nf_register_queue_handler(int pf, struct nf_queue_handler *qh) 26{ 27 int ret; 28 29 if (pf >= NPROTO) 30 return -EINVAL; 31 32 write_lock_bh(&queue_handler_lock); 33 if (queue_handler[pf] == qh) 34 ret = -EEXIST; 35 else if (queue_handler[pf]) 36 ret = -EBUSY; 37 else { 38 queue_handler[pf] = qh; 39 ret = 0; 40 } 41 write_unlock_bh(&queue_handler_lock); 42 43 return ret; 44} 45EXPORT_SYMBOL(nf_register_queue_handler); 46 47/* The caller must flush their queue before this */ 48int nf_unregister_queue_handler(int pf) 49{ 50 if (pf >= NPROTO) 51 return -EINVAL; 52 53 write_lock_bh(&queue_handler_lock); 54 queue_handler[pf] = NULL; 55 write_unlock_bh(&queue_handler_lock); 56 57 return 0; 58} 59EXPORT_SYMBOL(nf_unregister_queue_handler); 60 61int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer) 62{ 63 if (pf >= NPROTO) 64 return -EINVAL; 65 66 write_lock_bh(&queue_handler_lock); 67 memcpy(&queue_rerouter[pf], rer, sizeof(queue_rerouter[pf])); 68 write_unlock_bh(&queue_handler_lock); 69 70 return 0; 71} 72EXPORT_SYMBOL_GPL(nf_register_queue_rerouter); 73 74int nf_unregister_queue_rerouter(int pf) 75{ 76 if (pf >= NPROTO) 77 return -EINVAL; 78 79 write_lock_bh(&queue_handler_lock); 80 memset(&queue_rerouter[pf], 0, sizeof(queue_rerouter[pf])); 81 write_unlock_bh(&queue_handler_lock); 82 return 0; 83} 84EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); 85 86void nf_unregister_queue_handlers(struct nf_queue_handler *qh) 87{ 88 int pf; 89 90 write_lock_bh(&queue_handler_lock); 91 for (pf = 0; pf < NPROTO; pf++) { 92 if (queue_handler[pf] == qh) 93 queue_handler[pf] = NULL; 94 } 95 write_unlock_bh(&queue_handler_lock); 96} 97EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); 98 99/* 100 * Any packet that leaves via this function must come back 101 * through nf_reinject(). 102 */ 103int nf_queue(struct sk_buff **skb, 104 struct list_head *elem, 105 int pf, unsigned int hook, 106 struct net_device *indev, 107 struct net_device *outdev, 108 int (*okfn)(struct sk_buff *), 109 unsigned int queuenum) 110{ 111 int status; 112 struct nf_info *info; 113#ifdef CONFIG_BRIDGE_NETFILTER 114 struct net_device *physindev = NULL; 115 struct net_device *physoutdev = NULL; 116#endif 117 118 /* QUEUE == DROP if noone is waiting, to be safe. */ 119 read_lock(&queue_handler_lock); 120 if (!queue_handler[pf]->outfn) { 121 read_unlock(&queue_handler_lock); 122 kfree_skb(*skb); 123 return 1; 124 } 125 126 info = kmalloc(sizeof(*info)+queue_rerouter[pf].rer_size, GFP_ATOMIC); 127 if (!info) { 128 if (net_ratelimit()) 129 printk(KERN_ERR "OOM queueing packet %p\n", 130 *skb); 131 read_unlock(&queue_handler_lock); 132 kfree_skb(*skb); 133 return 1; 134 } 135 136 *info = (struct nf_info) { 137 (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn }; 138 139 /* If it's going away, ignore hook. */ 140 if (!try_module_get(info->elem->owner)) { 141 read_unlock(&queue_handler_lock); 142 kfree(info); 143 return 0; 144 } 145 146 /* Bump dev refs so they don't vanish while packet is out */ 147 if (indev) dev_hold(indev); 148 if (outdev) dev_hold(outdev); 149 150#ifdef CONFIG_BRIDGE_NETFILTER 151 if ((*skb)->nf_bridge) { 152 physindev = (*skb)->nf_bridge->physindev; 153 if (physindev) dev_hold(physindev); 154 physoutdev = (*skb)->nf_bridge->physoutdev; 155 if (physoutdev) dev_hold(physoutdev); 156 } 157#endif 158 if (queue_rerouter[pf].save) 159 queue_rerouter[pf].save(*skb, info); 160 161 status = queue_handler[pf]->outfn(*skb, info, queuenum, 162 queue_handler[pf]->data); 163 164 if (status >= 0 && queue_rerouter[pf].reroute) 165 status = queue_rerouter[pf].reroute(skb, info); 166 167 read_unlock(&queue_handler_lock); 168 169 if (status < 0) { 170 /* James M doesn't say fuck enough. */ 171 if (indev) dev_put(indev); 172 if (outdev) dev_put(outdev); 173#ifdef CONFIG_BRIDGE_NETFILTER 174 if (physindev) dev_put(physindev); 175 if (physoutdev) dev_put(physoutdev); 176#endif 177 module_put(info->elem->owner); 178 kfree(info); 179 kfree_skb(*skb); 180 181 return 1; 182 } 183 184 return 1; 185} 186 187void nf_reinject(struct sk_buff *skb, struct nf_info *info, 188 unsigned int verdict) 189{ 190 struct list_head *elem = &info->elem->list; 191 struct list_head *i; 192 193 rcu_read_lock(); 194 195 /* Release those devices we held, or Alexey will kill me. */ 196 if (info->indev) dev_put(info->indev); 197 if (info->outdev) dev_put(info->outdev); 198#ifdef CONFIG_BRIDGE_NETFILTER 199 if (skb->nf_bridge) { 200 if (skb->nf_bridge->physindev) 201 dev_put(skb->nf_bridge->physindev); 202 if (skb->nf_bridge->physoutdev) 203 dev_put(skb->nf_bridge->physoutdev); 204 } 205#endif 206 207 /* Drop reference to owner of hook which queued us. */ 208 module_put(info->elem->owner); 209 210 list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) { 211 if (i == elem) 212 break; 213 } 214 215 if (elem == &nf_hooks[info->pf][info->hook]) { 216 /* The module which sent it to userspace is gone. */ 217 NFDEBUG("%s: module disappeared, dropping packet.\n", 218 __FUNCTION__); 219 verdict = NF_DROP; 220 } 221 222 /* Continue traversal iff userspace said ok... */ 223 if (verdict == NF_REPEAT) { 224 elem = elem->prev; 225 verdict = NF_ACCEPT; 226 } 227 228 if (verdict == NF_ACCEPT) { 229 next_hook: 230 verdict = nf_iterate(&nf_hooks[info->pf][info->hook], 231 &skb, info->hook, 232 info->indev, info->outdev, &elem, 233 info->okfn, INT_MIN); 234 } 235 236 switch (verdict & NF_VERDICT_MASK) { 237 case NF_ACCEPT: 238 info->okfn(skb); 239 break; 240 241 case NF_QUEUE: 242 if (!nf_queue(&skb, elem, info->pf, info->hook, 243 info->indev, info->outdev, info->okfn, 244 verdict >> NF_VERDICT_BITS)) 245 goto next_hook; 246 break; 247 } 248 rcu_read_unlock(); 249 250 if (verdict == NF_DROP) 251 kfree_skb(skb); 252 253 kfree(info); 254 return; 255} 256EXPORT_SYMBOL(nf_reinject); 257 258#ifdef CONFIG_PROC_FS 259static void *seq_start(struct seq_file *seq, loff_t *pos) 260{ 261 if (*pos >= NPROTO) 262 return NULL; 263 264 return pos; 265} 266 267static void *seq_next(struct seq_file *s, void *v, loff_t *pos) 268{ 269 (*pos)++; 270 271 if (*pos >= NPROTO) 272 return NULL; 273 274 return pos; 275} 276 277static void seq_stop(struct seq_file *s, void *v) 278{ 279 280} 281 282static int seq_show(struct seq_file *s, void *v) 283{ 284 int ret; 285 loff_t *pos = v; 286 struct nf_queue_handler *qh; 287 288 read_lock_bh(&queue_handler_lock); 289 qh = queue_handler[*pos]; 290 if (!qh) 291 ret = seq_printf(s, "%2lld NONE\n", *pos); 292 else 293 ret = seq_printf(s, "%2lld %s\n", *pos, qh->name); 294 read_unlock_bh(&queue_handler_lock); 295 296 return ret; 297} 298 299static struct seq_operations nfqueue_seq_ops = { 300 .start = seq_start, 301 .next = seq_next, 302 .stop = seq_stop, 303 .show = seq_show, 304}; 305 306static int nfqueue_open(struct inode *inode, struct file *file) 307{ 308 return seq_open(file, &nfqueue_seq_ops); 309} 310 311static struct file_operations nfqueue_file_ops = { 312 .owner = THIS_MODULE, 313 .open = nfqueue_open, 314 .read = seq_read, 315 .llseek = seq_lseek, 316 .release = seq_release, 317}; 318#endif /* PROC_FS */ 319 320 321int __init netfilter_queue_init(void) 322{ 323#ifdef CONFIG_PROC_FS 324 struct proc_dir_entry *pde; 325#endif 326 queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter), 327 GFP_KERNEL); 328 if (!queue_rerouter) 329 return -ENOMEM; 330 331#ifdef CONFIG_PROC_FS 332 pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter); 333 if (!pde) { 334 kfree(queue_rerouter); 335 return -1; 336 } 337 pde->proc_fops = &nfqueue_file_ops; 338#endif 339 memset(queue_rerouter, 0, NPROTO * sizeof(struct nf_queue_rerouter)); 340 341 return 0; 342} 343