xref: /illumos-gate/usr/src/cmd/fs.d/nfs/lib/nfs_resolve.c (revision 8509e9ca)
12f172c55SRobert Thurlow /*
22f172c55SRobert Thurlow  * CDDL HEADER START
32f172c55SRobert Thurlow  *
42f172c55SRobert Thurlow  * The contents of this file are subject to the terms of the
52f172c55SRobert Thurlow  * Common Development and Distribution License (the "License").
62f172c55SRobert Thurlow  * You may not use this file except in compliance with the License.
72f172c55SRobert Thurlow  *
82f172c55SRobert Thurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92f172c55SRobert Thurlow  * or http://www.opensolaris.org/os/licensing.
102f172c55SRobert Thurlow  * See the License for the specific language governing permissions
112f172c55SRobert Thurlow  * and limitations under the License.
122f172c55SRobert Thurlow  *
132f172c55SRobert Thurlow  * When distributing Covered Code, include this CDDL HEADER in each
142f172c55SRobert Thurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152f172c55SRobert Thurlow  * If applicable, add the following below this CDDL HEADER, with the
162f172c55SRobert Thurlow  * fields enclosed by brackets "[]" replaced with your own identifying
172f172c55SRobert Thurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
182f172c55SRobert Thurlow  *
192f172c55SRobert Thurlow  * CDDL HEADER END
202f172c55SRobert Thurlow  */
212f172c55SRobert Thurlow /*
222f172c55SRobert Thurlow  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
232f172c55SRobert Thurlow  * Use is subject to license terms.
242f172c55SRobert Thurlow  */
252f172c55SRobert Thurlow 
262f172c55SRobert Thurlow 
272f172c55SRobert Thurlow /*
282f172c55SRobert Thurlow  * Helper routines for  nfsmapid and autod daemon
292f172c55SRobert Thurlow  * to translate hostname to IP address and Netinfo.
302f172c55SRobert Thurlow  */
312f172c55SRobert Thurlow #include <stdio.h>
322f172c55SRobert Thurlow #include <stdlib.h>
332f172c55SRobert Thurlow #include <alloca.h>
342f172c55SRobert Thurlow #include <signal.h>
352f172c55SRobert Thurlow #include <libintl.h>
362f172c55SRobert Thurlow #include <limits.h>
372f172c55SRobert Thurlow #include <errno.h>
382f172c55SRobert Thurlow #include <sys/types.h>
392f172c55SRobert Thurlow #include <string.h>
402f172c55SRobert Thurlow #include <memory.h>
412f172c55SRobert Thurlow #include <pwd.h>
422f172c55SRobert Thurlow #include <grp.h>
432f172c55SRobert Thurlow #include <door.h>
442f172c55SRobert Thurlow #include <syslog.h>
452f172c55SRobert Thurlow #include <fcntl.h>
462f172c55SRobert Thurlow #include <unistd.h>
472f172c55SRobert Thurlow #include <assert.h>
482f172c55SRobert Thurlow #include <deflt.h>
492f172c55SRobert Thurlow #include <netdir.h>
502f172c55SRobert Thurlow #include <nfs/nfs4.h>
512f172c55SRobert Thurlow #include <nfs/nfssys.h>
522f172c55SRobert Thurlow #include <nfs/nfsid_map.h>
532f172c55SRobert Thurlow #include <nfs/mapid.h>
542f172c55SRobert Thurlow #include <nfs/nfs_sec.h>
552f172c55SRobert Thurlow #include <sys/sdt.h>
562f172c55SRobert Thurlow #include <sys/idmap.h>
572f172c55SRobert Thurlow #include <idmap.h>
582f172c55SRobert Thurlow #include <sys/fs/autofs.h>
592f172c55SRobert Thurlow #include "nfs_resolve.h"
602f172c55SRobert Thurlow 
612f172c55SRobert Thurlow void
free_knconf(struct knetconfig * k)622f172c55SRobert Thurlow free_knconf(struct knetconfig *k)
632f172c55SRobert Thurlow {
642f172c55SRobert Thurlow 	if (k == NULL)
652f172c55SRobert Thurlow 		return;
662f172c55SRobert Thurlow 	if (k->knc_protofmly)
672f172c55SRobert Thurlow 		free(k->knc_protofmly);
682f172c55SRobert Thurlow 	if (k->knc_proto)
692f172c55SRobert Thurlow 		free(k->knc_proto);
702f172c55SRobert Thurlow 	free(k);
712f172c55SRobert Thurlow }
722f172c55SRobert Thurlow 
732f172c55SRobert Thurlow struct knetconfig *
get_knconf(struct netconfig * nconf)742f172c55SRobert Thurlow get_knconf(struct netconfig *nconf)
752f172c55SRobert Thurlow {
762f172c55SRobert Thurlow 	struct stat stbuf;
772f172c55SRobert Thurlow 	struct knetconfig *k = NULL;
782f172c55SRobert Thurlow 	int len;
792f172c55SRobert Thurlow 
802f172c55SRobert Thurlow 	if (stat(nconf->nc_device, &stbuf) < 0) {
812f172c55SRobert Thurlow 		syslog(LOG_ERR, "get_knconf: stat %s: %m", nconf->nc_device);
822f172c55SRobert Thurlow 		return (NULL);
832f172c55SRobert Thurlow 	}
842f172c55SRobert Thurlow 	k = (struct knetconfig *)malloc(sizeof (*k));
852f172c55SRobert Thurlow 	if (k == NULL)
862f172c55SRobert Thurlow 		goto nomem;
872f172c55SRobert Thurlow 	k->knc_semantics = nconf->nc_semantics;
882f172c55SRobert Thurlow 
892f172c55SRobert Thurlow 	len = strlen(nconf->nc_protofmly);
902f172c55SRobert Thurlow 	if (len <= 0)
912f172c55SRobert Thurlow 		goto err_out;
922f172c55SRobert Thurlow 	k->knc_protofmly = malloc(KNC_STRSIZE);
932f172c55SRobert Thurlow 	if (k->knc_protofmly == NULL)
942f172c55SRobert Thurlow 		goto nomem;
952f172c55SRobert Thurlow 	bzero(k->knc_protofmly, KNC_STRSIZE);
962f172c55SRobert Thurlow 	bcopy(nconf->nc_protofmly, k->knc_protofmly, len);
972f172c55SRobert Thurlow 
982f172c55SRobert Thurlow 	len = strlen(nconf->nc_proto);
992f172c55SRobert Thurlow 	if (len <= 0)
1002f172c55SRobert Thurlow 		goto err_out;
1012f172c55SRobert Thurlow 	k->knc_proto = malloc(KNC_STRSIZE);
1022f172c55SRobert Thurlow 	if (k->knc_proto == NULL)
1032f172c55SRobert Thurlow 		goto nomem;
1042f172c55SRobert Thurlow 	bzero(k->knc_proto, KNC_STRSIZE);
1052f172c55SRobert Thurlow 	bcopy(nconf->nc_proto, k->knc_proto, len);
1062f172c55SRobert Thurlow 
1072f172c55SRobert Thurlow 	k->knc_rdev = stbuf.st_rdev;
1082f172c55SRobert Thurlow 
1092f172c55SRobert Thurlow 	return (k);
1102f172c55SRobert Thurlow 
1112f172c55SRobert Thurlow nomem:
1122f172c55SRobert Thurlow 	syslog(LOG_ERR, "get_knconf: no memory");
1132f172c55SRobert Thurlow err_out:
1142f172c55SRobert Thurlow 	if (k != NULL)
1152f172c55SRobert Thurlow 		(void) free_knconf(k);
1162f172c55SRobert Thurlow 	return (NULL);
1172f172c55SRobert Thurlow }
1182f172c55SRobert Thurlow 
1192f172c55SRobert Thurlow /*
1202f172c55SRobert Thurlow  * Get the information needed for an NFSv4.x referral. This
1212f172c55SRobert Thurlow  * information includes the netbuf, netname and knconfig.
1222f172c55SRobert Thurlow  */
1232f172c55SRobert Thurlow struct nfs_fsl_info *
get_nfs4ref_info(char * host,int port,int nfsver)1242f172c55SRobert Thurlow get_nfs4ref_info(char *host, int port, int nfsver)
1252f172c55SRobert Thurlow {
1262f172c55SRobert Thurlow 	char netname[MAXNETNAMELEN + 1];
1272f172c55SRobert Thurlow 	enum clnt_stat cstat;
1282f172c55SRobert Thurlow 	struct nfs_fsl_info *fsl_retp = NULL;
1292f172c55SRobert Thurlow 	struct netconfig *netconf = NULL;
1302f172c55SRobert Thurlow 	char *nametemp, *namex = NULL;
1312f172c55SRobert Thurlow 	struct netbuf *nb = NULL;
1322f172c55SRobert Thurlow 	NCONF_HANDLE *nc = NULL;
1332f172c55SRobert Thurlow 
1342f172c55SRobert Thurlow 	fsl_retp = calloc(1, sizeof (struct nfs_fsl_info));
1352f172c55SRobert Thurlow 	if (fsl_retp == NULL) {
1362f172c55SRobert Thurlow 		syslog(LOG_ERR, "get_nfs4ref_info: no memory\n");
1372f172c55SRobert Thurlow 		return (NULL);
1382f172c55SRobert Thurlow 	}
1392f172c55SRobert Thurlow 
1402f172c55SRobert Thurlow 	nametemp = malloc(MAXNETNAMELEN + 1);
1412f172c55SRobert Thurlow 	if (nametemp == NULL) {
1422f172c55SRobert Thurlow 		free(fsl_retp);
1432f172c55SRobert Thurlow 		return (NULL);
1442f172c55SRobert Thurlow 	}
1452f172c55SRobert Thurlow 	host2netname(nametemp, host, NULL);
1462f172c55SRobert Thurlow 	namex = calloc(1, strlen(nametemp) + 1);
1472f172c55SRobert Thurlow 	if (namex == NULL) {
1482f172c55SRobert Thurlow 		free(nametemp);
1492f172c55SRobert Thurlow 		free(fsl_retp);
1502f172c55SRobert Thurlow 		return (NULL);
1512f172c55SRobert Thurlow 	}
1522f172c55SRobert Thurlow 	strncpy(namex, nametemp, strlen(nametemp));
1532f172c55SRobert Thurlow 	free(nametemp);
1542f172c55SRobert Thurlow 	fsl_retp->netname = namex;
1552f172c55SRobert Thurlow 	fsl_retp->netnm_len = strlen(namex) + 1;
1562f172c55SRobert Thurlow 
1572f172c55SRobert Thurlow 	fsl_retp->addr = resolve_netconf(host, NFS_PROGRAM, nfsver,
1582f172c55SRobert Thurlow 	    &netconf, port, NULL, NULL, TRUE, NULL, &cstat);
1592f172c55SRobert Thurlow 
1602f172c55SRobert Thurlow 	if (netconf == NULL || fsl_retp->addr == NULL)
1612f172c55SRobert Thurlow 		goto done;
1622f172c55SRobert Thurlow 
1632f172c55SRobert Thurlow 	fsl_retp->knconf = get_knconf(netconf);
1642f172c55SRobert Thurlow 	if (fsl_retp->knconf == NULL)
1652f172c55SRobert Thurlow 		goto done;
1662f172c55SRobert Thurlow 	fsl_retp->knconf_len = (sizeof (struct knetconfig) +
1672f172c55SRobert Thurlow 	    (KNC_STRSIZE * 2));
1682f172c55SRobert Thurlow 	fsl_retp->netbuf_len = (sizeof (struct netbuf) +
1692f172c55SRobert Thurlow 	    fsl_retp->addr->maxlen);
1702f172c55SRobert Thurlow 	return (fsl_retp);
1712f172c55SRobert Thurlow done:
1722f172c55SRobert Thurlow 	free_nfs4ref_info(fsl_retp);
1732f172c55SRobert Thurlow 	return (NULL);
1742f172c55SRobert Thurlow }
1752f172c55SRobert Thurlow 
1762f172c55SRobert Thurlow void
free_nfs4ref_info(struct nfs_fsl_info * fsl_retp)1772f172c55SRobert Thurlow free_nfs4ref_info(struct nfs_fsl_info *fsl_retp)
1782f172c55SRobert Thurlow {
1792f172c55SRobert Thurlow 	if (fsl_retp == NULL)
1802f172c55SRobert Thurlow 		return;
1812f172c55SRobert Thurlow 	free_knconf(fsl_retp->knconf);
1822f172c55SRobert Thurlow 	free(fsl_retp->netname);
1832f172c55SRobert Thurlow 	if (fsl_retp->addr != NULL) {
1842f172c55SRobert Thurlow 		free(fsl_retp->addr->buf);
1852f172c55SRobert Thurlow 		free(fsl_retp->addr);
1862f172c55SRobert Thurlow 	}
1872f172c55SRobert Thurlow 	free(fsl_retp);
1882f172c55SRobert Thurlow }
1892f172c55SRobert Thurlow 
1902f172c55SRobert Thurlow void
cleanup_tli_parms(struct t_bind * tbind,int fd)1912f172c55SRobert Thurlow cleanup_tli_parms(struct t_bind *tbind, int fd)
1922f172c55SRobert Thurlow {
1932f172c55SRobert Thurlow 	if (tbind != NULL) {
1942f172c55SRobert Thurlow 		t_free((char *)tbind, T_BIND);
1952f172c55SRobert Thurlow 		tbind = NULL;
1962f172c55SRobert Thurlow 	}
1972f172c55SRobert Thurlow 	if (fd >= 0)
1982f172c55SRobert Thurlow 		(void) t_close(fd);
1992f172c55SRobert Thurlow 	fd = -1;
2002f172c55SRobert Thurlow }
2012f172c55SRobert Thurlow 
2022f172c55SRobert Thurlow struct netbuf *
resolve_netconf(char * host,rpcprog_t prog,rpcvers_t nfsver,struct netconfig ** netconf,ushort_t port,struct t_info * tinfo,caddr_t * fhp,bool_t direct_to_server,char * fspath,enum clnt_stat * cstatp)2032f172c55SRobert Thurlow resolve_netconf(char *host, rpcprog_t prog, rpcvers_t nfsver,
2042f172c55SRobert Thurlow     struct netconfig **netconf, ushort_t port,
2052f172c55SRobert Thurlow     struct t_info *tinfo, caddr_t *fhp, bool_t direct_to_server,
2062f172c55SRobert Thurlow     char *fspath, enum clnt_stat *cstatp)
2072f172c55SRobert Thurlow {
2082f172c55SRobert Thurlow 	NCONF_HANDLE *nc;
2092f172c55SRobert Thurlow 	struct netconfig *nconf = NULL;
2102f172c55SRobert Thurlow 	int nthtry = FIRST_TRY;
2112f172c55SRobert Thurlow 	struct netbuf *nb;
2122f172c55SRobert Thurlow 	enum clnt_stat cstat;
2132f172c55SRobert Thurlow 
2142f172c55SRobert Thurlow 	nc = setnetpath();
2152f172c55SRobert Thurlow 	if (nc == NULL)
2162f172c55SRobert Thurlow 		goto done;
2172f172c55SRobert Thurlow retry:
2182f172c55SRobert Thurlow 	while (nconf = getnetpath(nc)) {
2192f172c55SRobert Thurlow 		if (nconf->nc_flag & NC_VISIBLE) {
2202f172c55SRobert Thurlow 			if (nthtry == FIRST_TRY) {
2212f172c55SRobert Thurlow 				if ((nconf->nc_semantics ==
2222f172c55SRobert Thurlow 				    NC_TPI_COTS_ORD) ||
2232f172c55SRobert Thurlow 				    (nconf->nc_semantics ==
2242f172c55SRobert Thurlow 				    NC_TPI_COTS)) {
2252f172c55SRobert Thurlow 					if (port == 0)
2262f172c55SRobert Thurlow 						break;
2272f172c55SRobert Thurlow 					if ((strcmp(nconf->nc_protofmly,
2282f172c55SRobert Thurlow 					    NC_INET) == 0 ||
2292f172c55SRobert Thurlow 					    strcmp(nconf->nc_protofmly,
2302f172c55SRobert Thurlow 					    NC_INET6) == 0) &&
2312f172c55SRobert Thurlow 					    (strcmp(nconf->nc_proto,
2322f172c55SRobert Thurlow 					    NC_TCP) == 0))
2332f172c55SRobert Thurlow 						break;
2342f172c55SRobert Thurlow 				}
2352f172c55SRobert Thurlow 			}
2362f172c55SRobert Thurlow 			if (nthtry == SECOND_TRY) {
2372f172c55SRobert Thurlow 				if (nconf->nc_semantics ==
2382f172c55SRobert Thurlow 				    NC_TPI_CLTS) {
2392f172c55SRobert Thurlow 					if (port == 0)
2402f172c55SRobert Thurlow 						break;
2412f172c55SRobert Thurlow 					if ((strcmp(nconf->nc_protofmly,
2422f172c55SRobert Thurlow 					    NC_INET) == 0 ||
2432f172c55SRobert Thurlow 					    strcmp(nconf->nc_protofmly,
2442f172c55SRobert Thurlow 					    NC_INET6) == 0) &&
2452f172c55SRobert Thurlow 					    (strcmp(nconf->nc_proto,
2462f172c55SRobert Thurlow 					    NC_UDP) == 0))
2472f172c55SRobert Thurlow 						break;
2482f172c55SRobert Thurlow 					}
2492f172c55SRobert Thurlow 			}
2502f172c55SRobert Thurlow 		}
2512f172c55SRobert Thurlow 	} /* while */
2522f172c55SRobert Thurlow 	if (nconf == NULL) {
2532f172c55SRobert Thurlow 		if (++nthtry <= MNT_PREF_LISTLEN) {
2542f172c55SRobert Thurlow 			endnetpath(nc);
2552f172c55SRobert Thurlow 			if ((nc = setnetpath()) == NULL)
2562f172c55SRobert Thurlow 				goto done;
2572f172c55SRobert Thurlow 			goto retry;
2582f172c55SRobert Thurlow 		} else
2592f172c55SRobert Thurlow 			return (NULL);
2602f172c55SRobert Thurlow 	} else {
2612f172c55SRobert Thurlow 		nb = get_server_addr(host, NFS_PROGRAM, nfsver,
2622f172c55SRobert Thurlow 		    nconf, port, NULL, NULL, TRUE, NULL, &cstat);
2632f172c55SRobert Thurlow 		if (cstat != RPC_SUCCESS)
2642f172c55SRobert Thurlow 			goto retry;
2652f172c55SRobert Thurlow 	}
2662f172c55SRobert Thurlow done:
2672f172c55SRobert Thurlow 	*netconf = nconf;
2682f172c55SRobert Thurlow 	*cstatp = cstat;
2692f172c55SRobert Thurlow 	if (nc)
2702f172c55SRobert Thurlow 		endnetpath(nc);
2712f172c55SRobert Thurlow 	return (nb);
2722f172c55SRobert Thurlow }
2732f172c55SRobert Thurlow 
2742f172c55SRobert Thurlow int
setup_nb_parms(struct netconfig * nconf,struct t_bind * tbind,struct t_info * tinfo,char * hostname,int fd,bool_t direct_to_server,ushort_t port,rpcprog_t prog,rpcvers_t vers,bool_t file_handle)2752f172c55SRobert Thurlow setup_nb_parms(struct netconfig *nconf, struct t_bind *tbind,
2762f172c55SRobert Thurlow     struct t_info *tinfo, char *hostname, int fd, bool_t direct_to_server,
2772f172c55SRobert Thurlow     ushort_t port, rpcprog_t prog, rpcvers_t vers, bool_t file_handle)
2782f172c55SRobert Thurlow {
2792f172c55SRobert Thurlow 	if (nconf == NULL) {
2802f172c55SRobert Thurlow 		return (-1);
2812f172c55SRobert Thurlow 	}
2822f172c55SRobert Thurlow 	if (direct_to_server == TRUE) {
2832f172c55SRobert Thurlow 		struct nd_hostserv hs;
2842f172c55SRobert Thurlow 		struct nd_addrlist *retaddrs;
2852f172c55SRobert Thurlow 		hs.h_host = hostname;
2862f172c55SRobert Thurlow 
2872f172c55SRobert Thurlow 		if (port == 0)
2882f172c55SRobert Thurlow 			hs.h_serv = "nfs";
2892f172c55SRobert Thurlow 		else
2902f172c55SRobert Thurlow 			hs.h_serv = NULL;
2912f172c55SRobert Thurlow 
2922f172c55SRobert Thurlow 		if (netdir_getbyname(nconf, &hs, &retaddrs) != ND_OK) {
2932f172c55SRobert Thurlow 			return (-1);
2942f172c55SRobert Thurlow 		}
2952f172c55SRobert Thurlow 		memcpy(tbind->addr.buf, retaddrs->n_addrs->buf,
2962f172c55SRobert Thurlow 		    retaddrs->n_addrs->len);
2972f172c55SRobert Thurlow 		tbind->addr.len = retaddrs->n_addrs->len;
2982f172c55SRobert Thurlow 		tbind->addr.maxlen = retaddrs->n_addrs->maxlen;
2992f172c55SRobert Thurlow 		netdir_free((void *)retaddrs, ND_ADDRLIST);
3002f172c55SRobert Thurlow 		if (port) {
3012f172c55SRobert Thurlow 			/* LINTED pointer alignment */
302*8509e9caSToomas Soome 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
3032f172c55SRobert Thurlow 				((struct sockaddr_in *)
3042f172c55SRobert Thurlow 				    tbind->addr.buf)->sin_port =
3052f172c55SRobert Thurlow 				    htons((ushort_t)port);
306*8509e9caSToomas Soome 			else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
3072f172c55SRobert Thurlow 				((struct sockaddr_in6 *)
3082f172c55SRobert Thurlow 				    tbind->addr.buf)->sin6_port =
3092f172c55SRobert Thurlow 				    htons((ushort_t)port);
3102f172c55SRobert Thurlow 		}
3112f172c55SRobert Thurlow 
3122f172c55SRobert Thurlow 		if (file_handle) {
3132f172c55SRobert Thurlow 			if (netdir_options(nconf, ND_SET_RESERVEDPORT, fd,
3142f172c55SRobert Thurlow 			    NULL) == -1)
3152f172c55SRobert Thurlow 				return (-1);
3162f172c55SRobert Thurlow 		}
3172f172c55SRobert Thurlow 	} else if (!file_handle) {
3182f172c55SRobert Thurlow 		if (port) {
3192f172c55SRobert Thurlow 			/* LINTED pointer alignment */
320*8509e9caSToomas Soome 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
3212f172c55SRobert Thurlow 				((struct sockaddr_in *)
3222f172c55SRobert Thurlow 				    tbind->addr.buf)->sin_port =
3232f172c55SRobert Thurlow 				    htons((ushort_t)port);
324*8509e9caSToomas Soome 			else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
3252f172c55SRobert Thurlow 				((struct sockaddr_in6 *)
3262f172c55SRobert Thurlow 				    tbind->addr.buf)->sin6_port =
3272f172c55SRobert Thurlow 				    htons((ushort_t)port);
3282f172c55SRobert Thurlow 		}
3292f172c55SRobert Thurlow 	} else {
3302f172c55SRobert Thurlow 		return (-1);
3312f172c55SRobert Thurlow 	}
3322f172c55SRobert Thurlow 	return (1);
3332f172c55SRobert Thurlow }
3342f172c55SRobert Thurlow 
3352f172c55SRobert Thurlow /*
3362f172c55SRobert Thurlow  * Sets up TLI interface and finds the address withe netdir_getbyname().
3372f172c55SRobert Thurlow  * returns the address returned from the call.
3382f172c55SRobert Thurlow  * Caller frees up the memory allocated here.
3392f172c55SRobert Thurlow  */
3402f172c55SRobert Thurlow struct netbuf *
get_server_addr(char * hostname,rpcprog_t prog,rpcvers_t vers,struct netconfig * nconf,ushort_t port,struct t_info * tinfo,caddr_t * fhp,bool_t direct_to_server,char * fspath,enum clnt_stat * cstat)3412f172c55SRobert Thurlow get_server_addr(char *hostname, rpcprog_t prog, rpcvers_t vers,
3422f172c55SRobert Thurlow     struct netconfig *nconf, ushort_t port,
3432f172c55SRobert Thurlow     struct t_info *tinfo, caddr_t *fhp, bool_t direct_to_server,
3442f172c55SRobert Thurlow     char *fspath, enum clnt_stat *cstat)
3452f172c55SRobert Thurlow {
3462f172c55SRobert Thurlow 	int fd = -1;
3472f172c55SRobert Thurlow 	struct t_bind *tbind = NULL;
3482f172c55SRobert Thurlow 	enum clnt_stat cs = RPC_SYSTEMERROR;
3492f172c55SRobert Thurlow 	struct netbuf *nb = NULL;
3502f172c55SRobert Thurlow 	int ret = -1;
3512f172c55SRobert Thurlow 
3522f172c55SRobert Thurlow 	if (prog == NFS_PROGRAM && vers == NFS_V4)
3532f172c55SRobert Thurlow 		if (strncasecmp(nconf->nc_proto, NC_UDP, strlen(NC_UDP)) == 0)
3542f172c55SRobert Thurlow 			goto done;
3552f172c55SRobert Thurlow 
3562f172c55SRobert Thurlow 	if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) < 0)
3572f172c55SRobert Thurlow 		goto done;
3582f172c55SRobert Thurlow 
3592f172c55SRobert Thurlow 	if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR)) == NULL)
3602f172c55SRobert Thurlow 		goto done;
3612f172c55SRobert Thurlow 
3622f172c55SRobert Thurlow 	if (setup_nb_parms(nconf, tbind, tinfo, hostname, fd, direct_to_server,
3632f172c55SRobert Thurlow 	    port, prog, vers, 0) < 0)
3642f172c55SRobert Thurlow 		goto done;
3652f172c55SRobert Thurlow 
3662f172c55SRobert Thurlow 	nb = (struct netbuf *)malloc(sizeof (struct netbuf));
3672f172c55SRobert Thurlow 	if (nb == NULL) {
3682f172c55SRobert Thurlow 		syslog(LOG_ERR, "no memory\n");
3692f172c55SRobert Thurlow 		goto done;
3702f172c55SRobert Thurlow 	}
3712f172c55SRobert Thurlow 	nb->buf = (char *)malloc(tbind->addr.maxlen);
3722f172c55SRobert Thurlow 	if (nb->buf == NULL) {
3732f172c55SRobert Thurlow 		syslog(LOG_ERR, "no memory\n");
3742f172c55SRobert Thurlow 		free(nb);
3752f172c55SRobert Thurlow 		nb = NULL;
3762f172c55SRobert Thurlow 		goto done;
3772f172c55SRobert Thurlow 	}
3782f172c55SRobert Thurlow 	(void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
3792f172c55SRobert Thurlow 	nb->len = tbind->addr.len;
3802f172c55SRobert Thurlow 	nb->maxlen = tbind->addr.maxlen;
3812f172c55SRobert Thurlow 	cs = RPC_SUCCESS;
3822f172c55SRobert Thurlow done:
3832f172c55SRobert Thurlow 	*cstat = cs;
3842f172c55SRobert Thurlow 	cleanup_tli_parms(tbind, fd);
3852f172c55SRobert Thurlow 	return (nb);
3862f172c55SRobert Thurlow }
387