hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/ipv6/netfilter.c
....@@ -16,6 +16,9 @@
1616 #include <net/ip6_route.h>
1717 #include <net/xfrm.h>
1818 #include <net/netfilter/nf_queue.h>
19
+#include <net/netfilter/nf_conntrack_bridge.h>
20
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
21
+#include "../bridge/br_private.h"
1922
2023 int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff *skb)
2124 {
....@@ -86,8 +89,8 @@
8689 return 0;
8790 }
8891
89
-static int nf_ip6_route(struct net *net, struct dst_entry **dst,
90
- struct flowi *fl, bool strict)
92
+int __nf_ip6_route(struct net *net, struct dst_entry **dst,
93
+ struct flowi *fl, bool strict)
9194 {
9295 static const struct ipv6_pinfo fake_pinfo;
9396 static const struct inet_sock fake_sk = {
....@@ -107,13 +110,144 @@
107110 *dst = result;
108111 return err;
109112 }
113
+EXPORT_SYMBOL_GPL(__nf_ip6_route);
114
+
115
+int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
116
+ struct nf_bridge_frag_data *data,
117
+ int (*output)(struct net *, struct sock *sk,
118
+ const struct nf_bridge_frag_data *data,
119
+ struct sk_buff *))
120
+{
121
+ int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
122
+ ktime_t tstamp = skb->tstamp;
123
+ struct ip6_frag_state state;
124
+ u8 *prevhdr, nexthdr = 0;
125
+ unsigned int mtu, hlen;
126
+ int hroom, err = 0;
127
+ __be32 frag_id;
128
+
129
+ err = ip6_find_1stfragopt(skb, &prevhdr);
130
+ if (err < 0)
131
+ goto blackhole;
132
+ hlen = err;
133
+ nexthdr = *prevhdr;
134
+
135
+ mtu = skb->dev->mtu;
136
+ if (frag_max_size > mtu ||
137
+ frag_max_size < IPV6_MIN_MTU)
138
+ goto blackhole;
139
+
140
+ mtu = frag_max_size;
141
+ if (mtu < hlen + sizeof(struct frag_hdr) + 8)
142
+ goto blackhole;
143
+ mtu -= hlen + sizeof(struct frag_hdr);
144
+
145
+ frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr,
146
+ &ipv6_hdr(skb)->saddr);
147
+
148
+ if (skb->ip_summed == CHECKSUM_PARTIAL &&
149
+ (err = skb_checksum_help(skb)))
150
+ goto blackhole;
151
+
152
+ hroom = LL_RESERVED_SPACE(skb->dev);
153
+ if (skb_has_frag_list(skb)) {
154
+ unsigned int first_len = skb_pagelen(skb);
155
+ struct ip6_fraglist_iter iter;
156
+ struct sk_buff *frag2;
157
+
158
+ if (first_len - hlen > mtu ||
159
+ skb_headroom(skb) < (hroom + sizeof(struct frag_hdr)))
160
+ goto blackhole;
161
+
162
+ if (skb_cloned(skb))
163
+ goto slow_path;
164
+
165
+ skb_walk_frags(skb, frag2) {
166
+ if (frag2->len > mtu ||
167
+ skb_headroom(frag2) < (hlen + hroom + sizeof(struct frag_hdr)))
168
+ goto blackhole;
169
+
170
+ /* Partially cloned skb? */
171
+ if (skb_shared(frag2))
172
+ goto slow_path;
173
+ }
174
+
175
+ err = ip6_fraglist_init(skb, hlen, prevhdr, nexthdr, frag_id,
176
+ &iter);
177
+ if (err < 0)
178
+ goto blackhole;
179
+
180
+ for (;;) {
181
+ /* Prepare header of the next frame,
182
+ * before previous one went down.
183
+ */
184
+ if (iter.frag)
185
+ ip6_fraglist_prepare(skb, &iter);
186
+
187
+ skb->tstamp = tstamp;
188
+ err = output(net, sk, data, skb);
189
+ if (err || !iter.frag)
190
+ break;
191
+
192
+ skb = ip6_fraglist_next(&iter);
193
+ }
194
+
195
+ kfree(iter.tmp_hdr);
196
+ if (!err)
197
+ return 0;
198
+
199
+ kfree_skb_list(iter.frag);
200
+ return err;
201
+ }
202
+slow_path:
203
+ /* This is a linearized skbuff, the original geometry is lost for us.
204
+ * This may also be a clone skbuff, we could preserve the geometry for
205
+ * the copies but probably not worth the effort.
206
+ */
207
+ ip6_frag_init(skb, hlen, mtu, skb->dev->needed_tailroom,
208
+ LL_RESERVED_SPACE(skb->dev), prevhdr, nexthdr, frag_id,
209
+ &state);
210
+
211
+ while (state.left > 0) {
212
+ struct sk_buff *skb2;
213
+
214
+ skb2 = ip6_frag_next(skb, &state);
215
+ if (IS_ERR(skb2)) {
216
+ err = PTR_ERR(skb2);
217
+ goto blackhole;
218
+ }
219
+
220
+ skb2->tstamp = tstamp;
221
+ err = output(net, sk, data, skb2);
222
+ if (err)
223
+ goto blackhole;
224
+ }
225
+ consume_skb(skb);
226
+ return err;
227
+
228
+blackhole:
229
+ kfree_skb(skb);
230
+ return 0;
231
+}
232
+EXPORT_SYMBOL_GPL(br_ip6_fragment);
110233
111234 static const struct nf_ipv6_ops ipv6ops = {
235
+#if IS_MODULE(CONFIG_IPV6)
112236 .chk_addr = ipv6_chk_addr,
113
- .route_input = ip6_route_input,
237
+ .route_me_harder = ip6_route_me_harder,
238
+ .dev_get_saddr = ipv6_dev_get_saddr,
239
+ .route = __nf_ip6_route,
240
+#if IS_ENABLED(CONFIG_SYN_COOKIES)
241
+ .cookie_init_sequence = __cookie_v6_init_sequence,
242
+ .cookie_v6_check = __cookie_v6_check,
243
+#endif
244
+#endif
245
+ .route_input = ip6_route_input,
114246 .fragment = ip6_fragment,
115
- .route = nf_ip6_route,
116247 .reroute = nf_ip6_reroute,
248
+#if IS_MODULE(CONFIG_IPV6)
249
+ .br_fragment = br_ip6_fragment,
250
+#endif
117251 };
118252
119253 int __init ipv6_netfilter_init(void)