Skip to content

Commit

Permalink
NFSv4: Fix up delegation callbacks
Browse files Browse the repository at this point in the history
Currently, the callback server is listening on IPv6 if it is enabled. This
means that IPv4 addresses will always be mapped.

Signed-off-by: Trond Myklebust <[email protected]>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Dec 23, 2008
1 parent b7391f4 commit 9082a5c
Showing 1 changed file with 38 additions and 19 deletions.
57 changes: 38 additions & 19 deletions fs/nfs/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,31 +223,54 @@ void nfs_put_client(struct nfs_client *clp)
}
}

static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
const struct sockaddr_in *sa2)
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static const struct in6_addr *nfs_map_ipv4_addr(const struct sockaddr *sa, struct in6_addr *addr_mapped)
{
return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr;
switch (sa->sa_family) {
default:
return NULL;
case AF_INET6:
return &((const struct sockaddr_in6 *)sa)->sin6_addr;
break;
case AF_INET:
ipv6_addr_set_v4mapped(((const struct sockaddr_in *)sa)->sin_addr.s_addr,
addr_mapped);
return addr_mapped;
}
}

static int nfs_sockaddr_match_ipaddr6(const struct sockaddr_in6 *sa1,
const struct sockaddr_in6 *sa2)
static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
const struct sockaddr *sa2)
{
const struct in6_addr *addr1;
const struct in6_addr *addr2;
struct in6_addr addr1_mapped;
struct in6_addr addr2_mapped;

addr1 = nfs_map_ipv4_addr(sa1, &addr1_mapped);
if (likely(addr1 != NULL)) {
addr2 = nfs_map_ipv4_addr(sa2, &addr2_mapped);
if (likely(addr2 != NULL))
return ipv6_addr_equal(addr1, addr2);
}
return 0;
}
#else
static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
const struct sockaddr_in *sa2)
{
return ipv6_addr_equal(&sa1->sin6_addr, &sa2->sin6_addr);
return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr;
}

static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
const struct sockaddr *sa2)
{
switch (sa1->sa_family) {
case AF_INET:
return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
(const struct sockaddr_in *)sa2);
case AF_INET6:
return nfs_sockaddr_match_ipaddr6((const struct sockaddr_in6 *)sa1,
(const struct sockaddr_in6 *)sa2);
}
BUG();
if (unlikely(sa1->sa_family != AF_INET || sa2->sa_family != AF_INET))
return 0;
return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
(const struct sockaddr_in *)sa2);
}
#endif

/*
* Find a client by IP address and protocol version
Expand All @@ -269,8 +292,6 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
if (clp->rpc_ops->version != nfsversion)
continue;

if (addr->sa_family != clap->sa_family)
continue;
/* Match only the IP address, not the port number */
if (!nfs_sockaddr_match_ipaddr(addr, clap))
continue;
Expand Down Expand Up @@ -304,8 +325,6 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
if (clp->rpc_ops->version != nfsvers)
continue;

if (sap->sa_family != clap->sa_family)
continue;
/* Match only the IP address, not the port number */
if (!nfs_sockaddr_match_ipaddr(sap, clap))
continue;
Expand Down

0 comments on commit 9082a5c

Please sign in to comment.