diff options
| author | Gael Blivet <gael.blivet@gmail.com> | 2026-09-14 01:26:38 +0200 |
|---|---|---|
| committer | Namjae Jeon <linkinjeon@kernel.org> | 2026-09-15 22:28:57 +0900 |
| commit | b3ebcc75b08453494e527cf078d22f323fb4d26d (patch) | |
| tree | cbf499f03aa6c019899f9cb469e4a1f1360d90f2 | |
| parent | 27847f6b54a5d2a45343a65f7df7a27aae927b58 (diff) | |
| download | linux-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.c | 2 | ||||
| -rw-r--r-- | fs/smb/server/connection.h | 3 | ||||
| -rw-r--r-- | fs/smb/server/mgmt/user_session.c | 4 | ||||
| -rw-r--r-- | fs/smb/server/transport_tcp.c | 1 |
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); |
