mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-29 07:02:29 -04:00
Merge branch 'inet-data-races'
Eric Dumazet says: ==================== inet: socket lock and data-races avoidance In this series, I converted 20 bits in "struct inet_sock" and made them truly atomic. This allows to implement many IP_ socket options in a lockless fashion (no need to acquire socket lock), and fixes data-races that were showing up in various KCSAN reports. I also took care of IP_TTL/IP_MINTTL, but left few other options for another series. v4: Rebased after recent mptcp changes. Added Reviewed-by: tags from Simon (thanks !) v3: fixed patch 7, feedback from build bot about ipvs set_mcast_loop() v2: addressed a feedback from a build bot in patch 9 by removing unused issk variable in mptcp_setsockopt_sol_ip_set_transparent() Added Acked-by: tags from Soheil (thanks !) ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -342,9 +342,9 @@ static inline bool inet_csk_in_pingpong_mode(struct sock *sk)
|
||||
return inet_csk(sk)->icsk_ack.pingpong >= TCP_PINGPONG_THRESH;
|
||||
}
|
||||
|
||||
static inline bool inet_csk_has_ulp(struct sock *sk)
|
||||
static inline bool inet_csk_has_ulp(const struct sock *sk)
|
||||
{
|
||||
return inet_sk(sk)->is_icsk && !!inet_csk(sk)->icsk_ulp_ops;
|
||||
return inet_test_bit(IS_ICSK, sk) && !!inet_csk(sk)->icsk_ulp_ops;
|
||||
}
|
||||
|
||||
#endif /* _INET_CONNECTION_SOCK_H */
|
||||
|
||||
@@ -194,13 +194,13 @@ struct rtable;
|
||||
* @inet_rcv_saddr - Bound local IPv4 addr
|
||||
* @inet_dport - Destination port
|
||||
* @inet_num - Local port
|
||||
* @inet_flags - various atomic flags
|
||||
* @inet_saddr - Sending source
|
||||
* @uc_ttl - Unicast TTL
|
||||
* @inet_sport - Source port
|
||||
* @inet_id - ID counter for DF pkts
|
||||
* @tos - TOS
|
||||
* @mc_ttl - Multicasting TTL
|
||||
* @is_icsk - is this an inet_connection_sock?
|
||||
* @uc_index - Unicast outgoing device index
|
||||
* @mc_index - Multicast device index
|
||||
* @mc_list - Group array
|
||||
@@ -218,57 +218,88 @@ struct inet_sock {
|
||||
#define inet_dport sk.__sk_common.skc_dport
|
||||
#define inet_num sk.__sk_common.skc_num
|
||||
|
||||
unsigned long inet_flags;
|
||||
__be32 inet_saddr;
|
||||
__s16 uc_ttl;
|
||||
__u16 cmsg_flags;
|
||||
struct ip_options_rcu __rcu *inet_opt;
|
||||
__be16 inet_sport;
|
||||
struct ip_options_rcu __rcu *inet_opt;
|
||||
__u16 inet_id;
|
||||
|
||||
__u8 tos;
|
||||
__u8 min_ttl;
|
||||
__u8 mc_ttl;
|
||||
__u8 pmtudisc;
|
||||
__u8 recverr:1,
|
||||
is_icsk:1,
|
||||
freebind:1,
|
||||
hdrincl:1,
|
||||
mc_loop:1,
|
||||
transparent:1,
|
||||
mc_all:1,
|
||||
nodefrag:1;
|
||||
__u8 bind_address_no_port:1,
|
||||
recverr_rfc4884:1,
|
||||
defer_connect:1; /* Indicates that fastopen_connect is set
|
||||
* and cookie exists so we defer connect
|
||||
* until first data frame is written
|
||||
*/
|
||||
__u8 rcv_tos;
|
||||
__u8 convert_csum;
|
||||
int uc_index;
|
||||
int mc_index;
|
||||
__be32 mc_addr;
|
||||
struct ip_mc_socklist __rcu *mc_list;
|
||||
struct inet_cork_full cork;
|
||||
struct {
|
||||
__u16 lo;
|
||||
__u16 hi;
|
||||
} local_port_range;
|
||||
|
||||
struct ip_mc_socklist __rcu *mc_list;
|
||||
struct inet_cork_full cork;
|
||||
};
|
||||
|
||||
#define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */
|
||||
#define IPCORK_ALLFRAG 2 /* always fragment (for ipv6 for now) */
|
||||
|
||||
enum {
|
||||
INET_FLAGS_PKTINFO = 0,
|
||||
INET_FLAGS_TTL = 1,
|
||||
INET_FLAGS_TOS = 2,
|
||||
INET_FLAGS_RECVOPTS = 3,
|
||||
INET_FLAGS_RETOPTS = 4,
|
||||
INET_FLAGS_PASSSEC = 5,
|
||||
INET_FLAGS_ORIGDSTADDR = 6,
|
||||
INET_FLAGS_CHECKSUM = 7,
|
||||
INET_FLAGS_RECVFRAGSIZE = 8,
|
||||
|
||||
INET_FLAGS_RECVERR = 9,
|
||||
INET_FLAGS_RECVERR_RFC4884 = 10,
|
||||
INET_FLAGS_FREEBIND = 11,
|
||||
INET_FLAGS_HDRINCL = 12,
|
||||
INET_FLAGS_MC_LOOP = 13,
|
||||
INET_FLAGS_MC_ALL = 14,
|
||||
INET_FLAGS_TRANSPARENT = 15,
|
||||
INET_FLAGS_IS_ICSK = 16,
|
||||
INET_FLAGS_NODEFRAG = 17,
|
||||
INET_FLAGS_BIND_ADDRESS_NO_PORT = 18,
|
||||
INET_FLAGS_DEFER_CONNECT = 19,
|
||||
};
|
||||
|
||||
/* 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)
|
||||
#define IP_CMSG_RECVFRAGSIZE BIT(8)
|
||||
#define IP_CMSG_PKTINFO BIT(INET_FLAGS_PKTINFO)
|
||||
#define IP_CMSG_TTL BIT(INET_FLAGS_TTL)
|
||||
#define IP_CMSG_TOS BIT(INET_FLAGS_TOS)
|
||||
#define IP_CMSG_RECVOPTS BIT(INET_FLAGS_RECVOPTS)
|
||||
#define IP_CMSG_RETOPTS BIT(INET_FLAGS_RETOPTS)
|
||||
#define IP_CMSG_PASSSEC BIT(INET_FLAGS_PASSSEC)
|
||||
#define IP_CMSG_ORIGDSTADDR BIT(INET_FLAGS_ORIGDSTADDR)
|
||||
#define IP_CMSG_CHECKSUM BIT(INET_FLAGS_CHECKSUM)
|
||||
#define IP_CMSG_RECVFRAGSIZE BIT(INET_FLAGS_RECVFRAGSIZE)
|
||||
|
||||
#define IP_CMSG_ALL (IP_CMSG_PKTINFO | IP_CMSG_TTL | \
|
||||
IP_CMSG_TOS | IP_CMSG_RECVOPTS | \
|
||||
IP_CMSG_RETOPTS | IP_CMSG_PASSSEC | \
|
||||
IP_CMSG_ORIGDSTADDR | IP_CMSG_CHECKSUM | \
|
||||
IP_CMSG_RECVFRAGSIZE)
|
||||
|
||||
static inline unsigned long inet_cmsg_flags(const struct inet_sock *inet)
|
||||
{
|
||||
return READ_ONCE(inet->inet_flags) & IP_CMSG_ALL;
|
||||
}
|
||||
|
||||
#define inet_test_bit(nr, sk) \
|
||||
test_bit(INET_FLAGS_##nr, &inet_sk(sk)->inet_flags)
|
||||
#define inet_set_bit(nr, sk) \
|
||||
set_bit(INET_FLAGS_##nr, &inet_sk(sk)->inet_flags)
|
||||
#define inet_clear_bit(nr, sk) \
|
||||
clear_bit(INET_FLAGS_##nr, &inet_sk(sk)->inet_flags)
|
||||
#define inet_assign_bit(nr, sk, val) \
|
||||
assign_bit(INET_FLAGS_##nr, &inet_sk(sk)->inet_flags, val)
|
||||
|
||||
static inline bool sk_is_inet(struct sock *sk)
|
||||
{
|
||||
@@ -363,7 +394,7 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
|
||||
{
|
||||
__u8 flags = 0;
|
||||
|
||||
if (inet_sk(sk)->transparent || inet_sk(sk)->hdrincl)
|
||||
if (inet_test_bit(TRANSPARENT, sk) || inet_test_bit(HDRINCL, sk))
|
||||
flags |= FLOWI_FLAG_ANYSRC;
|
||||
return flags;
|
||||
}
|
||||
@@ -389,7 +420,8 @@ static inline bool inet_can_nonlocal_bind(struct net *net,
|
||||
struct inet_sock *inet)
|
||||
{
|
||||
return READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind) ||
|
||||
inet->freebind || inet->transparent;
|
||||
test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
|
||||
test_bit(INET_FLAGS_TRANSPARENT, &inet->inet_flags);
|
||||
}
|
||||
|
||||
static inline bool inet_addr_valid_or_nonlocal(struct net *net,
|
||||
|
||||
@@ -937,7 +937,8 @@ static inline bool ipv6_can_nonlocal_bind(struct net *net,
|
||||
struct inet_sock *inet)
|
||||
{
|
||||
return net->ipv6.sysctl.ip_nonlocal_bind ||
|
||||
inet->freebind || inet->transparent;
|
||||
test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
|
||||
test_bit(INET_FLAGS_TRANSPARENT, &inet->inet_flags);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (inet_sk(sk)->transparent)
|
||||
if (inet_test_bit(TRANSPARENT, sk))
|
||||
flow_flags |= FLOWI_FLAG_ANYSRC;
|
||||
|
||||
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:
|
||||
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
|
||||
|
||||
@@ -767,7 +767,7 @@ bool sk_mc_loop(struct sock *sk)
|
||||
return true;
|
||||
switch (sk->sk_family) {
|
||||
case AF_INET:
|
||||
return inet_sk(sk)->mc_loop;
|
||||
return inet_test_bit(MC_LOOP, sk);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
case AF_INET6:
|
||||
return inet6_sk(sk)->mc_loop;
|
||||
|
||||
@@ -247,7 +247,6 @@ static int dccp_v4_err(struct sk_buff *skb, u32 info)
|
||||
const u8 offset = iph->ihl << 2;
|
||||
const struct dccp_hdr *dh;
|
||||
struct dccp_sock *dp;
|
||||
struct inet_sock *inet;
|
||||
const int type = icmp_hdr(skb)->type;
|
||||
const int code = icmp_hdr(skb)->code;
|
||||
struct sock *sk;
|
||||
@@ -361,8 +360,7 @@ static int dccp_v4_err(struct sk_buff *skb, u32 info)
|
||||
* --ANK (980905)
|
||||
*/
|
||||
|
||||
inet = inet_sk(sk);
|
||||
if (!sock_owned_by_user(sk) && inet->recverr) {
|
||||
if (!sock_owned_by_user(sk) && inet_test_bit(RECVERR, sk)) {
|
||||
sk->sk_err = err;
|
||||
sk_error_report(sk);
|
||||
} else { /* Only an error on timeout */
|
||||
|
||||
@@ -331,14 +331,14 @@ static int inet_create(struct net *net, struct socket *sock, int protocol,
|
||||
sk->sk_reuse = SK_CAN_REUSE;
|
||||
|
||||
inet = inet_sk(sk);
|
||||
inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
|
||||
inet_assign_bit(IS_ICSK, sk, INET_PROTOSW_ICSK & answer_flags);
|
||||
|
||||
inet->nodefrag = 0;
|
||||
inet_clear_bit(NODEFRAG, sk);
|
||||
|
||||
if (SOCK_RAW == sock->type) {
|
||||
inet->inet_num = protocol;
|
||||
if (IPPROTO_RAW == protocol)
|
||||
inet->hdrincl = 1;
|
||||
inet_set_bit(HDRINCL, sk);
|
||||
}
|
||||
|
||||
if (READ_ONCE(net->ipv4.sysctl_ip_no_pmtu_disc))
|
||||
@@ -356,9 +356,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol,
|
||||
sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash);
|
||||
|
||||
inet->uc_ttl = -1;
|
||||
inet->mc_loop = 1;
|
||||
inet_set_bit(MC_LOOP, sk);
|
||||
inet->mc_ttl = 1;
|
||||
inet->mc_all = 1;
|
||||
inet_set_bit(MC_ALL, sk);
|
||||
inet->mc_index = 0;
|
||||
inet->mc_list = NULL;
|
||||
inet->rcv_tos = 0;
|
||||
@@ -529,7 +529,7 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
|
||||
inet->inet_saddr = 0; /* Use device */
|
||||
|
||||
/* Make sure we are allowed to bind here. */
|
||||
if (snum || !(inet->bind_address_no_port ||
|
||||
if (snum || !(inet_test_bit(BIND_ADDRESS_NO_PORT, sk) ||
|
||||
(flags & BIND_FORCE_ADDRESS_NO_PORT))) {
|
||||
err = sk->sk_prot->get_port(sk, snum);
|
||||
if (err) {
|
||||
@@ -656,7 +656,7 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
|
||||
err = -EISCONN;
|
||||
goto out;
|
||||
case SS_CONNECTING:
|
||||
if (inet_sk(sk)->defer_connect)
|
||||
if (inet_test_bit(DEFER_CONNECT, sk))
|
||||
err = is_sendmsg ? -EINPROGRESS : -EISCONN;
|
||||
else
|
||||
err = -EALREADY;
|
||||
@@ -679,7 +679,7 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
|
||||
|
||||
sock->state = SS_CONNECTING;
|
||||
|
||||
if (!err && inet_sk(sk)->defer_connect)
|
||||
if (!err && inet_test_bit(DEFER_CONNECT, sk))
|
||||
goto out;
|
||||
|
||||
/* Just entered SS_CONNECTING state; the only
|
||||
|
||||
@@ -1881,7 +1881,7 @@ int cipso_v4_sock_setattr(struct sock *sk,
|
||||
|
||||
old = rcu_dereference_protected(sk_inet->inet_opt,
|
||||
lockdep_sock_is_held(sk));
|
||||
if (sk_inet->is_icsk) {
|
||||
if (inet_test_bit(IS_ICSK, sk)) {
|
||||
sk_conn = inet_csk(sk);
|
||||
if (old)
|
||||
sk_conn->icsk_ext_hdr_len -= old->opt.optlen;
|
||||
@@ -2051,7 +2051,7 @@ void cipso_v4_sock_delattr(struct sock *sk)
|
||||
sk_inet = inet_sk(sk);
|
||||
|
||||
hdr_delta = cipso_v4_delopt(&sk_inet->inet_opt);
|
||||
if (sk_inet->is_icsk && hdr_delta > 0) {
|
||||
if (inet_test_bit(IS_ICSK, sk) && hdr_delta > 0) {
|
||||
struct inet_connection_sock *sk_conn = inet_csk(sk);
|
||||
sk_conn->icsk_ext_hdr_len -= hdr_delta;
|
||||
sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
|
||||
|
||||
@@ -2658,7 +2658,7 @@ int ip_mc_sf_allow(const struct sock *sk, __be32 loc_addr, __be32 rmt_addr,
|
||||
(sdif && pmc->multi.imr_ifindex == sdif)))
|
||||
break;
|
||||
}
|
||||
ret = inet->mc_all;
|
||||
ret = inet_test_bit(MC_ALL, sk);
|
||||
if (!pmc)
|
||||
goto unlock;
|
||||
psl = rcu_dereference(pmc->sflist);
|
||||
|
||||
@@ -182,17 +182,17 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
|
||||
r->idiag_inode = sock_i_ino(sk);
|
||||
|
||||
memset(&inet_sockopt, 0, sizeof(inet_sockopt));
|
||||
inet_sockopt.recverr = inet->recverr;
|
||||
inet_sockopt.is_icsk = inet->is_icsk;
|
||||
inet_sockopt.freebind = inet->freebind;
|
||||
inet_sockopt.hdrincl = inet->hdrincl;
|
||||
inet_sockopt.mc_loop = inet->mc_loop;
|
||||
inet_sockopt.transparent = inet->transparent;
|
||||
inet_sockopt.mc_all = inet->mc_all;
|
||||
inet_sockopt.nodefrag = inet->nodefrag;
|
||||
inet_sockopt.bind_address_no_port = inet->bind_address_no_port;
|
||||
inet_sockopt.recverr_rfc4884 = inet->recverr_rfc4884;
|
||||
inet_sockopt.defer_connect = inet->defer_connect;
|
||||
inet_sockopt.recverr = inet_test_bit(RECVERR, sk);
|
||||
inet_sockopt.is_icsk = inet_test_bit(IS_ICSK, sk);
|
||||
inet_sockopt.freebind = inet_test_bit(FREEBIND, sk);
|
||||
inet_sockopt.hdrincl = inet_test_bit(HDRINCL, sk);
|
||||
inet_sockopt.mc_loop = inet_test_bit(MC_LOOP, sk);
|
||||
inet_sockopt.transparent = inet_test_bit(TRANSPARENT, sk);
|
||||
inet_sockopt.mc_all = inet_test_bit(MC_ALL, sk);
|
||||
inet_sockopt.nodefrag = inet_test_bit(NODEFRAG, sk);
|
||||
inet_sockopt.bind_address_no_port = inet_test_bit(BIND_ADDRESS_NO_PORT, sk);
|
||||
inet_sockopt.recverr_rfc4884 = inet_test_bit(RECVERR_RFC4884, sk);
|
||||
inet_sockopt.defer_connect = inet_test_bit(DEFER_CONNECT, sk);
|
||||
if (nla_put(skb, INET_DIAG_SOCKOPT, sizeof(inet_sockopt),
|
||||
&inet_sockopt))
|
||||
goto errout;
|
||||
|
||||
@@ -203,7 +203,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
|
||||
tw->tw_reuseport = sk->sk_reuseport;
|
||||
tw->tw_hash = sk->sk_hash;
|
||||
tw->tw_ipv6only = 0;
|
||||
tw->tw_transparent = inet->transparent;
|
||||
tw->tw_transparent = inet_test_bit(TRANSPARENT, sk);
|
||||
tw->tw_prot = sk->sk_prot_creator;
|
||||
atomic64_set(&tw->tw_cookie, atomic64_read(&sk->sk_cookie));
|
||||
twsk_net_set(tw, sock_net(sk));
|
||||
|
||||
@@ -133,7 +133,7 @@ EXPORT_SYMBOL_GPL(ip_local_out);
|
||||
static inline int ip_select_ttl(const struct inet_sock *inet,
|
||||
const struct dst_entry *dst)
|
||||
{
|
||||
int ttl = inet->uc_ttl;
|
||||
int ttl = READ_ONCE(inet->uc_ttl);
|
||||
|
||||
if (ttl < 0)
|
||||
ttl = ip4_dst_hoplimit(dst);
|
||||
@@ -1039,7 +1039,7 @@ static int __ip_append_data(struct sock *sk,
|
||||
}
|
||||
}
|
||||
} else if ((flags & MSG_SPLICE_PAGES) && length) {
|
||||
if (inet->hdrincl)
|
||||
if (inet_test_bit(HDRINCL, sk))
|
||||
return -EPERM;
|
||||
if (rt->dst.dev->features & NETIF_F_SG &&
|
||||
getfrag == ip_generic_getfrag)
|
||||
@@ -1467,7 +1467,8 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
|
||||
* so icmphdr does not in skb linear region and can not get icmp_type
|
||||
* by icmp_hdr(skb)->type.
|
||||
*/
|
||||
if (sk->sk_type == SOCK_RAW && !inet_sk(sk)->hdrincl)
|
||||
if (sk->sk_type == SOCK_RAW &&
|
||||
!inet_test_bit(HDRINCL, sk))
|
||||
icmp_type = fl4->fl4_icmp_type;
|
||||
else
|
||||
icmp_type = icmp_hdr(skb)->type;
|
||||
|
||||
@@ -171,8 +171,10 @@ static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
|
||||
void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
|
||||
struct sk_buff *skb, int tlen, int offset)
|
||||
{
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
unsigned int flags = inet->cmsg_flags;
|
||||
unsigned long flags = inet_cmsg_flags(inet_sk(sk));
|
||||
|
||||
if (!flags)
|
||||
return;
|
||||
|
||||
/* Ordered by supposed usage frequency */
|
||||
if (flags & IP_CMSG_PKTINFO) {
|
||||
@@ -431,7 +433,7 @@ void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
|
||||
serr->port = port;
|
||||
|
||||
if (skb_pull(skb, payload - skb->data)) {
|
||||
if (inet_sk(sk)->recverr_rfc4884)
|
||||
if (inet_test_bit(RECVERR_RFC4884, sk))
|
||||
ipv4_icmp_error_rfc4884(skb, &serr->ee.ee_rfc4884);
|
||||
|
||||
skb_reset_transport_header(skb);
|
||||
@@ -444,12 +446,11 @@ EXPORT_SYMBOL_GPL(ip_icmp_error);
|
||||
|
||||
void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info)
|
||||
{
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct sock_exterr_skb *serr;
|
||||
struct iphdr *iph;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!inet->recverr)
|
||||
if (!inet_test_bit(RECVERR, sk))
|
||||
return;
|
||||
|
||||
skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC);
|
||||
@@ -568,7 +569,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
|
||||
if (ipv4_datagram_support_cmsg(sk, skb, serr->ee.ee_origin)) {
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
|
||||
if (inet_sk(sk)->cmsg_flags)
|
||||
if (inet_cmsg_flags(inet_sk(sk)))
|
||||
ip_cmsg_recv(msg, skb);
|
||||
}
|
||||
|
||||
@@ -607,17 +608,13 @@ EXPORT_SYMBOL(ip_sock_set_tos);
|
||||
|
||||
void ip_sock_set_freebind(struct sock *sk)
|
||||
{
|
||||
lock_sock(sk);
|
||||
inet_sk(sk)->freebind = true;
|
||||
release_sock(sk);
|
||||
inet_set_bit(FREEBIND, sk);
|
||||
}
|
||||
EXPORT_SYMBOL(ip_sock_set_freebind);
|
||||
|
||||
void ip_sock_set_recverr(struct sock *sk)
|
||||
{
|
||||
lock_sock(sk);
|
||||
inet_sk(sk)->recverr = true;
|
||||
release_sock(sk);
|
||||
inet_set_bit(RECVERR, sk);
|
||||
}
|
||||
EXPORT_SYMBOL(ip_sock_set_recverr);
|
||||
|
||||
@@ -634,9 +631,7 @@ EXPORT_SYMBOL(ip_sock_set_mtu_discover);
|
||||
|
||||
void ip_sock_set_pktinfo(struct sock *sk)
|
||||
{
|
||||
lock_sock(sk);
|
||||
inet_sk(sk)->cmsg_flags |= IP_CMSG_PKTINFO;
|
||||
release_sock(sk);
|
||||
inet_set_bit(PKTINFO, sk);
|
||||
}
|
||||
EXPORT_SYMBOL(ip_sock_set_pktinfo);
|
||||
|
||||
@@ -950,6 +945,104 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
if (ip_mroute_opt(optname))
|
||||
return ip_mroute_setsockopt(sk, optname, optval, optlen);
|
||||
|
||||
/* Handle options that can be set without locking the socket. */
|
||||
switch (optname) {
|
||||
case IP_PKTINFO:
|
||||
inet_assign_bit(PKTINFO, sk, val);
|
||||
return 0;
|
||||
case IP_RECVTTL:
|
||||
inet_assign_bit(TTL, sk, val);
|
||||
return 0;
|
||||
case IP_RECVTOS:
|
||||
inet_assign_bit(TOS, sk, val);
|
||||
return 0;
|
||||
case IP_RECVOPTS:
|
||||
inet_assign_bit(RECVOPTS, sk, val);
|
||||
return 0;
|
||||
case IP_RETOPTS:
|
||||
inet_assign_bit(RETOPTS, sk, val);
|
||||
return 0;
|
||||
case IP_PASSSEC:
|
||||
inet_assign_bit(PASSSEC, sk, val);
|
||||
return 0;
|
||||
case IP_RECVORIGDSTADDR:
|
||||
inet_assign_bit(ORIGDSTADDR, sk, val);
|
||||
return 0;
|
||||
case IP_RECVFRAGSIZE:
|
||||
if (sk->sk_type != SOCK_RAW && sk->sk_type != SOCK_DGRAM)
|
||||
return -EINVAL;
|
||||
inet_assign_bit(RECVFRAGSIZE, sk, val);
|
||||
return 0;
|
||||
case IP_RECVERR:
|
||||
inet_assign_bit(RECVERR, sk, val);
|
||||
if (!val)
|
||||
skb_queue_purge(&sk->sk_error_queue);
|
||||
return 0;
|
||||
case IP_RECVERR_RFC4884:
|
||||
if (val < 0 || val > 1)
|
||||
return -EINVAL;
|
||||
inet_assign_bit(RECVERR_RFC4884, sk, val);
|
||||
return 0;
|
||||
case IP_FREEBIND:
|
||||
if (optlen < 1)
|
||||
return -EINVAL;
|
||||
inet_assign_bit(FREEBIND, sk, val);
|
||||
return 0;
|
||||
case IP_HDRINCL:
|
||||
if (sk->sk_type != SOCK_RAW)
|
||||
return -ENOPROTOOPT;
|
||||
inet_assign_bit(HDRINCL, sk, val);
|
||||
return 0;
|
||||
case IP_MULTICAST_LOOP:
|
||||
if (optlen < 1)
|
||||
return -EINVAL;
|
||||
inet_assign_bit(MC_LOOP, sk, val);
|
||||
return 0;
|
||||
case IP_MULTICAST_ALL:
|
||||
if (optlen < 1)
|
||||
return -EINVAL;
|
||||
if (val != 0 && val != 1)
|
||||
return -EINVAL;
|
||||
inet_assign_bit(MC_ALL, sk, val);
|
||||
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;
|
||||
case IP_NODEFRAG:
|
||||
if (sk->sk_type != SOCK_RAW)
|
||||
return -ENOPROTOOPT;
|
||||
inet_assign_bit(NODEFRAG, sk, val);
|
||||
return 0;
|
||||
case IP_BIND_ADDRESS_NO_PORT:
|
||||
inet_assign_bit(BIND_ADDRESS_NO_PORT, sk, val);
|
||||
return 0;
|
||||
case IP_TTL:
|
||||
if (optlen < 1)
|
||||
return -EINVAL;
|
||||
if (val != -1 && (val < 1 || val > 255))
|
||||
return -EINVAL;
|
||||
WRITE_ONCE(inet->uc_ttl, val);
|
||||
return 0;
|
||||
case IP_MINTTL:
|
||||
if (optlen < 1)
|
||||
return -EINVAL;
|
||||
if (val < 0 || val > 255)
|
||||
return -EINVAL;
|
||||
|
||||
if (val)
|
||||
static_branch_enable(&ip4_min_ttl);
|
||||
|
||||
WRITE_ONCE(inet->min_ttl, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
if (needs_rtnl)
|
||||
rtnl_lock();
|
||||
@@ -967,7 +1060,7 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
break;
|
||||
old = rcu_dereference_protected(inet->inet_opt,
|
||||
lockdep_sock_is_held(sk));
|
||||
if (inet->is_icsk) {
|
||||
if (inet_test_bit(IS_ICSK, sk)) {
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (sk->sk_family == PF_INET ||
|
||||
@@ -989,111 +1082,27 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
kfree_rcu(old, rcu);
|
||||
break;
|
||||
}
|
||||
case IP_PKTINFO:
|
||||
if (val)
|
||||
inet->cmsg_flags |= IP_CMSG_PKTINFO;
|
||||
else
|
||||
inet->cmsg_flags &= ~IP_CMSG_PKTINFO;
|
||||
break;
|
||||
case IP_RECVTTL:
|
||||
if (val)
|
||||
inet->cmsg_flags |= IP_CMSG_TTL;
|
||||
else
|
||||
inet->cmsg_flags &= ~IP_CMSG_TTL;
|
||||
break;
|
||||
case IP_RECVTOS:
|
||||
if (val)
|
||||
inet->cmsg_flags |= IP_CMSG_TOS;
|
||||
else
|
||||
inet->cmsg_flags &= ~IP_CMSG_TOS;
|
||||
break;
|
||||
case IP_RECVOPTS:
|
||||
if (val)
|
||||
inet->cmsg_flags |= IP_CMSG_RECVOPTS;
|
||||
else
|
||||
inet->cmsg_flags &= ~IP_CMSG_RECVOPTS;
|
||||
break;
|
||||
case IP_RETOPTS:
|
||||
if (val)
|
||||
inet->cmsg_flags |= IP_CMSG_RETOPTS;
|
||||
else
|
||||
inet->cmsg_flags &= ~IP_CMSG_RETOPTS;
|
||||
break;
|
||||
case IP_PASSSEC:
|
||||
if (val)
|
||||
inet->cmsg_flags |= IP_CMSG_PASSSEC;
|
||||
else
|
||||
inet->cmsg_flags &= ~IP_CMSG_PASSSEC;
|
||||
break;
|
||||
case IP_RECVORIGDSTADDR:
|
||||
if (val)
|
||||
inet->cmsg_flags |= IP_CMSG_ORIGDSTADDR;
|
||||
else
|
||||
inet->cmsg_flags &= ~IP_CMSG_ORIGDSTADDR;
|
||||
break;
|
||||
case IP_CHECKSUM:
|
||||
if (val) {
|
||||
if (!(inet->cmsg_flags & IP_CMSG_CHECKSUM)) {
|
||||
if (!(inet_test_bit(CHECKSUM, sk))) {
|
||||
inet_inc_convert_csum(sk);
|
||||
inet->cmsg_flags |= IP_CMSG_CHECKSUM;
|
||||
inet_set_bit(CHECKSUM, sk);
|
||||
}
|
||||
} else {
|
||||
if (inet->cmsg_flags & IP_CMSG_CHECKSUM) {
|
||||
if (inet_test_bit(CHECKSUM, sk)) {
|
||||
inet_dec_convert_csum(sk);
|
||||
inet->cmsg_flags &= ~IP_CMSG_CHECKSUM;
|
||||
inet_clear_bit(CHECKSUM, sk);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IP_RECVFRAGSIZE:
|
||||
if (sk->sk_type != SOCK_RAW && sk->sk_type != SOCK_DGRAM)
|
||||
goto e_inval;
|
||||
if (val)
|
||||
inet->cmsg_flags |= IP_CMSG_RECVFRAGSIZE;
|
||||
else
|
||||
inet->cmsg_flags &= ~IP_CMSG_RECVFRAGSIZE;
|
||||
break;
|
||||
case IP_TOS: /* This sets both TOS and Precedence */
|
||||
__ip_sock_set_tos(sk, val);
|
||||
break;
|
||||
case IP_TTL:
|
||||
if (optlen < 1)
|
||||
goto e_inval;
|
||||
if (val != -1 && (val < 1 || val > 255))
|
||||
goto e_inval;
|
||||
inet->uc_ttl = val;
|
||||
break;
|
||||
case IP_HDRINCL:
|
||||
if (sk->sk_type != SOCK_RAW) {
|
||||
err = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
inet->hdrincl = val ? 1 : 0;
|
||||
break;
|
||||
case IP_NODEFRAG:
|
||||
if (sk->sk_type != SOCK_RAW) {
|
||||
err = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
inet->nodefrag = val ? 1 : 0;
|
||||
break;
|
||||
case IP_BIND_ADDRESS_NO_PORT:
|
||||
inet->bind_address_no_port = val ? 1 : 0;
|
||||
break;
|
||||
case IP_MTU_DISCOVER:
|
||||
if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT)
|
||||
goto e_inval;
|
||||
inet->pmtudisc = val;
|
||||
break;
|
||||
case IP_RECVERR:
|
||||
inet->recverr = !!val;
|
||||
if (!val)
|
||||
skb_queue_purge(&sk->sk_error_queue);
|
||||
break;
|
||||
case IP_RECVERR_RFC4884:
|
||||
if (val < 0 || val > 1)
|
||||
goto e_inval;
|
||||
inet->recverr_rfc4884 = !!val;
|
||||
break;
|
||||
case IP_MULTICAST_TTL:
|
||||
if (sk->sk_type == SOCK_STREAM)
|
||||
goto e_inval;
|
||||
@@ -1105,11 +1114,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
goto e_inval;
|
||||
inet->mc_ttl = val;
|
||||
break;
|
||||
case IP_MULTICAST_LOOP:
|
||||
if (optlen < 1)
|
||||
goto e_inval;
|
||||
inet->mc_loop = !!val;
|
||||
break;
|
||||
case IP_UNICAST_IF:
|
||||
{
|
||||
struct net_device *dev = NULL;
|
||||
@@ -1214,7 +1218,7 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
struct ip_mreqn mreq;
|
||||
|
||||
err = -EPROTO;
|
||||
if (inet_sk(sk)->is_icsk)
|
||||
if (inet_test_bit(IS_ICSK, sk))
|
||||
break;
|
||||
|
||||
if (optlen < sizeof(struct ip_mreq))
|
||||
@@ -1325,20 +1329,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
else
|
||||
err = ip_set_mcast_msfilter(sk, optval, optlen);
|
||||
break;
|
||||
case IP_MULTICAST_ALL:
|
||||
if (optlen < 1)
|
||||
goto e_inval;
|
||||
if (val != 0 && val != 1)
|
||||
goto e_inval;
|
||||
inet->mc_all = val;
|
||||
break;
|
||||
|
||||
case IP_FREEBIND:
|
||||
if (optlen < 1)
|
||||
goto e_inval;
|
||||
inet->freebind = !!val;
|
||||
break;
|
||||
|
||||
case IP_IPSEC_POLICY:
|
||||
case IP_XFRM_POLICY:
|
||||
err = -EPERM;
|
||||
@@ -1347,32 +1337,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
err = xfrm_user_policy(sk, optname, optval, optlen);
|
||||
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:
|
||||
if (optlen < 1)
|
||||
goto e_inval;
|
||||
if (val < 0 || val > 255)
|
||||
goto e_inval;
|
||||
|
||||
if (val)
|
||||
static_branch_enable(&ip4_min_ttl);
|
||||
|
||||
/* tcp_v4_err() and tcp_v4_rcv() might read min_ttl
|
||||
* while we are changint it.
|
||||
*/
|
||||
WRITE_ONCE(inet->min_ttl, val);
|
||||
break;
|
||||
|
||||
case IP_LOCAL_PORT_RANGE:
|
||||
{
|
||||
const __u16 lo = val;
|
||||
@@ -1415,7 +1379,7 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct in_pktinfo *pktinfo = PKTINFO_SKB_CB(skb);
|
||||
bool prepare = (inet_sk(sk)->cmsg_flags & IP_CMSG_PKTINFO) ||
|
||||
bool prepare = inet_test_bit(PKTINFO, sk) ||
|
||||
ipv6_sk_rxinfo(sk);
|
||||
|
||||
if (prepare && skb_rtable(skb)) {
|
||||
@@ -1566,6 +1530,72 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Handle options that can be read without locking the socket. */
|
||||
switch (optname) {
|
||||
case IP_PKTINFO:
|
||||
val = inet_test_bit(PKTINFO, sk);
|
||||
goto copyval;
|
||||
case IP_RECVTTL:
|
||||
val = inet_test_bit(TTL, sk);
|
||||
goto copyval;
|
||||
case IP_RECVTOS:
|
||||
val = inet_test_bit(TOS, sk);
|
||||
goto copyval;
|
||||
case IP_RECVOPTS:
|
||||
val = inet_test_bit(RECVOPTS, sk);
|
||||
goto copyval;
|
||||
case IP_RETOPTS:
|
||||
val = inet_test_bit(RETOPTS, sk);
|
||||
goto copyval;
|
||||
case IP_PASSSEC:
|
||||
val = inet_test_bit(PASSSEC, sk);
|
||||
goto copyval;
|
||||
case IP_RECVORIGDSTADDR:
|
||||
val = inet_test_bit(ORIGDSTADDR, sk);
|
||||
goto copyval;
|
||||
case IP_CHECKSUM:
|
||||
val = inet_test_bit(CHECKSUM, sk);
|
||||
goto copyval;
|
||||
case IP_RECVFRAGSIZE:
|
||||
val = inet_test_bit(RECVFRAGSIZE, sk);
|
||||
goto copyval;
|
||||
case IP_RECVERR:
|
||||
val = inet_test_bit(RECVERR, sk);
|
||||
goto copyval;
|
||||
case IP_RECVERR_RFC4884:
|
||||
val = inet_test_bit(RECVERR_RFC4884, sk);
|
||||
goto copyval;
|
||||
case IP_FREEBIND:
|
||||
val = inet_test_bit(FREEBIND, sk);
|
||||
goto copyval;
|
||||
case IP_HDRINCL:
|
||||
val = inet_test_bit(HDRINCL, sk);
|
||||
goto copyval;
|
||||
case IP_MULTICAST_LOOP:
|
||||
val = inet_test_bit(MC_LOOP, sk);
|
||||
goto copyval;
|
||||
case IP_MULTICAST_ALL:
|
||||
val = inet_test_bit(MC_ALL, sk);
|
||||
goto copyval;
|
||||
case IP_TRANSPARENT:
|
||||
val = inet_test_bit(TRANSPARENT, sk);
|
||||
goto copyval;
|
||||
case IP_NODEFRAG:
|
||||
val = inet_test_bit(NODEFRAG, sk);
|
||||
goto copyval;
|
||||
case IP_BIND_ADDRESS_NO_PORT:
|
||||
val = inet_test_bit(BIND_ADDRESS_NO_PORT, sk);
|
||||
goto copyval;
|
||||
case IP_TTL:
|
||||
val = READ_ONCE(inet->uc_ttl);
|
||||
if (val < 0)
|
||||
val = READ_ONCE(sock_net(sk)->ipv4.sysctl_ip_default_ttl);
|
||||
goto copyval;
|
||||
case IP_MINTTL:
|
||||
val = READ_ONCE(inet->min_ttl);
|
||||
goto copyval;
|
||||
}
|
||||
|
||||
if (needs_rtnl)
|
||||
rtnl_lock();
|
||||
sockopt_lock_sock(sk);
|
||||
@@ -1600,53 +1630,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
case IP_PKTINFO:
|
||||
val = (inet->cmsg_flags & IP_CMSG_PKTINFO) != 0;
|
||||
break;
|
||||
case IP_RECVTTL:
|
||||
val = (inet->cmsg_flags & IP_CMSG_TTL) != 0;
|
||||
break;
|
||||
case IP_RECVTOS:
|
||||
val = (inet->cmsg_flags & IP_CMSG_TOS) != 0;
|
||||
break;
|
||||
case IP_RECVOPTS:
|
||||
val = (inet->cmsg_flags & IP_CMSG_RECVOPTS) != 0;
|
||||
break;
|
||||
case IP_RETOPTS:
|
||||
val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0;
|
||||
break;
|
||||
case IP_PASSSEC:
|
||||
val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0;
|
||||
break;
|
||||
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_RECVFRAGSIZE:
|
||||
val = (inet->cmsg_flags & IP_CMSG_RECVFRAGSIZE) != 0;
|
||||
break;
|
||||
case IP_TOS:
|
||||
val = inet->tos;
|
||||
break;
|
||||
case IP_TTL:
|
||||
{
|
||||
struct net *net = sock_net(sk);
|
||||
val = (inet->uc_ttl == -1 ?
|
||||
READ_ONCE(net->ipv4.sysctl_ip_default_ttl) :
|
||||
inet->uc_ttl);
|
||||
break;
|
||||
}
|
||||
case IP_HDRINCL:
|
||||
val = inet->hdrincl;
|
||||
break;
|
||||
case IP_NODEFRAG:
|
||||
val = inet->nodefrag;
|
||||
break;
|
||||
case IP_BIND_ADDRESS_NO_PORT:
|
||||
val = inet->bind_address_no_port;
|
||||
break;
|
||||
case IP_MTU_DISCOVER:
|
||||
val = inet->pmtudisc;
|
||||
break;
|
||||
@@ -1665,18 +1651,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IP_RECVERR:
|
||||
val = inet->recverr;
|
||||
break;
|
||||
case IP_RECVERR_RFC4884:
|
||||
val = inet->recverr_rfc4884;
|
||||
break;
|
||||
case IP_MULTICAST_TTL:
|
||||
val = inet->mc_ttl;
|
||||
break;
|
||||
case IP_MULTICAST_LOOP:
|
||||
val = inet->mc_loop;
|
||||
break;
|
||||
case IP_UNICAST_IF:
|
||||
val = (__force int)htonl((__u32) inet->uc_index);
|
||||
break;
|
||||
@@ -1715,9 +1692,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
||||
else
|
||||
err = ip_get_mcast_msfilter(sk, optval, optlen, len);
|
||||
goto out;
|
||||
case IP_MULTICAST_ALL:
|
||||
val = inet->mc_all;
|
||||
break;
|
||||
case IP_PKTOPTIONS:
|
||||
{
|
||||
struct msghdr msg;
|
||||
@@ -1737,7 +1711,7 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
||||
msg.msg_controllen = len;
|
||||
msg.msg_flags = in_compat_syscall() ? MSG_CMSG_COMPAT : 0;
|
||||
|
||||
if (inet->cmsg_flags & IP_CMSG_PKTINFO) {
|
||||
if (inet_test_bit(PKTINFO, sk)) {
|
||||
struct in_pktinfo info;
|
||||
|
||||
info.ipi_addr.s_addr = inet->inet_rcv_saddr;
|
||||
@@ -1745,26 +1719,17 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
||||
info.ipi_ifindex = inet->mc_index;
|
||||
put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
|
||||
}
|
||||
if (inet->cmsg_flags & IP_CMSG_TTL) {
|
||||
if (inet_test_bit(TTL, sk)) {
|
||||
int hlim = inet->mc_ttl;
|
||||
put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim);
|
||||
}
|
||||
if (inet->cmsg_flags & IP_CMSG_TOS) {
|
||||
if (inet_test_bit(TOS, sk)) {
|
||||
int tos = inet->rcv_tos;
|
||||
put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(tos), &tos);
|
||||
}
|
||||
len -= msg.msg_controllen;
|
||||
return copy_to_sockptr(optlen, &len, sizeof(int));
|
||||
}
|
||||
case IP_FREEBIND:
|
||||
val = inet->freebind;
|
||||
break;
|
||||
case IP_TRANSPARENT:
|
||||
val = inet->transparent;
|
||||
break;
|
||||
case IP_MINTTL:
|
||||
val = inet->min_ttl;
|
||||
break;
|
||||
case IP_LOCAL_PORT_RANGE:
|
||||
val = inet->local_port_range.hi << 16 | inet->local_port_range.lo;
|
||||
break;
|
||||
@@ -1776,7 +1741,7 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
sockopt_release_sock(sk);
|
||||
|
||||
copyval:
|
||||
if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) {
|
||||
unsigned char ucval = (unsigned char)val;
|
||||
len = 1;
|
||||
|
||||
@@ -66,7 +66,7 @@ static unsigned int ipv4_conntrack_defrag(void *priv,
|
||||
struct sock *sk = skb->sk;
|
||||
|
||||
if (sk && sk_fullsock(sk) && (sk->sk_family == PF_INET) &&
|
||||
inet_sk(sk)->nodefrag)
|
||||
inet_test_bit(NODEFRAG, sk))
|
||||
return NF_ACCEPT;
|
||||
|
||||
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
|
||||
|
||||
@@ -580,7 +580,7 @@ void ping_err(struct sk_buff *skb, int offset, u32 info)
|
||||
* RFC1122: OK. Passes ICMP errors back to application, as per
|
||||
* 4.1.3.3.
|
||||
*/
|
||||
if ((family == AF_INET && !inet_sock->recverr) ||
|
||||
if ((family == AF_INET && !inet_test_bit(RECVERR, sk)) ||
|
||||
(family == AF_INET6 && !inet6_sk(sk)->recverr)) {
|
||||
if (!harderr || sk->sk_state != TCP_ESTABLISHED)
|
||||
goto out;
|
||||
@@ -894,7 +894,7 @@ int ping_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
|
||||
*addr_len = sizeof(*sin);
|
||||
}
|
||||
|
||||
if (isk->cmsg_flags)
|
||||
if (inet_cmsg_flags(isk))
|
||||
ip_cmsg_recv(msg, skb);
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
@@ -921,7 +921,8 @@ int ping_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
|
||||
if (skb->protocol == htons(ETH_P_IPV6) &&
|
||||
inet6_sk(sk)->rxopt.all)
|
||||
pingv6_ops.ip6_datagram_recv_specific_ctl(sk, msg, skb);
|
||||
else if (skb->protocol == htons(ETH_P_IP) && isk->cmsg_flags)
|
||||
else if (skb->protocol == htons(ETH_P_IP) &&
|
||||
inet_cmsg_flags(isk))
|
||||
ip_cmsg_recv(msg, skb);
|
||||
#endif
|
||||
} else {
|
||||
|
||||
@@ -203,8 +203,9 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
const int type = icmp_hdr(skb)->type;
|
||||
const int code = icmp_hdr(skb)->code;
|
||||
int err = 0;
|
||||
int harderr = 0;
|
||||
bool recverr;
|
||||
int err = 0;
|
||||
|
||||
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
|
||||
ipv4_sk_update_pmtu(skb, sk, info);
|
||||
@@ -218,7 +219,8 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
|
||||
2. Socket is connected (otherwise the error indication
|
||||
is useless without ip_recverr and error is hard.
|
||||
*/
|
||||
if (!inet->recverr && sk->sk_state != TCP_ESTABLISHED)
|
||||
recverr = inet_test_bit(RECVERR, sk);
|
||||
if (!recverr && sk->sk_state != TCP_ESTABLISHED)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
@@ -245,16 +247,16 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
|
||||
}
|
||||
}
|
||||
|
||||
if (inet->recverr) {
|
||||
if (recverr) {
|
||||
const struct iphdr *iph = (const struct iphdr *)skb->data;
|
||||
u8 *payload = skb->data + (iph->ihl << 2);
|
||||
|
||||
if (inet->hdrincl)
|
||||
if (inet_test_bit(HDRINCL, sk))
|
||||
payload = skb->data;
|
||||
ip_icmp_error(sk, skb, err, 0, info, payload);
|
||||
}
|
||||
|
||||
if (inet->recverr || harderr) {
|
||||
if (recverr || harderr) {
|
||||
sk->sk_err = err;
|
||||
sk_error_report(sk);
|
||||
}
|
||||
@@ -413,7 +415,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
|
||||
kfree_skb(skb);
|
||||
error:
|
||||
IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
|
||||
if (err == -ENOBUFS && !inet->recverr)
|
||||
if (err == -ENOBUFS && !inet_test_bit(RECVERR, sk))
|
||||
err = 0;
|
||||
return err;
|
||||
}
|
||||
@@ -489,12 +491,8 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
if (len > 0xFFFF)
|
||||
goto out;
|
||||
|
||||
/* hdrincl should be READ_ONCE(inet->hdrincl)
|
||||
* but READ_ONCE() doesn't work with bit fields.
|
||||
* Doing this indirectly yields the same result.
|
||||
*/
|
||||
hdrincl = inet->hdrincl;
|
||||
hdrincl = READ_ONCE(hdrincl);
|
||||
hdrincl = inet_test_bit(HDRINCL, sk);
|
||||
|
||||
/*
|
||||
* Check the flags.
|
||||
*/
|
||||
@@ -645,7 +643,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
ip_flush_pending_frames(sk);
|
||||
else if (!(msg->msg_flags & MSG_MORE)) {
|
||||
err = ip_push_pending_frames(sk, &fl4);
|
||||
if (err == -ENOBUFS && !inet->recverr)
|
||||
if (err == -ENOBUFS && !inet_test_bit(RECVERR, sk))
|
||||
err = 0;
|
||||
}
|
||||
release_sock(sk);
|
||||
@@ -767,7 +765,7 @@ static int raw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
|
||||
*addr_len = sizeof(*sin);
|
||||
}
|
||||
if (inet->cmsg_flags)
|
||||
if (inet_cmsg_flags(inet))
|
||||
ip_cmsg_recv(msg, skb);
|
||||
if (flags & MSG_TRUNC)
|
||||
copied = skb->len;
|
||||
|
||||
@@ -515,13 +515,12 @@ static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
|
||||
__u8 scope = RT_SCOPE_UNIVERSE;
|
||||
|
||||
if (sk) {
|
||||
const struct inet_sock *inet = inet_sk(sk);
|
||||
|
||||
oif = sk->sk_bound_dev_if;
|
||||
mark = READ_ONCE(sk->sk_mark);
|
||||
tos = ip_sock_rt_tos(sk);
|
||||
scope = ip_sock_rt_scope(sk);
|
||||
prot = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol;
|
||||
prot = inet_test_bit(HDRINCL, sk) ? IPPROTO_RAW :
|
||||
sk->sk_protocol;
|
||||
}
|
||||
|
||||
flowi4_init_output(fl4, oif, mark, tos & IPTOS_RT_MASK, scope,
|
||||
@@ -555,7 +554,8 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
|
||||
flowi4_init_output(fl4, sk->sk_bound_dev_if, READ_ONCE(sk->sk_mark),
|
||||
ip_sock_rt_tos(sk) & IPTOS_RT_MASK,
|
||||
ip_sock_rt_scope(sk),
|
||||
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
|
||||
inet_test_bit(HDRINCL, sk) ?
|
||||
IPPROTO_RAW : sk->sk_protocol,
|
||||
inet_sk_flowi_flags(sk),
|
||||
daddr, inet->inet_saddr, 0, 0, sk->sk_uid);
|
||||
rcu_read_unlock();
|
||||
|
||||
@@ -583,7 +583,8 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
|
||||
|
||||
if (urg_data & TCP_URG_VALID)
|
||||
mask |= EPOLLPRI;
|
||||
} else if (state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
|
||||
} else if (state == TCP_SYN_SENT &&
|
||||
inet_test_bit(DEFER_CONNECT, sk)) {
|
||||
/* Active TCP fastopen socket with defer_connect
|
||||
* Return EPOLLOUT so application can call write()
|
||||
* in order for kernel to generate SYN+data
|
||||
@@ -1007,7 +1008,7 @@ int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *copied,
|
||||
tp->fastopen_req->size = size;
|
||||
tp->fastopen_req->uarg = uarg;
|
||||
|
||||
if (inet->defer_connect) {
|
||||
if (inet_test_bit(DEFER_CONNECT, sk)) {
|
||||
err = tcp_connect(sk);
|
||||
/* Same failure procedure as in tcp_v4/6_connect */
|
||||
if (err) {
|
||||
@@ -1025,7 +1026,7 @@ int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *copied,
|
||||
if (tp->fastopen_req) {
|
||||
*copied = tp->fastopen_req->copied;
|
||||
tcp_free_fastopen_req(tp);
|
||||
inet->defer_connect = 0;
|
||||
inet_clear_bit(DEFER_CONNECT, sk);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -1066,7 +1067,8 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
|
||||
zc = MSG_SPLICE_PAGES;
|
||||
}
|
||||
|
||||
if (unlikely(flags & MSG_FASTOPEN || inet_sk(sk)->defer_connect) &&
|
||||
if (unlikely(flags & MSG_FASTOPEN ||
|
||||
inet_test_bit(DEFER_CONNECT, sk)) &&
|
||||
!tp->repair) {
|
||||
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size, uarg);
|
||||
if (err == -EINPROGRESS && copied_syn > 0)
|
||||
@@ -3088,7 +3090,7 @@ int tcp_disconnect(struct sock *sk, int flags)
|
||||
|
||||
/* Clean up fastopen related fields */
|
||||
tcp_free_fastopen_req(tp);
|
||||
inet->defer_connect = 0;
|
||||
inet_clear_bit(DEFER_CONNECT, sk);
|
||||
tp->fastopen_client_fail = 0;
|
||||
|
||||
WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
|
||||
|
||||
@@ -451,7 +451,7 @@ bool tcp_fastopen_defer_connect(struct sock *sk, int *err)
|
||||
|
||||
if (tp->fastopen_connect && !tp->fastopen_req) {
|
||||
if (tcp_fastopen_cookie_check(sk, &mss, &cookie)) {
|
||||
inet_sk(sk)->defer_connect = 1;
|
||||
inet_set_bit(DEFER_CONNECT, sk);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -7000,7 +7000,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
|
||||
|
||||
tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
|
||||
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 */
|
||||
inet_rsk(req)->ir_iif = inet_request_bound_dev_if(sk, skb);
|
||||
|
||||
@@ -477,7 +477,6 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
|
||||
const struct iphdr *iph = (const struct iphdr *)skb->data;
|
||||
struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
|
||||
struct tcp_sock *tp;
|
||||
struct inet_sock *inet;
|
||||
const int type = icmp_hdr(skb)->type;
|
||||
const int code = icmp_hdr(skb)->code;
|
||||
struct sock *sk;
|
||||
@@ -625,8 +624,8 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
|
||||
* --ANK (980905)
|
||||
*/
|
||||
|
||||
inet = inet_sk(sk);
|
||||
if (!sock_owned_by_user(sk) && inet->recverr) {
|
||||
if (!sock_owned_by_user(sk) &&
|
||||
inet_test_bit(RECVERR, sk)) {
|
||||
WRITE_ONCE(sk->sk_err, err);
|
||||
sk_error_report(sk);
|
||||
} else { /* Only an error on timeout */
|
||||
|
||||
@@ -289,9 +289,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
|
||||
if (tw) {
|
||||
struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
|
||||
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_priority = sk->sk_priority;
|
||||
tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale;
|
||||
|
||||
@@ -779,7 +779,7 @@ int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
|
||||
(u8 *)(uh+1));
|
||||
goto out;
|
||||
}
|
||||
if (!inet->recverr) {
|
||||
if (!inet_test_bit(RECVERR, sk)) {
|
||||
if (!harderr || sk->sk_state != TCP_ESTABLISHED)
|
||||
goto out;
|
||||
} else
|
||||
@@ -962,7 +962,8 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
|
||||
send:
|
||||
err = ip_send_skb(sock_net(sk), skb);
|
||||
if (err) {
|
||||
if (err == -ENOBUFS && !inet->recverr) {
|
||||
if (err == -ENOBUFS &&
|
||||
!inet_test_bit(RECVERR, sk)) {
|
||||
UDP_INC_STATS(sock_net(sk),
|
||||
UDP_MIB_SNDBUFERRORS, is_udplite);
|
||||
err = 0;
|
||||
@@ -1870,7 +1871,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
|
||||
if (udp_sk(sk)->gro_enabled)
|
||||
udp_cmsg_recv(msg, sk, skb);
|
||||
|
||||
if (inet->cmsg_flags)
|
||||
if (inet_cmsg_flags(inet))
|
||||
ip_cmsg_recv_offset(msg, sk, skb, sizeof(struct udphdr), off);
|
||||
|
||||
err = copied;
|
||||
|
||||
@@ -63,7 +63,7 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
/* Disable multicast loopback */
|
||||
inet_sk(sk)->mc_loop = 0;
|
||||
inet_clear_bit(MC_LOOP, sk);
|
||||
|
||||
/* Enable CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE conversion */
|
||||
inet_inc_convert_csum(sk);
|
||||
|
||||
@@ -200,12 +200,12 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
|
||||
sk->sk_reuse = SK_CAN_REUSE;
|
||||
|
||||
inet = inet_sk(sk);
|
||||
inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
|
||||
inet_assign_bit(IS_ICSK, sk, INET_PROTOSW_ICSK & answer_flags);
|
||||
|
||||
if (SOCK_RAW == sock->type) {
|
||||
inet->inet_num = protocol;
|
||||
if (IPPROTO_RAW == protocol)
|
||||
inet->hdrincl = 1;
|
||||
inet_set_bit(HDRINCL, sk);
|
||||
}
|
||||
|
||||
sk->sk_destruct = inet6_sock_destruct;
|
||||
@@ -229,7 +229,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
|
||||
*/
|
||||
inet->uc_ttl = -1;
|
||||
|
||||
inet->mc_loop = 1;
|
||||
inet_set_bit(MC_LOOP, sk);
|
||||
inet->mc_ttl = 1;
|
||||
inet->mc_index = 0;
|
||||
RCU_INIT_POINTER(inet->mc_list, NULL);
|
||||
@@ -399,7 +399,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
|
||||
sk->sk_ipv6only = 1;
|
||||
|
||||
/* Make sure we are allowed to bind here. */
|
||||
if (snum || !(inet->bind_address_no_port ||
|
||||
if (snum || !(inet_test_bit(BIND_ADDRESS_NO_PORT, sk) ||
|
||||
(flags & BIND_FORCE_ADDRESS_NO_PORT))) {
|
||||
err = sk->sk_prot->get_port(sk, snum);
|
||||
if (err) {
|
||||
|
||||
@@ -524,7 +524,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
|
||||
} else {
|
||||
ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
|
||||
&sin->sin6_addr);
|
||||
if (inet_sk(sk)->cmsg_flags)
|
||||
if (inet_cmsg_flags(inet_sk(sk)))
|
||||
ip_cmsg_recv(msg, skb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1591,7 +1591,7 @@ static int __ip6_append_data(struct sock *sk,
|
||||
}
|
||||
}
|
||||
} else if ((flags & MSG_SPLICE_PAGES) && length) {
|
||||
if (inet_sk(sk)->hdrincl)
|
||||
if (inet_test_bit(HDRINCL, sk))
|
||||
return -EPERM;
|
||||
if (rt->dst.dev->features & NETIF_F_SG &&
|
||||
getfrag == ip_generic_getfrag)
|
||||
@@ -1995,7 +1995,8 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
|
||||
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
|
||||
u8 icmp6_type;
|
||||
|
||||
if (sk->sk_socket->type == SOCK_RAW && !inet_sk(sk)->hdrincl)
|
||||
if (sk->sk_socket->type == SOCK_RAW &&
|
||||
!inet_test_bit(HDRINCL, sk))
|
||||
icmp6_type = fl6->fl6_icmp_type;
|
||||
else
|
||||
icmp6_type = icmp6_hdr(skb)->icmp6_type;
|
||||
|
||||
@@ -102,7 +102,7 @@ int ip6_ra_control(struct sock *sk, int sel)
|
||||
struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
|
||||
struct ipv6_txoptions *opt)
|
||||
{
|
||||
if (inet_sk(sk)->is_icsk) {
|
||||
if (inet_test_bit(IS_ICSK, sk)) {
|
||||
if (opt &&
|
||||
!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
|
||||
inet_sk(sk)->inet_daddr != LOOPBACK4_IPV6) {
|
||||
@@ -633,7 +633,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
if (optlen < sizeof(int))
|
||||
goto e_inval;
|
||||
/* 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;
|
||||
break;
|
||||
|
||||
@@ -641,7 +641,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
if (optlen < sizeof(int))
|
||||
goto e_inval;
|
||||
/* we also don't have a separate freebind bit for IPV6 */
|
||||
inet_sk(sk)->freebind = valbool;
|
||||
inet_assign_bit(FREEBIND, sk, valbool);
|
||||
retv = 0;
|
||||
break;
|
||||
|
||||
@@ -831,7 +831,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
goto e_inval;
|
||||
|
||||
retv = -EPROTO;
|
||||
if (inet_sk(sk)->is_icsk)
|
||||
if (inet_test_bit(IS_ICSK, sk))
|
||||
break;
|
||||
|
||||
retv = -EFAULT;
|
||||
@@ -1330,11 +1330,11 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
}
|
||||
|
||||
case IPV6_TRANSPARENT:
|
||||
val = inet_sk(sk)->transparent;
|
||||
val = inet_test_bit(TRANSPARENT, sk);
|
||||
break;
|
||||
|
||||
case IPV6_FREEBIND:
|
||||
val = inet_sk(sk)->freebind;
|
||||
val = inet_test_bit(FREEBIND, sk);
|
||||
break;
|
||||
|
||||
case IPV6_RECVORIGDSTADDR:
|
||||
|
||||
@@ -291,7 +291,6 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb,
|
||||
struct inet6_skb_parm *opt,
|
||||
u8 type, u8 code, int offset, __be32 info)
|
||||
{
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
int err;
|
||||
int harderr;
|
||||
@@ -315,7 +314,7 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb,
|
||||
}
|
||||
if (np->recverr) {
|
||||
u8 *payload = skb->data;
|
||||
if (!inet->hdrincl)
|
||||
if (!inet_test_bit(HDRINCL, sk))
|
||||
payload += offset;
|
||||
ipv6_icmp_error(sk, skb, err, 0, ntohl(info), payload);
|
||||
}
|
||||
@@ -406,7 +405,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
skb->len,
|
||||
inet->inet_num, 0));
|
||||
|
||||
if (inet->hdrincl) {
|
||||
if (inet_test_bit(HDRINCL, sk)) {
|
||||
if (skb_checksum_complete(skb)) {
|
||||
atomic_inc(&sk->sk_drops);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_SKB_CSUM);
|
||||
@@ -762,12 +761,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
if (msg->msg_flags & MSG_OOB)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* hdrincl should be READ_ONCE(inet->hdrincl)
|
||||
* but READ_ONCE() doesn't work with bit fields.
|
||||
* Doing this indirectly yields the same result.
|
||||
*/
|
||||
hdrincl = inet->hdrincl;
|
||||
hdrincl = READ_ONCE(hdrincl);
|
||||
hdrincl = inet_test_bit(HDRINCL, sk);
|
||||
|
||||
/*
|
||||
* Get and verify the address.
|
||||
@@ -1000,7 +994,7 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
case IPV6_HDRINCL:
|
||||
if (sk->sk_type != SOCK_RAW)
|
||||
return -EINVAL;
|
||||
inet_sk(sk)->hdrincl = !!val;
|
||||
inet_assign_bit(HDRINCL, sk, val);
|
||||
return 0;
|
||||
case IPV6_CHECKSUM:
|
||||
if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 &&
|
||||
@@ -1068,7 +1062,7 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
|
||||
switch (optname) {
|
||||
case IPV6_HDRINCL:
|
||||
val = inet_sk(sk)->hdrincl;
|
||||
val = inet_test_bit(HDRINCL, sk);
|
||||
break;
|
||||
case IPV6_CHECKSUM:
|
||||
/*
|
||||
|
||||
@@ -420,7 +420,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
ip6_datagram_recv_common_ctl(sk, msg, skb);
|
||||
|
||||
if (is_udp4) {
|
||||
if (inet->cmsg_flags)
|
||||
if (inet_cmsg_flags(inet))
|
||||
ip_cmsg_recv_offset(msg, sk, skb,
|
||||
sizeof(struct udphdr), off);
|
||||
} else {
|
||||
|
||||
@@ -552,7 +552,7 @@ static int l2tp_ip_recvmsg(struct sock *sk, struct msghdr *msg,
|
||||
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
|
||||
*addr_len = sizeof(*sin);
|
||||
}
|
||||
if (inet->cmsg_flags)
|
||||
if (inet_cmsg_flags(inet))
|
||||
ip_cmsg_recv(msg, skb);
|
||||
if (flags & MSG_TRUNC)
|
||||
copied = skb->len;
|
||||
|
||||
@@ -1686,7 +1686,7 @@ static int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
|
||||
if (!mptcp_disconnect(sk, 0))
|
||||
sk->sk_socket->state = SS_UNCONNECTED;
|
||||
}
|
||||
inet_sk(sk)->defer_connect = 0;
|
||||
inet_clear_bit(DEFER_CONNECT, sk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1704,7 +1704,8 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
if (unlikely(inet_sk(sk)->defer_connect || msg->msg_flags & MSG_FASTOPEN)) {
|
||||
if (unlikely(inet_test_bit(DEFER_CONNECT, sk) ||
|
||||
msg->msg_flags & MSG_FASTOPEN)) {
|
||||
int copied_syn = 0;
|
||||
|
||||
ret = mptcp_sendmsg_fastopen(sk, msg, len, &copied_syn);
|
||||
@@ -3601,7 +3602,7 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
inet_sk(sk)->defer_connect = inet_sk(ssk)->defer_connect;
|
||||
inet_assign_bit(DEFER_CONNECT, sk, inet_test_bit(DEFER_CONNECT, ssk));
|
||||
|
||||
out:
|
||||
if (!msk->fastopening)
|
||||
@@ -3827,7 +3828,8 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
|
||||
mask |= EPOLLOUT | EPOLLWRNORM;
|
||||
else
|
||||
mask |= mptcp_check_writeable(msk);
|
||||
} else if (state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
|
||||
} else if (state == TCP_SYN_SENT &&
|
||||
inet_test_bit(DEFER_CONNECT, sk)) {
|
||||
/* cf tcp_poll() note about TFO */
|
||||
mask |= EPOLLOUT | EPOLLWRNORM;
|
||||
}
|
||||
|
||||
@@ -416,10 +416,12 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
|
||||
sk->sk_ipv6only = ssk->sk_ipv6only;
|
||||
break;
|
||||
case IPV6_TRANSPARENT:
|
||||
inet_sk(sk)->transparent = inet_sk(ssk)->transparent;
|
||||
inet_assign_bit(TRANSPARENT, sk,
|
||||
inet_test_bit(TRANSPARENT, ssk));
|
||||
break;
|
||||
case IPV6_FREEBIND:
|
||||
inet_sk(sk)->freebind = inet_sk(ssk)->freebind;
|
||||
inet_assign_bit(FREEBIND, sk,
|
||||
inet_test_bit(FREEBIND, ssk));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -684,7 +686,6 @@ static int mptcp_setsockopt_sol_ip_set_transparent(struct mptcp_sock *msk, int o
|
||||
sockptr_t optval, unsigned int optlen)
|
||||
{
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
struct inet_sock *issk;
|
||||
struct sock *ssk;
|
||||
int err;
|
||||
|
||||
@@ -700,14 +701,13 @@ static int mptcp_setsockopt_sol_ip_set_transparent(struct mptcp_sock *msk, int o
|
||||
return PTR_ERR(ssk);
|
||||
}
|
||||
|
||||
issk = inet_sk(ssk);
|
||||
|
||||
switch (optname) {
|
||||
case IP_FREEBIND:
|
||||
issk->freebind = inet_sk(sk)->freebind;
|
||||
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
|
||||
break;
|
||||
case IP_TRANSPARENT:
|
||||
issk->transparent = inet_sk(sk)->transparent;
|
||||
inet_assign_bit(TRANSPARENT, ssk,
|
||||
inet_test_bit(TRANSPARENT, sk));
|
||||
break;
|
||||
default:
|
||||
release_sock(sk);
|
||||
@@ -1440,8 +1440,8 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
|
||||
__tcp_sock_set_cork(ssk, !!msk->cork);
|
||||
__tcp_sock_set_nodelay(ssk, !!msk->nodelay);
|
||||
|
||||
inet_sk(ssk)->transparent = inet_sk(sk)->transparent;
|
||||
inet_sk(ssk)->freebind = inet_sk(sk)->freebind;
|
||||
inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
|
||||
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
|
||||
}
|
||||
|
||||
static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
|
||||
|
||||
@@ -1346,7 +1346,7 @@ ip_vs_out_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *stat
|
||||
if (unlikely(sk && hooknum == NF_INET_LOCAL_OUT &&
|
||||
af == AF_INET)) {
|
||||
|
||||
if (sk->sk_family == PF_INET && inet_sk(sk)->nodefrag)
|
||||
if (sk->sk_family == PF_INET && inet_test_bit(NODEFRAG, sk))
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
@@ -1946,7 +1946,7 @@ ip_vs_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state
|
||||
if (unlikely(sk && hooknum == NF_INET_LOCAL_OUT &&
|
||||
af == AF_INET)) {
|
||||
|
||||
if (sk->sk_family == PF_INET && inet_sk(sk)->nodefrag)
|
||||
if (sk->sk_family == PF_INET && inet_test_bit(NODEFRAG, sk))
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
|
||||
@@ -1297,11 +1297,9 @@ static void set_sock_size(struct sock *sk, int mode, int val)
|
||||
*/
|
||||
static void set_mcast_loop(struct sock *sk, u_char loop)
|
||||
{
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
|
||||
/* setsockopt(sock, SOL_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); */
|
||||
lock_sock(sk);
|
||||
inet->mc_loop = loop ? 1 : 0;
|
||||
inet_assign_bit(MC_LOOP, sk, loop);
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (sk->sk_family == AF_INET6) {
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
|
||||
@@ -581,7 +581,7 @@ static void sctp_v4_err_handle(struct sctp_transport *t, struct sk_buff *skb,
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (!sock_owned_by_user(sk) && inet_sk(sk)->recverr) {
|
||||
if (!sock_owned_by_user(sk) && inet_test_bit(RECVERR, sk)) {
|
||||
sk->sk_err = err;
|
||||
sk_error_report(sk);
|
||||
} else { /* Only an error on timeout */
|
||||
|
||||
@@ -360,7 +360,7 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
|
||||
ret = inet_addr_type_table(net, addr->v4.sin_addr.s_addr, tb_id);
|
||||
if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
|
||||
ret != RTN_LOCAL &&
|
||||
!sp->inet.freebind &&
|
||||
!inet_test_bit(FREEBIND, sk) &&
|
||||
!READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind))
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -9482,7 +9482,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
|
||||
newinet->inet_id = get_random_u16();
|
||||
|
||||
newinet->uc_ttl = inet->uc_ttl;
|
||||
newinet->mc_loop = 1;
|
||||
inet_set_bit(MC_LOOP, newsk);
|
||||
newinet->mc_ttl = 1;
|
||||
newinet->mc_index = 0;
|
||||
newinet->mc_list = NULL;
|
||||
|
||||
Reference in New Issue
Block a user