Print this page
*** NO COMMENTS ***


 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.