Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 1 | #ifndef _NF_QUEUE_H |
| 2 | #define _NF_QUEUE_H |
| 3 | |
Eric Leblond | 97a2d41 | 2013-12-06 00:24:12 +0100 | [diff] [blame] | 4 | #include <linux/ip.h> |
| 5 | #include <linux/ipv6.h> |
| 6 | #include <linux/jhash.h> |
| 7 | |
Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 8 | /* Each queued (to userspace) skbuff has one of these. */ |
Patrick McHardy | 02f014d | 2007-12-05 01:26:33 -0800 | [diff] [blame] | 9 | struct nf_queue_entry { |
| 10 | struct list_head list; |
| 11 | struct sk_buff *skb; |
| 12 | unsigned int id; |
| 13 | |
Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 14 | struct nf_hook_ops *elem; |
Jan Engelhardt | 76108ce | 2008-10-08 11:35:00 +0200 | [diff] [blame] | 15 | u_int8_t pf; |
Florian Westphal | a5fedd43 | 2013-04-19 04:58:25 +0000 | [diff] [blame] | 16 | u16 size; /* sizeof(entry) + saved route keys */ |
Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 17 | unsigned int hook; |
| 18 | struct net_device *indev; |
| 19 | struct net_device *outdev; |
| 20 | int (*okfn)(struct sk_buff *); |
Florian Westphal | a5fedd43 | 2013-04-19 04:58:25 +0000 | [diff] [blame] | 21 | |
| 22 | /* extra space to store route keys */ |
Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 23 | }; |
| 24 | |
Patrick McHardy | 02f014d | 2007-12-05 01:26:33 -0800 | [diff] [blame] | 25 | #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry)) |
Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 26 | |
| 27 | /* Packet queuing */ |
| 28 | struct nf_queue_handler { |
Patrick McHardy | 02f014d | 2007-12-05 01:26:33 -0800 | [diff] [blame] | 29 | int (*outfn)(struct nf_queue_entry *entry, |
Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 30 | unsigned int queuenum); |
Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 31 | }; |
| 32 | |
Florian Westphal | 0360ae4 | 2012-11-23 06:22:21 +0000 | [diff] [blame] | 33 | void nf_register_queue_handler(const struct nf_queue_handler *qh); |
| 34 | void nf_unregister_queue_handler(void); |
Joe Perches | 4e77be4 | 2013-09-23 11:37:48 -0700 | [diff] [blame] | 35 | void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); |
Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 36 | |
Florian Westphal | a5fedd43 | 2013-04-19 04:58:25 +0000 | [diff] [blame] | 37 | bool nf_queue_entry_get_refs(struct nf_queue_entry *entry); |
| 38 | void nf_queue_entry_release_refs(struct nf_queue_entry *entry); |
| 39 | |
Eric Leblond | 97a2d41 | 2013-12-06 00:24:12 +0100 | [diff] [blame] | 40 | static inline void init_hashrandom(u32 *jhash_initval) |
| 41 | { |
| 42 | while (*jhash_initval == 0) |
| 43 | *jhash_initval = prandom_u32(); |
| 44 | } |
| 45 | |
| 46 | static inline u32 hash_v4(const struct sk_buff *skb, u32 jhash_initval) |
| 47 | { |
| 48 | const struct iphdr *iph = ip_hdr(skb); |
| 49 | |
| 50 | /* packets in either direction go into same queue */ |
| 51 | if ((__force u32)iph->saddr < (__force u32)iph->daddr) |
| 52 | return jhash_3words((__force u32)iph->saddr, |
| 53 | (__force u32)iph->daddr, iph->protocol, jhash_initval); |
| 54 | |
| 55 | return jhash_3words((__force u32)iph->daddr, |
| 56 | (__force u32)iph->saddr, iph->protocol, jhash_initval); |
| 57 | } |
| 58 | |
| 59 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
| 60 | static inline u32 hash_v6(const struct sk_buff *skb, u32 jhash_initval) |
| 61 | { |
| 62 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
| 63 | u32 a, b, c; |
| 64 | |
| 65 | if ((__force u32)ip6h->saddr.s6_addr32[3] < |
| 66 | (__force u32)ip6h->daddr.s6_addr32[3]) { |
| 67 | a = (__force u32) ip6h->saddr.s6_addr32[3]; |
| 68 | b = (__force u32) ip6h->daddr.s6_addr32[3]; |
| 69 | } else { |
| 70 | b = (__force u32) ip6h->saddr.s6_addr32[3]; |
| 71 | a = (__force u32) ip6h->daddr.s6_addr32[3]; |
| 72 | } |
| 73 | |
| 74 | if ((__force u32)ip6h->saddr.s6_addr32[1] < |
| 75 | (__force u32)ip6h->daddr.s6_addr32[1]) |
| 76 | c = (__force u32) ip6h->saddr.s6_addr32[1]; |
| 77 | else |
| 78 | c = (__force u32) ip6h->daddr.s6_addr32[1]; |
| 79 | |
| 80 | return jhash_3words(a, b, c, jhash_initval); |
| 81 | } |
| 82 | #endif |
| 83 | |
| 84 | static inline u32 |
| 85 | nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family, |
| 86 | u32 jhash_initval) |
| 87 | { |
| 88 | if (family == NFPROTO_IPV4) |
| 89 | queue += ((u64) hash_v4(skb, jhash_initval) * queues_total) >> 32; |
| 90 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
| 91 | else if (family == NFPROTO_IPV6) |
| 92 | queue += ((u64) hash_v6(skb, jhash_initval) * queues_total) >> 32; |
| 93 | #endif |
| 94 | |
| 95 | return queue; |
| 96 | } |
| 97 | |
Patrick McHardy | c01cd42 | 2007-12-05 01:24:48 -0800 | [diff] [blame] | 98 | #endif /* _NF_QUEUE_H */ |