Merge branch 'pci/misc' into next
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / ping.c
index 2a3720fb5a5ff5401c5efbef49427fb18dbbfa5e..208d5439e59b2e8c3ccb2da46c292ad4f75b3784 100644 (file)
@@ -259,6 +259,9 @@ int ping_init_sock(struct sock *sk)
        kgid_t low, high;
        int ret = 0;
 
+       if (sk->sk_family == AF_INET6)
+               sk->sk_ipv6only = 1;
+
        inet_get_ping_group_range_net(net, &low, &high);
        if (gid_lte(low, group) && gid_lte(group, high))
                return 0;
@@ -305,6 +308,11 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
                if (addr_len < sizeof(*addr))
                        return -EINVAL;
 
+               if (addr->sin_family != AF_INET &&
+                   !(addr->sin_family == AF_UNSPEC &&
+                     addr->sin_addr.s_addr == htonl(INADDR_ANY)))
+                       return -EAFNOSUPPORT;
+
                pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n",
                         sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port));
 
@@ -330,7 +338,7 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
                        return -EINVAL;
 
                if (addr->sin6_family != AF_INET6)
-                       return -EINVAL;
+                       return -EAFNOSUPPORT;
 
                pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n",
                         sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port));
@@ -599,18 +607,18 @@ int ping_getfrag(void *from, char *to,
        struct pingfakehdr *pfh = (struct pingfakehdr *)from;
 
        if (offset == 0) {
-               if (fraglen < sizeof(struct icmphdr))
+               fraglen -= sizeof(struct icmphdr);
+               if (fraglen < 0)
                        BUG();
-               if (csum_partial_copy_fromiovecend(to + sizeof(struct icmphdr),
-                           pfh->iov, 0, fraglen - sizeof(struct icmphdr),
-                           &pfh->wcheck))
+               if (csum_and_copy_from_iter(to + sizeof(struct icmphdr),
+                           fraglen, &pfh->wcheck,
+                           &pfh->msg->msg_iter) != fraglen)
                        return -EFAULT;
        } else if (offset < sizeof(struct icmphdr)) {
                        BUG();
        } else {
-               if (csum_partial_copy_fromiovecend
-                               (to, pfh->iov, offset - sizeof(struct icmphdr),
-                                fraglen, &pfh->wcheck))
+               if (csum_and_copy_from_iter(to, fraglen, &pfh->wcheck,
+                                           &pfh->msg->msg_iter) != fraglen)
                        return -EFAULT;
        }
 
@@ -716,7 +724,7 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
                if (msg->msg_namelen < sizeof(*usin))
                        return -EINVAL;
                if (usin->sin_family != AF_INET)
-                       return -EINVAL;
+                       return -EAFNOSUPPORT;
                daddr = usin->sin_addr.s_addr;
                /* no remote port */
        } else {
@@ -811,8 +819,7 @@ back_from_confirm:
        pfh.icmph.checksum = 0;
        pfh.icmph.un.echo.id = inet->inet_sport;
        pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence;
-       /* XXX: stripping const */
-       pfh.iov = (struct iovec *)msg->msg_iter.iov;
+       pfh.msg = msg;
        pfh.wcheck = 0;
        pfh.family = AF_INET;