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