summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGael Blivet <gael.blivet@gmail.com>2026-09-14 01:26:38 +0200
committerNamjae Jeon <linkinjeon@kernel.org>2026-09-15 22:28:57 +0900
commitb3ebcc75b08453494e527cf078d22f323fb4d26d (patch)
treecbf499f03aa6c019899f9cb469e4a1f1360d90f2
parent27847f6b54a5d2a45343a65f7df7a27aae927b58 (diff)
downloadlinux-next-b3ebcc75b08453494e527cf078d22f323fb4d26d.tar.gz
linux-next-b3ebcc75b08453494e527cf078d22f323fb4d26d.zip
ksmbd: print IPv6 client addresses correctly in procfs
conn->inet_addr and conn->inet6_addr share a union, and three procfs printers choose between them by testing whether inet_addr is zero. For an IPv6 peer that field aliases the first four bytes of the address, which are zero only for :: prefixed addresses, so a client with a global IPv6 address takes the IPv4 branch and is listed from those four bytes. A client at 2001:db8::1 is listed as 32.1.13.184. IPv4 mapped addresses begin with zero bytes, so the listing is correct until a native IPv6 client connects. Record the address family where the address is stored and select on that, in the client listing and in both session listings. Fixes: fe4dc5987d7d ("ksmbd: expose connection runtime state in procfs") Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Assisted-by: Claude:claude-opus-5 Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
-rw-r--r--fs/smb/server/connection.c2
-rw-r--r--fs/smb/server/connection.h3
-rw-r--r--fs/smb/server/mgmt/user_session.c4
-rw-r--r--fs/smb/server/transport_tcp.c1
4 files changed, 7 insertions, 3 deletions
diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
index d211861ff86f..cc600b89cfdb 100644
--- a/fs/smb/server/connection.c
+++ b/fs/smb/server/connection.c
@@ -114,7 +114,7 @@ static int proc_show_clients(struct seq_file *m, void *v)
sessions++;
rcu_read_unlock();
#if IS_ENABLED(CONFIG_IPV6)
- if (!conn->inet_addr)
+ if (conn->is_ipv6)
seq_printf(m, "client:\t%pI6c\n", &conn->inet6_addr);
else
#endif
diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h
index 371f17b4f02a..2026a2afa5e4 100644
--- a/fs/smb/server/connection.h
+++ b/fs/smb/server/connection.h
@@ -68,6 +68,9 @@ struct ksmbd_conn {
u8 inet6_addr[16];
#endif
};
+#if IS_ENABLED(CONFIG_IPV6)
+ bool is_ipv6;
+#endif
unsigned int inet_hash;
char *request_buf;
struct ksmbd_transport *transport;
diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
index 44dc3f800cd4..1321cd6c84e7 100644
--- a/fs/smb/server/mgmt/user_session.c
+++ b/fs/smb/server/mgmt/user_session.c
@@ -130,7 +130,7 @@ static int show_proc_session(struct seq_file *m, void *v)
const char *name;
#if IS_ENABLED(CONFIG_IPV6)
- if (chan->conn->inet_addr)
+ if (!chan->conn->is_ipv6)
seq_printf(m, "client:\t%pI4\n",
&chan->conn->inet_addr);
else
@@ -231,7 +231,7 @@ static int show_proc_sessions(struct seq_file *m, void *v)
ksmbd_user_session_get(session);
#if IS_ENABLED(CONFIG_IPV6)
- if (!chan->conn->inet_addr)
+ if (chan->conn->is_ipv6)
seq_printf(m, "client:\t%pI6c\n", &chan->conn->inet6_addr);
else
#endif
diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c
index 4968cfc1a572..09eb9a34a2a8 100644
--- a/fs/smb/server/transport_tcp.c
+++ b/fs/smb/server/transport_tcp.c
@@ -77,6 +77,7 @@ static struct tcp_transport *alloc_transport(struct socket *client_sk)
if (client_sk->sk->sk_family == AF_INET6) {
memcpy(&conn->inet6_addr, &client_sk->sk->sk_v6_daddr, 16);
conn->inet_hash = ipv6_addr_hash(&client_sk->sk->sk_v6_daddr);
+ conn->is_ipv6 = true;
} else {
conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr;
conn->inet_hash = ipv4_addr_hash(inet_sk(client_sk->sk)->inet_daddr);