Print this page
nfssrv: nfsstat reports zeroed data in zone


 178  * PUBLICFH_CHECK() checks if the dispatch routine supports
 179  * RPC_PUBLICFH_OK, if the filesystem is exported public, and if the
 180  * incoming request is using the public filehandle. The check duplicates
 181  * the exportmatch() call done in checkexport(), and we should consider
 182  * modifying those routines to avoid the duplication. For now, we optimize
 183  * by calling exportmatch() only after checking that the dispatch routine
 184  * supports RPC_PUBLICFH_OK, and if the filesystem is explicitly exported
 185  * public (i.e., not the placeholder).
 186  */
 187 #define PUBLICFH_CHECK(ne, disp, exi, fsid, xfid) \
 188                 ((disp->dis_flags & RPC_PUBLICFH_OK) && \
 189                 ((exi->exi_export.ex_flags & EX_PUBLIC) || \
 190                 (exi == ne->exi_public && exportmatch(ne->exi_root, \
 191                 fsid, xfid))))
 192 
 193 static void     nfs_srv_shutdown_all(int);
 194 static void     rfs4_server_start(nfs_globals_t *, int);
 195 static void     nullfree(void);
 196 static void     rfs_dispatch(struct svc_req *, SVCXPRT *);
 197 static void     acl_dispatch(struct svc_req *, SVCXPRT *);
 198 static void     common_dispatch(struct svc_req *, SVCXPRT *,
 199                 rpcvers_t, rpcvers_t, char *,
 200                 struct rpc_disptable *);
 201 static  int     checkauth(struct exportinfo *, struct svc_req *, cred_t *, int,
 202                 bool_t, bool_t *);
 203 static char     *client_name(struct svc_req *req);
 204 static char     *client_addr(struct svc_req *req, char *buf);
 205 extern  int     sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
 206 extern  bool_t  sec_svc_inrootlist(int, caddr_t, int, caddr_t *);
 207 static void     *nfs_server_zone_init(zoneid_t);
 208 static void     nfs_server_zone_fini(zoneid_t, void *);
 209 static void     nfs_server_zone_shutdown(zoneid_t, void *);
 210 
 211 #define NFSLOG_COPY_NETBUF(exi, xprt, nb)       {               \
 212         (nb)->maxlen = (xprt)->xp_rtaddr.maxlen;          \
 213         (nb)->len = (xprt)->xp_rtaddr.len;                        \
 214         (nb)->buf = kmem_alloc((nb)->len, KM_SLEEP);              \
 215         bcopy((xprt)->xp_rtaddr.buf, (nb)->buf, (nb)->len);    \
 216         }
 217 
 218 /*
 219  * Public Filehandle common nfs routines
 220  */


1317         /* RFS3_PATHCONF = 20 */
1318         PATHCONF3res nfs3_pathconf_res;
1319 
1320         /* RFS3_COMMIT = 21 */
1321         COMMIT3res nfs3_commit_res;
1322 
1323         /*
1324          * NFS VERSION 4
1325          */
1326 
1327         /* RFS_NULL = 0 */
1328 
1329         /* RFS4_COMPOUND = 1 */
1330         COMPOUND4res nfs4_compound_res;
1331 
1332 };
1333 
1334 static struct rpc_disptable rfs_disptable[] = {
1335         {sizeof (rfsdisptab_v2) / sizeof (rfsdisptab_v2[0]),
1336             rfscallnames_v2,
1337             &rfsproccnt_v2_ptr, rfsdisptab_v2},
1338         {sizeof (rfsdisptab_v3) / sizeof (rfsdisptab_v3[0]),
1339             rfscallnames_v3,
1340             &rfsproccnt_v3_ptr, rfsdisptab_v3},
1341         {sizeof (rfsdisptab_v4) / sizeof (rfsdisptab_v4[0]),
1342             rfscallnames_v4,
1343             &rfsproccnt_v4_ptr, rfsdisptab_v4},
1344 };
1345 
1346 /*
1347  * If nfs_portmon is set, then clients are required to use privileged
1348  * ports (ports < IPPORT_RESERVED) in order to get NFS services.
1349  *
1350  * N.B.: this attempt to carry forward the already ill-conceived notion
1351  * of privileged ports for TCP/UDP is really quite ineffectual.  Not only
1352  * is it transport-dependent, it's laughably easy to spoof.  If you're
1353  * really interested in security, you must start with secure RPC instead.
1354  */
1355 static int nfs_portmon = 0;
1356 
1357 #ifdef DEBUG
1358 static int cred_hits = 0;
1359 static int cred_misses = 0;
1360 #endif
1361 
1362 #ifdef DEBUG
1363 /*


1445         GETXATTRDIR3res acl3_getxattrdir_res;
1446 
1447 };
1448 
1449 static bool_t
1450 auth_tooweak(struct svc_req *req, char *res)
1451 {
1452 
1453         if (req->rq_vers == NFS_VERSION && req->rq_proc == RFS_LOOKUP) {
1454                 struct nfsdiropres *dr = (struct nfsdiropres *)res;
1455                 if ((enum wnfsstat)dr->dr_status == WNFSERR_CLNT_FLAVOR)
1456                         return (TRUE);
1457         } else if (req->rq_vers == NFS_V3 && req->rq_proc == NFSPROC3_LOOKUP) {
1458                 LOOKUP3res *resp = (LOOKUP3res *)res;
1459                 if ((enum wnfsstat)resp->status == WNFSERR_CLNT_FLAVOR)
1460                         return (TRUE);
1461         }
1462         return (FALSE);
1463 }
1464 
1465 
1466 static void
1467 common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
1468     rpcvers_t max_vers, char *pgmname, struct rpc_disptable *disptable)
1469 {
1470         int which;
1471         rpcvers_t vers;
1472         char *args;
1473         union {
1474                         union rfs_args ra;
1475                         union acl_args aa;
1476                 } args_buf;
1477         char *res;
1478         union {
1479                         union rfs_res rr;
1480                         union acl_res ar;
1481                 } res_buf;
1482         struct rpcdisp *disp = NULL;
1483         int dis_flags = 0;
1484         cred_t *cr;
1485         int error = 0;
1486         int anon_ok;
1487         struct exportinfo *exi = NULL;
1488         unsigned int nfslog_rec_id;
1489         int dupstat;
1490         struct dupreq *dr;
1491         int authres;
1492         bool_t publicfh_ok = FALSE;
1493         enum_t auth_flavor;
1494         bool_t dupcached = FALSE;
1495         struct netbuf   nb;
1496         bool_t logging_enabled = FALSE;
1497         struct exportinfo *nfslog_exi = NULL;
1498         char **procnames;
1499         char cbuf[INET6_ADDRSTRLEN];    /* to hold both IPv4 and IPv6 addr */
1500         bool_t ro = FALSE;
1501         nfs_export_t *ne = nfs_get_export();


1502 


1503         vers = req->rq_vers;
1504 




1505         if (vers < min_vers || vers > max_vers) {
1506                 svcerr_progvers(req->rq_xprt, min_vers, max_vers);
1507                 error++;
1508                 cmn_err(CE_NOTE, "%s: bad version number %u", pgmname, vers);
1509                 goto done;
1510         }
1511         vers -= min_vers;
1512 
1513         which = req->rq_proc;
1514         if (which < 0 || which >= disptable[(int)vers].dis_nprocs) {
1515                 svcerr_noproc(req->rq_xprt);
1516                 error++;
1517                 goto done;
1518         }
1519 
1520         (*(disptable[(int)vers].dis_proccntp))[which].value.ui64++;
1521 
1522         disp = &disptable[(int)vers].dis_table[which];
1523         procnames = disptable[(int)vers].dis_procnames;
1524 
1525         auth_flavor = req->rq_cred.oa_flavor;
1526 
1527         /*
1528          * Deserialize into the args struct.
1529          */
1530         args = (char *)&args_buf;
1531 
1532 #ifdef DEBUG
1533         if (rfs_no_fast_xdrargs || (auth_flavor == RPCSEC_GSS) ||
1534             disp->dis_fastxdrargs == NULL_xdrproc_t ||
1535             !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args))
1536 #else
1537         if ((auth_flavor == RPCSEC_GSS) ||
1538             disp->dis_fastxdrargs == NULL_xdrproc_t ||
1539             !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args))
1540 #endif


1822 
1823 done:
1824         /*
1825          * Free arguments struct
1826          */
1827         if (disp) {
1828                 if (!SVC_FREEARGS(xprt, disp->dis_xdrargs, args)) {
1829                         cmn_err(CE_NOTE, "%s: bad freeargs", pgmname);
1830                         error++;
1831                 }
1832         } else {
1833                 if (!SVC_FREEARGS(xprt, (xdrproc_t)0, (caddr_t)0)) {
1834                         cmn_err(CE_NOTE, "%s: bad freeargs", pgmname);
1835                         error++;
1836                 }
1837         }
1838 
1839         if (exi != NULL)
1840                 exi_rele(exi);
1841 
1842         global_svstat_ptr[req->rq_vers][NFS_BADCALLS].value.ui64 += error;
1843 
1844         global_svstat_ptr[req->rq_vers][NFS_CALLS].value.ui64++;
1845 }
1846 
1847 static void
1848 rfs_dispatch(struct svc_req *req, SVCXPRT *xprt)
1849 {
1850         common_dispatch(req, xprt, NFS_VERSMIN, NFS_VERSMAX,
1851             "NFS", rfs_disptable);
1852 }
1853 
1854 static char *aclcallnames_v2[] = {
1855         "ACL2_NULL",
1856         "ACL2_GETACL",
1857         "ACL2_SETACL",
1858         "ACL2_GETATTR",
1859         "ACL2_ACCESS",
1860         "ACL2_GETXATTRDIR"
1861 };
1862 
1863 static struct rpcdisp acldisptab_v2[] = {
1864         /*


1947             acl3_getacl_getfh},
1948 
1949         /* ACL3_SETACL = 2 */
1950         {acl3_setacl,
1951             xdr_SETACL3args, NULL_xdrproc_t, sizeof (SETACL3args),
1952             xdr_SETACL3res, NULL_xdrproc_t, sizeof (SETACL3res),
1953             nullfree, 0,
1954             acl3_setacl_getfh},
1955 
1956         /* ACL3_GETXATTRDIR = 3 */
1957         {acl3_getxattrdir,
1958             xdr_GETXATTRDIR3args, NULL_xdrproc_t, sizeof (GETXATTRDIR3args),
1959             xdr_GETXATTRDIR3res, NULL_xdrproc_t, sizeof (GETXATTRDIR3res),
1960             nullfree, RPC_IDEMPOTENT,
1961             acl3_getxattrdir_getfh},
1962 };
1963 
1964 static struct rpc_disptable acl_disptable[] = {
1965         {sizeof (acldisptab_v2) / sizeof (acldisptab_v2[0]),
1966                 aclcallnames_v2,
1967                 &aclproccnt_v2_ptr, acldisptab_v2},
1968         {sizeof (acldisptab_v3) / sizeof (acldisptab_v3[0]),
1969                 aclcallnames_v3,
1970                 &aclproccnt_v3_ptr, acldisptab_v3},
1971 };
1972 
1973 static void
1974 acl_dispatch(struct svc_req *req, SVCXPRT *xprt)
1975 {
1976         common_dispatch(req, xprt, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX,
1977             "ACL", acl_disptable);
1978 }
1979 
1980 int
1981 checkwin(int flavor, int window, struct svc_req *req)
1982 {
1983         struct authdes_cred *adc;
1984 
1985         switch (flavor) {
1986         case AUTH_DES:
1987                 adc = (struct authdes_cred *)req->rq_clntcred;
1988                 CTASSERT(sizeof (struct authdes_cred) <= RQCRED_SIZE);
1989                 if (adc->adc_fullname.window > window)
1990                         return (0);


2632 
2633         ng = kmem_zalloc(sizeof (*ng), KM_SLEEP);
2634 
2635         ng->nfs_versmin = NFS_VERSMIN_DEFAULT;
2636         ng->nfs_versmax = NFS_VERSMAX_DEFAULT;
2637 
2638         /* Init the stuff to control start/stop */
2639         ng->nfs_server_upordown = NFS_SERVER_STOPPED;
2640         mutex_init(&ng->nfs_server_upordown_lock, NULL, MUTEX_DEFAULT, NULL);
2641         cv_init(&ng->nfs_server_upordown_cv, NULL, CV_DEFAULT, NULL);
2642         mutex_init(&ng->rdma_wait_mutex, NULL, MUTEX_DEFAULT, NULL);
2643         cv_init(&ng->rdma_wait_cv, NULL, CV_DEFAULT, NULL);
2644 
2645         ng->nfs_zoneid = zoneid;
2646 
2647         /*
2648          * Order here is important.
2649          * export init must precede srv init calls.
2650          */
2651         nfs_export_zone_init(ng);

2652         rfs_srv_zone_init(ng);
2653         rfs3_srv_zone_init(ng);
2654         rfs4_srv_zone_init(ng);
2655         nfsauth_zone_init(ng);
2656 
2657         rw_enter(&nfssrv_globals_rwl, RW_WRITER);
2658         list_insert_tail(&nfssrv_globals_list, ng);
2659         rw_exit(&nfssrv_globals_rwl);
2660 
2661         return (ng);
2662 }
2663 
2664 /* ARGSUSED */
2665 static void
2666 nfs_server_zone_shutdown(zoneid_t zoneid, void *data)
2667 {
2668         nfs_globals_t *ng;
2669 
2670         ng = (nfs_globals_t *)data;
2671 


2680 /* ARGSUSED */
2681 static void
2682 nfs_server_zone_fini(zoneid_t zoneid, void *data)
2683 {
2684         nfs_globals_t *ng;
2685 
2686         ng = (nfs_globals_t *)data;
2687 
2688         rw_enter(&nfssrv_globals_rwl, RW_WRITER);
2689         list_remove(&nfssrv_globals_list, ng);
2690         rw_exit(&nfssrv_globals_rwl);
2691 
2692         /*
2693          * Order here is important.
2694          * reverse order from init
2695          */
2696         nfsauth_zone_fini(ng);
2697         rfs4_srv_zone_fini(ng);
2698         rfs3_srv_zone_fini(ng);
2699         rfs_srv_zone_fini(ng);

2700         nfs_export_zone_fini(ng);
2701 
2702         mutex_destroy(&ng->nfs_server_upordown_lock);
2703         cv_destroy(&ng->nfs_server_upordown_cv);
2704         mutex_destroy(&ng->rdma_wait_mutex);
2705         cv_destroy(&ng->rdma_wait_cv);
2706 
2707         kmem_free(ng, sizeof (*ng));
2708 }
2709 
2710 /*
2711  * Set up an iovec array of up to cnt pointers.
2712  */
2713 void
2714 mblk_to_iov(mblk_t *m, int cnt, struct iovec *iovp)
2715 {
2716         while (m != NULL && cnt-- > 0) {
2717                 iovp->iov_base = (caddr_t)m->b_rptr;
2718                 iovp->iov_len = (m->b_wptr - m->b_rptr);
2719                 iovp++;




 178  * PUBLICFH_CHECK() checks if the dispatch routine supports
 179  * RPC_PUBLICFH_OK, if the filesystem is exported public, and if the
 180  * incoming request is using the public filehandle. The check duplicates
 181  * the exportmatch() call done in checkexport(), and we should consider
 182  * modifying those routines to avoid the duplication. For now, we optimize
 183  * by calling exportmatch() only after checking that the dispatch routine
 184  * supports RPC_PUBLICFH_OK, and if the filesystem is explicitly exported
 185  * public (i.e., not the placeholder).
 186  */
 187 #define PUBLICFH_CHECK(ne, disp, exi, fsid, xfid) \
 188                 ((disp->dis_flags & RPC_PUBLICFH_OK) && \
 189                 ((exi->exi_export.ex_flags & EX_PUBLIC) || \
 190                 (exi == ne->exi_public && exportmatch(ne->exi_root, \
 191                 fsid, xfid))))
 192 
 193 static void     nfs_srv_shutdown_all(int);
 194 static void     rfs4_server_start(nfs_globals_t *, int);
 195 static void     nullfree(void);
 196 static void     rfs_dispatch(struct svc_req *, SVCXPRT *);
 197 static void     acl_dispatch(struct svc_req *, SVCXPRT *);



 198 static  int     checkauth(struct exportinfo *, struct svc_req *, cred_t *, int,
 199                 bool_t, bool_t *);
 200 static char     *client_name(struct svc_req *req);
 201 static char     *client_addr(struct svc_req *req, char *buf);
 202 extern  int     sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
 203 extern  bool_t  sec_svc_inrootlist(int, caddr_t, int, caddr_t *);
 204 static void     *nfs_server_zone_init(zoneid_t);
 205 static void     nfs_server_zone_fini(zoneid_t, void *);
 206 static void     nfs_server_zone_shutdown(zoneid_t, void *);
 207 
 208 #define NFSLOG_COPY_NETBUF(exi, xprt, nb)       {               \
 209         (nb)->maxlen = (xprt)->xp_rtaddr.maxlen;          \
 210         (nb)->len = (xprt)->xp_rtaddr.len;                        \
 211         (nb)->buf = kmem_alloc((nb)->len, KM_SLEEP);              \
 212         bcopy((xprt)->xp_rtaddr.buf, (nb)->buf, (nb)->len);    \
 213         }
 214 
 215 /*
 216  * Public Filehandle common nfs routines
 217  */


1314         /* RFS3_PATHCONF = 20 */
1315         PATHCONF3res nfs3_pathconf_res;
1316 
1317         /* RFS3_COMMIT = 21 */
1318         COMMIT3res nfs3_commit_res;
1319 
1320         /*
1321          * NFS VERSION 4
1322          */
1323 
1324         /* RFS_NULL = 0 */
1325 
1326         /* RFS4_COMPOUND = 1 */
1327         COMPOUND4res nfs4_compound_res;
1328 
1329 };
1330 
1331 static struct rpc_disptable rfs_disptable[] = {
1332         {sizeof (rfsdisptab_v2) / sizeof (rfsdisptab_v2[0]),
1333             rfscallnames_v2,
1334             rfsdisptab_v2},
1335         {sizeof (rfsdisptab_v3) / sizeof (rfsdisptab_v3[0]),
1336             rfscallnames_v3,
1337             rfsdisptab_v3},
1338         {sizeof (rfsdisptab_v4) / sizeof (rfsdisptab_v4[0]),
1339             rfscallnames_v4,
1340             rfsdisptab_v4},
1341 };
1342 
1343 /*
1344  * If nfs_portmon is set, then clients are required to use privileged
1345  * ports (ports < IPPORT_RESERVED) in order to get NFS services.
1346  *
1347  * N.B.: this attempt to carry forward the already ill-conceived notion
1348  * of privileged ports for TCP/UDP is really quite ineffectual.  Not only
1349  * is it transport-dependent, it's laughably easy to spoof.  If you're
1350  * really interested in security, you must start with secure RPC instead.
1351  */
1352 static int nfs_portmon = 0;
1353 
1354 #ifdef DEBUG
1355 static int cred_hits = 0;
1356 static int cred_misses = 0;
1357 #endif
1358 
1359 #ifdef DEBUG
1360 /*


1442         GETXATTRDIR3res acl3_getxattrdir_res;
1443 
1444 };
1445 
1446 static bool_t
1447 auth_tooweak(struct svc_req *req, char *res)
1448 {
1449 
1450         if (req->rq_vers == NFS_VERSION && req->rq_proc == RFS_LOOKUP) {
1451                 struct nfsdiropres *dr = (struct nfsdiropres *)res;
1452                 if ((enum wnfsstat)dr->dr_status == WNFSERR_CLNT_FLAVOR)
1453                         return (TRUE);
1454         } else if (req->rq_vers == NFS_V3 && req->rq_proc == NFSPROC3_LOOKUP) {
1455                 LOOKUP3res *resp = (LOOKUP3res *)res;
1456                 if ((enum wnfsstat)resp->status == WNFSERR_CLNT_FLAVOR)
1457                         return (TRUE);
1458         }
1459         return (FALSE);
1460 }
1461 

1462 static void
1463 common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
1464     rpcvers_t max_vers, char *pgmname, struct rpc_disptable *disptable)
1465 {
1466         int which;
1467         rpcvers_t vers;
1468         char *args;
1469         union {
1470                         union rfs_args ra;
1471                         union acl_args aa;
1472                 } args_buf;
1473         char *res;
1474         union {
1475                         union rfs_res rr;
1476                         union acl_res ar;
1477                 } res_buf;
1478         struct rpcdisp *disp = NULL;
1479         int dis_flags = 0;
1480         cred_t *cr;
1481         int error = 0;
1482         int anon_ok;
1483         struct exportinfo *exi = NULL;
1484         unsigned int nfslog_rec_id;
1485         int dupstat;
1486         struct dupreq *dr;
1487         int authres;
1488         bool_t publicfh_ok = FALSE;
1489         enum_t auth_flavor;
1490         bool_t dupcached = FALSE;
1491         struct netbuf   nb;
1492         bool_t logging_enabled = FALSE;
1493         struct exportinfo *nfslog_exi = NULL;
1494         char **procnames;
1495         char cbuf[INET6_ADDRSTRLEN];    /* to hold both IPv4 and IPv6 addr */
1496         bool_t ro = FALSE;
1497         nfs_export_t *ne = nfs_get_export();
1498         nfs_globals_t *ng = ne->ne_globals;
1499         kstat_named_t *svstat, *procstat;
1500 
1501         ASSERT(req->rq_prog == NFS_PROGRAM || req->rq_prog == NFS_ACL_PROGRAM);
1502 
1503         vers = req->rq_vers;
1504 
1505         svstat = ng->svstat[req->rq_vers];
1506         procstat = (req->rq_prog == NFS_PROGRAM) ?
1507             ng->rfsproccnt[vers] : ng->aclproccnt[vers];
1508 
1509         if (vers < min_vers || vers > max_vers) {
1510                 svcerr_progvers(req->rq_xprt, min_vers, max_vers);
1511                 error++;
1512                 cmn_err(CE_NOTE, "%s: bad version number %u", pgmname, vers);
1513                 goto done;
1514         }
1515         vers -= min_vers;
1516 
1517         which = req->rq_proc;
1518         if (which < 0 || which >= disptable[(int)vers].dis_nprocs) {
1519                 svcerr_noproc(req->rq_xprt);
1520                 error++;
1521                 goto done;
1522         }
1523 
1524         procstat[which].value.ui64++;
1525 
1526         disp = &disptable[(int)vers].dis_table[which];
1527         procnames = disptable[(int)vers].dis_procnames;
1528 
1529         auth_flavor = req->rq_cred.oa_flavor;
1530 
1531         /*
1532          * Deserialize into the args struct.
1533          */
1534         args = (char *)&args_buf;
1535 
1536 #ifdef DEBUG
1537         if (rfs_no_fast_xdrargs || (auth_flavor == RPCSEC_GSS) ||
1538             disp->dis_fastxdrargs == NULL_xdrproc_t ||
1539             !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args))
1540 #else
1541         if ((auth_flavor == RPCSEC_GSS) ||
1542             disp->dis_fastxdrargs == NULL_xdrproc_t ||
1543             !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args))
1544 #endif


1826 
1827 done:
1828         /*
1829          * Free arguments struct
1830          */
1831         if (disp) {
1832                 if (!SVC_FREEARGS(xprt, disp->dis_xdrargs, args)) {
1833                         cmn_err(CE_NOTE, "%s: bad freeargs", pgmname);
1834                         error++;
1835                 }
1836         } else {
1837                 if (!SVC_FREEARGS(xprt, (xdrproc_t)0, (caddr_t)0)) {
1838                         cmn_err(CE_NOTE, "%s: bad freeargs", pgmname);
1839                         error++;
1840                 }
1841         }
1842 
1843         if (exi != NULL)
1844                 exi_rele(exi);
1845 
1846         svstat[NFS_BADCALLS].value.ui64 += error;
1847         svstat[NFS_CALLS].value.ui64++;

1848 }
1849 
1850 static void
1851 rfs_dispatch(struct svc_req *req, SVCXPRT *xprt)
1852 {
1853         common_dispatch(req, xprt, NFS_VERSMIN, NFS_VERSMAX,
1854             "NFS", rfs_disptable);
1855 }
1856 
1857 static char *aclcallnames_v2[] = {
1858         "ACL2_NULL",
1859         "ACL2_GETACL",
1860         "ACL2_SETACL",
1861         "ACL2_GETATTR",
1862         "ACL2_ACCESS",
1863         "ACL2_GETXATTRDIR"
1864 };
1865 
1866 static struct rpcdisp acldisptab_v2[] = {
1867         /*


1950             acl3_getacl_getfh},
1951 
1952         /* ACL3_SETACL = 2 */
1953         {acl3_setacl,
1954             xdr_SETACL3args, NULL_xdrproc_t, sizeof (SETACL3args),
1955             xdr_SETACL3res, NULL_xdrproc_t, sizeof (SETACL3res),
1956             nullfree, 0,
1957             acl3_setacl_getfh},
1958 
1959         /* ACL3_GETXATTRDIR = 3 */
1960         {acl3_getxattrdir,
1961             xdr_GETXATTRDIR3args, NULL_xdrproc_t, sizeof (GETXATTRDIR3args),
1962             xdr_GETXATTRDIR3res, NULL_xdrproc_t, sizeof (GETXATTRDIR3res),
1963             nullfree, RPC_IDEMPOTENT,
1964             acl3_getxattrdir_getfh},
1965 };
1966 
1967 static struct rpc_disptable acl_disptable[] = {
1968         {sizeof (acldisptab_v2) / sizeof (acldisptab_v2[0]),
1969                 aclcallnames_v2,
1970                 acldisptab_v2},
1971         {sizeof (acldisptab_v3) / sizeof (acldisptab_v3[0]),
1972                 aclcallnames_v3,
1973                 acldisptab_v3},
1974 };
1975 
1976 static void
1977 acl_dispatch(struct svc_req *req, SVCXPRT *xprt)
1978 {
1979         common_dispatch(req, xprt, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX,
1980             "ACL", acl_disptable);
1981 }
1982 
1983 int
1984 checkwin(int flavor, int window, struct svc_req *req)
1985 {
1986         struct authdes_cred *adc;
1987 
1988         switch (flavor) {
1989         case AUTH_DES:
1990                 adc = (struct authdes_cred *)req->rq_clntcred;
1991                 CTASSERT(sizeof (struct authdes_cred) <= RQCRED_SIZE);
1992                 if (adc->adc_fullname.window > window)
1993                         return (0);


2635 
2636         ng = kmem_zalloc(sizeof (*ng), KM_SLEEP);
2637 
2638         ng->nfs_versmin = NFS_VERSMIN_DEFAULT;
2639         ng->nfs_versmax = NFS_VERSMAX_DEFAULT;
2640 
2641         /* Init the stuff to control start/stop */
2642         ng->nfs_server_upordown = NFS_SERVER_STOPPED;
2643         mutex_init(&ng->nfs_server_upordown_lock, NULL, MUTEX_DEFAULT, NULL);
2644         cv_init(&ng->nfs_server_upordown_cv, NULL, CV_DEFAULT, NULL);
2645         mutex_init(&ng->rdma_wait_mutex, NULL, MUTEX_DEFAULT, NULL);
2646         cv_init(&ng->rdma_wait_cv, NULL, CV_DEFAULT, NULL);
2647 
2648         ng->nfs_zoneid = zoneid;
2649 
2650         /*
2651          * Order here is important.
2652          * export init must precede srv init calls.
2653          */
2654         nfs_export_zone_init(ng);
2655         rfs_stat_zone_init(ng);
2656         rfs_srv_zone_init(ng);
2657         rfs3_srv_zone_init(ng);
2658         rfs4_srv_zone_init(ng);
2659         nfsauth_zone_init(ng);
2660 
2661         rw_enter(&nfssrv_globals_rwl, RW_WRITER);
2662         list_insert_tail(&nfssrv_globals_list, ng);
2663         rw_exit(&nfssrv_globals_rwl);
2664 
2665         return (ng);
2666 }
2667 
2668 /* ARGSUSED */
2669 static void
2670 nfs_server_zone_shutdown(zoneid_t zoneid, void *data)
2671 {
2672         nfs_globals_t *ng;
2673 
2674         ng = (nfs_globals_t *)data;
2675 


2684 /* ARGSUSED */
2685 static void
2686 nfs_server_zone_fini(zoneid_t zoneid, void *data)
2687 {
2688         nfs_globals_t *ng;
2689 
2690         ng = (nfs_globals_t *)data;
2691 
2692         rw_enter(&nfssrv_globals_rwl, RW_WRITER);
2693         list_remove(&nfssrv_globals_list, ng);
2694         rw_exit(&nfssrv_globals_rwl);
2695 
2696         /*
2697          * Order here is important.
2698          * reverse order from init
2699          */
2700         nfsauth_zone_fini(ng);
2701         rfs4_srv_zone_fini(ng);
2702         rfs3_srv_zone_fini(ng);
2703         rfs_srv_zone_fini(ng);
2704         rfs_stat_zone_fini(ng);
2705         nfs_export_zone_fini(ng);
2706 
2707         mutex_destroy(&ng->nfs_server_upordown_lock);
2708         cv_destroy(&ng->nfs_server_upordown_cv);
2709         mutex_destroy(&ng->rdma_wait_mutex);
2710         cv_destroy(&ng->rdma_wait_cv);
2711 
2712         kmem_free(ng, sizeof (*ng));
2713 }
2714 
2715 /*
2716  * Set up an iovec array of up to cnt pointers.
2717  */
2718 void
2719 mblk_to_iov(mblk_t *m, int cnt, struct iovec *iovp)
2720 {
2721         while (m != NULL && cnt-- > 0) {
2722                 iovp->iov_base = (caddr_t)m->b_rptr;
2723                 iovp->iov_len = (m->b_wptr - m->b_rptr);
2724                 iovp++;