nf_queue.c revision 76108cea065cda58366d16a7eb6ca90d717a1396
1f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#include <linux/kernel.h> 2f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#include <linux/init.h> 3f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#include <linux/module.h> 4f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#include <linux/proc_fs.h> 5f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#include <linux/skbuff.h> 6f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#include <linux/netfilter.h> 7bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte#include <linux/seq_file.h> 87a11b9848ae27e571f219fab5541bd84700f0d68Patrick McHardy#include <linux/rcupdate.h> 9f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#include <net/protocol.h> 10c01cd429fc118c5db92475c5f08b307718aa4efcPatrick McHardy#include <net/netfilter/nf_queue.h> 11f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 12f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#include "nf_internals.h" 13f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 14601e68e100b6bf8ba13a32db8faf92d43acaa997YOSHIFUJI Hideaki/* 15f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte * A queue handler may be registered for each protocol. Each is protected by 16f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte * long term mutex. The handler must provide an an outfn() to accept packets 17f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte * for queueing and must reinject all packets it receives, no matter what. 18f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte */ 19e3ac5298159c5286cef86f0865d4fa6a606bd391Patrick McHardystatic const struct nf_queue_handler *queue_handler[NPROTO]; 20f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 21585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakaistatic DEFINE_MUTEX(queue_handler_mutex); 22f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 23d72367b6f36e557f122beefaa8c6b80eb1c7f245Harald Welte/* return EBUSY when somebody else is registered, return EEXIST if the 24d72367b6f36e557f122beefaa8c6b80eb1c7f245Harald Welte * same handler is registered, return 0 in case of success. */ 2576108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtint nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) 26601e68e100b6bf8ba13a32db8faf92d43acaa997YOSHIFUJI Hideaki{ 27f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte int ret; 28f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 29f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte if (pf >= NPROTO) 30f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte return -EINVAL; 31f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 32585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai mutex_lock(&queue_handler_mutex); 33d72367b6f36e557f122beefaa8c6b80eb1c7f245Harald Welte if (queue_handler[pf] == qh) 34d72367b6f36e557f122beefaa8c6b80eb1c7f245Harald Welte ret = -EEXIST; 35d72367b6f36e557f122beefaa8c6b80eb1c7f245Harald Welte else if (queue_handler[pf]) 36f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte ret = -EBUSY; 37f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte else { 38585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai rcu_assign_pointer(queue_handler[pf], qh); 39f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte ret = 0; 40f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte } 41585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai mutex_unlock(&queue_handler_mutex); 42f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 43f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte return ret; 44f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte} 45f6ebe77f955d77a988ce726f0818ec0103b11323Harald WelteEXPORT_SYMBOL(nf_register_queue_handler); 46f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 47f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte/* The caller must flush their queue before this */ 4876108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardtint nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) 49f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte{ 50f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte if (pf >= NPROTO) 51f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte return -EINVAL; 52f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 53585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai mutex_lock(&queue_handler_mutex); 5494be1a3f365e2b9f2615575d7fef16a0bad106a3Patrick McHardy if (queue_handler[pf] && queue_handler[pf] != qh) { 55585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai mutex_unlock(&queue_handler_mutex); 56ce7663d84a87bb4e1743f62950bf7dceed723a13Yasuyuki Kozakai return -EINVAL; 57ce7663d84a87bb4e1743f62950bf7dceed723a13Yasuyuki Kozakai } 58ce7663d84a87bb4e1743f62950bf7dceed723a13Yasuyuki Kozakai 59585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai rcu_assign_pointer(queue_handler[pf], NULL); 60585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai mutex_unlock(&queue_handler_mutex); 61585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai 62585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai synchronize_rcu(); 63601e68e100b6bf8ba13a32db8faf92d43acaa997YOSHIFUJI Hideaki 64f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte return 0; 65f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte} 66f6ebe77f955d77a988ce726f0818ec0103b11323Harald WelteEXPORT_SYMBOL(nf_unregister_queue_handler); 67f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 68e3ac5298159c5286cef86f0865d4fa6a606bd391Patrick McHardyvoid nf_unregister_queue_handlers(const struct nf_queue_handler *qh) 69f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte{ 7076108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t pf; 71f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 72585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai mutex_lock(&queue_handler_mutex); 73f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte for (pf = 0; pf < NPROTO; pf++) { 74bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte if (queue_handler[pf] == qh) 75585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai rcu_assign_pointer(queue_handler[pf], NULL); 76f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte } 77585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai mutex_unlock(&queue_handler_mutex); 78585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai 79585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai synchronize_rcu(); 80f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte} 81f6ebe77f955d77a988ce726f0818ec0103b11323Harald WelteEXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); 82f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 83daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardystatic void nf_queue_entry_release_refs(struct nf_queue_entry *entry) 84daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy{ 85daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy /* Release those devices we held, or Alexey will kill me. */ 86daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy if (entry->indev) 87daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy dev_put(entry->indev); 88daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy if (entry->outdev) 89daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy dev_put(entry->outdev); 90daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy#ifdef CONFIG_BRIDGE_NETFILTER 91daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy if (entry->skb->nf_bridge) { 92daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; 93daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy 94daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy if (nf_bridge->physindev) 95daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy dev_put(nf_bridge->physindev); 96daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy if (nf_bridge->physoutdev) 97daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy dev_put(nf_bridge->physoutdev); 98daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy } 99daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy#endif 100daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy /* Drop reference to owner of hook which queued us. */ 101daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy module_put(entry->elem->owner); 102daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy} 103daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy 104601e68e100b6bf8ba13a32db8faf92d43acaa997YOSHIFUJI Hideaki/* 105601e68e100b6bf8ba13a32db8faf92d43acaa997YOSHIFUJI Hideaki * Any packet that leaves via this function must come back 106f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte * through nf_reinject(). 107f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte */ 108394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardystatic int __nf_queue(struct sk_buff *skb, 109394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy struct list_head *elem, 11076108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t pf, unsigned int hook, 111394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy struct net_device *indev, 112394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy struct net_device *outdev, 113394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy int (*okfn)(struct sk_buff *), 114394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy unsigned int queuenum) 115f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte{ 116f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte int status; 117daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy struct nf_queue_entry *entry = NULL; 118f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#ifdef CONFIG_BRIDGE_NETFILTER 119daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy struct net_device *physindev; 120daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy struct net_device *physoutdev; 121f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#endif 1221e796fda00f06bac584f0e4ad8750ab9430d79d3Patrick McHardy const struct nf_afinfo *afinfo; 123e3ac5298159c5286cef86f0865d4fa6a606bd391Patrick McHardy const struct nf_queue_handler *qh; 124f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 125f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte /* QUEUE == DROP if noone is waiting, to be safe. */ 126585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai rcu_read_lock(); 127585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai 128585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai qh = rcu_dereference(queue_handler[pf]); 129daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy if (!qh) 130daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy goto err_unlock; 131f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 132bce8032ef3cc58170ab3550e9e271dba7b4c4764Patrick McHardy afinfo = nf_get_afinfo(pf); 133daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy if (!afinfo) 134daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy goto err_unlock; 135bce8032ef3cc58170ab3550e9e271dba7b4c4764Patrick McHardy 13602f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC); 137daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy if (!entry) 138daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy goto err_unlock; 139f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 14002f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy *entry = (struct nf_queue_entry) { 14102f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy .skb = skb, 14202f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy .elem = list_entry(elem, struct nf_hook_ops, list), 14302f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy .pf = pf, 14402f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy .hook = hook, 14502f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy .indev = indev, 14602f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy .outdev = outdev, 14702f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy .okfn = okfn, 14802f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy }; 149f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 150f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte /* If it's going away, ignore hook. */ 15102f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy if (!try_module_get(entry->elem->owner)) { 152585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai rcu_read_unlock(); 15302f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy kfree(entry); 154f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte return 0; 155f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte } 156f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 157f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte /* Bump dev refs so they don't vanish while packet is out */ 1588b1cf0db2aced837fcd50072e81e32c5836a1ee1Patrick McHardy if (indev) 1598b1cf0db2aced837fcd50072e81e32c5836a1ee1Patrick McHardy dev_hold(indev); 1608b1cf0db2aced837fcd50072e81e32c5836a1ee1Patrick McHardy if (outdev) 1618b1cf0db2aced837fcd50072e81e32c5836a1ee1Patrick McHardy dev_hold(outdev); 162f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#ifdef CONFIG_BRIDGE_NETFILTER 163394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy if (skb->nf_bridge) { 164394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy physindev = skb->nf_bridge->physindev; 1658b1cf0db2aced837fcd50072e81e32c5836a1ee1Patrick McHardy if (physindev) 1668b1cf0db2aced837fcd50072e81e32c5836a1ee1Patrick McHardy dev_hold(physindev); 167394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy physoutdev = skb->nf_bridge->physoutdev; 1688b1cf0db2aced837fcd50072e81e32c5836a1ee1Patrick McHardy if (physoutdev) 1698b1cf0db2aced837fcd50072e81e32c5836a1ee1Patrick McHardy dev_hold(physoutdev); 170f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte } 171f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte#endif 17202f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy afinfo->saveroute(skb, entry); 17302f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy status = qh->outfn(entry, queuenum); 174f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 175585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai rcu_read_unlock(); 176f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 177f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte if (status < 0) { 178daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy nf_queue_entry_release_refs(entry); 179daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy goto err; 180f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte } 181f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 182f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte return 1; 183daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy 184daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardyerr_unlock: 185daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy rcu_read_unlock(); 186daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardyerr: 187daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy kfree_skb(skb); 188daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy kfree(entry); 189daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy return 1; 190f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte} 191f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 192394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardyint nf_queue(struct sk_buff *skb, 193394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy struct list_head *elem, 19476108cea065cda58366d16a7eb6ca90d717a1396Jan Engelhardt u_int8_t pf, unsigned int hook, 195394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy struct net_device *indev, 196394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy struct net_device *outdev, 197394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy int (*okfn)(struct sk_buff *), 198394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy unsigned int queuenum) 199394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy{ 200394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy struct sk_buff *segs; 201394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy 202394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy if (!skb_is_gso(skb)) 203394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy return __nf_queue(skb, elem, pf, hook, indev, outdev, okfn, 204394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy queuenum); 205394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy 206394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy switch (pf) { 207394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy case AF_INET: 208394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy skb->protocol = htons(ETH_P_IP); 209394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy break; 210394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy case AF_INET6: 211394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy skb->protocol = htons(ETH_P_IPV6); 212394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy break; 213394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy } 214394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy 215394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy segs = skb_gso_segment(skb, 0); 216394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy kfree_skb(skb); 217801678c5a3b4c79236970bcca27c733f5559e0d1Hirofumi Nakagawa if (IS_ERR(segs)) 218394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy return 1; 219394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy 220394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy do { 221394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy struct sk_buff *nskb = segs->next; 222394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy 223394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy segs->next = NULL; 224394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy if (!__nf_queue(segs, elem, pf, hook, indev, outdev, okfn, 225394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy queuenum)) 226394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy kfree_skb(segs); 227394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy segs = nskb; 228394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy } while (segs); 229394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy return 1; 230394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy} 231394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy 23202f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardyvoid nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) 233f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte{ 23402f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy struct sk_buff *skb = entry->skb; 23502f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy struct list_head *elem = &entry->elem->list; 2361e796fda00f06bac584f0e4ad8750ab9430d79d3Patrick McHardy const struct nf_afinfo *afinfo; 237f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 238f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte rcu_read_lock(); 239f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 240daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2Patrick McHardy nf_queue_entry_release_refs(entry); 241f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 242f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte /* Continue traversal iff userspace said ok... */ 243f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte if (verdict == NF_REPEAT) { 244f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte elem = elem->prev; 245f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte verdict = NF_ACCEPT; 246f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte } 247f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 248f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte if (verdict == NF_ACCEPT) { 24902f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy afinfo = nf_get_afinfo(entry->pf); 25002f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy if (!afinfo || afinfo->reroute(skb, entry) < 0) 2517a11b9848ae27e571f219fab5541bd84700f0d68Patrick McHardy verdict = NF_DROP; 2527a11b9848ae27e571f219fab5541bd84700f0d68Patrick McHardy } 2537a11b9848ae27e571f219fab5541bd84700f0d68Patrick McHardy 2547a11b9848ae27e571f219fab5541bd84700f0d68Patrick McHardy if (verdict == NF_ACCEPT) { 255f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte next_hook: 25602f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy verdict = nf_iterate(&nf_hooks[entry->pf][entry->hook], 25702f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy skb, entry->hook, 25802f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy entry->indev, entry->outdev, &elem, 25902f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy entry->okfn, INT_MIN); 260f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte } 261f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 262f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte switch (verdict & NF_VERDICT_MASK) { 263f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte case NF_ACCEPT: 2643bc38712e3a6e0596ccb6f8299043a826f983701Patrick McHardy case NF_STOP: 2654b3d15ef4a88683d93d1b76351297d2298a02a99Patrick McHardy local_bh_disable(); 26602f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy entry->okfn(skb); 2674b3d15ef4a88683d93d1b76351297d2298a02a99Patrick McHardy local_bh_enable(); 2683bc38712e3a6e0596ccb6f8299043a826f983701Patrick McHardy case NF_STOLEN: 269f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte break; 270f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte case NF_QUEUE: 27102f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy if (!__nf_queue(skb, elem, entry->pf, entry->hook, 27202f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy entry->indev, entry->outdev, entry->okfn, 273394f545db6e7e4d7a6a2fa3f543b755ca39d58acPatrick McHardy verdict >> NF_VERDICT_BITS)) 274f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte goto next_hook; 275f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte break; 2763bc38712e3a6e0596ccb6f8299043a826f983701Patrick McHardy default: 2773bc38712e3a6e0596ccb6f8299043a826f983701Patrick McHardy kfree_skb(skb); 278f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte } 279f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte rcu_read_unlock(); 28002f014d88831f73b895c1fe09badb66c88e932d3Patrick McHardy kfree(entry); 281f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte return; 282f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte} 283f6ebe77f955d77a988ce726f0818ec0103b11323Harald WelteEXPORT_SYMBOL(nf_reinject); 284f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 285bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte#ifdef CONFIG_PROC_FS 286bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Weltestatic void *seq_start(struct seq_file *seq, loff_t *pos) 287bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte{ 288bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte if (*pos >= NPROTO) 289bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte return NULL; 290bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 291bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte return pos; 292bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte} 293bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 294bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Weltestatic void *seq_next(struct seq_file *s, void *v, loff_t *pos) 295bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte{ 296bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte (*pos)++; 297bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 298bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte if (*pos >= NPROTO) 299bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte return NULL; 300bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 301bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte return pos; 302bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte} 303bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 304bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Weltestatic void seq_stop(struct seq_file *s, void *v) 305bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte{ 306bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 307bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte} 308bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 309bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Weltestatic int seq_show(struct seq_file *s, void *v) 310bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte{ 311bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte int ret; 312bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte loff_t *pos = v; 313e3ac5298159c5286cef86f0865d4fa6a606bd391Patrick McHardy const struct nf_queue_handler *qh; 314bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 315585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai rcu_read_lock(); 316585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai qh = rcu_dereference(queue_handler[*pos]); 317bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte if (!qh) 318bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte ret = seq_printf(s, "%2lld NONE\n", *pos); 319bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte else 320bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte ret = seq_printf(s, "%2lld %s\n", *pos, qh->name); 321585426fdc5b4cccaacf0afc8cf821ff763750ae8Yasuyuki Kozakai rcu_read_unlock(); 322bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 323bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte return ret; 324bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte} 325bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 32656b3d975bbce65f655c5612b4822da671f9fd9b2Philippe De Muyterstatic const struct seq_operations nfqueue_seq_ops = { 327bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte .start = seq_start, 328bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte .next = seq_next, 329bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte .stop = seq_stop, 330bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte .show = seq_show, 331bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte}; 332bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 333bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Weltestatic int nfqueue_open(struct inode *inode, struct file *file) 334bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte{ 335bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte return seq_open(file, &nfqueue_seq_ops); 336bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte} 337bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 338da7071d7e32d15149cc513f096a3638097b66387Arjan van de Venstatic const struct file_operations nfqueue_file_ops = { 339bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte .owner = THIS_MODULE, 340bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte .open = nfqueue_open, 341bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte .read = seq_read, 342bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte .llseek = seq_lseek, 343bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte .release = seq_release, 344bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte}; 345bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte#endif /* PROC_FS */ 346bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 347bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte 348f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welteint __init netfilter_queue_init(void) 349f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte{ 350bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte#ifdef CONFIG_PROC_FS 3518eeee8b152ae6bbe181518efaf62ba8e9c613693Denis V. Lunev if (!proc_create("nf_queue", S_IRUGO, 3528eeee8b152ae6bbe181518efaf62ba8e9c613693Denis V. Lunev proc_net_netfilter, &nfqueue_file_ops)) 353bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte return -1; 354bbd86b9fc469b7e91dc7444e6abb8930811d79cbHarald Welte#endif 355f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte return 0; 356f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte} 357f6ebe77f955d77a988ce726f0818ec0103b11323Harald Welte 358