summaryrefslogtreecommitdiff
path: root/usr/src/cmd/fs.d/autofs/autod_nfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/fs.d/autofs/autod_nfs.c')
-rw-r--r--usr/src/cmd/fs.d/autofs/autod_nfs.c868
1 files changed, 387 insertions, 481 deletions
diff --git a/usr/src/cmd/fs.d/autofs/autod_nfs.c b/usr/src/cmd/fs.d/autofs/autod_nfs.c
index 89f278b904..32f96245ad 100644
--- a/usr/src/cmd/fs.d/autofs/autod_nfs.c
+++ b/usr/src/cmd/fs.d/autofs/autod_nfs.c
@@ -74,9 +74,9 @@
#include "replica.h"
#include "nfs_subr.h"
#include "webnfs.h"
+#include "nfs_resolve.h"
#include <sys/sockio.h>
#include <net/if.h>
-#include <assert.h>
#include <rpcsvc/daemon_utils.h>
#include <pwd.h>
#include <strings.h>
@@ -91,11 +91,6 @@ extern enum snego_stat nfs_sec_nego();
#define MAXHOSTS 512
-/* number of transports to try */
-#define MNT_PREF_LISTLEN 2
-#define FIRST_TRY 1
-#define SECOND_TRY 2
-
#define MNTTYPE_CACHEFS "cachefs"
/*
@@ -134,9 +129,7 @@ static enum nfsstat nfsmount(struct mapfs *, char *, char *, int, int, uid_t,
action_list *);
static int is_nfs_port(char *);
-void netbuf_free(struct netbuf *);
-struct knetconfig *get_knconf(struct netconfig *);
-void free_knconf(struct knetconfig *);
+static void netbuf_free(struct netbuf *);
static int get_pathconf(CLIENT *, char *, char *, struct pathcnf **, int);
static struct mapfs *enum_servers(struct mapent *, char *);
static struct mapfs *get_mysubnet_servers(struct mapfs *);
@@ -156,12 +149,18 @@ enum type_of_stuff {
SERVER_FH = 2
};
-void *get_server_stuff(enum type_of_stuff, char *, rpcprog_t,
+static void *get_server_netinfo(enum type_of_stuff, char *, rpcprog_t,
rpcvers_t, mfs_snego_t *, struct netconfig **, char *, ushort_t,
struct t_info *, caddr_t *, bool_t, char *, enum clnt_stat *);
-
-void *get_the_stuff(enum type_of_stuff, char *, rpcprog_t,
- rpcvers_t, mfs_snego_t *, struct netconfig *, ushort_t, struct t_info *,
+static void *get_netconfig_info(enum type_of_stuff, char *, rpcprog_t,
+ rpcvers_t, struct netconfig *, ushort_t, struct t_info *,
+ struct t_bind *, caddr_t *, bool_t, char *, enum clnt_stat *,
+ mfs_snego_t *);
+static void *get_server_addrorping(char *, rpcprog_t, rpcvers_t,
+ struct netconfig *, ushort_t, struct t_info *, struct t_bind *,
+ caddr_t *, bool_t, char *, enum clnt_stat *, int);
+static void *get_server_fh(char *, rpcprog_t, rpcvers_t, mfs_snego_t *,
+ struct netconfig *, ushort_t, struct t_info *, struct t_bind *,
caddr_t *, bool_t, char *, enum clnt_stat *);
struct mapfs *add_mfs(struct mapfs *, int, struct mapfs **, struct mapfs **);
@@ -1877,13 +1876,14 @@ try_mnt_slash:
/*
* For NFSv4, we want to avoid rpcbind, so call
- * get_server_stuff() directly to tell it that
+ * get_server_netinfo() directly to tell it that
* we want to go "direct_to_server". Otherwise,
* do what has always been done.
*/
if (nfsvers == NFS_V4) {
enum clnt_stat cstat;
- argp->addr = get_server_stuff(SERVER_ADDR,
+
+ argp->addr = get_server_netinfo(SERVER_ADDR,
host, NFS_PROGRAM, nfsvers, NULL,
&nconf, nfs_proto, thisport, NULL,
NULL, TRUE, NULL, &cstat);
@@ -2010,7 +2010,7 @@ try_mnt_slash:
*
* Eventurally, we want to move this code to nfs_clnt_secdata()
* when autod_nfs.c and mount.c can share the same
- * get_the_addr/get_the_stuff routine.
+ * get_the_addr/get_netconfig_info routine.
*/
secflags = 0;
syncaddr = NULL;
@@ -2024,9 +2024,10 @@ try_mnt_slash:
*/
if ((mfs->mfs_flags & MFS_FH_VIA_WEBNFS) == 0 &&
nfsvers != NFS_V4) {
- syncaddr = get_the_stuff(SERVER_ADDR, host, RPCBPROG,
- RPCBVERS, NULL, nconf, 0, NULL, NULL, FALSE,
- NULL, NULL);
+ enum clnt_stat cstat;
+ syncaddr = get_server_netinfo(SERVER_ADDR,
+ host, RPCBPROG, RPCBVERS, NULL, &nconf,
+ NULL, 0, NULL, NULL, FALSE, NULL, &cstat);
}
if (syncaddr != NULL) {
@@ -2527,50 +2528,6 @@ get_pathconf(CLIENT *cl, char *path, char *fsname, struct pathcnf **pcnf,
return (RET_OK);
}
-struct knetconfig *
-get_knconf(nconf)
- struct netconfig *nconf;
-{
- struct stat stbuf;
- struct knetconfig *k;
-
- if (stat(nconf->nc_device, &stbuf) < 0) {
- syslog(LOG_ERR, "get_knconf: stat %s: %m", nconf->nc_device);
- return (NULL);
- }
- k = (struct knetconfig *)malloc(sizeof (*k));
- if (k == NULL)
- goto nomem;
- k->knc_semantics = nconf->nc_semantics;
- k->knc_protofmly = strdup(nconf->nc_protofmly);
- if (k->knc_protofmly == NULL)
- goto nomem;
- k->knc_proto = strdup(nconf->nc_proto);
- if (k->knc_proto == NULL)
- goto nomem;
- k->knc_rdev = stbuf.st_rdev;
-
- return (k);
-
-nomem:
- syslog(LOG_ERR, "get_knconf: no memory");
- free_knconf(k);
- return (NULL);
-}
-
-void
-free_knconf(k)
- struct knetconfig *k;
-{
- if (k == NULL)
- return;
- if (k->knc_protofmly)
- free(k->knc_protofmly);
- if (k->knc_proto)
- free(k->knc_proto);
- free(k);
-}
-
void
netbuf_free(nb)
struct netbuf *nb;
@@ -2833,393 +2790,6 @@ get_cached_srv_addr(char *hostname, rpcprog_t prog, rpcvers_t vers,
}
/*
- * Get the network address on "hostname" for program "prog"
- * with version "vers" by using the nconf configuration data
- * passed in.
- *
- * If the address of a netconfig pointer is null then
- * information is not sufficient and no netbuf will be returned.
- *
- * tinfo argument is for matching the get_the_addr() defined in
- * ../nfs/mount/mount.c
- */
-void *
-get_the_stuff(
- enum type_of_stuff type_of_stuff,
- char *hostname,
- rpcprog_t prog,
- rpcprog_t vers,
- mfs_snego_t *mfssnego,
- struct netconfig *nconf,
- ushort_t port,
- struct t_info *tinfo,
- caddr_t *fhp,
- bool_t direct_to_server,
- char *fspath,
- enum clnt_stat *cstat)
-
-{
- struct netbuf *nb = NULL;
- struct t_bind *tbind = NULL;
- int fd = -1;
- enum clnt_stat cs = RPC_TIMEDOUT;
- CLIENT *cl = NULL;
- struct timeval tv;
- AUTH *ah = NULL;
- AUTH *new_ah = NULL;
- struct snego_t snego;
-
- if (nconf == NULL) {
- goto done;
- }
-
- if (prog == NFS_PROGRAM && vers == NFS_V4)
- if (strncasecmp(nconf->nc_proto, NC_UDP, strlen(NC_UDP)) == 0)
- goto done;
-
- if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) < 0) {
- goto done;
- }
-
- /* LINTED pointer alignment */
- if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR))
- == NULL) {
- goto done;
- }
-
- if (direct_to_server == TRUE) {
- struct nd_hostserv hs;
- struct nd_addrlist *retaddrs;
- hs.h_host = hostname;
-
- if (trace > 1)
- trace_prt(1, " get_the_stuff: %s call "
- "direct to server %s\n",
- type_of_stuff == SERVER_FH ? "pub fh" :
- type_of_stuff == SERVER_ADDR ? "get address" :
- type_of_stuff == SERVER_PING ? "ping" :
- "unknown", hostname);
- if (port == 0)
- hs.h_serv = "nfs";
- else
- hs.h_serv = NULL;
-
- if (netdir_getbyname(nconf, &hs, &retaddrs) != ND_OK) {
- goto done;
- }
- memcpy(tbind->addr.buf, retaddrs->n_addrs->buf,
- retaddrs->n_addrs->len);
- tbind->addr.len = retaddrs->n_addrs->len;
- netdir_free((void *)retaddrs, ND_ADDRLIST);
- if (port) {
- /* LINTED pointer alignment */
-
- if (strcmp(nconf->nc_protofmly, NC_INET) == NULL)
- ((struct sockaddr_in *)
- tbind->addr.buf)->sin_port =
- htons((ushort_t)port);
- else if (strcmp(nconf->nc_protofmly, NC_INET6) == NULL)
- ((struct sockaddr_in6 *)
- tbind->addr.buf)->sin6_port =
- htons((ushort_t)port);
- }
-
- if (type_of_stuff == SERVER_FH) {
- if (netdir_options(nconf, ND_SET_RESERVEDPORT, fd,
- NULL) == -1)
- if (trace > 1)
- trace_prt(1, "\tget_the_stuff: "
- "ND_SET_RESERVEDPORT(%s) "
- "failed\n", hostname);
- }
-
- cl = clnt_tli_create(fd, nconf, &tbind->addr, prog,
- vers, 0, 0);
-
- if (trace > 1)
- trace_prt(1, " get_the_stuff: clnt_tli_create(%s) "
- "returned %p\n", hostname, cl);
- if (cl == NULL)
- goto done;
-#ifdef MALLOC_DEBUG
- add_alloc("CLNT_HANDLE", cl, 0, __FILE__, __LINE__);
- add_alloc("AUTH_HANDLE", cl->cl_auth, 0,
- __FILE__, __LINE__);
-#endif
-
- switch (type_of_stuff) {
- case SERVER_FH:
- {
- enum snego_stat sec;
-
- ah = authsys_create_default();
- if (ah != NULL) {
-#ifdef MALLOC_DEBUG
- drop_alloc("AUTH_HANDLE", cl->cl_auth,
- __FILE__, __LINE__);
-#endif
- AUTH_DESTROY(cl->cl_auth);
- cl->cl_auth = ah;
-#ifdef MALLOC_DEBUG
- add_alloc("AUTH_HANDLE", cl->cl_auth, 0,
- __FILE__, __LINE__);
-#endif
- }
-
- if (!mfssnego->snego_done && vers != NFS_V4) {
- /*
- * negotiate sec flavor.
- */
- snego.cnt = 0;
- if ((sec = nfs_sec_nego(vers, cl, fspath, &snego)) ==
- SNEGO_SUCCESS) {
- int jj;
-
- /*
- * check if server supports the one
- * specified in the sec= option.
- */
- if (mfssnego->sec_opt) {
- for (jj = 0; jj < snego.cnt; jj++) {
- if (snego.array[jj] ==
- mfssnego->nfs_sec.sc_nfsnum) {
- mfssnego->snego_done = TRUE;
- break;
- }
- }
- }
-
- /*
- * find a common sec flavor
- */
- if (!mfssnego->snego_done) {
- for (jj = 0; jj < snego.cnt; jj++) {
- if (!nfs_getseconfig_bynumber(
- snego.array[jj], &mfssnego->nfs_sec)) {
- mfssnego->snego_done = TRUE;
- break;
- }
- }
- }
- if (!mfssnego->snego_done)
- return (NULL);
-
- /*
- * Now that the flavor has been
- * negotiated, get the fh.
- *
- * First, create an auth handle using the negotiated
- * sec flavor in the next lookup to
- * fetch the filehandle.
- */
- new_ah = nfs_create_ah(cl, hostname,
- &mfssnego->nfs_sec);
- if (new_ah == NULL)
- goto done;
-#ifdef MALLOC_DEBUG
- drop_alloc("AUTH_HANDLE", cl->cl_auth,
- __FILE__, __LINE__);
-#endif
- AUTH_DESTROY(cl->cl_auth);
- cl->cl_auth = new_ah;
-#ifdef MALLOC_DEBUG
- add_alloc("AUTH_HANDLE", cl->cl_auth, 0,
- __FILE__, __LINE__);
-#endif
- } else if (sec == SNEGO_ARRAY_TOO_SMALL ||
- sec == SNEGO_FAILURE) {
- goto done;
- }
- /*
- * Note that if sec == SNEGO_DEF_VALID
- * the default sec flavor is acceptable.
- * Use it to get the filehandle.
- */
- }
- }
-
- switch (vers) {
- case NFS_VERSION:
- {
- wnl_diropargs arg;
- wnl_diropres res;
-
- memset((char *)&arg.dir, 0, sizeof (wnl_fh));
- memset((char *)&res, 0, sizeof (wnl_diropres));
- arg.name = fspath;
- if (wnlproc_lookup_2(&arg, &res, cl) !=
- RPC_SUCCESS || res.status != NFS_OK)
- goto done;
- *fhp = malloc(sizeof (wnl_fh));
-
- if (*fhp == NULL) {
- syslog(LOG_ERR, "no memory\n");
- goto done;
- }
-
- memcpy((char *)*fhp,
- (char *)&res.wnl_diropres_u.wnl_diropres.file,
- sizeof (wnl_fh));
- cs = RPC_SUCCESS;
- }
- break;
- case NFS_V3:
- {
- WNL_LOOKUP3args arg;
- WNL_LOOKUP3res res;
- nfs_fh3 *fh3p;
-
- memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
- memset((char *)&res, 0, sizeof (WNL_LOOKUP3res));
- arg.what.name = fspath;
- if (wnlproc3_lookup_3(&arg, &res, cl) !=
- RPC_SUCCESS || res.status != NFS3_OK)
- goto done;
-
- fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
-
- if (fh3p == NULL) {
- syslog(LOG_ERR, "no memory\n");
- goto done;
- }
-
- fh3p->fh3_length = res.
- WNL_LOOKUP3res_u.res_ok.object.data.data_len;
- memcpy(fh3p->fh3_u.data, res.
- WNL_LOOKUP3res_u.res_ok.object.data.data_val,
- fh3p->fh3_length);
-
- *fhp = (caddr_t)fh3p;
-
- cs = RPC_SUCCESS;
- }
- break;
- case NFS_V4:
- tv.tv_sec = 10;
- tv.tv_usec = 0;
- cs = clnt_call(cl, NULLPROC, xdr_void, 0,
- xdr_void, 0, tv);
- if (cs != RPC_SUCCESS)
- goto done;
- *fhp = strdup(fspath);
- break;
- }
- break;
- case SERVER_ADDR:
- case SERVER_PING:
- tv.tv_sec = 10;
- tv.tv_usec = 0;
- cs = clnt_call(cl, NULLPROC, xdr_void, 0,
- xdr_void, 0, tv);
- if (trace > 1)
- trace_prt(1,
- "get_the_stuff: clnt_call(%s) "
- "returned %s\n",
- hostname,
- cs == RPC_SUCCESS ? "success" :
- "failure");
-
- if (cs != RPC_SUCCESS)
- goto done;
- break;
- }
-
- } else if (type_of_stuff != SERVER_FH) {
-
- if (type_of_stuff == SERVER_ADDR) {
- if (get_cached_srv_addr(hostname, prog, vers, nconf,
- &tbind->addr) == 0)
- goto done;
- }
-
- if (port) {
- /* LINTED pointer alignment */
- if (strcmp(nconf->nc_protofmly, NC_INET) == NULL)
- ((struct sockaddr_in *)
- tbind->addr.buf)->sin_port =
- htons((ushort_t)port);
- else if (strcmp(nconf->nc_protofmly, NC_INET6) == NULL)
- ((struct sockaddr_in6 *)
- tbind->addr.buf)->sin6_port =
- htons((ushort_t)port);
- cl = clnt_tli_create(fd, nconf, &tbind->addr,
- prog, vers, 0, 0);
- if (cl == NULL)
- goto done;
-#ifdef MALLOC_DEBUG
- add_alloc("CLNT_HANDLE", cl, 0, __FILE__, __LINE__);
- add_alloc("AUTH_HANDLE", cl->cl_auth, 0,
- __FILE__, __LINE__);
-#endif
- tv.tv_sec = 10;
- tv.tv_usec = 0;
- cs = clnt_call(cl, NULLPROC, xdr_void, 0, xdr_void,
- 0, tv);
- if (cs != RPC_SUCCESS)
- goto done;
- }
-
- } else {
- /* can't happen */
- goto done;
- }
-
- if (type_of_stuff != SERVER_PING) {
-
- cs = RPC_SYSTEMERROR;
-
- /*
- * Make a copy of the netbuf to return
- */
- nb = (struct netbuf *)malloc(sizeof (struct netbuf));
- if (nb == NULL) {
- syslog(LOG_ERR, "no memory\n");
- goto done;
- }
- *nb = tbind->addr;
- nb->buf = (char *)malloc(nb->maxlen);
- if (nb->buf == NULL) {
- syslog(LOG_ERR, "no memory\n");
- free(nb);
- nb = NULL;
- goto done;
- }
- (void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
-
- cs = RPC_SUCCESS;
- }
-
-done:
- if (cl != NULL) {
- if (ah != NULL) {
-#ifdef MALLOC_DEBUG
- drop_alloc("AUTH_HANDLE", cl->cl_auth,
- __FILE__, __LINE__);
-#endif
- AUTH_DESTROY(cl->cl_auth);
- cl->cl_auth = NULL;
- }
-#ifdef MALLOC_DEBUG
- drop_alloc("CLNT_HANDLE", cl, __FILE__, __LINE__);
-#endif
- clnt_destroy(cl);
- }
-
- if (tbind) {
- t_free((char *)tbind, T_BIND);
- tbind = NULL;
- }
-
- if (fd >= 0)
- (void) t_close(fd);
-
- if (cstat != NULL)
- *cstat = cs;
-
- return (nb);
-}
-
-/*
* Get a network address on "hostname" for program "prog"
* with version "vers". If the port number is specified (non zero)
* then try for a TCP/UDP transport and set the port number of the
@@ -3242,7 +2812,7 @@ get_addr(char *hostname, rpcprog_t prog, rpcvers_t vers,
{
enum clnt_stat cstat;
- return (get_server_stuff(SERVER_ADDR, hostname, prog, vers, NULL,
+ return (get_server_netinfo(SERVER_ADDR, hostname, prog, vers, NULL,
nconfp, proto, port, tinfo, NULL, FALSE, NULL, &cstat));
}
@@ -3253,7 +2823,7 @@ get_pubfh(char *hostname, rpcvers_t vers, mfs_snego_t *mfssnego,
{
enum clnt_stat cstat;
- return (get_server_stuff(SERVER_FH, hostname, NFS_PROGRAM, vers,
+ return (get_server_netinfo(SERVER_FH, hostname, NFS_PROGRAM, vers,
mfssnego, nconfp, proto, port, tinfo, fhp, get_pubfh, fspath,
&cstat));
}
@@ -3264,14 +2834,15 @@ get_ping(char *hostname, rpcprog_t prog, rpcvers_t vers,
{
enum clnt_stat cstat;
- (void) get_server_stuff(SERVER_PING, hostname, prog, vers, NULL, nconfp,
- NULL, port, NULL, NULL, direct_to_server, NULL, &cstat);
+ (void) get_server_netinfo(SERVER_PING, hostname, prog,
+ vers, NULL, nconfp, NULL, port, NULL, NULL,
+ direct_to_server, NULL, &cstat);
return (cstat);
}
void *
-get_server_stuff(
+get_server_netinfo(
enum type_of_stuff type_of_stuff,
char *hostname,
rpcprog_t prog,
@@ -3289,13 +2860,16 @@ get_server_stuff(
struct netbuf *nb = NULL;
struct netconfig *nconf = NULL;
NCONF_HANDLE *nc = NULL;
+ int error = 0;
+ int fd = 0;
+ struct t_bind *tbind = NULL;
int nthtry = FIRST_TRY;
- if (nconfp && *nconfp)
- return (get_the_stuff(type_of_stuff, hostname, prog, vers,
- mfssnego, *nconfp, port, tinfo, fhp, direct_to_server,
- fspath, cstatp));
-
+ if (nconfp && *nconfp) {
+ return (get_netconfig_info(type_of_stuff, hostname,
+ prog, vers, nconf, port, tinfo, tbind, fhp,
+ direct_to_server, fspath, cstatp, mfssnego));
+ }
/*
* No nconf passed in.
@@ -3314,8 +2888,7 @@ get_server_stuff(
* otherwise try COTS first, if failed, then try CLTS.
*/
if (proto) {
-
- while (nconf = getnetpath(nc)) {
+ while ((nconf = getnetpath(nc)) != NULL) {
if (strcmp(nconf->nc_proto, proto))
continue;
/*
@@ -3329,24 +2902,20 @@ get_server_stuff(
strcmp(nconf->nc_proto, NC_UDP)))
continue;
}
-
- nb = get_the_stuff(type_of_stuff, hostname, prog, vers,
- mfssnego, nconf, port, tinfo, fhp,
- direct_to_server, fspath, cstatp);
-
+ nb = get_netconfig_info(type_of_stuff, hostname,
+ prog, vers, nconf, port, tinfo, tbind, fhp,
+ direct_to_server, fspath, cstatp, mfssnego);
if (*cstatp == RPC_SUCCESS)
break;
assert(nb == NULL);
- } /* end of while */
-
+ }
if (nconf == NULL)
goto done;
-
} else {
retry:
- while (nconf = getnetpath(nc)) {
+ while ((nconf = getnetpath(nc)) != NULL) {
if (nconf->nc_flag & NC_VISIBLE) {
if (nthtry == FIRST_TRY) {
if ((nconf->nc_semantics ==
@@ -3379,7 +2948,8 @@ retry:
}
}
}
- } /* while */
+ }
+
if (nconf == NULL) {
if (++nthtry <= MNT_PREF_LISTLEN) {
endnetpath(nc);
@@ -3389,9 +2959,9 @@ retry:
} else
goto done;
} else {
- nb = get_the_stuff(type_of_stuff, hostname, prog, vers,
- mfssnego, nconf, port, tinfo, fhp, direct_to_server,
- fspath, cstatp);
+ nb = get_netconfig_info(type_of_stuff, hostname,
+ prog, vers, nconf, port, tinfo, tbind, fhp,
+ direct_to_server, fspath, cstatp, mfssnego);
if (*cstatp != RPC_SUCCESS)
/*
* Continue the same search path in the
@@ -3400,17 +2970,20 @@ retry:
*/
goto retry;
}
- } /* if !proto */
+ }
/*
* Got nconf and nb. Now dup the netconfig structure (nconf)
* and return it thru nconfp.
*/
- *nconfp = getnetconfigent(nconf->nc_netid);
- if (*nconfp == NULL) {
- syslog(LOG_ERR, "no memory\n");
- free(nb);
- nb = NULL;
+ if (nconf != NULL) {
+ if ((*nconfp = getnetconfigent(nconf->nc_netid)) == NULL) {
+ syslog(LOG_ERR, "no memory\n");
+ free(nb);
+ nb = NULL;
+ }
+ } else {
+ *nconfp = NULL;
}
done:
if (nc)
@@ -3418,6 +2991,221 @@ done:
return (nb);
}
+void *
+get_server_fh(char *hostname, rpcprog_t prog, rpcvers_t vers,
+ mfs_snego_t *mfssnego, struct netconfig *nconf, ushort_t port,
+ struct t_info *tinfo, struct t_bind *tbind, caddr_t *fhp,
+ bool_t direct_to_server, char *fspath, enum clnt_stat *cstat)
+{
+ AUTH *ah = NULL;
+ AUTH *new_ah = NULL;
+ struct snego_t snego;
+ enum clnt_stat cs = RPC_TIMEDOUT;
+ struct timeval tv;
+ bool_t file_handle = 1;
+ enum snego_stat sec;
+ CLIENT *cl = NULL;
+ int fd = -1;
+ struct netbuf *nb = NULL;
+
+ if (direct_to_server != TRUE)
+ return (NULL);
+
+ if (prog == NFS_PROGRAM && vers == NFS_V4)
+ if (strncasecmp(nconf->nc_proto, NC_UDP, strlen(NC_UDP)) == 0)
+ goto done;
+
+ if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) < 0)
+ goto done;
+
+ /* LINTED pointer alignment */
+ if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR)) == NULL)
+ goto done;
+
+ if (setup_nb_parms(nconf, tbind, tinfo, hostname, fd,
+ direct_to_server, port, prog, vers, file_handle) < 0) {
+ goto done;
+ }
+
+ cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0);
+ if (cl == NULL)
+ goto done;
+
+ ah = authsys_create_default();
+ if (ah != NULL) {
+#ifdef MALLOC_DEBUG
+ drop_alloc("AUTH_HANDLE", cl->cl_auth,
+ __FILE__, __LINE__);
+#endif
+ AUTH_DESTROY(cl->cl_auth);
+ cl->cl_auth = ah;
+#ifdef MALLOC_DEBUG
+ add_alloc("AUTH_HANDLE", cl->cl_auth, 0,
+ __FILE__, __LINE__);
+#endif
+ }
+
+ if (!mfssnego->snego_done && vers != NFS_V4) {
+ /*
+ * negotiate sec flavor.
+ */
+ snego.cnt = 0;
+ if ((sec = nfs_sec_nego(vers, cl, fspath, &snego)) ==
+ SNEGO_SUCCESS) {
+ int jj;
+
+ /*
+ * check if server supports the one
+ * specified in the sec= option.
+ */
+ if (mfssnego->sec_opt) {
+ for (jj = 0; jj < snego.cnt; jj++) {
+ if (snego.array[jj] ==
+ mfssnego->nfs_sec.sc_nfsnum) {
+ mfssnego->snego_done = TRUE;
+ break;
+ }
+ }
+ }
+
+ /*
+ * find a common sec flavor
+ */
+ if (!mfssnego->snego_done) {
+ for (jj = 0; jj < snego.cnt; jj++) {
+ if (!nfs_getseconfig_bynumber(
+ snego.array[jj],
+ &mfssnego->nfs_sec)) {
+ mfssnego->snego_done = TRUE;
+ break;
+ }
+ }
+ }
+ if (!mfssnego->snego_done)
+ goto done;
+ /*
+ * Now that the flavor has been
+ * negotiated, get the fh.
+ *
+ * First, create an auth handle using the negotiated
+ * sec flavor in the next lookup to
+ * fetch the filehandle.
+ */
+ new_ah = nfs_create_ah(cl, hostname,
+ &mfssnego->nfs_sec);
+ if (new_ah == NULL)
+ goto done;
+#ifdef MALLOC_DEBUG
+ drop_alloc("AUTH_HANDLE", cl->cl_auth,
+ __FILE__, __LINE__);
+#endif
+ AUTH_DESTROY(cl->cl_auth);
+ cl->cl_auth = new_ah;
+#ifdef MALLOC_DEBUG
+ add_alloc("AUTH_HANDLE", cl->cl_auth, 0,
+ __FILE__, __LINE__);
+#endif
+ } else if (sec == SNEGO_ARRAY_TOO_SMALL ||
+ sec == SNEGO_FAILURE) {
+ goto done;
+ }
+ }
+
+ switch (vers) {
+ case NFS_VERSION:
+ {
+ wnl_diropargs arg;
+ wnl_diropres res;
+
+ memset((char *)&arg.dir, 0, sizeof (wnl_fh));
+ memset((char *)&res, 0, sizeof (wnl_diropres));
+ arg.name = fspath;
+ if (wnlproc_lookup_2(&arg, &res, cl) !=
+ RPC_SUCCESS || res.status != NFS_OK)
+ goto done;
+ *fhp = malloc(sizeof (wnl_fh));
+
+ if (*fhp == NULL) {
+ syslog(LOG_ERR, "no memory\n");
+ goto done;
+ }
+
+ memcpy((char *)*fhp,
+ (char *)&res.wnl_diropres_u.wnl_diropres.file,
+ sizeof (wnl_fh));
+ cs = RPC_SUCCESS;
+ }
+ break;
+ case NFS_V3:
+ {
+ WNL_LOOKUP3args arg;
+ WNL_LOOKUP3res res;
+ nfs_fh3 *fh3p;
+
+ memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
+ memset((char *)&res, 0, sizeof (WNL_LOOKUP3res));
+ arg.what.name = fspath;
+ if (wnlproc3_lookup_3(&arg, &res, cl) !=
+ RPC_SUCCESS || res.status != NFS3_OK)
+ goto done;
+
+ fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
+
+ if (fh3p == NULL) {
+ syslog(LOG_ERR, "no memory\n");
+ goto done;
+ }
+
+ fh3p->fh3_length =
+ res.WNL_LOOKUP3res_u.res_ok.object.data.data_len;
+ memcpy(fh3p->fh3_u.data,
+ res.WNL_LOOKUP3res_u.res_ok.object.data.data_val,
+ fh3p->fh3_length);
+
+ *fhp = (caddr_t)fh3p;
+
+ cs = RPC_SUCCESS;
+ }
+ break;
+ case NFS_V4:
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+ cs = clnt_call(cl, NULLPROC, xdr_void, 0,
+ xdr_void, 0, tv);
+ if (cs != RPC_SUCCESS)
+ goto done;
+
+ *fhp = strdup(fspath);
+ if (fhp == NULL) {
+ cs = RPC_SYSTEMERROR;
+ goto done;
+ }
+ break;
+ }
+ nb = (struct netbuf *)malloc(sizeof (struct netbuf));
+ if (nb == NULL) {
+ syslog(LOG_ERR, "no memory\n");
+ cs = RPC_SYSTEMERROR;
+ goto done;
+ }
+ nb->buf = (char *)malloc(tbind->addr.maxlen);
+ if (nb->buf == NULL) {
+ syslog(LOG_ERR, "no memory\n");
+ free(nb);
+ nb = NULL;
+ cs = RPC_SYSTEMERROR;
+ goto done;
+ }
+ (void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
+ nb->len = tbind->addr.len;
+ nb->maxlen = tbind->addr.maxlen;
+done:
+ if (cstat != NULL)
+ *cstat = cs;
+ destroy_auth_client_handle(cl);
+ cleanup_tli_parms(tbind, fd);
+ return (nb);
+}
/*
* Sends a null call to the remote host's (NFS program, versp). versp
@@ -4535,3 +4323,121 @@ free_nfs_args(struct nfs_args *argp)
free(oldp);
}
}
+
+void *
+get_netconfig_info(enum type_of_stuff type_of_stuff, char *hostname,
+ rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
+ ushort_t port, struct t_info *tinfo, struct t_bind *tbind,
+ caddr_t *fhp, bool_t direct_to_server, char *fspath,
+ enum clnt_stat *cstat, mfs_snego_t *mfssnego)
+{
+ struct netconfig *nb = NULL;
+ int ping_server = 0;
+
+
+ if (nconf == NULL)
+ return (NULL);
+
+ switch (type_of_stuff) {
+ case SERVER_FH:
+ nb = get_server_fh(hostname, prog, vers, mfssnego,
+ nconf, port, tinfo, tbind, fhp, direct_to_server,
+ fspath, cstat);
+ break;
+ case SERVER_PING:
+ ping_server = 1;
+ case SERVER_ADDR:
+ nb = get_server_addrorping(hostname, prog, vers,
+ nconf, port, tinfo, tbind, fhp, direct_to_server,
+ fspath, cstat, ping_server);
+ break;
+ default:
+ assert(nb != NULL);
+ }
+ return (nb);
+}
+
+/*
+ * Get the server address or can we ping it or not.
+ * Check the portmap cache first for server address.
+ * If no entries there, ping the server with a NULLPROC rpc.
+ */
+void *
+get_server_addrorping(char *hostname, rpcprog_t prog, rpcvers_t vers,
+ struct netconfig *nconf, ushort_t port, struct t_info *tinfo,
+ struct t_bind *tbind, caddr_t *fhp, bool_t direct_to_server,
+ char *fspath, enum clnt_stat *cstat, int ping_server)
+{
+ struct timeval tv;
+ enum clnt_stat cs = RPC_TIMEDOUT;
+ struct netbuf *nb = NULL;
+ CLIENT *cl = NULL;
+ int fd = -1;
+
+ if (prog == NFS_PROGRAM && vers == NFS_V4)
+ if (strncasecmp(nconf->nc_proto, NC_UDP, strlen(NC_UDP)) == 0)
+ goto done;
+
+ if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) < 0) {
+ goto done;
+ }
+
+ /* LINTED pointer alignment */
+ if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR))
+ == NULL) {
+ goto done;
+ }
+
+ if (direct_to_server != TRUE) {
+ if (!ping_server) {
+ if (get_cached_srv_addr(hostname, prog, vers,
+ nconf, &tbind->addr) == 0)
+ goto done;
+ } else {
+ if (port == 0)
+ goto done;
+ }
+ }
+ if (setup_nb_parms(nconf, tbind, tinfo, hostname,
+ fd, direct_to_server, port, prog, vers, 0) < 0)
+ goto done;
+
+ if (port || (direct_to_server == TRUE)) {
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+ cl = clnt_tli_create(fd, nconf, &tbind->addr,
+ prog, vers, 0, 0);
+ if (cl == NULL)
+ goto done;
+
+ cs = clnt_call(cl, NULLPROC, xdr_void, 0,
+ xdr_void, 0, tv);
+ if (cs != RPC_SUCCESS) {
+ syslog(LOG_ERR, "error is %d", cs);
+ goto done;
+ }
+ }
+ if (!ping_server) {
+ nb = (struct netbuf *)malloc(sizeof (struct netbuf));
+ if (nb == NULL) {
+ syslog(LOG_ERR, "no memory\n");
+ goto done;
+ }
+ nb->buf = (char *)malloc(tbind->addr.maxlen);
+ if (nb->buf == NULL) {
+ syslog(LOG_ERR, "no memory\n");
+ free(nb);
+ nb = NULL;
+ goto done;
+ }
+ (void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
+ nb->len = tbind->addr.len;
+ nb->maxlen = tbind->addr.maxlen;
+ cs = RPC_SUCCESS;
+ }
+done:
+ destroy_auth_client_handle(cl);
+ cleanup_tli_parms(tbind, fd);
+ *cstat = cs;
+ return (nb);
+}