summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/tcp_metrics.c64
1 files changed, 40 insertions, 24 deletions
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index 9ae48b4a37d1..d547075d8300 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -274,24 +274,32 @@ static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock
unsigned int hash;
struct net *net;
- saddr.family = tw->tw_family;
- daddr.family = tw->tw_family;
- switch (daddr.family) {
- case AF_INET:
+ if (tw->tw_family == AF_INET) {
+ saddr.family = AF_INET;
saddr.addr.a4 = tw->tw_rcv_saddr;
+ daddr.family = AF_INET;
daddr.addr.a4 = tw->tw_daddr;
hash = (__force unsigned int) daddr.addr.a4;
- break;
+ }
#if IS_ENABLED(CONFIG_IPV6)
- case AF_INET6:
- *(struct in6_addr *)saddr.addr.a6 = tw->tw_v6_rcv_saddr;
- *(struct in6_addr *)daddr.addr.a6 = tw->tw_v6_daddr;
- hash = ipv6_addr_hash(&tw->tw_v6_daddr);
- break;
+ else if (tw->tw_family == AF_INET6) {
+ if (ipv6_addr_v4mapped(&tw->tw_v6_daddr)) {
+ saddr.family = AF_INET;
+ saddr.addr.a4 = tw->tw_rcv_saddr;
+ daddr.family = AF_INET;
+ daddr.addr.a4 = tw->tw_daddr;
+ hash = (__force unsigned int) daddr.addr.a4;
+ } else {
+ saddr.family = AF_INET6;
+ *(struct in6_addr *)saddr.addr.a6 = tw->tw_v6_rcv_saddr;
+ daddr.family = AF_INET6;
+ *(struct in6_addr *)daddr.addr.a6 = tw->tw_v6_daddr;
+ hash = ipv6_addr_hash(&tw->tw_v6_daddr);
+ }
+ }
#endif
- default:
+ else
return NULL;
- }
net = twsk_net(tw);
hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
@@ -314,24 +322,32 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
unsigned int hash;
struct net *net;
- saddr.family = sk->sk_family;
- daddr.family = sk->sk_family;
- switch (daddr.family) {
- case AF_INET:
+ if (sk->sk_family == AF_INET) {
+ saddr.family = AF_INET;
saddr.addr.a4 = inet_sk(sk)->inet_saddr;
+ daddr.family = AF_INET;
daddr.addr.a4 = inet_sk(sk)->inet_daddr;
hash = (__force unsigned int) daddr.addr.a4;
- break;
+ }
#if IS_ENABLED(CONFIG_IPV6)
- case AF_INET6:
- *(struct in6_addr *)saddr.addr.a6 = sk->sk_v6_rcv_saddr;
- *(struct in6_addr *)daddr.addr.a6 = sk->sk_v6_daddr;
- hash = ipv6_addr_hash(&sk->sk_v6_daddr);
- break;
+ else if (sk->sk_family == AF_INET6) {
+ if (ipv6_addr_v4mapped(&sk->sk_v6_daddr)) {
+ saddr.family = AF_INET;
+ saddr.addr.a4 = inet_sk(sk)->inet_saddr;
+ daddr.family = AF_INET;
+ daddr.addr.a4 = inet_sk(sk)->inet_daddr;
+ hash = (__force unsigned int) daddr.addr.a4;
+ } else {
+ saddr.family = AF_INET6;
+ *(struct in6_addr *)saddr.addr.a6 = sk->sk_v6_rcv_saddr;
+ daddr.family = AF_INET6;
+ *(struct in6_addr *)daddr.addr.a6 = sk->sk_v6_daddr;
+ hash = ipv6_addr_hash(&sk->sk_v6_daddr);
+ }
+ }
#endif
- default:
+ else
return NULL;
- }
net = dev_net(dst->dev);
hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);