summaryrefslogtreecommitdiffstats
path: root/support/export/client.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2010-05-05 15:41:07 -0400
committerSteve Dickson <steved@redhat.com>2010-05-05 15:42:36 -0400
commit6299a310d77e6495efdf7c50491f0b055fee2cfe (patch)
tree636a10692ff37c4d7fb65f59d4be8a9c91724409 /support/export/client.c
parent6ff1fd42db18c657fbc5f81169a566b41d53e731 (diff)
downloadnfs-utils-6299a310d77e6495efdf7c50491f0b055fee2cfe.tar.gz
nfs-utils-6299a310d77e6495efdf7c50491f0b055fee2cfe.tar.xz
nfs-utils-6299a310d77e6495efdf7c50491f0b055fee2cfe.zip
mountd/exportfs: Make m_addrlist field a nfs_sockaddr
To store non-AF_INET addresses in the nfs_client structure, we need to use more than in_addr for the m_addrlist field. Make m_addrlist larger, then add a few helper functions to handle type casting and array indexing cleanly. We could treat the nfs_client address list as if all the addresses in the list were the same family. This might work for MCL_SUBNETWORK type nfs_clients. However, during the transition to IPv6, most hosts will have at least one IPv4 and one IPv6 address. For MCL_FQDN, I think we need to have the ability to store addresses from both families in one nfs_client. Additionally, IPv6 scope IDs are not part of struct sin6_addr. To support link-local IPv6 addresses and the like, a scope ID must be stored. Thus, each slot in the address list needs to be capable of storing an entire socket address, and not simply the network address part. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'support/export/client.c')
-rw-r--r--support/export/client.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/support/export/client.c b/support/export/client.c
index 4600255..21ad272 100644
--- a/support/export/client.c
+++ b/support/export/client.c
@@ -37,6 +37,9 @@ nfs_client *clientlist[MCL_MAXTYPES] = { NULL, };
static void
init_addrlist(nfs_client *clp, const struct hostent *hp)
{
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ };
char **ap;
int i;
@@ -44,9 +47,10 @@ init_addrlist(nfs_client *clp, const struct hostent *hp)
return;
ap = hp->h_addr_list;
- for (i = 0; *ap != NULL && i < NFSCLNT_ADDRMAX; i++, ap++)
- clp->m_addrlist[i] = *(struct in_addr *)*ap;
-
+ for (i = 0; *ap != NULL && i < NFSCLNT_ADDRMAX; i++, ap++) {
+ sin.sin_addr = *(struct in_addr *)*ap;
+ set_addrlist_in(clp, i, &sin);
+ }
clp->m_naddr = i;
}
@@ -60,17 +64,22 @@ client_free(nfs_client *clp)
static int
init_netmask(nfs_client *clp, const char *slash)
{
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ };
+
if (strchr(slash + 1, '.') != NULL)
- clp->m_addrlist[1].s_addr = inet_addr(slash + 1);
+ sin.sin_addr.s_addr = inet_addr(slash + 1);
else {
int prefixlen = atoi(slash + 1);
if (0 < prefixlen && prefixlen <= 32)
- clp->m_addrlist[1].s_addr =
+ sin.sin_addr.s_addr =
htonl((uint32_t)~0 << (32 - prefixlen));
else
goto out_badprefix;
}
+ set_addrlist_in(clp, 1, &sin);
return 1;
out_badprefix:
@@ -81,6 +90,9 @@ out_badprefix:
static int
init_subnetwork(nfs_client *clp)
{
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ };
static char slash32[] = "/32";
char *cp;
@@ -89,7 +101,8 @@ init_subnetwork(nfs_client *clp)
cp = slash32;
*cp = '\0';
- clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname);
+ sin.sin_addr.s_addr = inet_addr(clp->m_hostname);
+ set_addrlist_in(clp, 0, &sin);
*cp = '/';
return init_netmask(clp, cp);
@@ -366,6 +379,7 @@ add_name(char *old, const char *add)
static int
check_fqdn(const nfs_client *clp, const struct hostent *hp)
{
+ const struct sockaddr_in *sin;
struct in_addr addr;
char **ap;
int i;
@@ -373,9 +387,11 @@ check_fqdn(const nfs_client *clp, const struct hostent *hp)
for (ap = hp->h_addr_list; *ap; ap++) {
addr = *(struct in_addr *)*ap;
- for (i = 0; i < clp->m_naddr; i++)
- if (clp->m_addrlist[i].s_addr == addr.s_addr)
+ for (i = 0; i < clp->m_naddr; i++) {
+ sin = get_addrlist_in(clp, i);
+ if (sin->sin_addr.s_addr == addr.s_addr)
return 1;
+ }
}
return 0;
}
@@ -388,14 +404,17 @@ check_fqdn(const nfs_client *clp, const struct hostent *hp)
static int
check_subnetwork(const nfs_client *clp, const struct hostent *hp)
{
+ const struct sockaddr_in *address, *mask;
struct in_addr addr;
char **ap;
for (ap = hp->h_addr_list; *ap; ap++) {
+ address = get_addrlist_in(clp, 0);
+ mask = get_addrlist_in(clp, 1);
addr = *(struct in_addr *)*ap;
- if (!((clp->m_addrlist[0].s_addr ^ addr.s_addr) &
- clp->m_addrlist[1].s_addr))
+ if (!((address->sin_addr.s_addr ^ addr.s_addr) &
+ mask->sin_addr.s_addr))
return 1;
}
return 0;