Print this page
*** NO COMMENTS ***


 108 #define SET_ERR_RET(errst, etype, eval) \
 109         if (errst) { \
 110                 (errst)->error_type = etype; \
 111                 (errst)->error_value = eval; \
 112         }
 113 
 114 /* number of transports to try */
 115 #define MNT_PREF_LISTLEN        2
 116 #define FIRST_TRY               1
 117 #define SECOND_TRY              2
 118 
 119 #define BIGRETRY        10000
 120 
 121 /* maximum length of RPC header for NFS messages */
 122 #define NFS_RPC_HDR     432
 123 
 124 #define NFS_ARGS_EXTB_secdata(args, secdata) \
 125         { (args)->nfs_args_ext = NFS_ARGS_EXTB, \
 126         (args)->nfs_ext_u.nfs_extB.secdata = secdata; }
 127 
 128 extern int __clnt_bindresvport();
 129 extern char *nfs_get_qop_name();
 130 extern AUTH * nfs_create_ah();
 131 extern enum snego_stat nfs_sec_nego();
 132 
 133 static void usage(void);
 134 static int retry(struct mnttab *, int);
 135 static int set_args(int *, struct nfs_args *, char *, struct mnttab *);
 136 static int get_fh_via_pub(struct nfs_args *, char *, char *, bool_t, bool_t,
 137         int *, struct netconfig **, ushort_t);
 138 static int get_fh(struct nfs_args *, char *, char *, int *, bool_t,
 139         struct netconfig **, ushort_t);
 140 static int make_secure(struct nfs_args *, char *, struct netconfig *,
 141         bool_t, rpcvers_t);
 142 static int mount_nfs(struct mnttab *, int, err_ret_t *);
 143 static int getaddr_nfs(struct nfs_args *, char *, struct netconfig **,
 144                     bool_t, char *, ushort_t, err_ret_t *, bool_t);
 145 static void pr_err(const char *fmt, ...);
 146 static void usage(void);
 147 static struct netbuf *get_addr(char *, rpcprog_t, rpcvers_t,
 148         struct netconfig **, char *, ushort_t, struct t_info *,


1235         sec_data_t *secdata;
1236         int flags;
1237         struct netbuf *syncaddr = NULL;
1238         struct nd_addrlist *retaddrs = NULL;
1239         char netname[MAXNETNAMELEN+1];
1240 
1241         /*
1242          * check to see if any secure mode is requested.
1243          * if not, use default security mode.
1244          */
1245         if (!snego_done && !sec_opt) {
1246                 /*
1247                  *  Get default security mode.
1248                  *  AUTH_UNIX has been the default choice for a long time.
1249                  *  The better NFS security service becomes, the better chance
1250                  *  we will set stronger security service as the default NFS
1251                  *  security mode.
1252                  *
1253                  */
1254             if (nfs_getseconfig_default(&nfs_sec)) {
1255                 pr_err(gettext("error getting default security entry\n"));

1256                 return (-1);
1257             }
1258             args->flags |= NFSMNT_SECDEFAULT;
1259         }
1260 
1261         /*
1262          * Get the network address for the time service on the server.
1263          * If an RPC based time service is not available then try the
1264          * IP time service.
1265          *
1266          * This is for AUTH_DH processing. We will also pass down syncaddr
1267          * and netname for NFS V4 even if AUTH_DH is not requested right now.
1268          * NFS V4 does security negotiation in the kernel via SECINFO.
1269          * These information might be needed later in the kernel.
1270          *
1271          * Eventurally, we want to move this code to nfs_clnt_secdata()
1272          * when autod_nfs.c and mount.c can share the same get_the_addr()
1273          * routine.
1274          */
1275         flags = 0;


1298                         error = netdir_getbyname(nconf, &hs, &retaddrs);
1299 
1300                         if (error != ND_OK && (nfs_sec.sc_rpcnum == AUTH_DH)) {
1301                             pr_err(gettext("%s: secure: no time service\n"),
1302                                                 hostname);
1303                             return (-1);
1304                         }
1305 
1306                         if (error == ND_OK)
1307                                 syncaddr = retaddrs->n_addrs;
1308 
1309                         /*
1310                          * For NFS_V4 if AUTH_DH is negotiated later in the
1311                          * kernel thru SECINFO, it will need syncaddr
1312                          * and netname data.
1313                          */
1314                         if (vers == NFS_V4 && syncaddr &&
1315                                     host2netname(netname, hostname, NULL)) {
1316                             args->syncaddr = malloc(sizeof (struct netbuf));
1317                             args->syncaddr->buf = malloc(syncaddr->len);
1318                             (void) memcpy(args->syncaddr->buf, syncaddr->buf,
1319                                                         syncaddr->len);
1320                             args->syncaddr->len = syncaddr->len;
1321                             args->syncaddr->maxlen = syncaddr->maxlen;
1322                             args->netname = strdup(netname);
1323                             args->flags |= NFSMNT_SECURE;
1324                         }
1325                 }
1326         }
1327 
1328         /*
1329          * For the initial chosen flavor (any flavor defined in nfssec.conf),
1330          * the data will be stored in the sec_data structure via
1331          * nfs_clnt_secdata() and be passed to the kernel via nfs_args_*
1332          * extended data structure.
1333          */
1334         if (!(secdata = nfs_clnt_secdata(&nfs_sec, hostname, args->knconf,
1335                                         syncaddr, flags))) {
1336                 pr_err(gettext("errors constructing security related data\n"));
1337                 if (flags & AUTH_F_RPCTIMESYNC) {
1338                         free(syncaddr->buf);
1339                         free(syncaddr);


1428                         retaddrs->n_addrs->len);
1429                 tbind->addr.len = retaddrs->n_addrs->len;
1430                 netdir_free((void *)retaddrs, ND_ADDRLIST);
1431                 (void) netdir_options(nconf, ND_SET_RESERVEDPORT, fd, NULL);
1432 
1433         } else {
1434                 if (rpcb_getaddr(prog, vers, nconf, &tbind->addr,
1435                     hostname) == FALSE) {
1436                         goto done;
1437                 }
1438         }
1439 
1440         if (port) {
1441                 /* LINTED pointer alignment */
1442                 if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
1443                         ((struct sockaddr_in *)tbind->addr.buf)->sin_port
1444                                 = port;
1445                 else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
1446                         ((struct sockaddr_in6 *)tbind->addr.buf)->sin6_port
1447                                 = port;
1448 
1449         }
1450 
1451         cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0);
1452         if (cl == NULL) {
1453                 /*
1454                  * clnt_tli_create() returns either RPC_SYSTEMERROR,
1455                  * RPC_UNKNOWNPROTO or RPC_TLIERROR. The RPC_TLIERROR translates
1456                  * to "Misc. TLI error". This is not too helpful. Most likely
1457                  * the connection to the remote server timed out, so this
1458                  * error is at least less perplexing.
1459                  * See: usr/src/cmd/rpcinfo/rpcinfo.c
1460                  */
1461                 if (rpc_createerr.cf_stat == RPC_TLIERROR) {
1462                         SET_ERR_RET(error, ERR_RPCERROR, RPC_PMAPFAILURE);
1463                 } else {
1464                         SET_ERR_RET(error, ERR_RPCERROR, rpc_createerr.cf_stat);
1465                 }
1466                 goto done;
1467         }
1468 
1469         ah = authsys_create_default();
1470         if (ah != NULL)
1471                 cl->cl_auth = ah;
1472 
1473         tv.tv_sec = 5;
1474         tv.tv_usec = 0;
1475 
1476         (void) clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
1477 
1478         if ((get_pubfh == TRUE) && (vers != NFS_V4)) {
1479             enum snego_stat sec;
1480 
1481             if (!snego_done) {
1482                 /*
1483                  * negotiate sec flavor.
1484                  */
1485                 snego.cnt = 0;
1486                 if ((sec = nfs_sec_nego(vers, cl, fspath, &snego)) ==
1487                         SNEGO_SUCCESS) {
1488                     int jj;
1489 
1490                 /*
1491                  * check if server supports the one
1492                  * specified in the sec= option.
1493                  */
1494                     if (sec_opt) {
1495                         for (jj = 0; jj < snego.cnt; jj++) {
1496                             if (snego.array[jj] == nfs_sec.sc_nfsnum) {

1497                                 snego_done = TRUE;
1498                                 break;
1499                             }
1500                         }
1501                     }
1502 
1503                 /*
1504                  * find a common sec flavor
1505                  */
1506                     if (!snego_done) {
1507                         if (sec_opt) {
1508                             pr_err(gettext(
1509                                 "Server does not support the security"

1510                                 " flavor specified.\n"));
1511                         }

1512                         for (jj = 0; jj < snego.cnt; jj++) {
1513                             if (!nfs_getseconfig_bynumber(snego.array[jj],

1514                                 &nfs_sec)) {
1515                                 snego_done = TRUE;
1516                                 if (sec_opt) {
1517                                     pr_err(gettext(
1518                                         "Security flavor %d was negotiated and"
1519                                         " will be used.\n"),
1520                                         nfs_sec.sc_nfsnum);
1521                                 }

1522                                 break;
1523                             }
1524                         }
1525                     }
1526                     if (!snego_done)
1527                         return (NULL);

1528 
1529                 /*
1530                  * Now that the flavor has been
1531                  * negotiated, get the fh.
1532                  *
1533                  * First, create an auth handle using the negotiated
1534                  * sec flavor in the next lookup to
1535                  * fetch the filehandle.
1536                  */
1537                     new_ah = nfs_create_ah(cl, hostname, &nfs_sec);
1538                     if (new_ah == NULL)
1539                         goto done;
1540                     cl->cl_auth = new_ah;
1541                 } else if (sec == SNEGO_ARRAY_TOO_SMALL || sec ==
1542                     SNEGO_FAILURE) {
1543                         goto done;
1544                 }

1545                 /*
1546                  * Note that if sec == SNEGO_DEF_VALID
1547                  * default sec flavor is acceptable.
1548                  * Use it to get the filehandle.
1549                  */
1550             }
1551 
1552             if (vers == NFS_VERSION) {
1553                 wnl_diropargs arg;
1554                 wnl_diropres *res;
1555 
1556                 memset((char *)&arg.dir, 0, sizeof (wnl_fh));
1557                 arg.name = fspath;
1558                 res = wnlproc_lookup_2(&arg, cl);
1559 
1560                 if (res == NULL || res->status != NFS_OK)
1561                     goto done;
1562                 *fhp = malloc(sizeof (wnl_fh));
1563 
1564                 if (*fhp == NULL) {


1568 
1569                 memcpy((char *)*fhp,
1570                     (char *)&res->wnl_diropres_u.wnl_diropres.file,
1571                     sizeof (wnl_fh));
1572             } else {
1573                 WNL_LOOKUP3args arg;
1574                 WNL_LOOKUP3res *res;
1575                 nfs_fh3 *fh3p;
1576 
1577                 memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
1578                 arg.what.name = fspath;
1579                 res = wnlproc3_lookup_3(&arg, cl);
1580 
1581                 if (res == NULL || res->status != NFS3_OK)
1582                     goto done;
1583 
1584                 fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
1585 
1586                 if (fh3p == NULL) {
1587                     pr_err(gettext("no memory\n"));
1588                     CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res);

1589                     goto done;
1590                 }
1591 
1592                 fh3p->fh3_length =
1593                     res->WNL_LOOKUP3res_u.res_ok.object.data.data_len;
1594                 memcpy(fh3p->fh3_u.data,
1595                     res->WNL_LOOKUP3res_u.res_ok.object.data.data_val,
1596                     fh3p->fh3_length);
1597 
1598                 *fhp = (caddr_t)fh3p;
1599 
1600                 CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res);
1601             }
1602         } else {
1603                 void *res;
1604                 struct rpc_err r_err;
1605 
1606                 if (vers == NFS_VERSION)
1607                     res = wnlproc_null_2(NULL, cl);
1608                 else if (vers == NFS_V3)


1725 
1726         /*
1727          * If proto is specified, then only search for the match,
1728          * otherwise try COTS first, if failed, try CLTS.
1729          */
1730         if (proto) {
1731                 /* no matching proto name */
1732                 SET_ERR_RET(error, ERR_PROTO_INVALID, 0);
1733 
1734                 while (nconf = getnetpath(nc)) {
1735                         if (strcmp(nconf->nc_netid, proto))
1736                                 continue;
1737 
1738                         /* may be unsupported */
1739                         SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
1740 
1741                         if ((port != 0) &&
1742                                 ((strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
1743                                 strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
1744                                 (strcmp(nconf->nc_proto, NC_TCP) != 0 &&
1745                                 strcmp(nconf->nc_proto, NC_UDP) != 0)))
1746 
1747                                 continue;
1748 
1749                         else {
1750                                 nb = get_the_addr(hostname, prog,
1751                                         vers, nconf, port, tinfo,
1752                                                 fhp, get_pubfh, fspath, error);
1753 
1754                                 if (nb != NULL)
1755                                         break;
1756 
1757                                 /* nb is NULL - deal with errors */
1758                                 if (error) {
1759                                         if (error->error_type == ERR_NOHOST)
1760                                                 SET_ERR_RET(&errsave_nohost,
1761                                                         error->error_type,
1762                                                         error->error_value);
1763                                         if (error->error_type == ERR_RPCERROR)
1764                                                 SET_ERR_RET(&errsave_rpcerr,
1765                                                         error->error_type,
1766                                                         error->error_value);
1767                                 }
1768                                 /*
1769                                  * continue with same protocol
1770                                  * selection
1771                                  */
1772                                 continue;
1773                         }
1774                 } /* end of while */
1775 
1776                 if (nconf == NULL)
1777                         goto done;
1778 
1779                 if ((nb = get_the_addr(hostname, prog, vers, nconf, port,
1780                                 tinfo, fhp, get_pubfh, fspath, error)) == NULL)
1781                         goto done;
1782 
1783 
1784         } else {
1785 retry:
1786                 SET_ERR_RET(error, ERR_NETPATH, 0);
1787                 while (nconf = getnetpath(nc)) {
1788                         SET_ERR_RET(error, ERR_PROTO_NONE, 0);
1789                         if (nconf->nc_flag & NC_VISIBLE) {
1790                                 if (nthtry == FIRST_TRY) {
1791                                         if ((nconf->nc_semantics ==
1792                                                 NC_TPI_COTS_ORD) ||
1793                                             (nconf->nc_semantics ==
1794                                                 NC_TPI_COTS)) {
1795 
1796                                                 if (port == 0)
1797                                                         break;
1798 
1799                                                 if ((strcmp(nconf->nc_protofmly,
1800                                                         NC_INET) == 0 ||
1801                                                         strcmp(nconf->
1802                                                         nc_protofmly,
1803                                                         NC_INET6) == 0) &&
1804                                                     (strcmp(nconf->nc_proto,
1805                                                         NC_TCP) == 0))
1806 
1807                                                         break;
1808                                         }
1809                                 }
1810                                 if (nthtry == SECOND_TRY) {
1811                                         if (nconf->nc_semantics ==
1812                                                 NC_TPI_CLTS) {
1813                                                 if (port == 0)
1814                                                         break;
1815                                                 if ((strcmp(nconf->nc_protofmly,
1816                                                         NC_INET) == 0 ||
1817                                                         strcmp(nconf->
1818                                                         nc_protofmly, NC_INET6)
1819                                                         == 0) &&
1820                                                         (strcmp(
1821                                                         nconf->nc_proto,
1822                                                         NC_UDP) == 0))
1823                                                         break;
1824                                         }
1825                                 }
1826                         }
1827                 } /* while */

1828                 if (nconf == NULL) {
1829                         if (++nthtry <= MNT_PREF_LISTLEN) {
1830                                 endnetpath(nc);
1831                                 if ((nc = setnetpath()) == NULL)
1832                                         goto done;
1833                                 goto retry;
1834                         } else
1835                                 goto done;
1836                 } else {
1837                         if ((nb = get_the_addr(hostname, prog, vers, nconf,
1838                                 port, tinfo, fhp, get_pubfh, fspath, error))
1839                                 == NULL) {

1840                                 /* nb is NULL - deal with errors */
1841                                 if (error) {
1842                                         if (error->error_type == ERR_NOHOST)
1843                                                 SET_ERR_RET(&errsave_nohost,
1844                                                         error->error_type,
1845                                                         error->error_value);
1846                                         if (error->error_type == ERR_RPCERROR)
1847                                                 SET_ERR_RET(&errsave_rpcerr,
1848                                                         error->error_type,
1849                                                         error->error_value);
1850                                 }
1851                                 /*
1852                                  * Continue the same search path in the
1853                                  * netconfig db until no more matched
1854                                  * nconf (nconf == NULL).
1855                                  */
1856                                 goto retry;
1857                         }
1858                 }
1859         }


2024                         vers_min = vers_min_default;
2025                 }
2026 
2027                 break;
2028         }
2029 
2030         /*
2031          * In the case of version 4, just NULL proc the server since
2032          * there is no MOUNT program.  If this fails, then decrease
2033          * vers_to_try and continue on with regular MOUNT program
2034          * processing.
2035          */
2036         if (vers_to_try == NFS_V4) {
2037                 int savevers = nfsvers_to_use;
2038                 err_ret_t error;
2039                 int retval;
2040                 SET_ERR_RET(&error, ERR_PROTO_NONE, 0);
2041 
2042                 /* Let's hope for the best */
2043                 nfsvers_to_use = NFS_V4;
2044                 retval =
2045                         getaddr_nfs(args, fshost, nconfp, FALSE,
2046                                     fspath, port, &error, vers_min == NFS_V4);
2047 
2048                 if (retval == RET_OK) {
2049                         *versp = nfsvers_to_use = NFS_V4;
2050                         fstype = MNTTYPE_NFS4;
2051                         args->fh = strdup(fspath);
2052                         if (args->fh == NULL) {
2053                                 pr_err(gettext("no memory\n"));
2054                                 *versp = nfsvers_to_use = savevers;
2055                                 return (RET_ERR);
2056                         }
2057                         return (RET_OK);
2058                 }
2059                 nfsvers_to_use = savevers;
2060 
2061                 vers_to_try--;
2062                 /* If no more versions to try, let the user know. */
2063                 if (vers_to_try < vers_min) {
2064                         return (retval);
2065                 }


2142                 clnt_destroy(cl);
2143                 return (RET_RETRY);
2144         }
2145 
2146         switch (outvers) {
2147         case MOUNTVERS:
2148         case MOUNTVERS_POSIX:
2149                 *versp = nfsvers_to_use = NFS_VERSION;
2150                 rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2151                         (caddr_t)&fspath, xdr_fhstatus, (caddr_t)&fhs, timeout);
2152                 if (rpc_stat != RPC_SUCCESS) {
2153                         pr_err(gettext("%s:%s: server not responding %s\n"),
2154                             fshost, fspath, clnt_sperror(cl, ""));
2155                         clnt_destroy(cl);
2156                         return (RET_RETRY);
2157                 }
2158 
2159                 if ((errno = fhs.fhs_status) != MNT_OK) {
2160                         if (loud_on_mnt_err) {
2161                             if (errno == EACCES) {
2162                                 pr_err(gettext("%s:%s: access denied\n"),

2163                                     fshost, fspath);
2164                             } else {
2165                                 pr_err(gettext("%s:%s: %s\n"), fshost, fspath,
2166                                     strerror(errno));
2167                             }
2168                         }
2169                         clnt_destroy(cl);
2170                         return (RET_MNTERR);
2171                 }
2172                 args->fh = malloc(sizeof (fhs.fhstatus_u.fhs_fhandle));
2173                 if (args->fh == NULL) {
2174                         pr_err(gettext("no memory\n"));
2175                         return (RET_ERR);
2176                 }
2177                 memcpy((caddr_t)args->fh, (caddr_t)&fhs.fhstatus_u.fhs_fhandle,
2178                         sizeof (fhs.fhstatus_u.fhs_fhandle));
2179                 if (!errno && posix) {
2180                         rpc_stat = clnt_call(cl, MOUNTPROC_PATHCONF,
2181                                 xdr_dirpath, (caddr_t)&fspath, xdr_ppathcnf,
2182                                 (caddr_t)&p, timeout);
2183                         if (rpc_stat != RPC_SUCCESS) {
2184                                 pr_err(gettext(
2185                                     "%s:%s: server not responding %s\n"),
2186                                     fshost, fspath, clnt_sperror(cl, ""));


2195                                 free(args->fh);
2196                                 clnt_destroy(cl);
2197                                 return (RET_ERR);
2198                         }
2199                         args->flags |= NFSMNT_POSIX;
2200                         args->pathconf = malloc(sizeof (p));
2201                         if (args->pathconf == NULL) {
2202                                 pr_err(gettext("no memory\n"));
2203                                 free(args->fh);
2204                                 clnt_destroy(cl);
2205                                 return (RET_ERR);
2206                         }
2207                         memcpy((caddr_t)args->pathconf, (caddr_t)&p,
2208                                 sizeof (p));
2209                 }
2210                 break;
2211 
2212         case MOUNTVERS3:
2213                 *versp = nfsvers_to_use = NFS_V3;
2214                 rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2215                                 (caddr_t)&fspath,
2216                                 xdr_mountres3, (caddr_t)&mountres3, timeout);
2217                 if (rpc_stat != RPC_SUCCESS) {
2218                         pr_err(gettext("%s:%s: server not responding %s\n"),
2219                             fshost, fspath, clnt_sperror(cl, ""));
2220                         clnt_destroy(cl);
2221                         return (RET_RETRY);
2222                 }
2223 
2224                 /*
2225                  * Assume here that most of the MNT3ERR_*
2226                  * codes map into E* errors.
2227                  */
2228                 if ((errno = mountres3.fhs_status) != MNT_OK) {
2229                     if (loud_on_mnt_err) {
2230                         switch (errno) {
2231                         case MNT3ERR_NAMETOOLONG:
2232                                 msg = "path name is too long";
2233                                 break;
2234                         case MNT3ERR_NOTSUPP:
2235                                 msg = "operation not supported";
2236                                 break;
2237                         case MNT3ERR_SERVERFAULT:
2238                                 msg = "server fault";
2239                                 break;
2240                         default:
2241                                 msg = strerror(errno);
2242                                 break;
2243                         }
2244                         pr_err(gettext("%s:%s: %s\n"), fshost, fspath, msg);


2245                     }

2246                     clnt_destroy(cl);
2247                     return (RET_MNTERR);
2248                 }
2249 
2250                 fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
2251                 if (fh3p == NULL) {
2252                         pr_err(gettext("no memory\n"));
2253                         return (RET_ERR);
2254                 }
2255                 fh3p->fh3_length =
2256                         mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len;
2257                 (void) memcpy(fh3p->fh3_u.data,
2258                         mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val,
2259                         fh3p->fh3_length);
2260                 args->fh = (caddr_t)fh3p;
2261                 fstype = MNTTYPE_NFS3;
2262 
2263                 /*
2264                  * Check the security flavor to be used.
2265                  *
2266                  * If "secure" or "sec=flavor" is a mount
2267                  * option, check if the server supports the "flavor".
2268                  * If the server does not support the flavor, return
2269                  * error.
2270                  *
2271                  * If no mount option is given then use the first supported
2272                  * security flavor (by the client) in the auth list returned
2273                  * from the server.
2274                  *
2275                  */
2276                 auths =
2277                 mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val;

2278                 count =
2279                 mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_len;

2280 
2281                 if (sec_opt) {
2282                         for (i = 0; i < count; i++) {
2283                                 if (auths[i] == nfs_sec.sc_nfsnum)
2284                                     break;
2285                         }
2286                         if (i >= count) {
2287                                 goto autherr;
2288                         }
2289                 } else {
2290                     if (count > 0) {
2291                         for (i = 0; i < count; i++) {
2292                             if (!nfs_getseconfig_bynumber(auths[i], &nfs_sec)) {

2293                                 sec_opt++;
2294                                 break;
2295                             }
2296                         }
2297                         if (i >= count) {

2298                             goto autherr;
2299                         }
2300                     }
2301                 }
2302                 break;
2303         default:
2304                 pr_err(gettext("%s:%s: Unknown MOUNT version %d\n"),
2305                     fshost, fspath, outvers);
2306                 clnt_destroy(cl);
2307                 return (RET_ERR);
2308         }
2309 
2310         clnt_destroy(cl);
2311         return (RET_OK);
2312 
2313 autherr:
2314         pr_err(gettext(
2315                 "security mode does not match the server exporting %s:%s\n"),
2316                 fshost, fspath);
2317         clnt_destroy(cl);
2318         return (RET_ERR);
2319 }
2320 
2321 /*


2367                  */
2368                 if (nfs_proto == NULL)
2369                         args->flags |= NFSMNT_TRYRDMA;
2370         }
2371 
2372         if (args->addr == NULL) {
2373                 /*
2374                  * We could have failed because the server had no public
2375                  * file handle support. So don't print a message and don't
2376                  * retry.
2377                  */
2378                 if (get_pubfh == TRUE)
2379                         return (RET_ERR);
2380 
2381                 if (!printed) {
2382                         switch (addr_error.error_type) {
2383                         case 0:
2384                                 printed = 1;
2385                                 break;
2386                         case ERR_RPCERROR:
2387                                 if (!print_rpcerror)
2388                                         /* no error print at this time */

2389                                         break;
2390                                 pr_err(gettext("%s NFS service not"
2391                                             " available %s\n"), fshost,
2392                                     clnt_sperrno(addr_error.error_value));
2393                                 printed = 1;
2394                                 break;
2395                         case ERR_NETPATH:
2396                                 pr_err(gettext("%s: Error in NETPATH.\n"),
2397                                         fshost);
2398                                 printed = 1;
2399                                 break;
2400                         case ERR_PROTO_INVALID:
2401                                 pr_err(gettext("%s: NFS service does not"
2402                                         " recognize protocol: %s.\n"), fshost,
2403                                         nfs_proto);
2404                                 printed = 1;
2405                                 break;
2406                         case ERR_PROTO_UNSUPP:
2407                                 if (nfsvers || nfsvers_to_use == NFS_VERSMIN) {
2408                                         /*


2422                                          * Otherwise we decrement the version
2423                                          * and retry below.
2424                                          */
2425                                         pr_err(gettext("%s: NFS service does"
2426                                                 " not support protocol: %s.\n"),
2427                                                 fshost, nfs_proto);
2428                                 }
2429                                 break;
2430                         case ERR_NOHOST:
2431                                 pr_err("%s: %s\n", fshost, "Unknown host");
2432                                 printed = 1;
2433                                 break;
2434                         default:
2435                                 /* case ERR_PROTO_NONE falls through */
2436                                 pr_err(gettext("%s: NFS service not responding"
2437                                         "\n"), fshost);
2438                                 printed = 1;
2439                                 break;
2440                         }
2441                 }

2442                 SET_ERR_RET(error,
2443                         addr_error.error_type, addr_error.error_value);
2444                 if (addr_error.error_type == ERR_PROTO_NONE)
2445                         return (RET_RETRY);
2446                 else if (addr_error.error_type == ERR_RPCERROR &&
2447                         ! IS_UNRECOVERABLE_RPC(addr_error.error_value)) {
2448                         return (RET_RETRY);
2449                 } else if (nfsvers == 0 && addr_error.error_type ==
2450                         ERR_PROTO_UNSUPP && nfsvers_to_use != NFS_VERSMIN) {
2451                         /*
2452                          * If no version is specified, and the error is due
2453                          * to an unsupported transport, then decrement the
2454                          * version and retry.
2455                          */
2456                         return (RET_RETRY);
2457                 } else
2458                         return (RET_ERR);
2459         }
2460         nconf = *nconfp;
2461 




 108 #define SET_ERR_RET(errst, etype, eval) \
 109         if (errst) { \
 110                 (errst)->error_type = etype; \
 111                 (errst)->error_value = eval; \
 112         }
 113 
 114 /* number of transports to try */
 115 #define MNT_PREF_LISTLEN        2
 116 #define FIRST_TRY               1
 117 #define SECOND_TRY              2
 118 
 119 #define BIGRETRY        10000
 120 
 121 /* maximum length of RPC header for NFS messages */
 122 #define NFS_RPC_HDR     432
 123 
 124 #define NFS_ARGS_EXTB_secdata(args, secdata) \
 125         { (args)->nfs_args_ext = NFS_ARGS_EXTB, \
 126         (args)->nfs_ext_u.nfs_extB.secdata = secdata; }
 127 
 128 extern int __clnt_bindresvport(CLIENT *);
 129 extern char *nfs_get_qop_name();
 130 extern AUTH * nfs_create_ah();
 131 extern enum snego_stat nfs_sec_nego();
 132 
 133 static void usage(void);
 134 static int retry(struct mnttab *, int);
 135 static int set_args(int *, struct nfs_args *, char *, struct mnttab *);
 136 static int get_fh_via_pub(struct nfs_args *, char *, char *, bool_t, bool_t,
 137         int *, struct netconfig **, ushort_t);
 138 static int get_fh(struct nfs_args *, char *, char *, int *, bool_t,
 139         struct netconfig **, ushort_t);
 140 static int make_secure(struct nfs_args *, char *, struct netconfig *,
 141         bool_t, rpcvers_t);
 142 static int mount_nfs(struct mnttab *, int, err_ret_t *);
 143 static int getaddr_nfs(struct nfs_args *, char *, struct netconfig **,
 144                     bool_t, char *, ushort_t, err_ret_t *, bool_t);
 145 static void pr_err(const char *fmt, ...);
 146 static void usage(void);
 147 static struct netbuf *get_addr(char *, rpcprog_t, rpcvers_t,
 148         struct netconfig **, char *, ushort_t, struct t_info *,


1235         sec_data_t *secdata;
1236         int flags;
1237         struct netbuf *syncaddr = NULL;
1238         struct nd_addrlist *retaddrs = NULL;
1239         char netname[MAXNETNAMELEN+1];
1240 
1241         /*
1242          * check to see if any secure mode is requested.
1243          * if not, use default security mode.
1244          */
1245         if (!snego_done && !sec_opt) {
1246                 /*
1247                  *  Get default security mode.
1248                  *  AUTH_UNIX has been the default choice for a long time.
1249                  *  The better NFS security service becomes, the better chance
1250                  *  we will set stronger security service as the default NFS
1251                  *  security mode.
1252                  *
1253                  */
1254                 if (nfs_getseconfig_default(&nfs_sec)) {
1255                         pr_err(gettext("error getting default"
1256                             " security entry\n"));
1257                         return (-1);
1258                 }
1259                 args->flags |= NFSMNT_SECDEFAULT;
1260         }
1261 
1262         /*
1263          * Get the network address for the time service on the server.
1264          * If an RPC based time service is not available then try the
1265          * IP time service.
1266          *
1267          * This is for AUTH_DH processing. We will also pass down syncaddr
1268          * and netname for NFS V4 even if AUTH_DH is not requested right now.
1269          * NFS V4 does security negotiation in the kernel via SECINFO.
1270          * These information might be needed later in the kernel.
1271          *
1272          * Eventurally, we want to move this code to nfs_clnt_secdata()
1273          * when autod_nfs.c and mount.c can share the same get_the_addr()
1274          * routine.
1275          */
1276         flags = 0;


1299                         error = netdir_getbyname(nconf, &hs, &retaddrs);
1300 
1301                         if (error != ND_OK && (nfs_sec.sc_rpcnum == AUTH_DH)) {
1302                                 pr_err(gettext("%s: secure: no time service\n"),
1303                                     hostname);
1304                                 return (-1);
1305                         }
1306 
1307                         if (error == ND_OK)
1308                                 syncaddr = retaddrs->n_addrs;
1309 
1310                         /*
1311                          * For NFS_V4 if AUTH_DH is negotiated later in the
1312                          * kernel thru SECINFO, it will need syncaddr
1313                          * and netname data.
1314                          */
1315                         if (vers == NFS_V4 && syncaddr &&
1316                             host2netname(netname, hostname, NULL)) {
1317                                 args->syncaddr = malloc(sizeof (struct netbuf));
1318                                 args->syncaddr->buf = malloc(syncaddr->len);
1319                                 (void) memcpy(args->syncaddr->buf,
1320                                     syncaddr->buf, syncaddr->len);
1321                                 args->syncaddr->len = syncaddr->len;
1322                                 args->syncaddr->maxlen = syncaddr->maxlen;
1323                                 args->netname = strdup(netname);
1324                                 args->flags |= NFSMNT_SECURE;
1325                         }
1326                 }
1327         }
1328 
1329         /*
1330          * For the initial chosen flavor (any flavor defined in nfssec.conf),
1331          * the data will be stored in the sec_data structure via
1332          * nfs_clnt_secdata() and be passed to the kernel via nfs_args_*
1333          * extended data structure.
1334          */
1335         if (!(secdata = nfs_clnt_secdata(&nfs_sec, hostname, args->knconf,
1336             syncaddr, flags))) {
1337                 pr_err(gettext("errors constructing security related data\n"));
1338                 if (flags & AUTH_F_RPCTIMESYNC) {
1339                         free(syncaddr->buf);
1340                         free(syncaddr);


1429                     retaddrs->n_addrs->len);
1430                 tbind->addr.len = retaddrs->n_addrs->len;
1431                 netdir_free((void *)retaddrs, ND_ADDRLIST);
1432                 (void) netdir_options(nconf, ND_SET_RESERVEDPORT, fd, NULL);
1433 
1434         } else {
1435                 if (rpcb_getaddr(prog, vers, nconf, &tbind->addr,
1436                     hostname) == FALSE) {
1437                         goto done;
1438                 }
1439         }
1440 
1441         if (port) {
1442                 /* LINTED pointer alignment */
1443                 if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
1444                         ((struct sockaddr_in *)tbind->addr.buf)->sin_port
1445                             = port;
1446                 else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
1447                         ((struct sockaddr_in6 *)tbind->addr.buf)->sin6_port
1448                             = port;

1449         }
1450 
1451         cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0);
1452         if (cl == NULL) {
1453                 /*
1454                  * clnt_tli_create() returns either RPC_SYSTEMERROR,
1455                  * RPC_UNKNOWNPROTO or RPC_TLIERROR. The RPC_TLIERROR translates
1456                  * to "Misc. TLI error". This is not too helpful. Most likely
1457                  * the connection to the remote server timed out, so this
1458                  * error is at least less perplexing.
1459                  * See: usr/src/cmd/rpcinfo/rpcinfo.c
1460                  */
1461                 if (rpc_createerr.cf_stat == RPC_TLIERROR) {
1462                         SET_ERR_RET(error, ERR_RPCERROR, RPC_PMAPFAILURE);
1463                 } else {
1464                         SET_ERR_RET(error, ERR_RPCERROR, rpc_createerr.cf_stat);
1465                 }
1466                 goto done;
1467         }
1468 
1469         ah = authsys_create_default();
1470         if (ah != NULL)
1471                 cl->cl_auth = ah;
1472 
1473         tv.tv_sec = 5;
1474         tv.tv_usec = 0;
1475 
1476         (void) clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
1477 
1478         if ((get_pubfh == TRUE) && (vers != NFS_V4)) {
1479                 enum snego_stat sec;
1480 
1481                 if (!snego_done) {
1482                         /*
1483                          * negotiate sec flavor.
1484                          */
1485                         snego.cnt = 0;
1486                         if ((sec = nfs_sec_nego(vers, cl,
1487                             fspath, &snego)) == SNEGO_SUCCESS) {
1488                                 int jj;
1489 
1490                                 /*
1491                                  * check if server supports the one
1492                                  * specified in the sec= option.
1493                                  */
1494                                 if (sec_opt) {
1495                                         for (jj = 0; jj < snego.cnt; jj++) {
1496                                                 if (snego.array[jj] ==
1497                                                     nfs_sec.sc_nfsnum) {
1498                                                         snego_done = TRUE;
1499                                                         break;
1500                                                 }
1501                                         }
1502                                 }
1503 
1504                                 /*
1505                                  * find a common sec flavor
1506                                  */
1507                                 if (!snego_done) {
1508                                         if (sec_opt) {
1509                                                 pr_err(gettext(
1510                                                     "Server does not support"
1511                                                     " the security"
1512                                                     " flavor specified.\n"));
1513                                         }
1514 
1515                                         for (jj = 0; jj < snego.cnt; jj++) {
1516                                                 if (!nfs_getseconfig_bynumber(
1517                                                     snego.array[jj],
1518                                                     &nfs_sec)) {
1519                                                         snego_done = TRUE;
1520                                                         if (sec_opt) {
1521                                                                 pr_err(gettext(
1522                 "Security flavor %d was negotiated and will be used.\n"),
1523                                                                     nfs_sec.
1524                                                                     sc_nfsnum);
1525                                                         }
1526 
1527                                                         break;
1528                                                 }
1529                                         }
1530 
1531                                         if (!snego_done)
1532                                                 return (NULL);
1533                                 }
1534 
1535                                 /*
1536                                  * Now that the flavor has been
1537                                  * negotiated, get the fh.
1538                                  *
1539                                  * First, create an auth handle using
1540                                  * the negotiated sec flavor in the
1541                                  * next lookup to fetch the filehandle.
1542                                  */
1543                                 new_ah = nfs_create_ah(cl, hostname, &nfs_sec);
1544                                 if (new_ah == NULL)
1545                                         goto done;
1546                                 cl->cl_auth = new_ah;
1547                         } else if (sec == SNEGO_ARRAY_TOO_SMALL || sec ==
1548                             SNEGO_FAILURE) {
1549                                 goto done;
1550                         }
1551 
1552                         /*
1553                          * Note that if sec == SNEGO_DEF_VALID
1554                          * default sec flavor is acceptable.
1555                          * Use it to get the filehandle.
1556                          */
1557                 }
1558 
1559                 if (vers == NFS_VERSION) {
1560                         wnl_diropargs arg;
1561                         wnl_diropres *res;
1562 
1563                         memset((char *)&arg.dir, 0, sizeof (wnl_fh));
1564                         arg.name = fspath;
1565                         res = wnlproc_lookup_2(&arg, cl);
1566 
1567                         if (res == NULL || res->status != NFS_OK)
1568                                 goto done;
1569                         *fhp = malloc(sizeof (wnl_fh));
1570 
1571                         if (*fhp == NULL) {


1575 
1576                         memcpy((char *)*fhp,
1577                             (char *)&res->wnl_diropres_u.wnl_diropres.file,
1578                             sizeof (wnl_fh));
1579                 } else {
1580                         WNL_LOOKUP3args arg;
1581                         WNL_LOOKUP3res *res;
1582                         nfs_fh3 *fh3p;
1583 
1584                         memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
1585                         arg.what.name = fspath;
1586                         res = wnlproc3_lookup_3(&arg, cl);
1587 
1588                         if (res == NULL || res->status != NFS3_OK)
1589                                 goto done;
1590 
1591                         fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
1592 
1593                         if (fh3p == NULL) {
1594                                 pr_err(gettext("no memory\n"));
1595                                 CLNT_FREERES(cl, xdr_WNL_LOOKUP3res,
1596                                     (char *)res);
1597                                 goto done;
1598                         }
1599 
1600                         fh3p->fh3_length =
1601                             res->WNL_LOOKUP3res_u.res_ok.object.data.data_len;
1602                         memcpy(fh3p->fh3_u.data,
1603                             res->WNL_LOOKUP3res_u.res_ok.object.data.data_val,
1604                             fh3p->fh3_length);
1605 
1606                         *fhp = (caddr_t)fh3p;
1607 
1608                         CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res);
1609                 }
1610         } else {
1611                 void *res;
1612                 struct rpc_err r_err;
1613 
1614                 if (vers == NFS_VERSION)
1615                         res = wnlproc_null_2(NULL, cl);
1616                 else if (vers == NFS_V3)


1733 
1734         /*
1735          * If proto is specified, then only search for the match,
1736          * otherwise try COTS first, if failed, try CLTS.
1737          */
1738         if (proto) {
1739                 /* no matching proto name */
1740                 SET_ERR_RET(error, ERR_PROTO_INVALID, 0);
1741 
1742                 while (nconf = getnetpath(nc)) {
1743                         if (strcmp(nconf->nc_netid, proto))
1744                                 continue;
1745 
1746                         /* may be unsupported */
1747                         SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
1748 
1749                         if ((port != 0) &&
1750                             ((strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
1751                             strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
1752                             (strcmp(nconf->nc_proto, NC_TCP) != 0 &&
1753                             strcmp(nconf->nc_proto, NC_UDP) != 0))) {

1754                                 continue;
1755                         } else {

1756                                 nb = get_the_addr(hostname, prog,
1757                                     vers, nconf, port, tinfo,
1758                                     fhp, get_pubfh, fspath, error);
1759 
1760                                 if (nb != NULL)
1761                                         break;
1762 
1763                                 /* nb is NULL - deal with errors */
1764                                 if (error) {
1765                                         if (error->error_type == ERR_NOHOST)
1766                                                 SET_ERR_RET(&errsave_nohost,
1767                                                     error->error_type,
1768                                                     error->error_value);
1769                                         if (error->error_type == ERR_RPCERROR)
1770                                                 SET_ERR_RET(&errsave_rpcerr,
1771                                                     error->error_type,
1772                                                     error->error_value);
1773                                 }
1774                                 /*
1775                                  * continue with same protocol
1776                                  * selection
1777                                  */
1778                                 continue;
1779                         }
1780                 } /* end of while */
1781 
1782                 if (nconf == NULL)
1783                         goto done;
1784 
1785                 if ((nb = get_the_addr(hostname, prog, vers, nconf, port,
1786                     tinfo, fhp, get_pubfh, fspath, error)) == NULL)
1787                         goto done;


1788         } else {
1789 retry:
1790                 SET_ERR_RET(error, ERR_NETPATH, 0);
1791                 while (nconf = getnetpath(nc)) {
1792                         SET_ERR_RET(error, ERR_PROTO_NONE, 0);
1793                         if (nconf->nc_flag & NC_VISIBLE) {
1794                                 if (nthtry == FIRST_TRY) {
1795                                         if ((nconf->nc_semantics ==
1796                                             NC_TPI_COTS_ORD) ||
1797                                             (nconf->nc_semantics ==
1798                                             NC_TPI_COTS)) {
1799 
1800                                                 if (port == 0)
1801                                                         break;
1802 
1803                                                 if ((strcmp(nconf->nc_protofmly,
1804                                                     NC_INET) == 0 ||
1805                                                     strcmp(nconf->nc_protofmly,

1806                                                     NC_INET6) == 0) &&
1807                                                     (strcmp(nconf->nc_proto,
1808                                                     NC_TCP) == 0))

1809                                                         break;
1810                                         }
1811                                 }
1812                                 if (nthtry == SECOND_TRY) {
1813                                         if (nconf->nc_semantics ==
1814                                             NC_TPI_CLTS) {
1815                                                 if (port == 0)
1816                                                         break;
1817                                                 if ((strcmp(nconf->nc_protofmly,
1818                                                     NC_INET) == 0 ||
1819                                                     strcmp(nconf->nc_protofmly,
1820                                                     NC_INET6) == 0) &&
1821                                                     (strcmp(nconf->nc_proto,


1822                                                     NC_UDP) == 0))
1823                                                         break;
1824                                         }
1825                                 }
1826                         }
1827                 } /* while */
1828 
1829                 if (nconf == NULL) {
1830                         if (++nthtry <= MNT_PREF_LISTLEN) {
1831                                 endnetpath(nc);
1832                                 if ((nc = setnetpath()) == NULL)
1833                                         goto done;
1834                                 goto retry;
1835                         } else
1836                                 goto done;
1837                 } else {
1838                         if ((nb = get_the_addr(hostname, prog, vers, nconf,
1839                             port, tinfo, fhp, get_pubfh, fspath, error))
1840                             == NULL) {
1841 
1842                                 /* nb is NULL - deal with errors */
1843                                 if (error) {
1844                                         if (error->error_type == ERR_NOHOST)
1845                                                 SET_ERR_RET(&errsave_nohost,
1846                                                     error->error_type,
1847                                                     error->error_value);
1848                                         if (error->error_type == ERR_RPCERROR)
1849                                                 SET_ERR_RET(&errsave_rpcerr,
1850                                                     error->error_type,
1851                                                     error->error_value);
1852                                 }
1853                                 /*
1854                                  * Continue the same search path in the
1855                                  * netconfig db until no more matched
1856                                  * nconf (nconf == NULL).
1857                                  */
1858                                 goto retry;
1859                         }
1860                 }
1861         }


2026                         vers_min = vers_min_default;
2027                 }
2028 
2029                 break;
2030         }
2031 
2032         /*
2033          * In the case of version 4, just NULL proc the server since
2034          * there is no MOUNT program.  If this fails, then decrease
2035          * vers_to_try and continue on with regular MOUNT program
2036          * processing.
2037          */
2038         if (vers_to_try == NFS_V4) {
2039                 int savevers = nfsvers_to_use;
2040                 err_ret_t error;
2041                 int retval;
2042                 SET_ERR_RET(&error, ERR_PROTO_NONE, 0);
2043 
2044                 /* Let's hope for the best */
2045                 nfsvers_to_use = NFS_V4;
2046                 retval = getaddr_nfs(args, fshost, nconfp, FALSE,

2047                     fspath, port, &error, vers_min == NFS_V4);
2048 
2049                 if (retval == RET_OK) {
2050                         *versp = nfsvers_to_use = NFS_V4;
2051                         fstype = MNTTYPE_NFS4;
2052                         args->fh = strdup(fspath);
2053                         if (args->fh == NULL) {
2054                                 pr_err(gettext("no memory\n"));
2055                                 *versp = nfsvers_to_use = savevers;
2056                                 return (RET_ERR);
2057                         }
2058                         return (RET_OK);
2059                 }
2060                 nfsvers_to_use = savevers;
2061 
2062                 vers_to_try--;
2063                 /* If no more versions to try, let the user know. */
2064                 if (vers_to_try < vers_min) {
2065                         return (retval);
2066                 }


2143                 clnt_destroy(cl);
2144                 return (RET_RETRY);
2145         }
2146 
2147         switch (outvers) {
2148         case MOUNTVERS:
2149         case MOUNTVERS_POSIX:
2150                 *versp = nfsvers_to_use = NFS_VERSION;
2151                 rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2152                     (caddr_t)&fspath, xdr_fhstatus, (caddr_t)&fhs, timeout);
2153                 if (rpc_stat != RPC_SUCCESS) {
2154                         pr_err(gettext("%s:%s: server not responding %s\n"),
2155                             fshost, fspath, clnt_sperror(cl, ""));
2156                         clnt_destroy(cl);
2157                         return (RET_RETRY);
2158                 }
2159 
2160                 if ((errno = fhs.fhs_status) != MNT_OK) {
2161                         if (loud_on_mnt_err) {
2162                                 if (errno == EACCES) {
2163                                         pr_err(gettext(
2164                                             "%s:%s: access denied\n"),
2165                                             fshost, fspath);
2166                                 } else {
2167                                         pr_err(gettext("%s:%s: %s\n"),
2168                                             fshost, fspath, strerror(errno));
2169                                 }
2170                         }
2171                         clnt_destroy(cl);
2172                         return (RET_MNTERR);
2173                 }
2174                 args->fh = malloc(sizeof (fhs.fhstatus_u.fhs_fhandle));
2175                 if (args->fh == NULL) {
2176                         pr_err(gettext("no memory\n"));
2177                         return (RET_ERR);
2178                 }
2179                 memcpy((caddr_t)args->fh, (caddr_t)&fhs.fhstatus_u.fhs_fhandle,
2180                     sizeof (fhs.fhstatus_u.fhs_fhandle));
2181                 if (!errno && posix) {
2182                         rpc_stat = clnt_call(cl, MOUNTPROC_PATHCONF,
2183                             xdr_dirpath, (caddr_t)&fspath, xdr_ppathcnf,
2184                             (caddr_t)&p, timeout);
2185                         if (rpc_stat != RPC_SUCCESS) {
2186                                 pr_err(gettext(
2187                                     "%s:%s: server not responding %s\n"),
2188                                     fshost, fspath, clnt_sperror(cl, ""));


2197                                 free(args->fh);
2198                                 clnt_destroy(cl);
2199                                 return (RET_ERR);
2200                         }
2201                         args->flags |= NFSMNT_POSIX;
2202                         args->pathconf = malloc(sizeof (p));
2203                         if (args->pathconf == NULL) {
2204                                 pr_err(gettext("no memory\n"));
2205                                 free(args->fh);
2206                                 clnt_destroy(cl);
2207                                 return (RET_ERR);
2208                         }
2209                         memcpy((caddr_t)args->pathconf, (caddr_t)&p,
2210                             sizeof (p));
2211                 }
2212                 break;
2213 
2214         case MOUNTVERS3:
2215                 *versp = nfsvers_to_use = NFS_V3;
2216                 rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2217                     (caddr_t)&fspath, xdr_mountres3,
2218                     (caddr_t)&mountres3, timeout);
2219                 if (rpc_stat != RPC_SUCCESS) {
2220                         pr_err(gettext("%s:%s: server not responding %s\n"),
2221                             fshost, fspath, clnt_sperror(cl, ""));
2222                         clnt_destroy(cl);
2223                         return (RET_RETRY);
2224                 }
2225 
2226                 /*
2227                  * Assume here that most of the MNT3ERR_*
2228                  * codes map into E* errors.
2229                  */
2230                 if ((errno = mountres3.fhs_status) != MNT_OK) {
2231                         if (loud_on_mnt_err) {
2232                                 switch (errno) {
2233                                 case MNT3ERR_NAMETOOLONG:
2234                                         msg = "path name is too long";
2235                                         break;
2236                                 case MNT3ERR_NOTSUPP:
2237                                         msg = "operation not supported";
2238                                         break;
2239                                 case MNT3ERR_SERVERFAULT:
2240                                         msg = "server fault";
2241                                         break;
2242                                 default:
2243                                         msg = strerror(errno);
2244                                         break;
2245                                 }
2246 
2247                                 pr_err(gettext("%s:%s: %s\n"),
2248                                     fshost, fspath, msg);
2249                         }
2250 
2251                         clnt_destroy(cl);
2252                         return (RET_MNTERR);
2253                 }
2254 
2255                 fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
2256                 if (fh3p == NULL) {
2257                         pr_err(gettext("no memory\n"));
2258                         return (RET_ERR);
2259                 }
2260                 fh3p->fh3_length =
2261                     mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len;
2262                 (void) memcpy(fh3p->fh3_u.data,
2263                     mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val,
2264                     fh3p->fh3_length);
2265                 args->fh = (caddr_t)fh3p;
2266                 fstype = MNTTYPE_NFS3;
2267 
2268                 /*
2269                  * Check the security flavor to be used.
2270                  *
2271                  * If "secure" or "sec=flavor" is a mount
2272                  * option, check if the server supports the "flavor".
2273                  * If the server does not support the flavor, return
2274                  * error.
2275                  *
2276                  * If no mount option is given then use the first supported
2277                  * security flavor (by the client) in the auth list returned
2278                  * from the server.
2279                  *
2280                  */
2281                 auths =
2282                     mountres3.mountres3_u.mountinfo.auth_flavors.
2283                     auth_flavors_val;
2284                 count =
2285                     mountres3.mountres3_u.mountinfo.auth_flavors.
2286                     auth_flavors_len;
2287 
2288                 if (sec_opt) {
2289                         for (i = 0; i < count; i++) {
2290                                 if (auths[i] == nfs_sec.sc_nfsnum)
2291                                         break;
2292                         }
2293                         if (i >= count)
2294                                 goto autherr;

2295                 } else {
2296                         if (count > 0) {
2297                                 for (i = 0; i < count; i++) {
2298                                         if (!nfs_getseconfig_bynumber(auths[i],
2299                                             &nfs_sec)) {
2300                                                 sec_opt++;
2301                                                 break;
2302                                         }
2303                                 }
2304 
2305                                 if (i >= count)
2306                                         goto autherr;
2307                         }
2308                 }

2309                 break;
2310         default:
2311                 pr_err(gettext("%s:%s: Unknown MOUNT version %d\n"),
2312                     fshost, fspath, outvers);
2313                 clnt_destroy(cl);
2314                 return (RET_ERR);
2315         }
2316 
2317         clnt_destroy(cl);
2318         return (RET_OK);
2319 
2320 autherr:
2321         pr_err(gettext(
2322             "security mode does not match the server exporting %s:%s\n"),
2323             fshost, fspath);
2324         clnt_destroy(cl);
2325         return (RET_ERR);
2326 }
2327 
2328 /*


2374                  */
2375                 if (nfs_proto == NULL)
2376                         args->flags |= NFSMNT_TRYRDMA;
2377         }
2378 
2379         if (args->addr == NULL) {
2380                 /*
2381                  * We could have failed because the server had no public
2382                  * file handle support. So don't print a message and don't
2383                  * retry.
2384                  */
2385                 if (get_pubfh == TRUE)
2386                         return (RET_ERR);
2387 
2388                 if (!printed) {
2389                         switch (addr_error.error_type) {
2390                         case 0:
2391                                 printed = 1;
2392                                 break;
2393                         case ERR_RPCERROR:

2394                                 /* no error print at this time */
2395                                 if (!print_rpcerror)
2396                                         break;
2397                                 pr_err(gettext("%s NFS service not"
2398                                     " available %s\n"), fshost,
2399                                     clnt_sperrno(addr_error.error_value));
2400                                 printed = 1;
2401                                 break;
2402                         case ERR_NETPATH:
2403                                 pr_err(gettext("%s: Error in NETPATH.\n"),
2404                                     fshost);
2405                                 printed = 1;
2406                                 break;
2407                         case ERR_PROTO_INVALID:
2408                                 pr_err(gettext("%s: NFS service does not"
2409                                     " recognize protocol: %s.\n"), fshost,
2410                                     nfs_proto);
2411                                 printed = 1;
2412                                 break;
2413                         case ERR_PROTO_UNSUPP:
2414                                 if (nfsvers || nfsvers_to_use == NFS_VERSMIN) {
2415                                         /*


2429                                          * Otherwise we decrement the version
2430                                          * and retry below.
2431                                          */
2432                                         pr_err(gettext("%s: NFS service does"
2433                                             " not support protocol: %s.\n"),
2434                                             fshost, nfs_proto);
2435                                 }
2436                                 break;
2437                         case ERR_NOHOST:
2438                                 pr_err("%s: %s\n", fshost, "Unknown host");
2439                                 printed = 1;
2440                                 break;
2441                         default:
2442                                 /* case ERR_PROTO_NONE falls through */
2443                                 pr_err(gettext("%s: NFS service not responding"
2444                                     "\n"), fshost);
2445                                 printed = 1;
2446                                 break;
2447                         }
2448                 }
2449 
2450                 SET_ERR_RET(error,
2451                     addr_error.error_type, addr_error.error_value);
2452                 if (addr_error.error_type == ERR_PROTO_NONE)
2453                         return (RET_RETRY);
2454                 else if (addr_error.error_type == ERR_RPCERROR &&
2455                     ! IS_UNRECOVERABLE_RPC(addr_error.error_value)) {
2456                         return (RET_RETRY);
2457                 } else if (nfsvers == 0 && addr_error.error_type ==
2458                     ERR_PROTO_UNSUPP && nfsvers_to_use != NFS_VERSMIN) {
2459                         /*
2460                          * If no version is specified, and the error is due
2461                          * to an unsupported transport, then decrement the
2462                          * version and retry.
2463                          */
2464                         return (RET_RETRY);
2465                 } else
2466                         return (RET_ERR);
2467         }
2468         nconf = *nconfp;
2469