1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Definitions and Declarations for tuple. |
4 | * |
5 | * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> |
6 | * - generalize L3 protocol dependent part. |
7 | * |
8 | * Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h |
9 | */ |
10 | |
11 | #ifndef _NF_CONNTRACK_TUPLE_H |
12 | #define _NF_CONNTRACK_TUPLE_H |
13 | |
14 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter/nf_conntrack_tuple_common.h> |
16 | #include <linux/list_nulls.h> |
17 | |
18 | /* A `tuple' is a structure containing the information to uniquely |
19 | identify a connection. ie. if two packets have the same tuple, they |
20 | are in the same connection; if not, they are not. |
21 | |
22 | We divide the structure along "manipulatable" and |
23 | "non-manipulatable" lines, for the benefit of the NAT code. |
24 | */ |
25 | |
26 | #define NF_CT_TUPLE_L3SIZE ARRAY_SIZE(((union nf_inet_addr *)NULL)->all) |
27 | |
28 | /* The manipulable part of the tuple. */ |
29 | struct nf_conntrack_man { |
30 | union nf_inet_addr u3; |
31 | union nf_conntrack_man_proto u; |
32 | /* Layer 3 protocol */ |
33 | u_int16_t l3num; |
34 | }; |
35 | |
36 | /* This contains the information to distinguish a connection. */ |
37 | struct nf_conntrack_tuple { |
38 | struct nf_conntrack_man src; |
39 | |
40 | /* These are the parts of the tuple which are fixed. */ |
41 | struct { |
42 | union nf_inet_addr u3; |
43 | union { |
44 | /* Add other protocols here. */ |
45 | __be16 all; |
46 | |
47 | struct { |
48 | __be16 port; |
49 | } tcp; |
50 | struct { |
51 | __be16 port; |
52 | } udp; |
53 | struct { |
54 | u_int8_t type, code; |
55 | } icmp; |
56 | struct { |
57 | __be16 port; |
58 | } dccp; |
59 | struct { |
60 | __be16 port; |
61 | } sctp; |
62 | struct { |
63 | __be16 key; |
64 | } gre; |
65 | } u; |
66 | |
67 | /* The protocol. */ |
68 | u_int8_t protonum; |
69 | |
70 | /* The direction must be ignored for the tuplehash */ |
71 | struct { } __nfct_hash_offsetend; |
72 | |
73 | /* The direction (for tuplehash) */ |
74 | u_int8_t dir; |
75 | } dst; |
76 | }; |
77 | |
78 | struct nf_conntrack_tuple_mask { |
79 | struct { |
80 | union nf_inet_addr u3; |
81 | union nf_conntrack_man_proto u; |
82 | } src; |
83 | }; |
84 | |
85 | static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t) |
86 | { |
87 | #ifdef DEBUG |
88 | printk("tuple %p: %u %pI4:%hu -> %pI4:%hu\n" , |
89 | t, t->dst.protonum, |
90 | &t->src.u3.ip, ntohs(t->src.u.all), |
91 | &t->dst.u3.ip, ntohs(t->dst.u.all)); |
92 | #endif |
93 | } |
94 | |
95 | static inline void nf_ct_dump_tuple_ipv6(const struct nf_conntrack_tuple *t) |
96 | { |
97 | #ifdef DEBUG |
98 | printk("tuple %p: %u %pI6 %hu -> %pI6 %hu\n" , |
99 | t, t->dst.protonum, |
100 | t->src.u3.all, ntohs(t->src.u.all), |
101 | t->dst.u3.all, ntohs(t->dst.u.all)); |
102 | #endif |
103 | } |
104 | |
105 | static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t) |
106 | { |
107 | switch (t->src.l3num) { |
108 | case AF_INET: |
109 | nf_ct_dump_tuple_ip(t); |
110 | break; |
111 | case AF_INET6: |
112 | nf_ct_dump_tuple_ipv6(t); |
113 | break; |
114 | } |
115 | } |
116 | |
117 | /* If we're the first tuple, it's the original dir. */ |
118 | #define NF_CT_DIRECTION(h) \ |
119 | ((enum ip_conntrack_dir)(h)->tuple.dst.dir) |
120 | |
121 | /* Connections have two entries in the hash table: one for each way */ |
122 | struct nf_conntrack_tuple_hash { |
123 | struct hlist_nulls_node hnnode; |
124 | struct nf_conntrack_tuple tuple; |
125 | }; |
126 | |
127 | static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1, |
128 | const struct nf_conntrack_tuple *t2) |
129 | { |
130 | return (nf_inet_addr_cmp(a1: &t1->src.u3, a2: &t2->src.u3) && |
131 | t1->src.u.all == t2->src.u.all && |
132 | t1->src.l3num == t2->src.l3num); |
133 | } |
134 | |
135 | static inline bool __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1, |
136 | const struct nf_conntrack_tuple *t2) |
137 | { |
138 | return (nf_inet_addr_cmp(a1: &t1->dst.u3, a2: &t2->dst.u3) && |
139 | t1->dst.u.all == t2->dst.u.all && |
140 | t1->dst.protonum == t2->dst.protonum); |
141 | } |
142 | |
143 | static inline bool nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1, |
144 | const struct nf_conntrack_tuple *t2) |
145 | { |
146 | return __nf_ct_tuple_src_equal(t1, t2) && |
147 | __nf_ct_tuple_dst_equal(t1, t2); |
148 | } |
149 | |
150 | static inline bool |
151 | nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1, |
152 | const struct nf_conntrack_tuple_mask *m2) |
153 | { |
154 | return (nf_inet_addr_cmp(a1: &m1->src.u3, a2: &m2->src.u3) && |
155 | m1->src.u.all == m2->src.u.all); |
156 | } |
157 | |
158 | static inline bool |
159 | nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1, |
160 | const struct nf_conntrack_tuple *t2, |
161 | const struct nf_conntrack_tuple_mask *mask) |
162 | { |
163 | int count; |
164 | |
165 | for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) { |
166 | if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) & |
167 | mask->src.u3.all[count]) |
168 | return false; |
169 | } |
170 | |
171 | if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all) |
172 | return false; |
173 | |
174 | if (t1->src.l3num != t2->src.l3num || |
175 | t1->dst.protonum != t2->dst.protonum) |
176 | return false; |
177 | |
178 | return true; |
179 | } |
180 | |
181 | static inline bool |
182 | nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t, |
183 | const struct nf_conntrack_tuple *tuple, |
184 | const struct nf_conntrack_tuple_mask *mask) |
185 | { |
186 | return nf_ct_tuple_src_mask_cmp(t1: t, t2: tuple, mask) && |
187 | __nf_ct_tuple_dst_equal(t1: t, t2: tuple); |
188 | } |
189 | |
190 | #endif /* _NF_CONNTRACK_TUPLE_H */ |
191 | |