forked from mirrors/linux
		
	net: SO_RCVMARK socket option for SO_MARK with recvmsg()
Adding a new socket option, SO_RCVMARK, to indicate that SO_MARK should be included in the ancillary data returned by recvmsg(). Renamed the sock_recv_ts_and_drops() function to sock_recv_cmsgs(). Signed-off-by: Erin MacNeil <lnx.erin@gmail.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: David Ahern <dsahern@kernel.org> Acked-by: Marc Kleine-Budde <mkl@pengutronix.de> Link: https://lore.kernel.org/r/20220427200259.2564-1-lnx.erin@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
		
							parent
							
								
									0e55546b18
								
							
						
					
					
						commit
						6fd1d51cfa
					
				
					 23 changed files with 56 additions and 27 deletions
				
			
		|  | @ -135,6 +135,8 @@ | ||||||
| 
 | 
 | ||||||
| #define SO_TXREHASH		74 | #define SO_TXREHASH		74 | ||||||
| 
 | 
 | ||||||
|  | #define SO_RCVMARK		75 | ||||||
|  | 
 | ||||||
| #if !defined(__KERNEL__) | #if !defined(__KERNEL__) | ||||||
| 
 | 
 | ||||||
| #if __BITS_PER_LONG == 64 | #if __BITS_PER_LONG == 64 | ||||||
|  |  | ||||||
|  | @ -146,6 +146,8 @@ | ||||||
| 
 | 
 | ||||||
| #define SO_TXREHASH		74 | #define SO_TXREHASH		74 | ||||||
| 
 | 
 | ||||||
|  | #define SO_RCVMARK		75 | ||||||
|  | 
 | ||||||
| #if !defined(__KERNEL__) | #if !defined(__KERNEL__) | ||||||
| 
 | 
 | ||||||
| #if __BITS_PER_LONG == 64 | #if __BITS_PER_LONG == 64 | ||||||
|  |  | ||||||
|  | @ -127,6 +127,8 @@ | ||||||
| 
 | 
 | ||||||
| #define SO_TXREHASH		0x4048 | #define SO_TXREHASH		0x4048 | ||||||
| 
 | 
 | ||||||
|  | #define SO_RCVMARK		0x4049 | ||||||
|  | 
 | ||||||
| #if !defined(__KERNEL__) | #if !defined(__KERNEL__) | ||||||
| 
 | 
 | ||||||
| #if __BITS_PER_LONG == 64 | #if __BITS_PER_LONG == 64 | ||||||
|  |  | ||||||
|  | @ -128,6 +128,7 @@ | ||||||
| 
 | 
 | ||||||
| #define SO_TXREHASH              0x0053 | #define SO_TXREHASH              0x0053 | ||||||
| 
 | 
 | ||||||
|  | #define SO_RCVMARK               0x0054 | ||||||
| 
 | 
 | ||||||
| #if !defined(__KERNEL__) | #if !defined(__KERNEL__) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -893,6 +893,7 @@ enum sock_flags { | ||||||
| 	SOCK_TXTIME, | 	SOCK_TXTIME, | ||||||
| 	SOCK_XDP, /* XDP is attached */ | 	SOCK_XDP, /* XDP is attached */ | ||||||
| 	SOCK_TSTAMP_NEW, /* Indicates 64 bit timestamps always */ | 	SOCK_TSTAMP_NEW, /* Indicates 64 bit timestamps always */ | ||||||
|  | 	SOCK_RCVMARK, /* Receive SO_MARK  ancillary data with packet */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) | #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) | ||||||
|  | @ -2647,20 +2648,21 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) | ||||||
| 		__sock_recv_wifi_status(msg, sk, skb); | 		__sock_recv_wifi_status(msg, sk, skb); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, | void __sock_recv_cmsgs(struct msghdr *msg, struct sock *sk, | ||||||
| 			      struct sk_buff *skb); | 		       struct sk_buff *skb); | ||||||
| 
 | 
 | ||||||
| #define SK_DEFAULT_STAMP (-1L * NSEC_PER_SEC) | #define SK_DEFAULT_STAMP (-1L * NSEC_PER_SEC) | ||||||
| static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, | static inline void sock_recv_cmsgs(struct msghdr *msg, struct sock *sk, | ||||||
| 					  struct sk_buff *skb) | 				   struct sk_buff *skb) | ||||||
| { | { | ||||||
| #define FLAGS_TS_OR_DROPS ((1UL << SOCK_RXQ_OVFL)			| \ | #define FLAGS_RECV_CMSGS ((1UL << SOCK_RXQ_OVFL)			| \ | ||||||
| 			   (1UL << SOCK_RCVTSTAMP)) | 			   (1UL << SOCK_RCVTSTAMP)			| \ | ||||||
|  | 			   (1UL << SOCK_RCVMARK)) | ||||||
| #define TSFLAGS_ANY	  (SOF_TIMESTAMPING_SOFTWARE			| \ | #define TSFLAGS_ANY	  (SOF_TIMESTAMPING_SOFTWARE			| \ | ||||||
| 			   SOF_TIMESTAMPING_RAW_HARDWARE) | 			   SOF_TIMESTAMPING_RAW_HARDWARE) | ||||||
| 
 | 
 | ||||||
| 	if (sk->sk_flags & FLAGS_TS_OR_DROPS || sk->sk_tsflags & TSFLAGS_ANY) | 	if (sk->sk_flags & FLAGS_RECV_CMSGS || sk->sk_tsflags & TSFLAGS_ANY) | ||||||
| 		__sock_recv_ts_and_drops(msg, sk, skb); | 		__sock_recv_cmsgs(msg, sk, skb); | ||||||
| 	else if (unlikely(sock_flag(sk, SOCK_TIMESTAMP))) | 	else if (unlikely(sock_flag(sk, SOCK_TIMESTAMP))) | ||||||
| 		sock_write_timestamp(sk, skb->tstamp); | 		sock_write_timestamp(sk, skb->tstamp); | ||||||
| 	else if (unlikely(sk->sk_stamp == SK_DEFAULT_STAMP)) | 	else if (unlikely(sk->sk_stamp == SK_DEFAULT_STAMP)) | ||||||
|  |  | ||||||
|  | @ -130,6 +130,8 @@ | ||||||
| 
 | 
 | ||||||
| #define SO_TXREHASH		74 | #define SO_TXREHASH		74 | ||||||
| 
 | 
 | ||||||
|  | #define SO_RCVMARK		75 | ||||||
|  | 
 | ||||||
| #if !defined(__KERNEL__) | #if !defined(__KERNEL__) | ||||||
| 
 | 
 | ||||||
| #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__)) | #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__)) | ||||||
|  |  | ||||||
|  | @ -553,7 +553,7 @@ int vcc_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | ||||||
| 	error = skb_copy_datagram_msg(skb, 0, msg, copied); | 	error = skb_copy_datagram_msg(skb, 0, msg, copied); | ||||||
| 	if (error) | 	if (error) | ||||||
| 		return error; | 		return error; | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	if (!(flags & MSG_PEEK)) { | 	if (!(flags & MSG_PEEK)) { | ||||||
| 		pr_debug("%d -= %d\n", atomic_read(&sk->sk_rmem_alloc), | 		pr_debug("%d -= %d\n", atomic_read(&sk->sk_rmem_alloc), | ||||||
|  |  | ||||||
|  | @ -280,7 +280,7 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | ||||||
| 	skb_reset_transport_header(skb); | 	skb_reset_transport_header(skb); | ||||||
| 	err = skb_copy_datagram_msg(skb, 0, msg, copied); | 	err = skb_copy_datagram_msg(skb, 0, msg, copied); | ||||||
| 	if (err == 0) { | 	if (err == 0) { | ||||||
| 		sock_recv_ts_and_drops(msg, sk, skb); | 		sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 		if (msg->msg_name && bt_sk(sk)->skb_msg_name) | 		if (msg->msg_name && bt_sk(sk)->skb_msg_name) | ||||||
| 			bt_sk(sk)->skb_msg_name(skb, msg->msg_name, | 			bt_sk(sk)->skb_msg_name(skb, msg->msg_name, | ||||||
|  | @ -384,7 +384,7 @@ int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg, | ||||||
| 		copied += chunk; | 		copied += chunk; | ||||||
| 		size   -= chunk; | 		size   -= chunk; | ||||||
| 
 | 
 | ||||||
| 		sock_recv_ts_and_drops(msg, sk, skb); | 		sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 		if (!(flags & MSG_PEEK)) { | 		if (!(flags & MSG_PEEK)) { | ||||||
| 			int skb_len = skb_headlen(skb); | 			int skb_len = skb_headlen(skb); | ||||||
|  |  | ||||||
|  | @ -1647,7 +1647,7 @@ static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | ||||||
| 		return err; | 		return err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	if (msg->msg_name) { | 	if (msg->msg_name) { | ||||||
| 		__sockaddr_check_size(BCM_MIN_NAMELEN); | 		__sockaddr_check_size(BCM_MIN_NAMELEN); | ||||||
|  |  | ||||||
|  | @ -841,7 +841,7 @@ static int j1939_sk_recvmsg(struct socket *sock, struct msghdr *msg, | ||||||
| 		paddr->can_addr.j1939.pgn = skcb->addr.pgn; | 		paddr->can_addr.j1939.pgn = skcb->addr.pgn; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 	msg->msg_flags |= skcb->msg_flags; | 	msg->msg_flags |= skcb->msg_flags; | ||||||
| 	skb_free_datagram(sk, skb); | 	skb_free_datagram(sk, skb); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -866,7 +866,7 @@ static int raw_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | ||||||
| 		return err; | 		return err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	if (msg->msg_name) { | 	if (msg->msg_name) { | ||||||
| 		__sockaddr_check_size(RAW_MIN_NAMELEN); | 		__sockaddr_check_size(RAW_MIN_NAMELEN); | ||||||
|  |  | ||||||
|  | @ -1311,6 +1311,9 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 
 | 
 | ||||||
| 		__sock_set_mark(sk, val); | 		__sock_set_mark(sk, val); | ||||||
| 		break; | 		break; | ||||||
|  | 	case SO_RCVMARK: | ||||||
|  | 		sock_valbool_flag(sk, SOCK_RCVMARK, valbool); | ||||||
|  | 		break; | ||||||
| 
 | 
 | ||||||
| 	case SO_RXQ_OVFL: | 	case SO_RXQ_OVFL: | ||||||
| 		sock_valbool_flag(sk, SOCK_RXQ_OVFL, valbool); | 		sock_valbool_flag(sk, SOCK_RXQ_OVFL, valbool); | ||||||
|  | @ -1737,6 +1740,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | ||||||
| 		v.val = sk->sk_mark; | 		v.val = sk->sk_mark; | ||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
|  | 	case SO_RCVMARK: | ||||||
|  | 		v.val = sock_flag(sk, SOCK_RCVMARK); | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
| 	case SO_RXQ_OVFL: | 	case SO_RXQ_OVFL: | ||||||
| 		v.val = sock_flag(sk, SOCK_RXQ_OVFL); | 		v.val = sock_flag(sk, SOCK_RXQ_OVFL); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
|  | @ -328,7 +328,7 @@ static int raw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, | ||||||
| 	if (err) | 	if (err) | ||||||
| 		goto done; | 		goto done; | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	if (flags & MSG_TRUNC) | 	if (flags & MSG_TRUNC) | ||||||
| 		copied = skb->len; | 		copied = skb->len; | ||||||
|  | @ -718,7 +718,7 @@ static int dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, | ||||||
| 	if (err) | 	if (err) | ||||||
| 		goto done; | 		goto done; | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	if (saddr) { | 	if (saddr) { | ||||||
| 		/* Clear the implicit padding in struct sockaddr_ieee802154
 | 		/* Clear the implicit padding in struct sockaddr_ieee802154
 | ||||||
|  |  | ||||||
|  | @ -783,7 +783,7 @@ static int raw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, | ||||||
| 	if (err) | 	if (err) | ||||||
| 		goto done; | 		goto done; | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	/* Copy the address. */ | 	/* Copy the address. */ | ||||||
| 	if (sin) { | 	if (sin) { | ||||||
|  |  | ||||||
|  | @ -1909,7 +1909,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags, | ||||||
| 		UDP_INC_STATS(sock_net(sk), | 		UDP_INC_STATS(sock_net(sk), | ||||||
| 			      UDP_MIB_INDATAGRAMS, is_udplite); | 			      UDP_MIB_INDATAGRAMS, is_udplite); | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	/* Copy the address. */ | 	/* Copy the address. */ | ||||||
| 	if (sin) { | 	if (sin) { | ||||||
|  |  | ||||||
|  | @ -512,7 +512,7 @@ static int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, | ||||||
| 		*addr_len = sizeof(*sin6); | 		*addr_len = sizeof(*sin6); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	if (np->rxopt.all) | 	if (np->rxopt.all) | ||||||
| 		ip6_datagram_recv_ctl(sk, msg, skb); | 		ip6_datagram_recv_ctl(sk, msg, skb); | ||||||
|  |  | ||||||
|  | @ -391,7 +391,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, | ||||||
| 	if (!peeking) | 	if (!peeking) | ||||||
| 		SNMP_INC_STATS(mib, UDP_MIB_INDATAGRAMS); | 		SNMP_INC_STATS(mib, UDP_MIB_INDATAGRAMS); | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	/* Copy the address. */ | 	/* Copy the address. */ | ||||||
| 	if (msg->msg_name) { | 	if (msg->msg_name) { | ||||||
|  |  | ||||||
|  | @ -3711,7 +3711,7 @@ static int pfkey_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | ||||||
| 	if (err) | 	if (err) | ||||||
| 		goto out_free; | 		goto out_free; | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	err = (flags & MSG_TRUNC) ? skb->len : copied; | 	err = (flags & MSG_TRUNC) ? skb->len : copied; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -238,7 +238,7 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | ||||||
| 	if (rc < 0) | 	if (rc < 0) | ||||||
| 		goto out_free; | 		goto out_free; | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	if (addr) { | 	if (addr) { | ||||||
| 		struct mctp_skb_cb *cb = mctp_cb(skb); | 		struct mctp_skb_cb *cb = mctp_cb(skb); | ||||||
|  |  | ||||||
|  | @ -3477,7 +3477,7 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | ||||||
| 		sll->sll_protocol = skb->protocol; | 		sll->sll_protocol = skb->protocol; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sock_recv_ts_and_drops(msg, sk, skb); | 	sock_recv_cmsgs(msg, sk, skb); | ||||||
| 
 | 
 | ||||||
| 	if (msg->msg_name) { | 	if (msg->msg_name) { | ||||||
| 		const size_t max_len = min(sizeof(skb->cb), | 		const size_t max_len = min(sizeof(skb->cb), | ||||||
|  |  | ||||||
|  | @ -2128,7 +2128,7 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, | ||||||
| 		head_skb = event->chunk->head_skb; | 		head_skb = event->chunk->head_skb; | ||||||
| 	else | 	else | ||||||
| 		head_skb = skb; | 		head_skb = skb; | ||||||
| 	sock_recv_ts_and_drops(msg, sk, head_skb); | 	sock_recv_cmsgs(msg, sk, head_skb); | ||||||
| 	if (sctp_ulpevent_is_notification(event)) { | 	if (sctp_ulpevent_is_notification(event)) { | ||||||
| 		msg->msg_flags |= MSG_NOTIFICATION; | 		msg->msg_flags |= MSG_NOTIFICATION; | ||||||
| 		sp->pf->event_msgname(event, msg->msg_name, addr_len); | 		sp->pf->event_msgname(event, msg->msg_name, addr_len); | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								net/socket.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								net/socket.c
									
									
									
									
									
								
							|  | @ -930,13 +930,22 @@ static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, | ||||||
| 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount); | 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, | static void sock_recv_mark(struct msghdr *msg, struct sock *sk, | ||||||
| 	struct sk_buff *skb) | 			   struct sk_buff *skb) | ||||||
|  | { | ||||||
|  | 	if (sock_flag(sk, SOCK_RCVMARK) && skb) | ||||||
|  | 		put_cmsg(msg, SOL_SOCKET, SO_MARK, sizeof(__u32), | ||||||
|  | 			 &skb->mark); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void __sock_recv_cmsgs(struct msghdr *msg, struct sock *sk, | ||||||
|  | 		       struct sk_buff *skb) | ||||||
| { | { | ||||||
| 	sock_recv_timestamp(msg, sk, skb); | 	sock_recv_timestamp(msg, sk, skb); | ||||||
| 	sock_recv_drops(msg, sk, skb); | 	sock_recv_drops(msg, sk, skb); | ||||||
|  | 	sock_recv_mark(msg, sk, skb); | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); | EXPORT_SYMBOL_GPL(__sock_recv_cmsgs); | ||||||
| 
 | 
 | ||||||
| INDIRECT_CALLABLE_DECLARE(int inet_recvmsg(struct socket *, struct msghdr *, | INDIRECT_CALLABLE_DECLARE(int inet_recvmsg(struct socket *, struct msghdr *, | ||||||
| 					   size_t, int)); | 					   size_t, int)); | ||||||
|  |  | ||||||
|  | @ -119,6 +119,8 @@ | ||||||
| 
 | 
 | ||||||
| #define SO_DETACH_REUSEPORT_BPF 68 | #define SO_DETACH_REUSEPORT_BPF 68 | ||||||
| 
 | 
 | ||||||
|  | #define SO_RCVMARK		75 | ||||||
|  | 
 | ||||||
| #if !defined(__KERNEL__) | #if !defined(__KERNEL__) | ||||||
| 
 | 
 | ||||||
| #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__)) | #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__)) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Erin MacNeil
						Erin MacNeil