diff options
author | Ka-Cheong Poon <ka-cheong.poon@oracle.com> | 2018-07-23 20:51:21 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-07-23 21:17:44 -0700 |
commit | eee2fa6ab3225192d6d894c54a6fb02ac9efdff6 (patch) | |
tree | 3031ff1c766052744eb5dc7c373ea25bebd75f36 /net/rds/tcp.c | |
parent | a6c90dd321bfeb5e48fc2eb6623b7b976106f6d7 (diff) | |
download | linux-eee2fa6ab3225192d6d894c54a6fb02ac9efdff6.tar.bz2 |
rds: Changing IP address internal representation to struct in6_addr
This patch changes 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.
v2: Fixed sparse warnings.
Signed-off-by: Ka-Cheong Poon <ka-cheong.poon@oracle.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/rds/tcp.c')
-rw-r--r-- | net/rds/tcp.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/net/rds/tcp.c b/net/rds/tcp.c index 351a28474667..dadb33790333 100644 --- a/net/rds/tcp.c +++ b/net/rds/tcp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Oracle. All rights reserved. + * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -37,6 +37,8 @@ #include <net/tcp.h> #include <net/net_namespace.h> #include <net/netns/generic.h> +#include <net/tcp.h> +#include <net/addrconf.h> #include "rds.h" #include "tcp.h" @@ -262,9 +264,33 @@ out: spin_unlock_irqrestore(&rds_tcp_tc_list_lock, flags); } -static int rds_tcp_laddr_check(struct net *net, __be32 addr) +static int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr, + __u32 scope_id) { - if (inet_addr_type(net, addr) == RTN_LOCAL) + struct net_device *dev = NULL; + int ret; + + if (ipv6_addr_v4mapped(addr)) { + if (inet_addr_type(net, addr->s6_addr32[3]) == RTN_LOCAL) + return 0; + return -EADDRNOTAVAIL; + } + + /* If the scope_id is specified, check only those addresses + * hosted on the specified interface. + */ + if (scope_id != 0) { + rcu_read_lock(); + dev = dev_get_by_index_rcu(net, scope_id); + /* scope_id is not valid... */ + if (!dev) { + rcu_read_unlock(); + return -EADDRNOTAVAIL; + } + rcu_read_unlock(); + } + ret = ipv6_chk_addr(net, addr, dev, 0); + if (ret) return 0; return -EADDRNOTAVAIL; } |