]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/ipv4/ip_sockglue.c
ata: ahci_platform: fix owner module reference mismatch for scsi host
[karo-tx-linux.git] / net / ipv4 / ip_sockglue.c
index 9daf2177dc005c339c536c618fedc11259c178bc..8a89c738b7a3b43407293f521bd6d7e009ee7c80 100644 (file)
@@ -192,7 +192,7 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc,
        int err, val;
        struct cmsghdr *cmsg;
 
-       for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+       for_each_cmsghdr(cmsg, msg) {
                if (!CMSG_OK(msg, cmsg))
                        return -EINVAL;
 #if IS_ENABLED(CONFIG_IPV6)
@@ -399,6 +399,22 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf
                kfree_skb(skb);
 }
 
+static bool ipv4_pktinfo_prepare_errqueue(const struct sock *sk,
+                                         const struct sk_buff *skb,
+                                         int ee_origin)
+{
+       struct in_pktinfo *info = PKTINFO_SKB_CB(skb);
+
+       if ((ee_origin != SO_EE_ORIGIN_TIMESTAMPING) ||
+           (!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG)) ||
+           (!skb->dev))
+               return false;
+
+       info->ipi_spec_dst.s_addr = ip_hdr(skb)->saddr;
+       info->ipi_ifindex = skb->dev->ifindex;
+       return true;
+}
+
 /*
  *     Handle MSG_ERRQUEUE
  */
@@ -414,6 +430,8 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
        int err;
        int copied;
 
+       WARN_ON_ONCE(sk->sk_family == AF_INET6);
+
        err = -EAGAIN;
        skb = sock_dequeue_err_skb(sk);
        if (skb == NULL)
@@ -424,7 +442,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
                msg->msg_flags |= MSG_TRUNC;
                copied = len;
        }
-       err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+       err = skb_copy_datagram_msg(skb, 0, msg, copied);
        if (err)
                goto out_free_skb;
 
@@ -444,7 +462,9 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
        memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
        sin = &errhdr.offender;
        sin->sin_family = AF_UNSPEC;
-       if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) {
+
+       if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
+           ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) {
                struct inet_sock *inet = inet_sk(sk);
 
                sin->sin_family = AF_INET;
@@ -1049,7 +1069,7 @@ e_inval:
 }
 
 /**
- * ipv4_pktinfo_prepare - transfert some info from rtable to skb
+ * ipv4_pktinfo_prepare - transfer some info from rtable to skb
  * @sk: socket
  * @skb: buffer
  *