Warning: This file is not a C or C++ file. It does not have highlighting.
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
---|---|
2 | #ifndef _NF_QUEUE_H |
3 | #define _NF_QUEUE_H |
4 | |
5 | #include <linux/ip.h> |
6 | #include <linux/ipv6.h> |
7 | #include <linux/jhash.h> |
8 | #include <linux/netfilter.h> |
9 | #include <linux/skbuff.h> |
10 | |
11 | /* Each queued (to userspace) skbuff has one of these. */ |
12 | struct nf_queue_entry { |
13 | struct list_head list; |
14 | struct sk_buff *skb; |
15 | unsigned int id; |
16 | unsigned int hook_index; /* index in hook_entries->hook[] */ |
17 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
18 | struct net_device *physin; |
19 | struct net_device *physout; |
20 | #endif |
21 | struct nf_hook_state state; |
22 | u16 size; /* sizeof(entry) + saved route keys */ |
23 | |
24 | /* extra space to store route keys */ |
25 | }; |
26 | |
27 | #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry)) |
28 | |
29 | /* Packet queuing */ |
30 | struct nf_queue_handler { |
31 | int (*outfn)(struct nf_queue_entry *entry, |
32 | unsigned int queuenum); |
33 | void (*nf_hook_drop)(struct net *net); |
34 | }; |
35 | |
36 | void nf_register_queue_handler(const struct nf_queue_handler *qh); |
37 | void nf_unregister_queue_handler(void); |
38 | |
39 | bool nf_queue_entry_get_refs(struct nf_queue_entry *entry); |
40 | void nf_queue_entry_free(struct nf_queue_entry *entry); |
41 | |
42 | static inline void init_hashrandom(u32 *jhash_initval) |
43 | { |
44 | while (*jhash_initval == 0) |
45 | *jhash_initval = get_random_u32(); |
46 | } |
47 | |
48 | static inline u32 hash_v4(const struct iphdr *iph, u32 initval) |
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, initval); |
54 | |
55 | return jhash_3words((__force u32)iph->daddr, |
56 | (__force u32)iph->saddr, iph->protocol, initval); |
57 | } |
58 | |
59 | static inline u32 hash_v6(const struct ipv6hdr *ip6h, u32 initval) |
60 | { |
61 | u32 a, b, c; |
62 | |
63 | if ((__force u32)ip6h->saddr.s6_addr32[3] < |
64 | (__force u32)ip6h->daddr.s6_addr32[3]) { |
65 | a = (__force u32) ip6h->saddr.s6_addr32[3]; |
66 | b = (__force u32) ip6h->daddr.s6_addr32[3]; |
67 | } else { |
68 | b = (__force u32) ip6h->saddr.s6_addr32[3]; |
69 | a = (__force u32) ip6h->daddr.s6_addr32[3]; |
70 | } |
71 | |
72 | if ((__force u32)ip6h->saddr.s6_addr32[1] < |
73 | (__force u32)ip6h->daddr.s6_addr32[1]) |
74 | c = (__force u32) ip6h->saddr.s6_addr32[1]; |
75 | else |
76 | c = (__force u32) ip6h->daddr.s6_addr32[1]; |
77 | |
78 | return jhash_3words(a, b, c, initval); |
79 | } |
80 | |
81 | static inline u32 hash_bridge(const struct sk_buff *skb, u32 initval) |
82 | { |
83 | struct ipv6hdr *ip6h, _ip6h; |
84 | struct iphdr *iph, _iph; |
85 | |
86 | switch (eth_hdr(skb)->h_proto) { |
87 | case htons(ETH_P_IP): |
88 | iph = skb_header_pointer(skb, skb_network_offset(skb), |
89 | sizeof(*iph), &_iph); |
90 | if (iph) |
91 | return hash_v4(iph, initval); |
92 | break; |
93 | case htons(ETH_P_IPV6): |
94 | ip6h = skb_header_pointer(skb, skb_network_offset(skb), |
95 | sizeof(*ip6h), &_ip6h); |
96 | if (ip6h) |
97 | return hash_v6(ip6h, initval); |
98 | break; |
99 | } |
100 | |
101 | return 0; |
102 | } |
103 | |
104 | static inline u32 |
105 | nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family, |
106 | u32 initval) |
107 | { |
108 | switch (family) { |
109 | case NFPROTO_IPV4: |
110 | queue += reciprocal_scale(hash_v4(ip_hdr(skb), initval), |
111 | queues_total); |
112 | break; |
113 | case NFPROTO_IPV6: |
114 | queue += reciprocal_scale(hash_v6(ipv6_hdr(skb), initval), |
115 | queues_total); |
116 | break; |
117 | case NFPROTO_BRIDGE: |
118 | queue += reciprocal_scale(hash_bridge(skb, initval), |
119 | queues_total); |
120 | break; |
121 | } |
122 | |
123 | return queue; |
124 | } |
125 | |
126 | int nf_queue(struct sk_buff *skb, struct nf_hook_state *state, |
127 | unsigned int index, unsigned int verdict); |
128 | |
129 | #endif /* _NF_QUEUE_H */ |
130 |
Warning: This file is not a C or C++ file. It does not have highlighting.