Allow the application the ability to use MSG_PEEK with sk_error_queue so that it can peek and re-read message in cases where MSG_TRUNC may be encountered.
Signed-off-by: Sowmini Varadhan <sowmini.varad...@oracle.com> --- drivers/net/tun.c | 2 +- include/net/sock.h | 2 +- net/core/sock.c | 7 +++++-- net/packet/af_packet.c | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 2fba3be..cfd0e0f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2313,7 +2313,7 @@ static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len, } if (flags & MSG_ERRQUEUE) { ret = sock_recv_errqueue(sock->sk, m, total_len, - SOL_PACKET, TUN_TX_TIMESTAMP); + SOL_PACKET, TUN_TX_TIMESTAMP, flags); goto out; } ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT, ptr); diff --git a/include/net/sock.h b/include/net/sock.h index 73b7830..f0b6990 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2343,7 +2343,7 @@ static inline bool sk_listener(const struct sock *sk) int sock_get_timestamp(struct sock *, struct timeval __user *); int sock_get_timestampns(struct sock *, struct timespec __user *); int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, int level, - int type); + int type, int flags); bool sk_ns_capable(const struct sock *sk, struct user_namespace *user_ns, int cap); diff --git a/net/core/sock.c b/net/core/sock.c index 72d14b2..4f52677 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2887,7 +2887,7 @@ void sock_enable_timestamp(struct sock *sk, int flag) } int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, - int level, int type) + int level, int type, int flags) { struct sock_exterr_skb *serr; struct sk_buff *skb; @@ -2916,7 +2916,10 @@ int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, err = copied; out_free_skb: - kfree_skb(skb); + if (likely(!(flags & MSG_PEEK))) + kfree_skb(skb); + else + skb_queue_head(&sk->sk_error_queue, skb); out: return err; } diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ee7aa0b..4314f31 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3294,7 +3294,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, if (flags & MSG_ERRQUEUE) { err = sock_recv_errqueue(sk, msg, len, - SOL_PACKET, PACKET_TX_TIMESTAMP); + SOL_PACKET, PACKET_TX_TIMESTAMP, + flags); goto out; } -- 1.7.1