Skip to content

Commit 4d2cc57

Browse files
kcp-gitLinuxMinion
authored andcommitted
rds: Changed IP address internal representation to struct in6_addr
This patch changed the internal representation of an IP address to use struct in6_addr. IPv4 address is stored as an IPv4 mapped address. All the functions which take an IP address as argument are also changed to use struct in6_addr. But RDS socket layer is not modified such that it still does not accept IPv6 address from an application. And RDS layer does not accept nor initiate IPv6 connections. The RDS netfilter header is changed. User of RDS netfilter will need to be re-compiled. Orabug: 25410192 Signed-off-by: Ka-Cheong Poon <[email protected]> Reviewed-by: Håkon Bugge <[email protected]>
1 parent a37d690 commit 4d2cc57

24 files changed

+1002
-539
lines changed

include/uapi/linux/rds.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008 Oracle. All rights reserved.
2+
* Copyright (c) 2008, 2017 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This software is available to you under a choice of one of two
55
* licenses. You may choose to be licensed under the terms of the GNU
@@ -370,11 +370,11 @@ struct rds_rdma_send_notify {
370370

371371
/* netfilter related components */
372372
struct rds_nf_hdr {
373-
__be32 saddr; /* source address of request */
374-
__be32 daddr; /* destination address */
375-
__be16 sport; /* source port number */
376-
__be16 dport; /* destination port number */
377-
__be16 protocol; /* rds socket protocol family to use */
373+
struct in6_addr saddr; /* source address of request */
374+
struct in6_addr daddr; /* destination address */
375+
__be16 sport; /* source port number */
376+
__be16 dport; /* destination port number */
377+
__be16 protocol; /* rds socket protocol family to use */
378378

379379
#define RDS_NF_HDR_FLAG_BOTH (0x1) /* request needs to go locally and remote */
380380
#define RDS_NF_HDR_FLAG_DONE (0x2) /* the request is consumed and done */

net/rds/af_rds.c

Lines changed: 100 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <linux/errno.h>
3636
#include <linux/kernel.h>
3737
#include <linux/in.h>
38+
#include <linux/ipv6.h>
3839
#include <linux/poll.h>
3940
#include <linux/version.h>
4041
#include <linux/random.h>
@@ -145,26 +146,51 @@ void rds_wake_sk_sleep(struct rds_sock *rs)
145146
static int rds_getname(struct socket *sock, struct sockaddr *uaddr,
146147
int *uaddr_len, int peer)
147148
{
148-
struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
149149
struct rds_sock *rs = rds_sk_to_rs(sock->sk);
150-
151-
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
150+
struct sockaddr_in6 *sin6;
151+
struct sockaddr_in *sin;
152152

153153
/* racey, don't care */
154154
if (peer) {
155-
if (!rs->rs_conn_addr)
155+
if (ipv6_addr_any(&rs->rs_conn_addr))
156156
return -ENOTCONN;
157157

158-
sin->sin_port = rs->rs_conn_port;
159-
sin->sin_addr.s_addr = rs->rs_conn_addr;
158+
if (ipv6_addr_v4mapped(&rs->rs_conn_addr)) {
159+
sin = (struct sockaddr_in *)uaddr;
160+
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
161+
sin->sin_family = AF_INET;
162+
sin->sin_port = rs->rs_conn_port;
163+
sin->sin_addr.s_addr = rs->rs_conn_addr_v4;
164+
*uaddr_len = sizeof(*sin);
165+
} else {
166+
sin6 = (struct sockaddr_in6 *)uaddr;
167+
sin6->sin6_family = AF_INET6;
168+
sin6->sin6_port = rs->rs_conn_port;
169+
sin6->sin6_addr = rs->rs_conn_addr;
170+
sin6->sin6_flowinfo = 0;
171+
/* scope_id is the same as in the bound address. */
172+
sin6->sin6_scope_id = rs->rs_bound_scope_id;
173+
*uaddr_len = sizeof(*sin6);
174+
}
160175
} else {
161-
sin->sin_port = rs->rs_bound_port;
162-
sin->sin_addr.s_addr = rs->rs_bound_addr;
176+
if (ipv6_addr_v4mapped(&rs->rs_bound_addr)) {
177+
sin = (struct sockaddr_in *)uaddr;
178+
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
179+
sin->sin_family = AF_INET;
180+
sin->sin_port = rs->rs_bound_port;
181+
sin->sin_addr.s_addr = rs->rs_bound_addr_v4;
182+
*uaddr_len = sizeof(*sin);
183+
} else {
184+
sin6 = (struct sockaddr_in6 *)uaddr;
185+
sin6->sin6_family = AF_INET6;
186+
sin6->sin6_port = rs->rs_bound_port;
187+
sin6->sin6_addr = rs->rs_bound_addr;
188+
sin6->sin6_flowinfo = 0;
189+
sin6->sin6_scope_id = rs->rs_bound_scope_id;
190+
*uaddr_len = sizeof(*sin6);
191+
}
163192
}
164193

165-
sin->sin_family = AF_INET;
166-
167-
*uaddr_len = sizeof(*sin);
168194
return 0;
169195
}
170196

@@ -269,26 +295,36 @@ static int rds_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
269295
static int rds_cancel_sent_to(struct rds_sock *rs, char __user *optval,
270296
int len)
271297
{
298+
struct sockaddr_in6 sin6;
272299
struct sockaddr_in sin;
273300
int ret = 0;
274301

275302
/* racing with another thread binding seems ok here */
276-
if (rs->rs_bound_addr == 0) {
303+
if (ipv6_addr_any(&rs->rs_bound_addr)) {
277304
ret = -ENOTCONN; /* XXX not a great errno */
278305
goto out;
279306
}
280307

281308
if (len < sizeof(struct sockaddr_in)) {
282309
ret = -EINVAL;
283310
goto out;
311+
} else if (len < sizeof(struct sockaddr_in6)) {
312+
/* Assume IPv4 */
313+
if (copy_from_user(&sin, optval, sizeof(struct sockaddr_in))) {
314+
ret = -EFAULT;
315+
goto out;
316+
}
317+
ipv6_addr_set_v4mapped(sin.sin_addr.s_addr, &sin6.sin6_addr);
318+
sin6.sin6_port = sin.sin_port;
319+
} else {
320+
if (copy_from_user(&sin6, optval,
321+
sizeof(struct sockaddr_in6))) {
322+
ret = -EFAULT;
323+
goto out;
324+
}
284325
}
285326

286-
if (copy_from_user(&sin, optval, sizeof(sin))) {
287-
ret = -EFAULT;
288-
goto out;
289-
}
290-
291-
rds_send_drop_to(rs, &sin);
327+
rds_send_drop_to(rs, &sin6);
292328
out:
293329
return ret;
294330
}
@@ -346,6 +382,7 @@ static int rds_user_reset(struct rds_sock *rs, char __user *optval, int optlen)
346382
{
347383
struct rds_reset reset;
348384
struct rds_connection *conn;
385+
struct in6_addr src6, dst6;
349386
LIST_HEAD(s_addr_conns);
350387

351388
if (optlen != sizeof(struct rds_reset))
@@ -356,30 +393,32 @@ static int rds_user_reset(struct rds_sock *rs, char __user *optval, int optlen)
356393
return -EFAULT;
357394

358395
/* Reset all conns associated with source addr */
396+
ipv6_addr_set_v4mapped(reset.src.s_addr, &src6);
359397
if (reset.dst.s_addr == 0) {
360398
pr_info("RDS: Reset ALL conns for Source %pI4\n",
361399
&reset.src.s_addr);
362400

363401
rds_conn_laddr_list(sock_net(rds_rs_to_sk(rs)),
364-
reset.src.s_addr, &s_addr_conns);
402+
&src6, &s_addr_conns);
365403
if (list_empty(&s_addr_conns))
366404
goto done;
367405

368406
list_for_each_entry(conn, &s_addr_conns, c_laddr_node)
369407
if (conn)
370-
rds_user_conn_paths_drop(conn, 1);
408+
rds_conn_drop(conn, DR_USER_RESET);
371409
goto done;
372410
}
373411

374-
conn = rds_conn_find(sock_net(rds_rs_to_sk(rs)),
375-
reset.src.s_addr, reset.dst.s_addr,
376-
rs->rs_transport, reset.tos);
412+
ipv6_addr_set_v4mapped(reset.dst.s_addr, &dst6);
413+
conn = rds_conn_find(sock_net(rds_rs_to_sk(rs)), &src6, &dst6,
414+
rs->rs_transport, reset.tos,
415+
rs->rs_bound_scope_id);
377416

378417
if (conn) {
379418
bool is_tcp = conn->c_trans->t_type == RDS_TRANS_TCP;
380419

381420
printk(KERN_NOTICE "Resetting RDS/%s connection <%pI4,%pI4,%d>\n",
382-
is_tcp ? "tcp" : "IB",
421+
is_tcp ? "TCP" : "IB",
383422
&reset.src.s_addr,
384423
&reset.dst.s_addr, conn->c_tos);
385424
rds_user_conn_paths_drop(conn, DR_USER_RESET);
@@ -571,31 +610,41 @@ static int rds_connect(struct socket *sock, struct sockaddr *uaddr,
571610
int addr_len, int flags)
572611
{
573612
struct sock *sk = sock->sk;
574-
struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
613+
struct sockaddr_in *sin;
575614
struct rds_sock *rs = rds_sk_to_rs(sk);
576615
int ret = 0;
577616

578617
lock_sock(sk);
579618

580-
if (addr_len != sizeof(struct sockaddr_in)) {
581-
ret = -EINVAL;
582-
goto out;
583-
}
619+
switch (addr_len) {
620+
case sizeof(struct sockaddr_in):
621+
sin = (struct sockaddr_in *)uaddr;
622+
if (sin->sin_family != AF_INET) {
623+
ret = -EAFNOSUPPORT;
624+
break;
625+
}
626+
if (sin->sin_addr.s_addr == INADDR_ANY) {
627+
ret = -EDESTADDRREQ;
628+
break;
629+
}
630+
if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) ||
631+
sin->sin_addr.s_addr == INADDR_BROADCAST) {
632+
ret = -EINVAL;
633+
break;
634+
}
635+
ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &rs->rs_conn_addr);
636+
rs->rs_conn_port = sin->sin_port;
637+
break;
584638

585-
if (sin->sin_family != AF_INET) {
586-
ret = -EAFNOSUPPORT;
587-
goto out;
588-
}
639+
case sizeof(struct sockaddr_in6):
640+
ret = -EPROTONOSUPPORT;
641+
break;
589642

590-
if (sin->sin_addr.s_addr == htonl(INADDR_ANY)) {
591-
ret = -EDESTADDRREQ;
592-
goto out;
643+
default:
644+
ret = -EINVAL;
645+
break;
593646
}
594647

595-
rs->rs_conn_addr = sin->sin_addr.s_addr;
596-
rs->rs_conn_port = sin->sin_port;
597-
598-
out:
599648
release_sock(sk);
600649
return ret;
601650
}
@@ -659,8 +708,10 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol)
659708
rs->rs_netfilter_enabled = 0;
660709
rs->rs_rx_traces = 0;
661710

662-
if (rs->rs_bound_addr)
663-
printk(KERN_CRIT "bound addr %x at create\n", rs->rs_bound_addr);
711+
if (!ipv6_addr_any(&rs->rs_bound_addr)) {
712+
printk(KERN_CRIT "bound addr %pI6c at create\n",
713+
&rs->rs_bound_addr);
714+
}
664715

665716
spin_lock_bh(&rds_sock_lock);
666717
list_add_tail(&rs->rs_item, &rds_sock_list);
@@ -756,8 +807,10 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len,
756807
list_for_each_entry(inc, &rs->rs_recv_queue, i_item) {
757808
total++;
758809
if (total <= len)
759-
rds_inc_info_copy(inc, iter, inc->i_saddr,
760-
rs->rs_bound_addr, 1);
810+
rds_inc_info_copy(inc, iter,
811+
inc->i_saddr.s6_addr32[3],
812+
rs->rs_bound_addr_v4,
813+
1);
761814
}
762815

763816
read_unlock(&rs->rs_recv_lock);
@@ -786,8 +839,8 @@ static void rds_sock_info(struct socket *sock, unsigned int len,
786839
list_for_each_entry(rs, &rds_sock_list, rs_item) {
787840
sinfo.sndbuf = rds_sk_sndbuf(rs);
788841
sinfo.rcvbuf = rds_sk_rcvbuf(rs);
789-
sinfo.bound_addr = rs->rs_bound_addr;
790-
sinfo.connected_addr = rs->rs_conn_addr;
842+
sinfo.bound_addr = rs->rs_bound_addr_v4;
843+
sinfo.connected_addr = rs->rs_conn_addr_v4;
791844
sinfo.bound_port = rs->rs_bound_port;
792845
sinfo.connected_port = rs->rs_conn_port;
793846
sinfo.inum = sock_i_ino(rds_rs_to_sk(rs));
@@ -913,8 +966,8 @@ static void __exit rds_exit(void)
913966
rds_page_exit();
914967
rds_info_deregister_func(RDS_INFO_SOCKETS, rds_sock_info);
915968
rds_info_deregister_func(RDS_INFO_RECV_MESSAGES, rds_sock_inc_info);
916-
917969
}
970+
918971
module_exit(rds_exit);
919972

920973
u32 rds_gen_num;

0 commit comments

Comments
 (0)