aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/inet_diag.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 0c34bfabc11f..16cfa42cfd99 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -44,6 +44,10 @@ struct inet_diag_entry {
44 u16 dport; 44 u16 dport;
45 u16 family; 45 u16 family;
46 u16 userlocks; 46 u16 userlocks;
47#if IS_ENABLED(CONFIG_IPV6)
48 struct in6_addr saddr_storage; /* for IPv4-mapped-IPv6 addresses */
49 struct in6_addr daddr_storage; /* for IPv4-mapped-IPv6 addresses */
50#endif
47}; 51};
48 52
49static DEFINE_MUTEX(inet_diag_table_mutex); 53static DEFINE_MUTEX(inet_diag_table_mutex);
@@ -596,6 +600,36 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,
596 cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); 600 cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
597} 601}
598 602
603/* Get the IPv4, IPv6, or IPv4-mapped-IPv6 local and remote addresses
604 * from a request_sock. For IPv4-mapped-IPv6 we must map IPv4 to IPv6.
605 */
606static inline void inet_diag_req_addrs(const struct sock *sk,
607 const struct request_sock *req,
608 struct inet_diag_entry *entry)
609{
610 struct inet_request_sock *ireq = inet_rsk(req);
611
612#if IS_ENABLED(CONFIG_IPV6)
613 if (sk->sk_family == AF_INET6) {
614 if (req->rsk_ops->family == AF_INET6) {
615 entry->saddr = inet6_rsk(req)->loc_addr.s6_addr32;
616 entry->daddr = inet6_rsk(req)->rmt_addr.s6_addr32;
617 } else if (req->rsk_ops->family == AF_INET) {
618 ipv6_addr_set_v4mapped(ireq->loc_addr,
619 &entry->saddr_storage);
620 ipv6_addr_set_v4mapped(ireq->rmt_addr,
621 &entry->daddr_storage);
622 entry->saddr = entry->saddr_storage.s6_addr32;
623 entry->daddr = entry->daddr_storage.s6_addr32;
624 }
625 } else
626#endif
627 {
628 entry->saddr = &ireq->loc_addr;
629 entry->daddr = &ireq->rmt_addr;
630 }
631}
632
599static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, 633static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
600 struct request_sock *req, 634 struct request_sock *req,
601 struct user_namespace *user_ns, 635 struct user_namespace *user_ns,
@@ -637,8 +671,10 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
637 r->idiag_inode = 0; 671 r->idiag_inode = 0;
638#if IS_ENABLED(CONFIG_IPV6) 672#if IS_ENABLED(CONFIG_IPV6)
639 if (r->idiag_family == AF_INET6) { 673 if (r->idiag_family == AF_INET6) {
640 *(struct in6_addr *)r->id.idiag_src = inet6_rsk(req)->loc_addr; 674 struct inet_diag_entry entry;
641 *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr; 675 inet_diag_req_addrs(sk, req, &entry);
676 memcpy(r->id.idiag_src, entry.saddr, sizeof(struct in6_addr));
677 memcpy(r->id.idiag_dst, entry.daddr, sizeof(struct in6_addr));
642 } 678 }
643#endif 679#endif
644 680
@@ -691,18 +727,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
691 continue; 727 continue;
692 728
693 if (bc) { 729 if (bc) {
694 entry.saddr = 730 inet_diag_req_addrs(sk, req, &entry);
695#if IS_ENABLED(CONFIG_IPV6)
696 (entry.family == AF_INET6) ?
697 inet6_rsk(req)->loc_addr.s6_addr32 :
698#endif
699 &ireq->loc_addr;
700 entry.daddr =
701#if IS_ENABLED(CONFIG_IPV6)
702 (entry.family == AF_INET6) ?
703 inet6_rsk(req)->rmt_addr.s6_addr32 :
704#endif
705 &ireq->rmt_addr;
706 entry.dport = ntohs(ireq->rmt_port); 731 entry.dport = ntohs(ireq->rmt_port);
707 732
708 if (!inet_diag_bc_run(bc, &entry)) 733 if (!inet_diag_bc_run(bc, &entry))