mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 03:10:12 +00:00
Merge branch 'listener_refactor_part_9'
Eric Dumazet says: ==================== inet: tcp listener refactoring, part 9 This preliminary work pushes socket convergence a bit more: 1) request sock ir_iif is universally set 2) inet_diag can use common helpers to reduce LOC ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
6922022af5
5 changed files with 54 additions and 104 deletions
|
@ -643,6 +643,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
|
||||||
ireq->ir_rmt_addr = ip_hdr(skb)->saddr;
|
ireq->ir_rmt_addr = ip_hdr(skb)->saddr;
|
||||||
write_pnet(&ireq->ireq_net, sock_net(sk));
|
write_pnet(&ireq->ireq_net, sock_net(sk));
|
||||||
ireq->ireq_family = AF_INET;
|
ireq->ireq_family = AF_INET;
|
||||||
|
ireq->ir_iif = sk->sk_bound_dev_if;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Step 3: Process LISTEN state
|
* Step 3: Process LISTEN state
|
||||||
|
|
|
@ -44,10 +44,6 @@ struct inet_diag_entry {
|
||||||
u16 dport;
|
u16 dport;
|
||||||
u16 family;
|
u16 family;
|
||||||
u16 userlocks;
|
u16 userlocks;
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
|
||||||
struct in6_addr saddr_storage; /* for IPv4-mapped-IPv6 addresses */
|
|
||||||
struct in6_addr daddr_storage; /* for IPv4-mapped-IPv6 addresses */
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_MUTEX(inet_diag_table_mutex);
|
static DEFINE_MUTEX(inet_diag_table_mutex);
|
||||||
|
@ -70,6 +66,30 @@ static void inet_diag_unlock_handler(const struct inet_diag_handler *handler)
|
||||||
mutex_unlock(&inet_diag_table_mutex);
|
mutex_unlock(&inet_diag_table_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk)
|
||||||
|
{
|
||||||
|
r->idiag_family = sk->sk_family;
|
||||||
|
|
||||||
|
r->id.idiag_sport = htons(sk->sk_num);
|
||||||
|
r->id.idiag_dport = sk->sk_dport;
|
||||||
|
r->id.idiag_if = sk->sk_bound_dev_if;
|
||||||
|
sock_diag_save_cookie(sk, r->id.idiag_cookie);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
if (sk->sk_family == AF_INET6) {
|
||||||
|
*(struct in6_addr *)r->id.idiag_src = sk->sk_v6_rcv_saddr;
|
||||||
|
*(struct in6_addr *)r->id.idiag_dst = sk->sk_v6_daddr;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
|
||||||
|
memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
|
||||||
|
|
||||||
|
r->id.idiag_src[0] = sk->sk_rcv_saddr;
|
||||||
|
r->id.idiag_dst[0] = sk->sk_daddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
|
int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
|
||||||
struct sk_buff *skb, const struct inet_diag_req_v2 *req,
|
struct sk_buff *skb, const struct inet_diag_req_v2 *req,
|
||||||
struct user_namespace *user_ns,
|
struct user_namespace *user_ns,
|
||||||
|
@ -93,24 +113,13 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
|
||||||
r = nlmsg_data(nlh);
|
r = nlmsg_data(nlh);
|
||||||
BUG_ON(sk->sk_state == TCP_TIME_WAIT);
|
BUG_ON((1 << sk->sk_state) & (TCPF_TIME_WAIT | TCPF_NEW_SYN_RECV));
|
||||||
|
|
||||||
r->idiag_family = sk->sk_family;
|
inet_diag_msg_common_fill(r, sk);
|
||||||
r->idiag_state = sk->sk_state;
|
r->idiag_state = sk->sk_state;
|
||||||
r->idiag_timer = 0;
|
r->idiag_timer = 0;
|
||||||
r->idiag_retrans = 0;
|
r->idiag_retrans = 0;
|
||||||
|
|
||||||
r->id.idiag_if = sk->sk_bound_dev_if;
|
|
||||||
sock_diag_save_cookie(sk, r->id.idiag_cookie);
|
|
||||||
|
|
||||||
r->id.idiag_sport = inet->inet_sport;
|
|
||||||
r->id.idiag_dport = inet->inet_dport;
|
|
||||||
|
|
||||||
memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
|
|
||||||
memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
|
|
||||||
|
|
||||||
r->id.idiag_src[0] = inet->inet_rcv_saddr;
|
|
||||||
r->id.idiag_dst[0] = inet->inet_daddr;
|
|
||||||
|
|
||||||
if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown))
|
if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown))
|
||||||
goto errout;
|
goto errout;
|
||||||
|
@ -124,9 +133,6 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
if (r->idiag_family == AF_INET6) {
|
if (r->idiag_family == AF_INET6) {
|
||||||
*(struct in6_addr *)r->id.idiag_src = sk->sk_v6_rcv_saddr;
|
|
||||||
*(struct in6_addr *)r->id.idiag_dst = sk->sk_v6_daddr;
|
|
||||||
|
|
||||||
if (ext & (1 << (INET_DIAG_TCLASS - 1)))
|
if (ext & (1 << (INET_DIAG_TCLASS - 1)))
|
||||||
if (nla_put_u8(skb, INET_DIAG_TCLASS,
|
if (nla_put_u8(skb, INET_DIAG_TCLASS,
|
||||||
inet6_sk(sk)->tclass) < 0)
|
inet6_sk(sk)->tclass) < 0)
|
||||||
|
@ -244,21 +250,9 @@ static int inet_twsk_diag_fill(struct sock *sk,
|
||||||
if (tmo < 0)
|
if (tmo < 0)
|
||||||
tmo = 0;
|
tmo = 0;
|
||||||
|
|
||||||
r->idiag_family = tw->tw_family;
|
inet_diag_msg_common_fill(r, sk);
|
||||||
r->idiag_retrans = 0;
|
r->idiag_retrans = 0;
|
||||||
|
|
||||||
r->id.idiag_if = tw->tw_bound_dev_if;
|
|
||||||
sock_diag_save_cookie(sk, r->id.idiag_cookie);
|
|
||||||
|
|
||||||
r->id.idiag_sport = tw->tw_sport;
|
|
||||||
r->id.idiag_dport = tw->tw_dport;
|
|
||||||
|
|
||||||
memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
|
|
||||||
memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
|
|
||||||
|
|
||||||
r->id.idiag_src[0] = tw->tw_rcv_saddr;
|
|
||||||
r->id.idiag_dst[0] = tw->tw_daddr;
|
|
||||||
|
|
||||||
r->idiag_state = tw->tw_substate;
|
r->idiag_state = tw->tw_substate;
|
||||||
r->idiag_timer = 3;
|
r->idiag_timer = 3;
|
||||||
r->idiag_expires = jiffies_to_msecs(tmo);
|
r->idiag_expires = jiffies_to_msecs(tmo);
|
||||||
|
@ -266,12 +260,6 @@ static int inet_twsk_diag_fill(struct sock *sk,
|
||||||
r->idiag_wqueue = 0;
|
r->idiag_wqueue = 0;
|
||||||
r->idiag_uid = 0;
|
r->idiag_uid = 0;
|
||||||
r->idiag_inode = 0;
|
r->idiag_inode = 0;
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
|
||||||
if (tw->tw_family == AF_INET6) {
|
|
||||||
*(struct in6_addr *)r->id.idiag_src = tw->tw_v6_rcv_saddr;
|
|
||||||
*(struct in6_addr *)r->id.idiag_dst = tw->tw_v6_daddr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
nlmsg_end(skb, nlh);
|
nlmsg_end(skb, nlh);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -485,6 +473,23 @@ static int inet_diag_bc_run(const struct nlattr *_bc,
|
||||||
return len == 0;
|
return len == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This helper is available for all sockets (ESTABLISH, TIMEWAIT, SYN_RECV)
|
||||||
|
*/
|
||||||
|
static void entry_fill_addrs(struct inet_diag_entry *entry,
|
||||||
|
const struct sock *sk)
|
||||||
|
{
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
if (sk->sk_family == AF_INET6) {
|
||||||
|
entry->saddr = sk->sk_v6_rcv_saddr.s6_addr32;
|
||||||
|
entry->daddr = sk->sk_v6_daddr.s6_addr32;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
entry->saddr = &sk->sk_rcv_saddr;
|
||||||
|
entry->daddr = &sk->sk_daddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
|
int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
|
||||||
{
|
{
|
||||||
struct inet_sock *inet = inet_sk(sk);
|
struct inet_sock *inet = inet_sk(sk);
|
||||||
|
@ -494,16 +499,7 @@ int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
entry.family = sk->sk_family;
|
entry.family = sk->sk_family;
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
entry_fill_addrs(&entry, sk);
|
||||||
if (entry.family == AF_INET6) {
|
|
||||||
entry.saddr = sk->sk_v6_rcv_saddr.s6_addr32;
|
|
||||||
entry.daddr = sk->sk_v6_daddr.s6_addr32;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
entry.saddr = &inet->inet_rcv_saddr;
|
|
||||||
entry.daddr = &inet->inet_daddr;
|
|
||||||
}
|
|
||||||
entry.sport = inet->inet_num;
|
entry.sport = inet->inet_num;
|
||||||
entry.dport = ntohs(inet->inet_dport);
|
entry.dport = ntohs(inet->inet_dport);
|
||||||
entry.userlocks = (sk->sk_state != TCP_TIME_WAIT) ? sk->sk_userlocks : 0;
|
entry.userlocks = (sk->sk_state != TCP_TIME_WAIT) ? sk->sk_userlocks : 0;
|
||||||
|
@ -681,36 +677,6 @@ static int inet_twsk_diag_dump(struct sock *sk,
|
||||||
cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
|
cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the IPv4, IPv6, or IPv4-mapped-IPv6 local and remote addresses
|
|
||||||
* from a request_sock. For IPv4-mapped-IPv6 we must map IPv4 to IPv6.
|
|
||||||
*/
|
|
||||||
static void inet_diag_req_addrs(const struct sock *sk,
|
|
||||||
const struct request_sock *req,
|
|
||||||
struct inet_diag_entry *entry)
|
|
||||||
{
|
|
||||||
const struct inet_request_sock *ireq = inet_rsk(req);
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
|
||||||
if (sk->sk_family == AF_INET6) {
|
|
||||||
if (req->rsk_ops->family == AF_INET6) {
|
|
||||||
entry->saddr = ireq->ir_v6_loc_addr.s6_addr32;
|
|
||||||
entry->daddr = ireq->ir_v6_rmt_addr.s6_addr32;
|
|
||||||
} else if (req->rsk_ops->family == AF_INET) {
|
|
||||||
ipv6_addr_set_v4mapped(ireq->ir_loc_addr,
|
|
||||||
&entry->saddr_storage);
|
|
||||||
ipv6_addr_set_v4mapped(ireq->ir_rmt_addr,
|
|
||||||
&entry->daddr_storage);
|
|
||||||
entry->saddr = entry->saddr_storage.s6_addr32;
|
|
||||||
entry->daddr = entry->daddr_storage.s6_addr32;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
entry->saddr = &ireq->ir_loc_addr;
|
|
||||||
entry->daddr = &ireq->ir_rmt_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
|
static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
|
||||||
struct request_sock *req,
|
struct request_sock *req,
|
||||||
struct user_namespace *user_ns,
|
struct user_namespace *user_ns,
|
||||||
|
@ -728,44 +694,23 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
|
||||||
r = nlmsg_data(nlh);
|
r = nlmsg_data(nlh);
|
||||||
r->idiag_family = ireq->ireq_family;
|
inet_diag_msg_common_fill(r, (struct sock *)ireq);
|
||||||
r->idiag_state = TCP_SYN_RECV;
|
r->idiag_state = TCP_SYN_RECV;
|
||||||
r->idiag_timer = 1;
|
r->idiag_timer = 1;
|
||||||
r->idiag_retrans = req->num_retrans;
|
r->idiag_retrans = req->num_retrans;
|
||||||
|
|
||||||
r->id.idiag_if = sk->sk_bound_dev_if;
|
|
||||||
|
|
||||||
BUILD_BUG_ON(offsetof(struct inet_request_sock, ir_cookie) !=
|
BUILD_BUG_ON(offsetof(struct inet_request_sock, ir_cookie) !=
|
||||||
offsetof(struct sock, sk_cookie));
|
offsetof(struct sock, sk_cookie));
|
||||||
sock_diag_save_cookie((struct sock *)ireq, r->id.idiag_cookie);
|
|
||||||
|
|
||||||
tmo = req->expires - jiffies;
|
tmo = req->expires - jiffies;
|
||||||
if (tmo < 0)
|
if (tmo < 0)
|
||||||
tmo = 0;
|
tmo = 0;
|
||||||
|
|
||||||
r->id.idiag_sport = htons(ireq->ir_num);
|
|
||||||
r->id.idiag_dport = ireq->ir_rmt_port;
|
|
||||||
|
|
||||||
memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
|
|
||||||
memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
|
|
||||||
|
|
||||||
r->id.idiag_src[0] = ireq->ir_loc_addr;
|
|
||||||
r->id.idiag_dst[0] = ireq->ir_rmt_addr;
|
|
||||||
|
|
||||||
r->idiag_expires = jiffies_to_msecs(tmo);
|
r->idiag_expires = jiffies_to_msecs(tmo);
|
||||||
r->idiag_rqueue = 0;
|
r->idiag_rqueue = 0;
|
||||||
r->idiag_wqueue = 0;
|
r->idiag_wqueue = 0;
|
||||||
r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
|
r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
|
||||||
r->idiag_inode = 0;
|
r->idiag_inode = 0;
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
|
||||||
if (r->idiag_family == AF_INET6) {
|
|
||||||
struct inet_diag_entry entry;
|
|
||||||
|
|
||||||
inet_diag_req_addrs(sk, req, &entry);
|
|
||||||
memcpy(r->id.idiag_src, entry.saddr, sizeof(struct in6_addr));
|
|
||||||
memcpy(r->id.idiag_dst, entry.daddr, sizeof(struct in6_addr));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
nlmsg_end(skb, nlh);
|
nlmsg_end(skb, nlh);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -816,7 +761,8 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (bc) {
|
if (bc) {
|
||||||
inet_diag_req_addrs(sk, req, &entry);
|
/* Note: entry.sport and entry.userlocks are already set */
|
||||||
|
entry_fill_addrs(&entry, (struct sock *)req);
|
||||||
entry.dport = ntohs(ireq->ir_rmt_port);
|
entry.dport = ntohs(ireq->ir_rmt_port);
|
||||||
|
|
||||||
if (!inet_diag_bc_run(bc, &entry))
|
if (!inet_diag_bc_run(bc, &entry))
|
||||||
|
|
|
@ -349,6 +349,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
|
||||||
write_pnet(&ireq->ireq_net, sock_net(sk));
|
write_pnet(&ireq->ireq_net, sock_net(sk));
|
||||||
ireq->ireq_family = AF_INET;
|
ireq->ireq_family = AF_INET;
|
||||||
|
|
||||||
|
ireq->ir_iif = sk->sk_bound_dev_if;
|
||||||
|
|
||||||
/* We throwed the options of the initial SYN away, so we hope
|
/* We throwed the options of the initial SYN away, so we hope
|
||||||
* the ACK carries the same options again (see RFC1122 4.2.3.8)
|
* the ACK carries the same options again (see RFC1122 4.2.3.8)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5967,6 +5967,9 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
|
||||||
tcp_openreq_init(req, &tmp_opt, skb, sk);
|
tcp_openreq_init(req, &tmp_opt, skb, sk);
|
||||||
write_pnet(&inet_rsk(req)->ireq_net, sock_net(sk));
|
write_pnet(&inet_rsk(req)->ireq_net, sock_net(sk));
|
||||||
|
|
||||||
|
/* Note: tcp_v6_init_req() might override ir_iif for link locals */
|
||||||
|
inet_rsk(req)->ir_iif = sk->sk_bound_dev_if;
|
||||||
|
|
||||||
af_ops->init_req(req, sk, skb);
|
af_ops->init_req(req, sk, skb);
|
||||||
|
|
||||||
if (security_inet_conn_request(sk, skb, req))
|
if (security_inet_conn_request(sk, skb, req))
|
||||||
|
|
|
@ -734,8 +734,6 @@ static void tcp_v6_init_req(struct request_sock *req, struct sock *sk,
|
||||||
ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr;
|
ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr;
|
||||||
ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;
|
ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;
|
||||||
|
|
||||||
ireq->ir_iif = sk->sk_bound_dev_if;
|
|
||||||
|
|
||||||
/* So that link locals have meaning */
|
/* So that link locals have meaning */
|
||||||
if (!sk->sk_bound_dev_if &&
|
if (!sk->sk_bound_dev_if &&
|
||||||
ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL)
|
ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL)
|
||||||
|
|
Loading…
Reference in a new issue