mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	ip: Add offset parameter to ip_cmsg_recv
Add ip_cmsg_recv_offset function which takes an offset argument that indicates the starting offset in skb where data is being received from. This will be useful in the case of UDP and provided checksum to user space. ip_cmsg_recv is an inline call to ip_cmsg_recv_offset with offset of zero. Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									5961de9f19
								
							
						
					
					
						commit
						ad6f939ab1
					
				
					 4 changed files with 43 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -203,6 +203,7 @@ struct inet_sock {
 | 
			
		|||
#define IP_CMSG_RETOPTS		BIT(4)
 | 
			
		||||
#define IP_CMSG_PASSSEC		BIT(5)
 | 
			
		||||
#define IP_CMSG_ORIGDSTADDR	BIT(6)
 | 
			
		||||
#define IP_CMSG_CHECKSUM	BIT(7)
 | 
			
		||||
 | 
			
		||||
static inline struct inet_sock *inet_sk(const struct sock *sk)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,6 +109,7 @@ struct in_addr {
 | 
			
		|||
 | 
			
		||||
#define IP_MINTTL       21
 | 
			
		||||
#define IP_NODEFRAG     22
 | 
			
		||||
#define IP_CHECKSUM	23
 | 
			
		||||
 | 
			
		||||
/* IP_MTU_DISCOVER values */
 | 
			
		||||
#define IP_PMTUDISC_DONT		0	/* Never send DF frames */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@
 | 
			
		|||
#include <net/route.h>
 | 
			
		||||
#include <net/xfrm.h>
 | 
			
		||||
#include <net/compat.h>
 | 
			
		||||
#include <net/checksum.h>
 | 
			
		||||
#if IS_ENABLED(CONFIG_IPV6)
 | 
			
		||||
#include <net/transp_v6.h>
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +97,20 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
 | 
			
		|||
	put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
 | 
			
		||||
				  int offset)
 | 
			
		||||
{
 | 
			
		||||
	__wsum csum = skb->csum;
 | 
			
		||||
 | 
			
		||||
	if (skb->ip_summed != CHECKSUM_COMPLETE)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (offset != 0)
 | 
			
		||||
		csum = csum_sub(csum, csum_partial(skb->data, offset, 0));
 | 
			
		||||
 | 
			
		||||
	put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 | 
			
		||||
{
 | 
			
		||||
	char *secdata;
 | 
			
		||||
| 
						 | 
				
			
			@ -191,9 +206,16 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb,
 | 
			
		|||
			return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & IP_CMSG_ORIGDSTADDR)
 | 
			
		||||
	if (flags & IP_CMSG_ORIGDSTADDR) {
 | 
			
		||||
		ip_cmsg_recv_dstaddr(msg, skb);
 | 
			
		||||
 | 
			
		||||
		flags &= ~IP_CMSG_ORIGDSTADDR;
 | 
			
		||||
		if (!flags)
 | 
			
		||||
			return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & IP_CMSG_CHECKSUM)
 | 
			
		||||
		ip_cmsg_recv_checksum(msg, skb, offset);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ip_cmsg_recv_offset);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -533,6 +555,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
 | 
			
		|||
	case IP_MULTICAST_ALL:
 | 
			
		||||
	case IP_MULTICAST_LOOP:
 | 
			
		||||
	case IP_RECVORIGDSTADDR:
 | 
			
		||||
	case IP_CHECKSUM:
 | 
			
		||||
		if (optlen >= sizeof(int)) {
 | 
			
		||||
			if (get_user(val, (int __user *) optval))
 | 
			
		||||
				return -EFAULT;
 | 
			
		||||
| 
						 | 
				
			
			@ -630,6 +653,19 @@ static int do_ip_setsockopt(struct sock *sk, int level,
 | 
			
		|||
		else
 | 
			
		||||
			inet->cmsg_flags &= ~IP_CMSG_ORIGDSTADDR;
 | 
			
		||||
		break;
 | 
			
		||||
	case IP_CHECKSUM:
 | 
			
		||||
		if (val) {
 | 
			
		||||
			if (!(inet->cmsg_flags & IP_CMSG_CHECKSUM)) {
 | 
			
		||||
				inet_inc_convert_csum(sk);
 | 
			
		||||
				inet->cmsg_flags |= IP_CMSG_CHECKSUM;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if (inet->cmsg_flags & IP_CMSG_CHECKSUM) {
 | 
			
		||||
				inet_dec_convert_csum(sk);
 | 
			
		||||
				inet->cmsg_flags &= ~IP_CMSG_CHECKSUM;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case IP_TOS:	/* This sets both TOS and Precedence */
 | 
			
		||||
		if (sk->sk_type == SOCK_STREAM) {
 | 
			
		||||
			val &= ~INET_ECN_MASK;
 | 
			
		||||
| 
						 | 
				
			
			@ -1233,6 +1269,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
 | 
			
		|||
	case IP_RECVORIGDSTADDR:
 | 
			
		||||
		val = (inet->cmsg_flags & IP_CMSG_ORIGDSTADDR) != 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case IP_CHECKSUM:
 | 
			
		||||
		val = (inet->cmsg_flags & IP_CMSG_CHECKSUM) != 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case IP_TOS:
 | 
			
		||||
		val = inet->tos;
 | 
			
		||||
		break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1329,7 +1329,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 | 
			
		|||
		*addr_len = sizeof(*sin);
 | 
			
		||||
	}
 | 
			
		||||
	if (inet->cmsg_flags)
 | 
			
		||||
		ip_cmsg_recv(msg, skb);
 | 
			
		||||
		ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr));
 | 
			
		||||
 | 
			
		||||
	err = copied;
 | 
			
		||||
	if (flags & MSG_TRUNC)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue