diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
| -rw-r--r-- | net/ipv4/af_inet.c | 75 | 
1 files changed, 45 insertions, 30 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index c8f7aee587d1..fe4582ca969a 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -157,6 +157,7 @@ void inet_sock_destruct(struct sock *sk)  	kfree(rcu_dereference_protected(inet->inet_opt, 1));  	dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); +	dst_release(sk->sk_rx_dst);  	sk_refcnt_debug_dec(sk);  }  EXPORT_SYMBOL(inet_sock_destruct); @@ -242,20 +243,18 @@ void build_ehash_secret(void)  }  EXPORT_SYMBOL(build_ehash_secret); -static inline int inet_netns_ok(struct net *net, int protocol) +static inline int inet_netns_ok(struct net *net, __u8 protocol)  { -	int hash;  	const struct net_protocol *ipprot;  	if (net_eq(net, &init_net))  		return 1; -	hash = protocol & (MAX_INET_PROTOS - 1); -	ipprot = rcu_dereference(inet_protos[hash]); - -	if (ipprot == NULL) +	ipprot = rcu_dereference(inet_protos[protocol]); +	if (ipprot == NULL) {  		/* raw IP is OK */  		return 1; +	}  	return ipprot->netns_ok;  } @@ -553,15 +552,16 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,  	if (!inet_sk(sk)->inet_num && inet_autobind(sk))  		return -EAGAIN; -	return sk->sk_prot->connect(sk, (struct sockaddr *)uaddr, addr_len); +	return sk->sk_prot->connect(sk, uaddr, addr_len);  }  EXPORT_SYMBOL(inet_dgram_connect); -static long inet_wait_for_connect(struct sock *sk, long timeo) +static long inet_wait_for_connect(struct sock *sk, long timeo, int writebias)  {  	DEFINE_WAIT(wait);  	prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); +	sk->sk_write_pending += writebias;  	/* Basic assumption: if someone sets sk->sk_err, he _must_  	 * change state of the socket from TCP_SYN_*. @@ -577,6 +577,7 @@ static long inet_wait_for_connect(struct sock *sk, long timeo)  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);  	}  	finish_wait(sk_sleep(sk), &wait); +	sk->sk_write_pending -= writebias;  	return timeo;  } @@ -584,8 +585,8 @@ static long inet_wait_for_connect(struct sock *sk, long timeo)   *	Connect to a remote host. There is regrettably still a little   *	TCP 'magic' in here.   */ -int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, -			int addr_len, int flags) +int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, +			  int addr_len, int flags)  {  	struct sock *sk = sock->sk;  	int err; @@ -594,8 +595,6 @@ int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,  	if (addr_len < sizeof(uaddr->sa_family))  		return -EINVAL; -	lock_sock(sk); -  	if (uaddr->sa_family == AF_UNSPEC) {  		err = sk->sk_prot->disconnect(sk, flags);  		sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED; @@ -635,8 +634,12 @@ int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,  	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);  	if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { +		int writebias = (sk->sk_protocol == IPPROTO_TCP) && +				tcp_sk(sk)->fastopen_req && +				tcp_sk(sk)->fastopen_req->data ? 1 : 0; +  		/* Error code is set above */ -		if (!timeo || !inet_wait_for_connect(sk, timeo)) +		if (!timeo || !inet_wait_for_connect(sk, timeo, writebias))  			goto out;  		err = sock_intr_errno(timeo); @@ -658,7 +661,6 @@ int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,  	sock->state = SS_CONNECTED;  	err = 0;  out: -	release_sock(sk);  	return err;  sock_error: @@ -668,6 +670,18 @@ sock_error:  		sock->state = SS_DISCONNECTING;  	goto out;  } +EXPORT_SYMBOL(__inet_stream_connect); + +int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, +			int addr_len, int flags) +{ +	int err; + +	lock_sock(sock->sk); +	err = __inet_stream_connect(sock, uaddr, addr_len, flags); +	release_sock(sock->sk); +	return err; +}  EXPORT_SYMBOL(inet_stream_connect);  /* @@ -1216,8 +1230,8 @@ EXPORT_SYMBOL(inet_sk_rebuild_header);  static int inet_gso_send_check(struct sk_buff *skb)  { -	const struct iphdr *iph;  	const struct net_protocol *ops; +	const struct iphdr *iph;  	int proto;  	int ihl;  	int err = -EINVAL; @@ -1236,7 +1250,7 @@ static int inet_gso_send_check(struct sk_buff *skb)  	__skb_pull(skb, ihl);  	skb_reset_transport_header(skb);  	iph = ip_hdr(skb); -	proto = iph->protocol & (MAX_INET_PROTOS - 1); +	proto = iph->protocol;  	err = -EPROTONOSUPPORT;  	rcu_read_lock(); @@ -1253,8 +1267,8 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,  	netdev_features_t features)  {  	struct sk_buff *segs = ERR_PTR(-EINVAL); -	struct iphdr *iph;  	const struct net_protocol *ops; +	struct iphdr *iph;  	int proto;  	int ihl;  	int id; @@ -1286,7 +1300,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,  	skb_reset_transport_header(skb);  	iph = ip_hdr(skb);  	id = ntohs(iph->id); -	proto = iph->protocol & (MAX_INET_PROTOS - 1); +	proto = iph->protocol;  	segs = ERR_PTR(-EPROTONOSUPPORT);  	rcu_read_lock(); @@ -1340,7 +1354,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,  			goto out;  	} -	proto = iph->protocol & (MAX_INET_PROTOS - 1); +	proto = iph->protocol;  	rcu_read_lock();  	ops = rcu_dereference(inet_protos[proto]); @@ -1398,11 +1412,11 @@ out:  static int inet_gro_complete(struct sk_buff *skb)  { -	const struct net_protocol *ops; +	__be16 newlen = htons(skb->len - skb_network_offset(skb));  	struct iphdr *iph = ip_hdr(skb); -	int proto = iph->protocol & (MAX_INET_PROTOS - 1); +	const struct net_protocol *ops; +	int proto = iph->protocol;  	int err = -ENOSYS; -	__be16 newlen = htons(skb->len - skb_network_offset(skb));  	csum_replace2(&iph->check, iph->tot_len, newlen);  	iph->tot_len = newlen; @@ -1520,14 +1534,15 @@ static const struct net_protocol igmp_protocol = {  #endif  static const struct net_protocol tcp_protocol = { -	.handler =	tcp_v4_rcv, -	.err_handler =	tcp_v4_err, -	.gso_send_check = tcp_v4_gso_send_check, -	.gso_segment =	tcp_tso_segment, -	.gro_receive =	tcp4_gro_receive, -	.gro_complete =	tcp4_gro_complete, -	.no_policy =	1, -	.netns_ok =	1, +	.early_demux	=	tcp_v4_early_demux, +	.handler	=	tcp_v4_rcv, +	.err_handler	=	tcp_v4_err, +	.gso_send_check	=	tcp_v4_gso_send_check, +	.gso_segment	=	tcp_tso_segment, +	.gro_receive	=	tcp4_gro_receive, +	.gro_complete	=	tcp4_gro_complete, +	.no_policy	=	1, +	.netns_ok	=	1,  };  static const struct net_protocol udp_protocol = {  | 
