ip, ip6: Fix splice to raw and ping sockets
[platform/kernel/linux-starfive.git] / net / ipv6 / ip6_output.c
index 9554cf4..1e8c90e 100644 (file)
@@ -42,6 +42,7 @@
 #include <net/sock.h>
 #include <net/snmp.h>
 
+#include <net/gso.h>
 #include <net/ipv6.h>
 #include <net/ndisc.h>
 #include <net/protocol.h>
@@ -1589,6 +1590,15 @@ emsgsize:
                                skb_zcopy_set(skb, uarg, &extra_uref);
                        }
                }
+       } else if ((flags & MSG_SPLICE_PAGES) && length) {
+               if (inet_sk(sk)->hdrincl)
+                       return -EPERM;
+               if (rt->dst.dev->features & NETIF_F_SG &&
+                   getfrag == ip_generic_getfrag)
+                       /* We need an empty buffer to attach stuff to */
+                       paged = true;
+               else
+                       flags &= ~MSG_SPLICE_PAGES;
        }
 
        /*
@@ -1778,6 +1788,15 @@ alloc_new_skb:
                                err = -EFAULT;
                                goto error;
                        }
+               } else if (flags & MSG_SPLICE_PAGES) {
+                       struct msghdr *msg = from;
+
+                       err = skb_splice_from_iter(skb, &msg->msg_iter, copy,
+                                                  sk->sk_allocation);
+                       if (err < 0)
+                               goto error;
+                       copy = err;
+                       wmem_alloc_delta += copy;
                } else if (!zc) {
                        int i = skb_shinfo(skb)->nr_frags;