Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4253c62 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ip_cmsg_csum'



Tom Herbert says:

====================
ip: Support checksum returned in csmg

This patch set allows the packet checksum for a datagram socket
to be returned in csum data in recvmsg. This allows userspace
to implement its own checksum over the data, for instance if an
IP tunnel was be implemented in user space, the inner checksum
could be validated.

Changes in this patch set:
  - Move checksum conversion to inet_sock from udp_sock. This
    generalizes checksum conversion for use with other protocols.
  - Move IP cmsg constants to a header file and make processing
    of the flags more efficient in ip_cmsg_recv
  - Return checksum value in cmsg. This is specifically the unfolded
    32 bit checksum of the full packet starting from the first byte
    returned in recvmsg

Tested: Wrote a little server to get checksums in cmsg for UDP and
        verfied correct checksum is returned.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 149118d8 ad6f939a
Loading
Loading
Loading
Loading
+1 −15
Original line number Original line Diff line number Diff line
@@ -49,11 +49,7 @@ struct udp_sock {
	unsigned int	 corkflag;	/* Cork is required */
	unsigned int	 corkflag;	/* Cork is required */
	__u8		 encap_type;	/* Is this an Encapsulation socket? */
	__u8		 encap_type;	/* Is this an Encapsulation socket? */
	unsigned char	 no_check6_tx:1,/* Send zero UDP6 checksums on TX? */
	unsigned char	 no_check6_tx:1,/* Send zero UDP6 checksums on TX? */
			 no_check6_rx:1,/* Allow zero UDP6 checksums on RX? */
			 no_check6_rx:1;/* Allow zero UDP6 checksums on RX? */
			 convert_csum:1;/* On receive, convert checksum
					 * unnecessary to checksum complete
					 * if possible.
					 */
	/*
	/*
	 * Following member retains the information to create a UDP header
	 * Following member retains the information to create a UDP header
	 * when the socket is uncorked.
	 * when the socket is uncorked.
@@ -102,16 +98,6 @@ static inline bool udp_get_no_check6_rx(struct sock *sk)
	return udp_sk(sk)->no_check6_rx;
	return udp_sk(sk)->no_check6_rx;
}
}


static inline void udp_set_convert_csum(struct sock *sk, bool val)
{
	udp_sk(sk)->convert_csum = val;
}

static inline bool udp_get_convert_csum(struct sock *sk)
{
	return udp_sk(sk)->convert_csum;
}

#define udp_portaddr_for_each_entry(__sk, node, list) \
#define udp_portaddr_for_each_entry(__sk, node, list) \
	hlist_nulls_for_each_entry(__sk, node, list, __sk_common.skc_portaddr_node)
	hlist_nulls_for_each_entry(__sk, node, list, __sk_common.skc_portaddr_node)


+28 −1
Original line number Original line Diff line number Diff line
@@ -16,7 +16,7 @@
#ifndef _INET_SOCK_H
#ifndef _INET_SOCK_H
#define _INET_SOCK_H
#define _INET_SOCK_H



#include <linux/bitops.h>
#include <linux/kmemcheck.h>
#include <linux/kmemcheck.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/types.h>
@@ -184,6 +184,7 @@ struct inet_sock {
				mc_all:1,
				mc_all:1,
				nodefrag:1;
				nodefrag:1;
	__u8			rcv_tos;
	__u8			rcv_tos;
	__u8			convert_csum;
	int			uc_index;
	int			uc_index;
	int			mc_index;
	int			mc_index;
	__be32			mc_addr;
	__be32			mc_addr;
@@ -194,6 +195,16 @@ struct inet_sock {
#define IPCORK_OPT	1	/* ip-options has been held in ipcork.opt */
#define IPCORK_OPT	1	/* ip-options has been held in ipcork.opt */
#define IPCORK_ALLFRAG	2	/* always fragment (for ipv6 for now) */
#define IPCORK_ALLFRAG	2	/* always fragment (for ipv6 for now) */


/* cmsg flags for inet */
#define IP_CMSG_PKTINFO		BIT(0)
#define IP_CMSG_TTL		BIT(1)
#define IP_CMSG_TOS		BIT(2)
#define IP_CMSG_RECVOPTS	BIT(3)
#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)
static inline struct inet_sock *inet_sk(const struct sock *sk)
{
{
	return (struct inet_sock *)sk;
	return (struct inet_sock *)sk;
@@ -250,4 +261,20 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
	return flags;
	return flags;
}
}


static inline void inet_inc_convert_csum(struct sock *sk)
{
	inet_sk(sk)->convert_csum++;
}

static inline void inet_dec_convert_csum(struct sock *sk)
{
	if (inet_sk(sk)->convert_csum > 0)
		inet_sk(sk)->convert_csum--;
}

static inline bool inet_get_convert_csum(struct sock *sk)
{
	return !!inet_sk(sk)->convert_csum;
}

#endif	/* _INET_SOCK_H */
#endif	/* _INET_SOCK_H */
+6 −1
Original line number Original line Diff line number Diff line
@@ -537,7 +537,7 @@ int ip_options_rcv_srr(struct sk_buff *skb);
 */
 */


void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int offset);
int ip_cmsg_send(struct net *net, struct msghdr *msg,
int ip_cmsg_send(struct net *net, struct msghdr *msg,
		 struct ipcm_cookie *ipc, bool allow_ipv6);
		 struct ipcm_cookie *ipc, bool allow_ipv6);
int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
@@ -557,6 +557,11 @@ void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
		    u32 info);
		    u32 info);


static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
{
	ip_cmsg_recv_offset(msg, skb, 0);
}

bool icmp_global_allow(void);
bool icmp_global_allow(void);
extern int sysctl_icmp_msgs_per_sec;
extern int sysctl_icmp_msgs_per_sec;
extern int sysctl_icmp_msgs_burst;
extern int sysctl_icmp_msgs_burst;
+1 −0
Original line number Original line Diff line number Diff line
@@ -109,6 +109,7 @@ struct in_addr {


#define IP_MINTTL       21
#define IP_MINTTL       21
#define IP_NODEFRAG     22
#define IP_NODEFRAG     22
#define IP_CHECKSUM	23


/* IP_MTU_DISCOVER values */
/* IP_MTU_DISCOVER values */
#define IP_PMTUDISC_DONT		0	/* Never send DF frames */
#define IP_PMTUDISC_DONT		0	/* Never send DF frames */
+1 −1
Original line number Original line Diff line number Diff line
@@ -490,7 +490,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
	sk->sk_user_data = fou;
	sk->sk_user_data = fou;
	fou->sock = sock;
	fou->sock = sock;


	udp_set_convert_csum(sk, true);
	inet_inc_convert_csum(sk);


	sk->sk_allocation = GFP_ATOMIC;
	sk->sk_allocation = GFP_ATOMIC;


Loading