309 }
310 }
311
312 ct.cc_flags = 0;
313
314 /*
315 * Force modified metadata out to stable storage.
316 */
317 (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
318
319 VN_RELE(vp);
320
321 ns->ns_status = puterrno(error);
322 }
323 void *
324 rfs_setattr_getfh(struct nfssaargs *args)
325 {
326 return (&args->saa_fh);
327 }
328
329 /*
330 * Directory lookup.
331 * Returns an fhandle and file attributes for file name in a directory.
332 */
333 /* ARGSUSED */
334 void
335 rfs_lookup(struct nfsdiropargs *da, struct nfsdiropres *dr,
336 struct exportinfo *exi, struct svc_req *req, cred_t *cr)
337 {
338 int error;
339 vnode_t *dvp;
340 vnode_t *vp;
341 struct vattr va;
342 fhandle_t *fhp = da->da_fhandle;
343 struct sec_ol sec = {0, 0};
344 bool_t publicfh_flag = FALSE, auth_weak = FALSE;
345 char *name;
346 struct sockaddr *ca;
347
348 /*
382 * Not allow lookup beyond root.
383 * If the filehandle matches a filehandle of the exi,
384 * then the ".." refers beyond the root of an exported filesystem.
385 */
386 if (strcmp(da->da_name, "..") == 0 &&
387 EQFID(&exi->exi_fid, (fid_t *)&fhp->fh_len)) {
388 VN_RELE(dvp);
389 dr->dr_status = NFSERR_NOENT;
390 return;
391 }
392
393 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
394 name = nfscmd_convname(ca, exi, da->da_name, NFSCMD_CONV_INBOUND,
395 MAXPATHLEN);
396
397 if (name == NULL) {
398 dr->dr_status = NFSERR_ACCES;
399 return;
400 }
401
402 /*
403 * If the public filehandle is used then allow
404 * a multi-component lookup, i.e. evaluate
405 * a pathname and follow symbolic links if
406 * necessary.
407 *
408 * This may result in a vnode in another filesystem
409 * which is OK as long as the filesystem is exported.
410 */
411 if (PUBLIC_FH2(fhp)) {
412 publicfh_flag = TRUE;
413 error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &exi,
414 &sec);
415 } else {
416 /*
417 * Do a normal single component lookup.
418 */
419 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
420 NULL, NULL, NULL);
421 }
422
423 if (name != da->da_name)
424 kmem_free(name, MAXPATHLEN);
425
426
427 if (!error) {
428 va.va_mask = AT_ALL; /* we want everything */
429
430 error = rfs4_delegated_getattr(vp, &va, 0, cr);
431
432 /* check for overflows */
433 if (!error) {
434 acl_perm(vp, exi, &va, cr);
435 error = vattr_to_nattr(&va, &dr->dr_attr);
436 if (!error) {
437 if (sec.sec_flags & SEC_QUERY)
438 error = makefh_ol(&dr->dr_fhandle, exi,
439 sec.sec_index);
440 else {
441 error = makefh(&dr->dr_fhandle, vp,
442 exi);
443 if (!error && publicfh_flag &&
444 !chk_clnt_sec(exi, req))
445 auth_weak = TRUE;
446 }
447 }
448 }
449 VN_RELE(vp);
450 }
451
452 VN_RELE(dvp);
453
454 /*
455 * If publicfh_flag is true then we have called rfs_publicfh_mclookup
456 * and have obtained a new exportinfo in exi which needs to be
457 * released. Note the the original exportinfo pointed to by exi
458 * will be released by the caller, comon_dispatch.
459 */
460 if (publicfh_flag && exi != NULL)
461 exi_rele(exi);
462
463 /*
464 * If it's public fh, no 0x81, and client's flavor is
465 * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
466 * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
467 */
468 if (auth_weak)
469 dr->dr_status = (enum nfsstat)WNFSERR_CLNT_FLAVOR;
470 else
471 dr->dr_status = puterrno(error);
472 }
473 void *
474 rfs_lookup_getfh(struct nfsdiropargs *da)
475 {
476 return (da->da_fhandle);
477 }
478
479 /*
480 * Read symbolic link.
|
309 }
310 }
311
312 ct.cc_flags = 0;
313
314 /*
315 * Force modified metadata out to stable storage.
316 */
317 (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
318
319 VN_RELE(vp);
320
321 ns->ns_status = puterrno(error);
322 }
323 void *
324 rfs_setattr_getfh(struct nfssaargs *args)
325 {
326 return (&args->saa_fh);
327 }
328
329 /* Change and release @exip and @vpp only in success */
330 int
331 rfs_cross_mnt(vnode_t **vpp, struct exportinfo **exip)
332 {
333 struct exportinfo *exi;
334 vnode_t *vp;
335 fid_t fid;
336 int error;
337
338 vp = *vpp;
339
340 /* traverse() releases argument in success */
341 VN_HOLD(*vpp);
342
343 if ((error = traverse(&vp)) != 0) {
344 VN_RELE(*vpp);
345 return (error);
346 }
347
348 bzero(&fid, sizeof (fid));
349 fid.fid_len = MAXFIDSZ;
350 error = VOP_FID(vp, &fid, NULL);
351 if (error) {
352 VN_RELE(vp);
353 return (error);
354 }
355
356 exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid);
357 if (exi == NULL ||
358 (exi->exi_export.ex_flags & EX_NOHIDE) == 0) {
359 /* It is not error, just subdir is not exported
360 * or "nohide" is not set
361 */
362 VN_RELE(vp);
363 } else {
364 /* go to submount */
365 exi_rele(*exip);
366 *exip = exi;
367
368 VN_RELE(*vpp);
369 *vpp = vp;
370 }
371 return (0);
372 }
373
374 /*
375 * Directory lookup.
376 * Returns an fhandle and file attributes for file name in a directory.
377 */
378 /* ARGSUSED */
379 void
380 rfs_lookup(struct nfsdiropargs *da, struct nfsdiropres *dr,
381 struct exportinfo *exi, struct svc_req *req, cred_t *cr)
382 {
383 int error;
384 vnode_t *dvp;
385 vnode_t *vp;
386 struct vattr va;
387 fhandle_t *fhp = da->da_fhandle;
388 struct sec_ol sec = {0, 0};
389 bool_t publicfh_flag = FALSE, auth_weak = FALSE;
390 char *name;
391 struct sockaddr *ca;
392
393 /*
427 * Not allow lookup beyond root.
428 * If the filehandle matches a filehandle of the exi,
429 * then the ".." refers beyond the root of an exported filesystem.
430 */
431 if (strcmp(da->da_name, "..") == 0 &&
432 EQFID(&exi->exi_fid, (fid_t *)&fhp->fh_len)) {
433 VN_RELE(dvp);
434 dr->dr_status = NFSERR_NOENT;
435 return;
436 }
437
438 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
439 name = nfscmd_convname(ca, exi, da->da_name, NFSCMD_CONV_INBOUND,
440 MAXPATHLEN);
441
442 if (name == NULL) {
443 dr->dr_status = NFSERR_ACCES;
444 return;
445 }
446
447 exi_hold(exi);
448
449 /*
450 * If the public filehandle is used then allow
451 * a multi-component lookup, i.e. evaluate
452 * a pathname and follow symbolic links if
453 * necessary.
454 *
455 * This may result in a vnode in another filesystem
456 * which is OK as long as the filesystem is exported.
457 */
458 if (PUBLIC_FH2(fhp)) {
459 struct exportinfo *new;
460
461 publicfh_flag = TRUE;
462 error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &new,
463 &sec);
464
465 if (error == 0) {
466 exi_rele(exi);
467 exi = new;
468 }
469 } else {
470 /*
471 * Do a normal single component lookup.
472 */
473 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
474 NULL, NULL, NULL);
475 }
476
477 if (name != da->da_name)
478 kmem_free(name, MAXPATHLEN);
479
480 if (error == 0 && vn_ismntpt(vp)) {
481 error = rfs_cross_mnt(&vp, &exi);
482 if (error)
483 VN_RELE(vp);
484 }
485
486 if (!error) {
487 va.va_mask = AT_ALL; /* we want everything */
488
489 error = rfs4_delegated_getattr(vp, &va, 0, cr);
490
491 /* check for overflows */
492 if (!error) {
493 acl_perm(vp, exi, &va, cr);
494 error = vattr_to_nattr(&va, &dr->dr_attr);
495 if (!error) {
496 if (sec.sec_flags & SEC_QUERY)
497 error = makefh_ol(&dr->dr_fhandle, exi,
498 sec.sec_index);
499 else {
500 error = makefh(&dr->dr_fhandle, vp,
501 exi);
502 if (!error && publicfh_flag &&
503 !chk_clnt_sec(exi, req))
504 auth_weak = TRUE;
505 }
506 }
507 }
508 VN_RELE(vp);
509 }
510
511 VN_RELE(dvp);
512
513 /* The passed argument exportinfo is released by the
514 * caller, comon_dispatch
515 */
516 exi_rele(exi);
517
518 /*
519 * If it's public fh, no 0x81, and client's flavor is
520 * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
521 * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
522 */
523 if (auth_weak)
524 dr->dr_status = (enum nfsstat)WNFSERR_CLNT_FLAVOR;
525 else
526 dr->dr_status = puterrno(error);
527 }
528 void *
529 rfs_lookup_getfh(struct nfsdiropargs *da)
530 {
531 return (da->da_fhandle);
532 }
533
534 /*
535 * Read symbolic link.
|