mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
inet: move inet->transparent to inet->inet_flags
IP_TRANSPARENT socket option can now be set/read
without locking the socket.
v2: removed unused issk variable in mptcp_setsockopt_sol_ip_set_transparent()
v4: rebased after commit 3f326a821b
("mptcp: change the mpc check helper to return a sk")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
307b4ac6dc
commit
4bd0623f04
@ -231,7 +231,6 @@ struct inet_sock {
|
|||||||
__u8 mc_ttl;
|
__u8 mc_ttl;
|
||||||
__u8 pmtudisc;
|
__u8 pmtudisc;
|
||||||
__u8 is_icsk:1,
|
__u8 is_icsk:1,
|
||||||
transparent:1,
|
|
||||||
nodefrag:1;
|
nodefrag:1;
|
||||||
__u8 bind_address_no_port:1,
|
__u8 bind_address_no_port:1,
|
||||||
defer_connect:1; /* Indicates that fastopen_connect is set
|
defer_connect:1; /* Indicates that fastopen_connect is set
|
||||||
@ -271,6 +270,7 @@ enum {
|
|||||||
INET_FLAGS_HDRINCL = 12,
|
INET_FLAGS_HDRINCL = 12,
|
||||||
INET_FLAGS_MC_LOOP = 13,
|
INET_FLAGS_MC_LOOP = 13,
|
||||||
INET_FLAGS_MC_ALL = 14,
|
INET_FLAGS_MC_ALL = 14,
|
||||||
|
INET_FLAGS_TRANSPARENT = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* cmsg flags for inet */
|
/* cmsg flags for inet */
|
||||||
@ -397,7 +397,7 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
|
|||||||
{
|
{
|
||||||
__u8 flags = 0;
|
__u8 flags = 0;
|
||||||
|
|
||||||
if (inet_sk(sk)->transparent || inet_test_bit(HDRINCL, sk))
|
if (inet_test_bit(TRANSPARENT, sk) || inet_test_bit(HDRINCL, sk))
|
||||||
flags |= FLOWI_FLAG_ANYSRC;
|
flags |= FLOWI_FLAG_ANYSRC;
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
@ -424,7 +424,7 @@ static inline bool inet_can_nonlocal_bind(struct net *net,
|
|||||||
{
|
{
|
||||||
return READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind) ||
|
return READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind) ||
|
||||||
test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
|
test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
|
||||||
inet->transparent;
|
test_bit(INET_FLAGS_TRANSPARENT, &inet->inet_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool inet_addr_valid_or_nonlocal(struct net *net,
|
static inline bool inet_addr_valid_or_nonlocal(struct net *net,
|
||||||
|
@ -938,7 +938,7 @@ static inline bool ipv6_can_nonlocal_bind(struct net *net,
|
|||||||
{
|
{
|
||||||
return net->ipv6.sysctl.ip_nonlocal_bind ||
|
return net->ipv6.sysctl.ip_nonlocal_bind ||
|
||||||
test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
|
test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
|
||||||
inet->transparent;
|
test_bit(INET_FLAGS_TRANSPARENT, &inet->inet_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sysctl settings for net ipv6.auto_flowlabels */
|
/* Sysctl settings for net ipv6.auto_flowlabels */
|
||||||
|
@ -298,7 +298,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst,
|
|||||||
{
|
{
|
||||||
__u8 flow_flags = 0;
|
__u8 flow_flags = 0;
|
||||||
|
|
||||||
if (inet_sk(sk)->transparent)
|
if (inet_test_bit(TRANSPARENT, sk))
|
||||||
flow_flags |= FLOWI_FLAG_ANYSRC;
|
flow_flags |= FLOWI_FLAG_ANYSRC;
|
||||||
|
|
||||||
flowi4_init_output(fl4, oif, READ_ONCE(sk->sk_mark), ip_sock_rt_tos(sk),
|
flowi4_init_output(fl4, oif, READ_ONCE(sk->sk_mark), ip_sock_rt_tos(sk),
|
||||||
|
@ -2031,7 +2031,7 @@ static inline bool inet_sk_transparent(const struct sock *sk)
|
|||||||
case TCP_NEW_SYN_RECV:
|
case TCP_NEW_SYN_RECV:
|
||||||
return inet_rsk(inet_reqsk(sk))->no_srccheck;
|
return inet_rsk(inet_reqsk(sk))->no_srccheck;
|
||||||
}
|
}
|
||||||
return inet_sk(sk)->transparent;
|
return inet_test_bit(TRANSPARENT, sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determines whether this is a thin stream (which may suffer from
|
/* Determines whether this is a thin stream (which may suffer from
|
||||||
|
@ -187,7 +187,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
|
|||||||
inet_sockopt.freebind = inet_test_bit(FREEBIND, sk);
|
inet_sockopt.freebind = inet_test_bit(FREEBIND, sk);
|
||||||
inet_sockopt.hdrincl = inet_test_bit(HDRINCL, sk);
|
inet_sockopt.hdrincl = inet_test_bit(HDRINCL, sk);
|
||||||
inet_sockopt.mc_loop = inet_test_bit(MC_LOOP, sk);
|
inet_sockopt.mc_loop = inet_test_bit(MC_LOOP, sk);
|
||||||
inet_sockopt.transparent = inet->transparent;
|
inet_sockopt.transparent = inet_test_bit(TRANSPARENT, sk);
|
||||||
inet_sockopt.mc_all = inet_test_bit(MC_ALL, sk);
|
inet_sockopt.mc_all = inet_test_bit(MC_ALL, sk);
|
||||||
inet_sockopt.nodefrag = inet->nodefrag;
|
inet_sockopt.nodefrag = inet->nodefrag;
|
||||||
inet_sockopt.bind_address_no_port = inet->bind_address_no_port;
|
inet_sockopt.bind_address_no_port = inet->bind_address_no_port;
|
||||||
|
@ -203,7 +203,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
|
|||||||
tw->tw_reuseport = sk->sk_reuseport;
|
tw->tw_reuseport = sk->sk_reuseport;
|
||||||
tw->tw_hash = sk->sk_hash;
|
tw->tw_hash = sk->sk_hash;
|
||||||
tw->tw_ipv6only = 0;
|
tw->tw_ipv6only = 0;
|
||||||
tw->tw_transparent = inet->transparent;
|
tw->tw_transparent = inet_test_bit(TRANSPARENT, sk);
|
||||||
tw->tw_prot = sk->sk_prot_creator;
|
tw->tw_prot = sk->sk_prot_creator;
|
||||||
atomic64_set(&tw->tw_cookie, atomic64_read(&sk->sk_cookie));
|
atomic64_set(&tw->tw_cookie, atomic64_read(&sk->sk_cookie));
|
||||||
twsk_net_set(tw, sock_net(sk));
|
twsk_net_set(tw, sock_net(sk));
|
||||||
|
@ -1005,7 +1005,16 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
inet_assign_bit(MC_ALL, sk, val);
|
inet_assign_bit(MC_ALL, sk, val);
|
||||||
return 0;
|
return 0;
|
||||||
|
case IP_TRANSPARENT:
|
||||||
|
if (!!val && !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
|
||||||
|
!sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
|
||||||
|
err = -EPERM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (optlen < 1)
|
||||||
|
goto e_inval;
|
||||||
|
inet_assign_bit(TRANSPARENT, sk, val);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
@ -1319,17 +1328,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
|||||||
err = xfrm_user_policy(sk, optname, optval, optlen);
|
err = xfrm_user_policy(sk, optname, optval, optlen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IP_TRANSPARENT:
|
|
||||||
if (!!val && !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
|
|
||||||
!sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
|
|
||||||
err = -EPERM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (optlen < 1)
|
|
||||||
goto e_inval;
|
|
||||||
inet->transparent = !!val;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IP_MINTTL:
|
case IP_MINTTL:
|
||||||
if (optlen < 1)
|
if (optlen < 1)
|
||||||
goto e_inval;
|
goto e_inval;
|
||||||
@ -1585,6 +1583,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
|||||||
case IP_MULTICAST_ALL:
|
case IP_MULTICAST_ALL:
|
||||||
val = inet_test_bit(MC_ALL, sk);
|
val = inet_test_bit(MC_ALL, sk);
|
||||||
goto copyval;
|
goto copyval;
|
||||||
|
case IP_TRANSPARENT:
|
||||||
|
val = inet_test_bit(TRANSPARENT, sk);
|
||||||
|
goto copyval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needs_rtnl)
|
if (needs_rtnl)
|
||||||
@ -1735,9 +1736,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
|||||||
len -= msg.msg_controllen;
|
len -= msg.msg_controllen;
|
||||||
return copy_to_sockptr(optlen, &len, sizeof(int));
|
return copy_to_sockptr(optlen, &len, sizeof(int));
|
||||||
}
|
}
|
||||||
case IP_TRANSPARENT:
|
|
||||||
val = inet->transparent;
|
|
||||||
break;
|
|
||||||
case IP_MINTTL:
|
case IP_MINTTL:
|
||||||
val = inet->min_ttl;
|
val = inet->min_ttl;
|
||||||
break;
|
break;
|
||||||
|
@ -7000,7 +7000,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
|
|||||||
|
|
||||||
tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
|
tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
|
||||||
tcp_openreq_init(req, &tmp_opt, skb, sk);
|
tcp_openreq_init(req, &tmp_opt, skb, sk);
|
||||||
inet_rsk(req)->no_srccheck = inet_sk(sk)->transparent;
|
inet_rsk(req)->no_srccheck = inet_test_bit(TRANSPARENT, sk);
|
||||||
|
|
||||||
/* Note: tcp_v6_init_req() might override ir_iif for link locals */
|
/* Note: tcp_v6_init_req() might override ir_iif for link locals */
|
||||||
inet_rsk(req)->ir_iif = inet_request_bound_dev_if(sk, skb);
|
inet_rsk(req)->ir_iif = inet_request_bound_dev_if(sk, skb);
|
||||||
|
@ -289,9 +289,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
|
|||||||
if (tw) {
|
if (tw) {
|
||||||
struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
|
struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
|
||||||
const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
|
const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
|
||||||
struct inet_sock *inet = inet_sk(sk);
|
|
||||||
|
|
||||||
tw->tw_transparent = inet->transparent;
|
tw->tw_transparent = inet_test_bit(TRANSPARENT, sk);
|
||||||
tw->tw_mark = sk->sk_mark;
|
tw->tw_mark = sk->sk_mark;
|
||||||
tw->tw_priority = sk->sk_priority;
|
tw->tw_priority = sk->sk_priority;
|
||||||
tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale;
|
tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale;
|
||||||
|
@ -633,7 +633,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
|||||||
if (optlen < sizeof(int))
|
if (optlen < sizeof(int))
|
||||||
goto e_inval;
|
goto e_inval;
|
||||||
/* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
|
/* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
|
||||||
inet_sk(sk)->transparent = valbool;
|
inet_assign_bit(TRANSPARENT, sk, valbool);
|
||||||
retv = 0;
|
retv = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1330,7 +1330,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case IPV6_TRANSPARENT:
|
case IPV6_TRANSPARENT:
|
||||||
val = inet_sk(sk)->transparent;
|
val = inet_test_bit(TRANSPARENT, sk);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPV6_FREEBIND:
|
case IPV6_FREEBIND:
|
||||||
|
@ -416,7 +416,8 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
|
|||||||
sk->sk_ipv6only = ssk->sk_ipv6only;
|
sk->sk_ipv6only = ssk->sk_ipv6only;
|
||||||
break;
|
break;
|
||||||
case IPV6_TRANSPARENT:
|
case IPV6_TRANSPARENT:
|
||||||
inet_sk(sk)->transparent = inet_sk(ssk)->transparent;
|
inet_assign_bit(TRANSPARENT, sk,
|
||||||
|
inet_test_bit(TRANSPARENT, ssk));
|
||||||
break;
|
break;
|
||||||
case IPV6_FREEBIND:
|
case IPV6_FREEBIND:
|
||||||
inet_assign_bit(FREEBIND, sk,
|
inet_assign_bit(FREEBIND, sk,
|
||||||
@ -685,7 +686,6 @@ static int mptcp_setsockopt_sol_ip_set_transparent(struct mptcp_sock *msk, int o
|
|||||||
sockptr_t optval, unsigned int optlen)
|
sockptr_t optval, unsigned int optlen)
|
||||||
{
|
{
|
||||||
struct sock *sk = (struct sock *)msk;
|
struct sock *sk = (struct sock *)msk;
|
||||||
struct inet_sock *issk;
|
|
||||||
struct sock *ssk;
|
struct sock *ssk;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -701,14 +701,13 @@ static int mptcp_setsockopt_sol_ip_set_transparent(struct mptcp_sock *msk, int o
|
|||||||
return PTR_ERR(ssk);
|
return PTR_ERR(ssk);
|
||||||
}
|
}
|
||||||
|
|
||||||
issk = inet_sk(ssk);
|
|
||||||
|
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
case IP_FREEBIND:
|
case IP_FREEBIND:
|
||||||
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
|
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
|
||||||
break;
|
break;
|
||||||
case IP_TRANSPARENT:
|
case IP_TRANSPARENT:
|
||||||
issk->transparent = inet_sk(sk)->transparent;
|
inet_assign_bit(TRANSPARENT, ssk,
|
||||||
|
inet_test_bit(TRANSPARENT, sk));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
@ -1441,7 +1440,7 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
|
|||||||
__tcp_sock_set_cork(ssk, !!msk->cork);
|
__tcp_sock_set_cork(ssk, !!msk->cork);
|
||||||
__tcp_sock_set_nodelay(ssk, !!msk->nodelay);
|
__tcp_sock_set_nodelay(ssk, !!msk->nodelay);
|
||||||
|
|
||||||
inet_sk(ssk)->transparent = inet_sk(sk)->transparent;
|
inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
|
||||||
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
|
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user