lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1417654592.5303.148.camel@edumazet-glaptop2.roam.corp.google.com>
Date:	Wed, 03 Dec 2014 16:56:32 -0800
From:	Eric Dumazet <eric.dumazet@...il.com>
To:	Tom Herbert <therbert@...gle.com>,
	Michael Kerrisk <mtk.manpages@...il.com>
Cc:	davem@...emloft.net, netdev@...r.kernel.org
Subject: Re: [PATCH net-next 3/3] ip: Add support for IP_CHECKSUM cmsg

CC Michael Kerrisk <mtk.manpages@...il.com> for man pages...

On Wed, 2014-12-03 at 16:44 -0800, Tom Herbert wrote:
> New cmsg type is IP_CHECKSUM under SOL_IP. Enabled by standard
> setsockopt.
> 
> The value returned is the unfolded 32 bit checksum of the packet
> being received starting from the first byte returned in recvmsg
> through the end of the packet (truncation is disregarded).
> 
> Modified UDP to postpull checksum beyond UDP header before returning
> checksum for UDP data to userspace.
> 
> Signed-off-by: Tom Herbert <therbert@...gle.com>
> ---
>  include/net/inet_sock.h |  1 +
>  include/uapi/linux/in.h |  1 +
>  net/ipv4/ip_sockglue.c  | 34 +++++++++++++++++++++++++++++++++-
>  net/ipv4/udp.c          | 10 +++++++++-
>  4 files changed, 44 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
> index 4091fab..2823fc0 100644
> --- a/include/net/inet_sock.h
> +++ b/include/net/inet_sock.h
> @@ -203,6 +203,7 @@ struct inet_sock {
>  #define IP_CMSG_RETOPTS		(1 << 4)
>  #define IP_CMSG_PASSSEC		(1 << 5)
>  #define IP_CMSG_ORIGDSTADDR	(1 << 6)
> +#define IP_CMSG_CHECKSUM	(1 << 7)
>  
>  static inline struct inet_sock *inet_sk(const struct sock *sk)
>  {
> diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h
> index c33a65e..589ced0 100644
> --- a/include/uapi/linux/in.h
> +++ b/include/uapi/linux/in.h
> @@ -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 */
> diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
> index d4406aa..054280f 100644
> --- a/net/ipv4/ip_sockglue.c
> +++ b/net/ipv4/ip_sockglue.c
> @@ -96,6 +96,14 @@ 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)
> +{
> +	if (skb->ip_summed != CHECKSUM_COMPLETE)
> +		return;
> +
> +	put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &skb->csum);
> +}
> +
>  static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
>  {
>  	char *secdata;
> @@ -190,9 +198,16 @@ void ip_cmsg_recv(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);
>  }
>  EXPORT_SYMBOL(ip_cmsg_recv);
>  
> @@ -512,6 +527,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;
> @@ -609,6 +625,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;
> @@ -1212,6 +1241,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;
> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> index 221b53f..bba2e06 100644
> --- a/net/ipv4/udp.c
> +++ b/net/ipv4/udp.c
> @@ -1315,8 +1315,16 @@ try_again:
>  		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
>  		*addr_len = sizeof(*sin);
>  	}
> -	if (inet->cmsg_flags)
> +	if (inet->cmsg_flags) {
> +		/* Pull checksum past UDP header in case we are providing
> +		 * checksum in cmsg.
> +		 */
> +		if (inet->cmsg_flags & IP_CMSG_CHECKSUM)
> +			skb_postpull_rcsum(skb, skb->data,
> +					   sizeof(struct udphdr));
> +
>  		ip_cmsg_recv(msg, skb);
> +	}
>  
>  	err = copied;
>  	if (flags & MSG_TRUNC)


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ