struct hostent can store either IPv4 or IPv6 addresses, but it can't
store both address families concurrently for the same host. Neither
can hostent deal with parts of socket addresses that are outside of
the sin{,6}_addr field.
Replace the use of "struct hostent" everywhere in libexport.a, mountd,
and exportfs with "struct addrinfo". This is a large change, but
there are so many strong dependencies on struct hostent that this
can't easily be broken into smaller pieces.
One benefit of this change is that hostent_dup() is no longer
required, since the results of getaddrinfo(3) are already dynamically
allocated.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
-init_addrlist(nfs_client *clp, const struct hostent *hp)
+init_addrlist(nfs_client *clp, const struct addrinfo *ai)
- struct sockaddr_in sin = {
- .sin_family = AF_INET,
- };
- char **ap;
- ap = hp->h_addr_list;
- for (i = 0; *ap != NULL && i < NFSCLNT_ADDRMAX; i++, ap++) {
- sin.sin_addr = *(struct in_addr *)*ap;
- set_addrlist_in(clp, i, &sin);
+ for (i = 0; (ai != NULL) && (i < NFSCLNT_ADDRMAX); i++) {
+ set_addrlist(clp, i, ai->ai_addr);
+ ai = ai->ai_next;
-client_init(nfs_client *clp, const char *hname, const struct hostent *hp)
+client_init(nfs_client *clp, const char *hname, const struct addrinfo *ai)
{
clp->m_hostname = strdup(hname);
if (clp->m_hostname == NULL)
{
clp->m_hostname = strdup(hname);
if (clp->m_hostname == NULL)
if (clp->m_type == MCL_SUBNETWORK)
return init_subnetwork(clp);
if (clp->m_type == MCL_SUBNETWORK)
return init_subnetwork(clp);
- init_addrlist(clp, hp);
+ init_addrlist(clp, ai);
{
nfs_client *clp = NULL;
int htype;
{
nfs_client *clp = NULL;
int htype;
- struct hostent *hp = NULL;
+ struct addrinfo *ai = NULL;
htype = client_gettype(hname);
if (htype == MCL_FQDN && !canonical) {
htype = client_gettype(hname);
if (htype == MCL_FQDN && !canonical) {
- struct hostent *hp2;
- hp = gethostbyname(hname);
- if (hp == NULL || hp->h_addrtype != AF_INET) {
- xlog(L_ERROR, "%s has non-inet addr", hname);
- return NULL;
+ ai = host_addrinfo(hname);
+ if (!ai) {
+ xlog(L_ERROR, "Failed to resolve %s", hname);
+ goto out;
- /* make sure we have canonical name */
- hp2 = hostent_dup(hp);
- hp = gethostbyaddr(hp2->h_addr, hp2->h_length,
- hp2->h_addrtype);
- if (hp) {
- hp = hostent_dup(hp);
- /* but now we might not have all addresses... */
- if (hp2->h_addr_list[1]) {
- struct hostent *hp3 =
- gethostbyname(hp->h_name);
- if (hp3) {
- free(hp);
- hp = hostent_dup(hp3);
- }
- }
- free(hp2);
- } else
- hp = hp2;
-
- hname = (char *) hp->h_name;
+ hname = ai->ai_canonname;
- for (clp = clientlist[htype]; clp; clp = clp->m_next) {
- if (client_check(clp, hp))
+ for (clp = clientlist[htype]; clp; clp = clp->m_next)
+ if (client_check(clp, ai))
} else {
for (clp = clientlist[htype]; clp; clp = clp->m_next) {
if (strcasecmp(hname, clp->m_hostname)==0)
} else {
for (clp = clientlist[htype]; clp; clp = clp->m_next) {
if (strcasecmp(hname, clp->m_hostname)==0)
}
if (htype == MCL_FQDN && clp->m_naddr == 0)
}
if (htype == MCL_FQDN && clp->m_naddr == 0)
- init_addrlist(clp, hp);
+ init_addrlist(clp, ai);
+/**
+ * client_dup - create a copy of an nfs_client
+ * @clp: pointer to nfs_client to copy
+ * @ai: pointer to addrinfo used to initialize the new client's addrlist
+ *
+ * Returns a dynamically allocated nfs_client if successful, or
+ * NULL if some problem occurs. Caller must free the returned
+ * nfs_client with free(3).
+ */
-client_dup(nfs_client *clp, struct hostent *hp)
+client_dup(const nfs_client *clp, const struct addrinfo *ai)
new->m_type = MCL_FQDN;
new->m_hostname = NULL;
new->m_type = MCL_FQDN;
new->m_hostname = NULL;
- if (!client_init(new, hp->h_name, hp)) {
+ if (!client_init(new, ai->ai_canonname, ai)) {
client_free(new);
return NULL;
}
client_free(new);
return NULL;
}
-struct hostent *
-client_resolve(struct in_addr addr)
+/**
+ * client_resolve - look up an IP address
+ * @sap: pointer to socket address to resolve
+ *
+ * Returns an addrinfo structure, or NULL if some problem occurred.
+ * Caller must free the result with freeaddrinfo(3).
+ */
+struct addrinfo *
+client_resolve(const struct sockaddr *sap)
- struct hostent *he = NULL;
+ struct addrinfo *ai = NULL;
if (clientlist[MCL_WILDCARD] || clientlist[MCL_NETGROUP])
if (clientlist[MCL_WILDCARD] || clientlist[MCL_NETGROUP])
- he = get_reliable_hostbyaddr((const char*)&addr, sizeof(addr), AF_INET);
- if (he == NULL)
- he = get_hostent((const char*)&addr, sizeof(addr), AF_INET);
+ ai = host_reliable_addrinfo(sap);
+ if (ai == NULL)
+ ai = host_numeric_addrinfo(sap);
}
/**
* client_compose - Make a list of cached hostnames that match an IP address
}
/**
* client_compose - Make a list of cached hostnames that match an IP address
- * @he: pointer to hostent containing IP address information to match
+ * @ai: pointer to addrinfo containing IP address information to match
*
* Gather all known client hostnames that match the IP address, and sort
* the result into a comma-separated list.
*
* Gather all known client hostnames that match the IP address, and sort
* the result into a comma-separated list.
* returned string with free(3).
*/
char *
* returned string with free(3).
*/
char *
-client_compose(struct hostent *he)
+client_compose(const struct addrinfo *ai)
{
char *name = NULL;
int i;
{
char *name = NULL;
int i;
for (i = 0 ; i < MCL_MAXTYPES; i++) {
nfs_client *clp;
for (clp = clientlist[i]; clp ; clp = clp->m_next) {
for (i = 0 ; i < MCL_MAXTYPES; i++) {
nfs_client *clp;
for (clp = clientlist[i]; clp ; clp = clp->m_next) {
- if (!client_check(clp, he))
+ if (!client_check(clp, ai))
continue;
name = add_name(name, clp->m_hostname);
}
continue;
name = add_name(name, clp->m_hostname);
}
+static _Bool
+addrs_match4(const struct sockaddr *sa1, const struct sockaddr *sa2)
+{
+ const struct sockaddr_in *si1 = (const struct sockaddr_in *)sa1;
+ const struct sockaddr_in *si2 = (const struct sockaddr_in *)sa2;
+
+ return si1->sin_addr.s_addr == si2->sin_addr.s_addr;
+}
+
+static _Bool
+addrs_match(const struct sockaddr *sa1, const struct sockaddr *sa2)
+{
+ if (sa1->sa_family == sa2->sa_family)
+ switch (sa1->sa_family) {
+ case AF_INET:
+ return addrs_match4(sa1, sa2);
+ }
+
+ return false;
+}
+
- * Check each address listed in @hp against each address
+ * Check each address listed in @ai against each address
* stored in @clp. Return 1 if a match is found, otherwise
* zero.
*/
static int
* stored in @clp. Return 1 if a match is found, otherwise
* zero.
*/
static int
-check_fqdn(const nfs_client *clp, const struct hostent *hp)
+check_fqdn(const nfs_client *clp, const struct addrinfo *ai)
- const struct sockaddr_in *sin;
- struct in_addr addr;
- char **ap;
- for (ap = hp->h_addr_list; *ap; ap++) {
- addr = *(struct in_addr *)*ap;
-
- for (i = 0; i < clp->m_naddr; i++) {
- sin = get_addrlist_in(clp, i);
- if (sin->sin_addr.s_addr == addr.s_addr)
+ for (; ai; ai = ai->ai_next)
+ for (i = 0; i < clp->m_naddr; i++)
+ if (addrs_match(ai->ai_addr, get_addrlist(clp, i)))
+
+ return 0;
+}
+
+static _Bool
+mask_match(const uint32_t a, const uint32_t b, const uint32_t m)
+{
+ return ((a ^ b) & m) == 0;
+}
+
+static int
+check_subnet_v4(const struct sockaddr_in *address,
+ const struct sockaddr_in *mask, const struct addrinfo *ai)
+{
+ for (; ai; ai = ai->ai_next) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
+
+ if (sin->sin_family != AF_INET)
+ continue;
+
+ if (mask_match(address->sin_addr.s_addr,
+ sin->sin_addr.s_addr,
+ mask->sin_addr.s_addr))
+ return 1;
- * Check each address listed in @hp against the subnetwork or
+ * Check each address listed in @ai against the subnetwork or
* host address stored in @clp. Return 1 if an address in @hp
* matches the host address stored in @clp, otherwise zero.
*/
static int
* host address stored in @clp. Return 1 if an address in @hp
* matches the host address stored in @clp, otherwise zero.
*/
static int
-check_subnetwork(const nfs_client *clp, const struct hostent *hp)
+check_subnetwork(const nfs_client *clp, const struct addrinfo *ai)
- 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 (!((address->sin_addr.s_addr ^ addr.s_addr) &
- mask->sin_addr.s_addr))
- return 1;
+ switch (get_addrlist(clp, 0)->sa_family) {
+ case AF_INET:
+ return check_subnet_v4(get_addrlist_in(clp, 0),
+ get_addrlist_in(clp, 1), ai);
-check_wildcard(const nfs_client *clp, const struct hostent *hp)
+check_wildcard(const nfs_client *clp, const struct addrinfo *ai)
{
char *cname = clp->m_hostname;
{
char *cname = clp->m_hostname;
- char *hname = hp->h_name;
+ char *hname = ai->ai_canonname;
+ struct hostent *hp;
char **ap;
if (wildmat(hname, cname))
char **ap;
if (wildmat(hname, cname))
/* See if hname aliases listed in /etc/hosts or nis[+]
* match the requested wildcard */
/* See if hname aliases listed in /etc/hosts or nis[+]
* match the requested wildcard */
- for (ap = hp->h_aliases; *ap; ap++) {
- if (wildmat(*ap, cname))
- return 1;
+ hp = gethostbyname(hname);
+ if (hp != NULL) {
+ for (ap = hp->h_aliases; *ap; ap++)
+ if (wildmat(*ap, cname))
+ return 1;
- * Check if @hp's hostname or aliases fall in a given netgroup.
- * Return 1 if @hp represents a host in the netgroup, otherwise zero.
+ * Check if @ai's hostname or aliases fall in a given netgroup.
+ * Return 1 if @ai represents a host in the netgroup, otherwise
+ * zero.
*/
#ifdef HAVE_INNETGR
static int
*/
#ifdef HAVE_INNETGR
static int
-check_netgroup(const nfs_client *clp, const struct hostent *hp)
+check_netgroup(const nfs_client *clp, const struct addrinfo *ai)
{
const char *netgroup = clp->m_hostname + 1;
{
const char *netgroup = clp->m_hostname + 1;
- const char *hname = hp->h_name;
- struct hostent *nhp = NULL;
- struct sockaddr_in addr;
- int match, i;
+ const char *hname = ai->ai_canonname;
+ struct addrinfo *tmp = NULL;
+ struct hostent *hp;
+ int i, match;
char *dot;
/* First, try to match the hostname without
char *dot;
/* First, try to match the hostname without
/* See if hname aliases listed in /etc/hosts or nis[+]
* match the requested netgroup */
/* See if hname aliases listed in /etc/hosts or nis[+]
* match the requested netgroup */
- for (i = 0; hp->h_aliases[i]; i++) {
- if (innetgr(netgroup, hp->h_aliases[i], NULL, NULL))
- return 1;
+ hp = gethostbyname(hname);
+ if (hp != NULL) {
+ for (i = 0; hp->h_aliases[i]; i++)
+ if (innetgr(netgroup, hp->h_aliases[i], NULL, NULL))
+ return 1;
}
/* If hname is ip address convert to FQDN */
}
/* If hname is ip address convert to FQDN */
- if (inet_aton(hname, &addr.sin_addr) &&
- (nhp = gethostbyaddr((const char *)&(addr.sin_addr),
- sizeof(addr.sin_addr), AF_INET))) {
- hname = nhp->h_name;
+ tmp = host_pton(hname);
+ if (tmp != NULL) {
+ freeaddrinfo(tmp);
if (innetgr(netgroup, hname, NULL, NULL))
return 1;
}
if (innetgr(netgroup, hname, NULL, NULL))
return 1;
}
#else /* !HAVE_INNETGR */
static int
check_netgroup(__attribute__((unused)) const nfs_client *clp,
#else /* !HAVE_INNETGR */
static int
check_netgroup(__attribute__((unused)) const nfs_client *clp,
- __attribute__((unused)) const struct hostent *hp)
+ __attribute__((unused)) const struct addrinfo *ai)
/**
* client_check - check if IP address information matches a cached nfs_client
* @clp: pointer to a cached nfs_client record
/**
* client_check - check if IP address information matches a cached nfs_client
* @clp: pointer to a cached nfs_client record
- * @hp: pointer to hostent containing host IP information
+ * @ai: pointer to addrinfo to compare it with
*
* Returns 1 if the address information matches the cached nfs_client,
* otherwise zero.
*/
int
*
* Returns 1 if the address information matches the cached nfs_client,
* otherwise zero.
*/
int
-client_check(nfs_client *clp, struct hostent *hp)
+client_check(const nfs_client *clp, const struct addrinfo *ai)
{
switch (clp->m_type) {
case MCL_FQDN:
{
switch (clp->m_type) {
case MCL_FQDN:
- return check_fqdn(clp, hp);
+ return check_fqdn(clp, ai);
- return check_subnetwork(clp, hp);
+ return check_subnetwork(clp, ai);
- return check_wildcard(clp, hp);
+ return check_wildcard(clp, ai);
- return check_netgroup(clp, hp);
+ return check_netgroup(clp, ai);
case MCL_ANONYMOUS:
return 1;
case MCL_GSS:
case MCL_ANONYMOUS:
return 1;
case MCL_GSS:
static void export_init(nfs_export *exp, nfs_client *clp,
struct exportent *nep);
static void export_init(nfs_export *exp, nfs_client *clp,
struct exportent *nep);
-static int export_check(nfs_export *, struct hostent *, char *);
+static int export_check(const nfs_export *exp, const struct addrinfo *ai,
+ const char *path);
- export_allowed_internal(struct hostent *hp, char *path);
+ export_allowed_internal(const struct addrinfo *ai,
+ const char *path);
static void
export_free(nfs_export *exp)
static void
export_free(nfs_export *exp)
* original hostname from /etc/exports, while the in-core client struct
* gets the newly found FQDN.
*/
* original hostname from /etc/exports, while the in-core client struct
* gets the newly found FQDN.
*/
-nfs_export *
-export_dup(nfs_export *exp, struct hostent *hp)
+static nfs_export *
+export_dup(nfs_export *exp, const struct addrinfo *ai)
{
nfs_export *new;
nfs_client *clp;
{
nfs_export *new;
nfs_client *clp;
dupexportent(&new->m_export, &exp->m_export);
if (exp->m_export.e_hostname)
new->m_export.e_hostname = xstrdup(exp->m_export.e_hostname);
dupexportent(&new->m_export, &exp->m_export);
if (exp->m_export.e_hostname)
new->m_export.e_hostname = xstrdup(exp->m_export.e_hostname);
- clp = client_dup(exp->m_client, hp);
+ clp = client_dup(exp->m_client, ai);
if (clp == NULL) {
export_free(new);
return NULL;
if (clp == NULL) {
export_free(new);
return NULL;
+/**
+ * export_find - find or create a suitable nfs_export for @ai and @path
+ * @ai: pointer to addrinfo for client
+ * @path: '\0'-terminated ASCII string containing export path
+ *
+ * Returns a pointer to nfs_export data matching @ai and @path,
+ * or NULL if an error occurs.
+ */
-export_find(struct hostent *hp, char *path)
+export_find(const struct addrinfo *ai, const char *path)
{
nfs_export *exp;
int i;
for (i = 0; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
{
nfs_export *exp;
int i;
for (i = 0; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
- if (!export_check(exp, hp, path))
+ if (!export_check(exp, ai, path))
continue;
if (exp->m_client->m_type == MCL_FQDN)
return exp;
continue;
if (exp->m_client->m_type == MCL_FQDN)
return exp;
- return export_dup(exp, hp);
+ return export_dup(exp, ai);
-export_allowed_internal (struct hostent *hp, char *path)
+export_allowed_internal(const struct addrinfo *ai, const char *path)
{
nfs_export *exp;
int i;
{
nfs_export *exp;
int i;
for (i = 0; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
if (!exp->m_mayexport ||
for (i = 0; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
if (!exp->m_mayexport ||
- !export_check(exp, hp, path))
+ !export_check(exp, ai, path))
+/**
+ * export_allowed - determine if this export is allowed
+ * @ai: pointer to addrinfo for client
+ * @path: '\0'-terminated ASCII string containing export path
+ *
+ * Returns a pointer to nfs_export data matching @ai and @path,
+ * or NULL if the export is not allowed.
+ */
-export_allowed(struct hostent *hp, char *path)
+export_allowed(const struct addrinfo *ai, const char *path)
{
nfs_export *exp;
char epath[MAXPATHLEN+1];
{
nfs_export *exp;
char epath[MAXPATHLEN+1];
/* Try the longest matching exported pathname. */
while (1) {
/* Try the longest matching exported pathname. */
while (1) {
- exp = export_allowed_internal (hp, epath);
+ exp = export_allowed_internal(ai, epath);
if (exp)
return exp;
/* We have to treat the root, "/", specially. */
if (exp)
return exp;
/* We have to treat the root, "/", specially. */
-export_check(nfs_export *exp, struct hostent *hp, char *path)
+export_check(const nfs_export *exp, const struct addrinfo *ai, const char *path)
{
if (strcmp(path, exp->m_export.e_path))
return 0;
{
if (strcmp(path, exp->m_export.e_path))
return 0;
- return client_check(exp->m_client, hp);
+ return client_check(exp->m_client, ai);
rmtab_read_wildcard(struct rmtabent *rep)
{
nfs_export *exp, *exp2;
rmtab_read_wildcard(struct rmtabent *rep)
{
nfs_export *exp, *exp2;
- hp = gethostbyname(rep->r_client);
- if (hp == NULL)
- return;
- hp = hostent_dup(hp);
- if (hp == NULL)
+ ai = host_addrinfo(rep->r_client);
+ if (ai == NULL)
- exp = export_allowed(hp, rep->r_path);
- free(hp);
+ exp = export_allowed(ai, rep->r_path);
+ freeaddrinfo(ai);
extern nfs_client * clientlist[MCL_MAXTYPES];
nfs_client * client_lookup(char *hname, int canonical);
extern nfs_client * clientlist[MCL_MAXTYPES];
nfs_client * client_lookup(char *hname, int canonical);
-nfs_client * client_dup(nfs_client *, struct hostent *);
+nfs_client * client_dup(const nfs_client *clp,
+ const struct addrinfo *ai);
int client_gettype(char *hname);
int client_gettype(char *hname);
-int client_check(nfs_client *, struct hostent *);
+int client_check(const nfs_client *clp,
+ const struct addrinfo *ai);
void client_release(nfs_client *);
void client_freeall(void);
void client_release(nfs_client *);
void client_freeall(void);
-char * client_compose(struct hostent *he);
-struct hostent * client_resolve(struct in_addr addr);
+char * client_compose(const struct addrinfo *ai);
+struct addrinfo * client_resolve(const struct sockaddr *sap);
int client_member(const char *client,
const char *name);
int client_member(const char *client,
const char *name);
void export_add(nfs_export *);
void export_reset(nfs_export *);
nfs_export * export_lookup(char *hname, char *path, int caconical);
void export_add(nfs_export *);
void export_reset(nfs_export *);
nfs_export * export_lookup(char *hname, char *path, int caconical);
-nfs_export * export_find(struct hostent *, char *path);
-nfs_export * export_allowed(struct hostent *, char *path);
+nfs_export * export_find(const struct addrinfo *ai,
+ const char *path);
+nfs_export * export_allowed(const struct addrinfo *ai,
+ const char *path);
nfs_export * export_create(struct exportent *, int canonical);
nfs_export * export_create(struct exportent *, int canonical);
-nfs_export * export_dup(nfs_export *, struct hostent *);
void export_freeall(void);
int export_export(nfs_export *);
int export_unexport(nfs_export *);
void export_freeall(void);
int export_export(nfs_export *);
int export_unexport(nfs_export *);
{
struct exportent *eep;
nfs_export *exp;
{
struct exportent *eep;
nfs_export *exp;
- struct hostent *hp = NULL;
+ struct addrinfo *ai = NULL;
char *path;
char *hname = arg;
int htype;
char *path;
char *hname = arg;
int htype;
- if ((htype = client_gettype(hname)) == MCL_FQDN &&
- (hp = gethostbyname(hname)) != NULL) {
- struct hostent *hp2 = hostent_dup (hp);
- hp = gethostbyaddr(hp2->h_addr, hp2->h_length,
- hp2->h_addrtype);
- if (hp) {
- free(hp2);
- hp = hostent_dup(hp);
- } else
- hp = hp2;
- exp = export_find(hp, path);
- hname = hp->h_name;
- } else {
+ if ((htype = client_gettype(hname)) == MCL_FQDN) {
+ ai = host_addrinfo(hname);
+ if (ai != NULL) {
+ exp = export_find(ai, path);
+ hname = ai->ai_canonname;
+ }
+ } else
exp = export_lookup(hname, path, 0);
exp = export_lookup(hname, path, 0);
if (!exp) {
if (!(eep = mkexportent(hname, path, options)) ||
if (!exp) {
if (!(eep = mkexportent(hname, path, options)) ||
validate_export(exp);
out:
validate_export(exp);
out:
-static char *get_client_hostname(struct sockaddr_in *caller, struct hostent *hp, enum auth_error *error)
+static char *
+get_client_hostname(struct sockaddr_in *caller, struct addrinfo *ai,
+ enum auth_error *error)
{
char *n;
if (use_ipaddr)
return strdup(inet_ntoa(caller->sin_addr));
{
char *n;
if (use_ipaddr)
return strdup(inet_ntoa(caller->sin_addr));
- n = client_compose(hp);
+ n = client_compose(ai);
*error = unknown_host;
if (!n)
return NULL;
*error = unknown_host;
if (!n)
return NULL;
/* return static nfs_export with details filled in */
static nfs_export *
/* return static nfs_export with details filled in */
static nfs_export *
-auth_authenticate_newcache(char *what, struct sockaddr_in *caller,
- char *path, struct hostent *hp,
+auth_authenticate_newcache(struct sockaddr_in *caller,
+ char *path, struct addrinfo *ai,
enum auth_error *error)
{
nfs_export *exp;
enum auth_error *error)
{
nfs_export *exp;
free(my_client.m_hostname);
free(my_client.m_hostname);
- my_client.m_hostname = get_client_hostname(caller, hp, error);
+ my_client.m_hostname = get_client_hostname(caller, ai, error);
if (my_client.m_hostname == NULL)
return NULL;
if (my_client.m_hostname == NULL)
return NULL;
continue;
if (!use_ipaddr && !client_member(my_client.m_hostname, exp->m_client->m_hostname))
continue;
continue;
if (!use_ipaddr && !client_member(my_client.m_hostname, exp->m_client->m_hostname))
continue;
- if (use_ipaddr && !client_check(exp->m_client, hp))
+ if (use_ipaddr && !client_check(exp->m_client, ai))
-auth_authenticate_internal(char *what, struct sockaddr_in *caller,
- char *path, struct hostent *hp,
+auth_authenticate_internal(struct sockaddr_in *caller,
+ char *path, struct addrinfo *ai,
enum auth_error *error)
{
nfs_export *exp;
if (new_cache) {
enum auth_error *error)
{
nfs_export *exp;
if (new_cache) {
- exp = auth_authenticate_newcache(what, caller, path, hp, error);
+ exp = auth_authenticate_newcache(caller, path, ai, error);
if (!exp)
return NULL;
} else {
if (!exp)
return NULL;
} else {
- if (!(exp = export_find(hp, path))) {
+ exp = export_find(ai, path);
+ if (exp == NULL) {
*error = no_entry;
return NULL;
}
*error = no_entry;
return NULL;
}
nfs_export *exp = NULL;
char epath[MAXPATHLEN+1];
char *p = NULL;
nfs_export *exp = NULL;
char epath[MAXPATHLEN+1];
char *p = NULL;
- struct hostent *hp = NULL;
+ struct addrinfo *ai = NULL;
struct in_addr addr = caller->sin_addr;
enum auth_error error = bad_path;
struct in_addr addr = caller->sin_addr;
enum auth_error error = bad_path;
epath[sizeof (epath) - 1] = '\0';
auth_fixpath(epath); /* strip duplicate '/' etc */
epath[sizeof (epath) - 1] = '\0';
auth_fixpath(epath); /* strip duplicate '/' etc */
- hp = client_resolve(caller->sin_addr);
- if (!hp)
+ ai = client_resolve((struct sockaddr *)caller);
+ if (ai == NULL)
return exp;
/* Try the longest matching exported pathname. */
while (1) {
return exp;
/* Try the longest matching exported pathname. */
while (1) {
- exp = auth_authenticate_internal(what, caller, epath,
- hp, &error);
+ exp = auth_authenticate_internal(caller, epath,
+ ai, &error);
if (exp || (error != not_exported && error != no_entry))
break;
/* We have to treat the root, "/", specially. */
if (exp || (error != not_exported && error != no_entry))
break;
/* We have to treat the root, "/", specially. */
case no_entry:
xlog(L_WARNING, "refused %s request from %s for %s (%s): no export entry",
case no_entry:
xlog(L_WARNING, "refused %s request from %s for %s (%s): no export entry",
- what, hp->h_name, path, epath);
+ what, ai->ai_canonname, path, epath);
break;
case not_exported:
xlog(L_WARNING, "refused %s request from %s for %s (%s): not exported",
break;
case not_exported:
xlog(L_WARNING, "refused %s request from %s for %s (%s): not exported",
- what, hp->h_name, path, epath);
+ what, ai->ai_canonname, path, epath);
break;
case illegal_port:
xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %d",
break;
case illegal_port:
xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %d",
- what, hp->h_name, path, epath, ntohs(caller->sin_port));
+ what, ai->ai_canonname, path, epath, ntohs(caller->sin_port));
break;
case success:
xlog(L_NOTICE, "authenticated %s request from %s:%d for %s (%s)",
break;
case success:
xlog(L_NOTICE, "authenticated %s request from %s:%d for %s (%s)",
- what, hp->h_name, ntohs(caller->sin_port), path, epath);
+ what, ai->ai_canonname, ntohs(caller->sin_port), path, epath);
break;
default:
xlog(L_NOTICE, "%s request from %s:%d for %s (%s) gave %d",
break;
default:
xlog(L_NOTICE, "%s request from %s:%d for %s (%s) gave %d",
- what, hp->h_name, ntohs(caller->sin_port), path, epath, error);
+ what, ai->ai_canonname, ntohs(caller->sin_port),
+ path, epath, error);
char class[20];
char ipaddr[20];
char *client = NULL;
char class[20];
char ipaddr[20];
char *client = NULL;
- struct in_addr addr;
- struct hostent *he = NULL;
+ struct addrinfo *tmp = NULL;
+ struct addrinfo *ai = NULL;
if (readline(fileno(f), &lbuf, &lbuflen) != 1)
return;
if (readline(fileno(f), &lbuf, &lbuflen) != 1)
return;
if (qword_get(&cp, ipaddr, 20) <= 0)
return;
if (qword_get(&cp, ipaddr, 20) <= 0)
return;
- if (inet_aton(ipaddr, &addr)==0)
+ tmp = host_pton(ipaddr);
+ if (tmp == NULL)
return;
auth_reload();
/* addr is a valid, interesting address, find the domain name... */
if (!use_ipaddr) {
return;
auth_reload();
/* addr is a valid, interesting address, find the domain name... */
if (!use_ipaddr) {
- he = client_resolve(addr);
- client = client_compose(he);
+ ai = client_resolve(tmp->ai_addr);
+ client = client_compose(ai);
+ freeaddrinfo(ai);
qword_print(f, "nfsd");
qword_print(f, ipaddr);
qword_printint(f, time(0)+30*60);
qword_print(f, "nfsd");
qword_print(f, ipaddr);
qword_printint(f, time(0)+30*60);
qword_eol(f);
xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT");
qword_eol(f);
xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT");
- if (client) free(client);
- free(he);
}
void auth_unix_gid(FILE *f)
}
void auth_unix_gid(FILE *f)
unsigned int fsidnum=0;
char fsid[32];
struct exportent *found = NULL;
unsigned int fsidnum=0;
char fsid[32];
struct exportent *found = NULL;
- struct hostent *he = NULL;
- struct in_addr addr;
+ struct addrinfo *ai = NULL;
char *found_path = NULL;
nfs_export *exp;
int i;
char *found_path = NULL;
nfs_export *exp;
int i;
break;
}
if (use_ipaddr) {
break;
}
if (use_ipaddr) {
- if (he == NULL) {
- if (!inet_aton(dom, &addr))
+ if (ai == NULL) {
+ struct addrinfo *tmp;
+ tmp = host_pton(dom);
+ if (tmp == NULL)
- he = client_resolve(addr);
+ ai = client_resolve(tmp->ai_addr);
+ freeaddrinfo(tmp);
- if (!client_check(exp->m_client, he))
+ if (!client_check(exp->m_client, ai))
continue;
}
/* It's a match !! */
continue;
}
/* It's a match !! */
out:
if (found_path)
free(found_path);
out:
if (found_path)
free(found_path);
free(dom);
xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL);
return;
free(dom);
xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL);
return;
return strcmp(path, exp->m_export.e_path) == 0;
}
return strcmp(path, exp->m_export.e_path) == 0;
}
-static int client_matches(nfs_export *exp, char *dom, struct hostent *he)
+static int
+client_matches(nfs_export *exp, char *dom, struct addrinfo *ai)
- return client_check(exp->m_client, he);
+ return client_check(exp->m_client, ai);
return client_member(dom, exp->m_client->m_hostname);
}
return client_member(dom, exp->m_client->m_hostname);
}
-static int export_matches(nfs_export *exp, char *dom, char *path, struct hostent *he)
+static int
+export_matches(nfs_export *exp, char *dom, char *path, struct addrinfo *ai)
- return path_matches(exp, path) && client_matches(exp, dom, he);
+ return path_matches(exp, path) && client_matches(exp, dom, ai);
-static nfs_export *lookup_export(char *dom, char *path, struct hostent *he)
+static nfs_export *
+lookup_export(char *dom, char *path, struct addrinfo *ai)
{
nfs_export *exp;
nfs_export *found = NULL;
{
nfs_export *exp;
nfs_export *found = NULL;
for (i=0 ; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
for (i=0 ; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
- if (!export_matches(exp, dom, path, he))
+ if (!export_matches(exp, dom, path, ai))
continue;
if (!found) {
found = exp;
continue;
if (!found) {
found = exp;
char *cp;
char *dom, *path;
nfs_export *found = NULL;
char *cp;
char *dom, *path;
nfs_export *found = NULL;
- struct in_addr addr;
- struct hostent *he = NULL;
-
+ struct addrinfo *ai = NULL;
if (readline(fileno(f), &lbuf, &lbuflen) != 1)
return;
if (readline(fileno(f), &lbuf, &lbuflen) != 1)
return;
auth_reload();
if (use_ipaddr) {
auth_reload();
if (use_ipaddr) {
- if (!inet_aton(dom, &addr))
+ struct addrinfo *tmp;
+ tmp = host_pton(dom);
+ if (tmp == NULL)
+ goto out;
+ ai = client_resolve(tmp->ai_addr);
+ freeaddrinfo(tmp);
- he = client_resolve(addr);
- found = lookup_export(dom, path, he);
+ found = lookup_export(dom, path, ai);
if (found) {
if (dump_to_cache(f, dom, path, &found->m_export) < 0) {
if (found) {
if (dump_to_cache(f, dom, path, &found->m_export) < 0) {
xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL);
if (dom) free(dom);
if (path) free(path);
xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL);
if (dom) free(dom);
if (path) free(path);
static void prune_clients(nfs_export *exp, struct exportnode *e)
{
static void prune_clients(nfs_export *exp, struct exportnode *e)
{
+ struct addrinfo *ai = NULL;
struct groupnode *c, **cp;
cp = &e->ex_groups;
while ((c = *cp) != NULL) {
if (client_gettype(c->gr_name) == MCL_FQDN
struct groupnode *c, **cp;
cp = &e->ex_groups;
while ((c = *cp) != NULL) {
if (client_gettype(c->gr_name) == MCL_FQDN
- && (hp = gethostbyname(c->gr_name))) {
- hp = hostent_dup(hp);
- if (client_check(exp->m_client, hp)) {
+ && (ai = host_addrinfo(c->gr_name))) {
+ if (client_check(exp->m_client, ai)) {
*cp = c->gr_next;
xfree(c->gr_name);
xfree(c);
*cp = c->gr_next;
xfree(c->gr_name);
xfree(c);