diff options
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 59 | 
1 files changed, 35 insertions, 24 deletions
diff --git a/net/socket.c b/net/socket.c index abf56b2a14f9..4cdbc107606f 100644 --- a/net/socket.c +++ b/net/socket.c @@ -106,6 +106,7 @@  #include <linux/sockios.h>  #include <linux/atalk.h>  #include <net/busy_poll.h> +#include <linux/errqueue.h>  #ifdef CONFIG_NET_RX_BUSY_POLL  unsigned int sysctl_net_busy_read __read_mostly; @@ -609,15 +610,26 @@ void sock_release(struct socket *sock)  }  EXPORT_SYMBOL(sock_release); -void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) +void sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags)  { -	*tx_flags = 0; -	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) -		*tx_flags |= SKBTX_HW_TSTAMP; -	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) -		*tx_flags |= SKBTX_SW_TSTAMP; +	u8 flags = *tx_flags; + +	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE) +		flags |= SKBTX_HW_TSTAMP; + +	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) +		flags |= SKBTX_SW_TSTAMP; + +	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED) +		flags |= SKBTX_SCHED_TSTAMP; + +	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK) +		flags |= SKBTX_ACK_TSTAMP; +  	if (sock_flag(sk, SOCK_WIFI_STATUS)) -		*tx_flags |= SKBTX_WIFI_STATUS; +		flags |= SKBTX_WIFI_STATUS; + +	*tx_flags = flags;  }  EXPORT_SYMBOL(sock_tx_timestamp); @@ -697,7 +709,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,  	struct sk_buff *skb)  {  	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); -	struct timespec ts[3]; +	struct scm_timestamping tss;  	int empty = 1;  	struct skb_shared_hwtstamps *shhwtstamps =  		skb_hwtstamps(skb); @@ -714,28 +726,24 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,  			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,  				 sizeof(tv), &tv);  		} else { -			skb_get_timestampns(skb, &ts[0]); +			struct timespec ts; +			skb_get_timestampns(skb, &ts);  			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, -				 sizeof(ts[0]), &ts[0]); +				 sizeof(ts), &ts);  		}  	} - -	memset(ts, 0, sizeof(ts)); -	if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) && -	    ktime_to_timespec_cond(skb->tstamp, ts + 0)) +	memset(&tss, 0, sizeof(tss)); +	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && +	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) +		empty = 0; +	if (shhwtstamps && +	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && +	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))  		empty = 0; -	if (shhwtstamps) { -		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) && -		    ktime_to_timespec_cond(shhwtstamps->syststamp, ts + 1)) -			empty = 0; -		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && -		    ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts + 2)) -			empty = 0; -	}  	if (!empty)  		put_cmsg(msg, SOL_SOCKET, -			 SCM_TIMESTAMPING, sizeof(ts), &ts); +			 SCM_TIMESTAMPING, sizeof(tss), &tss);  }  EXPORT_SYMBOL_GPL(__sock_recv_timestamp); @@ -1988,6 +1996,9 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,  	if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))  		return -EFAULT; +	if (kmsg->msg_name == NULL) +		kmsg->msg_namelen = 0; +  	if (kmsg->msg_namelen < 0)  		return -EINVAL; @@ -2593,7 +2604,7 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)   *   *	This function is called by a protocol handler that wants to   *	advertise its address family, and have it linked into the - *	socket interface. The value ops->family coresponds to the + *	socket interface. The value ops->family corresponds to the   *	socket system call protocol family.   */  int sock_register(const struct net_proto_family *ops)  |