Skip to content

Commit a22a296

Browse files
Joshua Murphymartinetd
authored andcommitted
net/9p/fd: support ipv6 for trans=tcp
Allows specifying an IPv6 address when mounting a remote 9p file system. Signed-off-by: Joshua Murphy <joshuamurphy@posteo.net> Message-ID: <20250118192122.327-2-joshuamurphy@posteo.net> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
1 parent ffd294d commit a22a296

File tree

1 file changed

+24
-32
lines changed

1 file changed

+24
-32
lines changed

net/9p/trans_fd.c

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1212

1313
#include <linux/in.h>
14+
#include <linux/in6.h>
1415
#include <linux/module.h>
1516
#include <linux/net.h>
1617
#include <linux/ipv6.h>
@@ -954,64 +955,55 @@ static void p9_fd_close(struct p9_client *client)
954955
kfree(ts);
955956
}
956957

957-
/*
958-
* stolen from NFS - maybe should be made a generic function?
959-
*/
960-
static inline int valid_ipaddr4(const char *buf)
961-
{
962-
int rc, count, in[4];
963-
964-
rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
965-
if (rc != 4)
966-
return -EINVAL;
967-
for (count = 0; count < 4; count++) {
968-
if (in[count] > 255)
969-
return -EINVAL;
970-
}
971-
return 0;
972-
}
973-
974958
static int p9_bind_privport(struct socket *sock)
975959
{
976-
struct sockaddr_in cl;
960+
struct sockaddr_storage stor = { 0 };
977961
int port, err = -EINVAL;
978962

979-
memset(&cl, 0, sizeof(cl));
980-
cl.sin_family = AF_INET;
981-
cl.sin_addr.s_addr = htonl(INADDR_ANY);
963+
stor.ss_family = sock->ops->family;
964+
if (stor.ss_family == AF_INET)
965+
((struct sockaddr_in *)&stor)->sin_addr.s_addr = htonl(INADDR_ANY);
966+
else
967+
((struct sockaddr_in6 *)&stor)->sin6_addr = in6addr_any;
982968
for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) {
983-
cl.sin_port = htons((ushort)port);
984-
err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl));
969+
if (stor.ss_family == AF_INET)
970+
((struct sockaddr_in *)&stor)->sin_port = htons((ushort)port);
971+
else
972+
((struct sockaddr_in6 *)&stor)->sin6_port = htons((ushort)port);
973+
err = kernel_bind(sock, (struct sockaddr *)&stor, sizeof(stor));
985974
if (err != -EADDRINUSE)
986975
break;
987976
}
988977
return err;
989978
}
990979

991-
992980
static int
993981
p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
994982
{
995983
int err;
984+
char port_str[6];
996985
struct socket *csocket;
997-
struct sockaddr_in sin_server;
986+
struct sockaddr_storage stor = { 0 };
998987
struct p9_fd_opts opts;
999988

1000989
err = parse_opts(args, &opts);
1001990
if (err < 0)
1002991
return err;
1003992

1004-
if (addr == NULL || valid_ipaddr4(addr) < 0)
993+
if (!addr)
1005994
return -EINVAL;
1006995

996+
sprintf(port_str, "%u", opts.port);
997+
err = inet_pton_with_scope(current->nsproxy->net_ns, AF_UNSPEC, addr,
998+
port_str, &stor);
999+
if (err < 0)
1000+
return err;
1001+
10071002
csocket = NULL;
10081003

10091004
client->trans_opts.tcp.port = opts.port;
10101005
client->trans_opts.tcp.privport = opts.privport;
1011-
sin_server.sin_family = AF_INET;
1012-
sin_server.sin_addr.s_addr = in_aton(addr);
1013-
sin_server.sin_port = htons(opts.port);
1014-
err = __sock_create(current->nsproxy->net_ns, PF_INET,
1006+
err = __sock_create(current->nsproxy->net_ns, stor.ss_family,
10151007
SOCK_STREAM, IPPROTO_TCP, &csocket, 1);
10161008
if (err) {
10171009
pr_err("%s (%d): problem creating socket\n",
@@ -1030,8 +1022,8 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
10301022
}
10311023

10321024
err = READ_ONCE(csocket->ops)->connect(csocket,
1033-
(struct sockaddr *)&sin_server,
1034-
sizeof(struct sockaddr_in), 0);
1025+
(struct sockaddr *)&stor,
1026+
sizeof(stor), 0);
10351027
if (err < 0) {
10361028
pr_err("%s (%d): problem connecting socket to %s\n",
10371029
__func__, task_pid_nr(current), addr);

0 commit comments

Comments
 (0)