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++;
|