ip_output.c (24e8a2ca1f74574ad2ed1ac7af0260dd90fd911e) ip_output.c (956fe2190820df3a6ee530204e059da508159319)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * INET An implementation of the TCP/IP protocol suite for the LINUX
4 * operating system. INET is implemented using the BSD Socket
5 * interface as the means of communication with the user level.
6 *
7 * The Internet Protocol (IP) output module.
8 *

--- 273 unchanged lines hidden (view full) ---

282 if (err && ret == 0)
283 ret = err;
284 segs = nskb;
285 } while (segs);
286
287 return ret;
288}
289
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * INET An implementation of the TCP/IP protocol suite for the LINUX
4 * operating system. INET is implemented using the BSD Socket
5 * interface as the means of communication with the user level.
6 *
7 * The Internet Protocol (IP) output module.
8 *

--- 273 unchanged lines hidden (view full) ---

282 if (err && ret == 0)
283 ret = err;
284 segs = nskb;
285 } while (segs);
286
287 return ret;
288}
289
290static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)
290static int __ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)
291{
292 unsigned int mtu;
291{
292 unsigned int mtu;
293 int ret;
294
293
295 ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb);
296 if (ret) {
297 kfree_skb(skb);
298 return ret;
299 }
300
301#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
302 /* Policy lookup after SNAT yielded a new policy */
303 if (skb_dst(skb)->xfrm) {
304 IPCB(skb)->flags |= IPSKB_REROUTED;
305 return dst_output(net, sk, skb);
306 }
307#endif
308 mtu = ip_skb_dst_mtu(sk, skb);
309 if (skb_is_gso(skb))
310 return ip_finish_output_gso(net, sk, skb, mtu);
311
312 if (skb->len > mtu || (IPCB(skb)->flags & IPSKB_FRAG_PMTU))
313 return ip_fragment(net, sk, skb, mtu, ip_finish_output2);
314
315 return ip_finish_output2(net, sk, skb);
316}
317
294#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
295 /* Policy lookup after SNAT yielded a new policy */
296 if (skb_dst(skb)->xfrm) {
297 IPCB(skb)->flags |= IPSKB_REROUTED;
298 return dst_output(net, sk, skb);
299 }
300#endif
301 mtu = ip_skb_dst_mtu(sk, skb);
302 if (skb_is_gso(skb))
303 return ip_finish_output_gso(net, sk, skb, mtu);
304
305 if (skb->len > mtu || (IPCB(skb)->flags & IPSKB_FRAG_PMTU))
306 return ip_fragment(net, sk, skb, mtu, ip_finish_output2);
307
308 return ip_finish_output2(net, sk, skb);
309}
310
311static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)
312{
313 int ret;
314
315 ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb);
316 switch (ret) {
317 case NET_XMIT_SUCCESS:
318 return __ip_finish_output(net, sk, skb);
319 case NET_XMIT_CN:
320 return __ip_finish_output(net, sk, skb) ? : ret;
321 default:
322 kfree_skb(skb);
323 return ret;
324 }
325}
326
318static int ip_mc_finish_output(struct net *net, struct sock *sk,
319 struct sk_buff *skb)
320{
321 int ret;
322
323 ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb);
327static int ip_mc_finish_output(struct net *net, struct sock *sk,
328 struct sk_buff *skb)
329{
330 int ret;
331
332 ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb);
324 if (ret) {
333 switch (ret) {
334 case NET_XMIT_SUCCESS:
335 return dev_loopback_xmit(net, sk, skb);
336 case NET_XMIT_CN:
337 return dev_loopback_xmit(net, sk, skb) ? : ret;
338 default:
325 kfree_skb(skb);
326 return ret;
327 }
339 kfree_skb(skb);
340 return ret;
341 }
328
329 return dev_loopback_xmit(net, sk, skb);
330}
331
332int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)
333{
334 struct rtable *rt = skb_rtable(skb);
335 struct net_device *dev = rt->dst.dev;
336
337 /*

--- 1298 unchanged lines hidden ---
342}
343
344int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)
345{
346 struct rtable *rt = skb_rtable(skb);
347 struct net_device *dev = rt->dst.dev;
348
349 /*

--- 1298 unchanged lines hidden ---