diff --git a/include/net/sock.h b/include/net/sock.h index 3784d61d0adc7863b7359d8319042797ab6bc53e..254e220fdb7ff627061edf03b57d6fc6da3d9f69 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1642,12 +1642,14 @@ struct sockcm_cookie { u64 transmit_time; u32 mark; u16 tsflags; + struct skb_redundant_info redinfo; }; static inline void sockcm_init(struct sockcm_cookie *sockc, const struct sock *sk) { *sockc = (struct sockcm_cookie) { .tsflags = sk->sk_tsflags }; + memset(&sockc->redinfo, 0, sizeof(sockc->redinfo)); } int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, @@ -2457,6 +2459,18 @@ static inline void sock_recv_redundant_info(struct msghdr *msg, struct sock *sk, put_cmsg(msg, SOL_SOCKET, SCM_REDUNDANT, sizeof(*sred), sred); } +static inline void sock_tx_redundant_info(const struct sock *sk, + struct skb_redundant_info *redinfo, + struct sk_buff *skb) +{ + struct skb_redundant_info *sred; + + if (redinfo->io_port) { + sred = skb_redinfo(skb); + memcpy(sred, redinfo, sizeof(*sred)); + } +} + /** * sk_eat_skb - Release a skb if it is no longer needed * @sk: socket to eat this skb from diff --git a/net/core/sock.c b/net/core/sock.c index 371f30e353eaa7c21c61411053395930ffaa5590..6eb478f11381656d2a5114d841d972dedc5e38bb 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2270,6 +2270,7 @@ EXPORT_SYMBOL(sock_alloc_send_skb); int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, struct sockcm_cookie *sockc) { + struct skb_redundant_info *cred; u32 tsflags; switch (cmsg->cmsg_type) { @@ -2302,6 +2303,15 @@ int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, case SCM_RIGHTS: case SCM_CREDENTIALS: break; + case SCM_REDUNDANT: + if (cmsg->cmsg_len != + CMSG_LEN(sizeof(struct skb_redundant_info))) + return -EINVAL; + + cred = (struct skb_redundant_info *)CMSG_DATA(cmsg); + memcpy(&sockc->redinfo, cred, + sizeof(struct skb_redundant_info)); + break; default: return -EINVAL; } diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 3d5c3ea4a4ec2e4dab0c53b094f03566bc6e878b..c74689da8ee7d440d9e87c41ef258a3c53e9b488 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2950,6 +2950,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) skb_setup_tx_timestamp(skb, sockc.tsflags); + sock_tx_redundant_info(sk, &sockc.redinfo, skb); + if (!vnet_hdr.gso_type && (len > dev->mtu + reserve + extra_len) && !packet_extra_vlan_len_allowed(dev, skb)) { err = -EMSGSIZE;