1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software donated to Berkeley by 6 * Jan-Simon Pendry. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)portal_vnops.c 8.11 (Berkeley) 04/03/95 11 * 12 * $Id: portal_vnops.c,v 1.4 1992/05/30 10:05:24 jsp Exp jsp $ 13 */ 14 15 /* 16 * Portal Filesystem 17 */ 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/kernel.h> 22 #include <sys/types.h> 23 #include <sys/time.h> 24 #include <sys/proc.h> 25 #include <sys/filedesc.h> 26 #include <sys/vnode.h> 27 #include <sys/file.h> 28 #include <sys/stat.h> 29 #include <sys/mount.h> 30 #include <sys/malloc.h> 31 #include <sys/namei.h> 32 #include <sys/mbuf.h> 33 #include <sys/socket.h> 34 #include <sys/socketvar.h> 35 #include <sys/un.h> 36 #include <sys/unpcb.h> 37 #include <miscfs/portal/portal.h> 38 39 static int portal_fileid = PORTAL_ROOTFILEID+1; 40 41 static void 42 portal_closefd(p, fd) 43 struct proc *p; 44 int fd; 45 { 46 int error; 47 struct { 48 int fd; 49 } ua; 50 int rc; 51 52 ua.fd = fd; 53 error = close(p, &ua, &rc); 54 /* 55 * We should never get an error, and there isn't anything 56 * we could do if we got one, so just print a message. 57 */ 58 if (error) 59 printf("portal_closefd: error = %d\n", error); 60 } 61 62 /* 63 * vp is the current namei directory 64 * cnp is the name to locate in that directory... 65 */ 66 int 67 portal_lookup(ap) 68 struct vop_lookup_args /* { 69 struct vnode * a_dvp; 70 struct vnode ** a_vpp; 71 struct componentname * a_cnp; 72 } */ *ap; 73 { 74 char *pname = ap->a_cnp->cn_nameptr; 75 struct portalnode *pt; 76 int error; 77 struct vnode *fvp = 0; 78 char *path; 79 int size; 80 81 if (ap->a_cnp->cn_namelen == 1 && *pname == '.') { 82 *ap->a_vpp = ap->a_dvp; 83 VREF(ap->a_dvp); 84 /*VOP_LOCK(ap->a_dvp);*/ 85 return (0); 86 } 87 88 89 error = getnewvnode(VT_PORTAL, ap->a_dvp->v_mount, portal_vnodeop_p, &fvp); 90 if (error) 91 goto bad; 92 fvp->v_type = VREG; 93 MALLOC(fvp->v_data, void *, sizeof(struct portalnode), 94 M_TEMP, M_WAITOK); 95 96 pt = VTOPORTAL(fvp); 97 /* 98 * Save all of the remaining pathname and 99 * advance the namei next pointer to the end 100 * of the string. 101 */ 102 for (size = 0, path = pname; *path; path++) 103 size++; 104 ap->a_cnp->cn_consume = size - ap->a_cnp->cn_namelen; 105 106 pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK); 107 pt->pt_size = size+1; 108 bcopy(pname, pt->pt_arg, pt->pt_size); 109 pt->pt_fileid = portal_fileid++; 110 111 *ap->a_vpp = fvp; 112 /*VOP_LOCK(fvp);*/ 113 return (0); 114 115 bad:; 116 if (fvp) { 117 vrele(fvp); 118 } 119 *ap->a_vpp = NULL; 120 return (error); 121 } 122 123 static int 124 portal_connect(so, so2) 125 struct socket *so; 126 struct socket *so2; 127 { 128 /* from unp_connect, bypassing the namei stuff... */ 129 struct socket *so3; 130 struct unpcb *unp2; 131 struct unpcb *unp3; 132 133 if (so2 == 0) 134 return (ECONNREFUSED); 135 136 if (so->so_type != so2->so_type) 137 return (EPROTOTYPE); 138 139 if ((so2->so_options & SO_ACCEPTCONN) == 0) 140 return (ECONNREFUSED); 141 142 if ((so3 = sonewconn(so2, 0)) == 0) 143 return (ECONNREFUSED); 144 145 unp2 = sotounpcb(so2); 146 unp3 = sotounpcb(so3); 147 if (unp2->unp_addr) 148 unp3->unp_addr = m_copy(unp2->unp_addr, 0, (int)M_COPYALL); 149 150 so2 = so3; 151 152 153 return (unp_connect2(so, so2)); 154 } 155 156 int 157 portal_open(ap) 158 struct vop_open_args /* { 159 struct vnode *a_vp; 160 int a_mode; 161 struct ucred *a_cred; 162 struct proc *a_p; 163 } */ *ap; 164 { 165 struct socket *so = 0; 166 struct portalnode *pt; 167 struct proc *p = ap->a_p; 168 struct vnode *vp = ap->a_vp; 169 int s; 170 struct uio auio; 171 struct iovec aiov[2]; 172 int res; 173 struct mbuf *cm = 0; 174 struct cmsghdr *cmsg; 175 int newfds; 176 int *ip; 177 int fd; 178 int error; 179 int len; 180 struct portalmount *fmp; 181 struct file *fp; 182 struct portal_cred pcred; 183 184 /* 185 * Nothing to do when opening the root node. 186 */ 187 if (vp->v_flag & VROOT) 188 return (0); 189 190 /* 191 * Can't be opened unless the caller is set up 192 * to deal with the side effects. Check for this 193 * by testing whether the p_dupfd has been set. 194 */ 195 if (p->p_dupfd >= 0) 196 return (ENODEV); 197 198 pt = VTOPORTAL(vp); 199 fmp = VFSTOPORTAL(vp->v_mount); 200 201 /* 202 * Create a new socket. 203 */ 204 error = socreate(AF_UNIX, &so, SOCK_STREAM, 0); 205 if (error) 206 goto bad; 207 208 /* 209 * Reserve some buffer space 210 */ 211 res = pt->pt_size + sizeof(pcred) + 512; /* XXX */ 212 error = soreserve(so, res, res); 213 if (error) 214 goto bad; 215 216 /* 217 * Kick off connection 218 */ 219 error = portal_connect(so, (struct socket *)fmp->pm_server->f_data); 220 if (error) 221 goto bad; 222 223 /* 224 * Wait for connection to complete 225 */ 226 /* 227 * XXX: Since the mount point is holding a reference on the 228 * underlying server socket, it is not easy to find out whether 229 * the server process is still running. To handle this problem 230 * we loop waiting for the new socket to be connected (something 231 * which will only happen if the server is still running) or for 232 * the reference count on the server socket to drop to 1, which 233 * will happen if the server dies. Sleep for 5 second intervals 234 * and keep polling the reference count. XXX. 235 */ 236 s = splnet(); 237 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 238 if (fmp->pm_server->f_count == 1) { 239 error = ECONNREFUSED; 240 splx(s); 241 goto bad; 242 } 243 (void) tsleep((caddr_t) &so->so_timeo, PSOCK, "portalcon", 5 * hz); 244 } 245 splx(s); 246 247 if (so->so_error) { 248 error = so->so_error; 249 goto bad; 250 } 251 252 /* 253 * Set miscellaneous flags 254 */ 255 so->so_rcv.sb_timeo = 0; 256 so->so_snd.sb_timeo = 0; 257 so->so_rcv.sb_flags |= SB_NOINTR; 258 so->so_snd.sb_flags |= SB_NOINTR; 259 260 261 pcred.pcr_flag = ap->a_mode; 262 pcred.pcr_uid = ap->a_cred->cr_uid; 263 pcred.pcr_ngroups = ap->a_cred->cr_ngroups; 264 bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t)); 265 aiov[0].iov_base = (caddr_t) &pcred; 266 aiov[0].iov_len = sizeof(pcred); 267 aiov[1].iov_base = pt->pt_arg; 268 aiov[1].iov_len = pt->pt_size; 269 auio.uio_iov = aiov; 270 auio.uio_iovcnt = 2; 271 auio.uio_rw = UIO_WRITE; 272 auio.uio_segflg = UIO_SYSSPACE; 273 auio.uio_procp = p; 274 auio.uio_offset = 0; 275 auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len; 276 277 error = sosend(so, (struct mbuf *) 0, &auio, 278 (struct mbuf *) 0, (struct mbuf *) 0, 0); 279 if (error) 280 goto bad; 281 282 len = auio.uio_resid = sizeof(int); 283 do { 284 struct mbuf *m = 0; 285 int flags = MSG_WAITALL; 286 error = soreceive(so, (struct mbuf **) 0, &auio, 287 &m, &cm, &flags); 288 if (error) 289 goto bad; 290 291 /* 292 * Grab an error code from the mbuf. 293 */ 294 if (m) { 295 m = m_pullup(m, sizeof(int)); /* Needed? */ 296 if (m) { 297 error = *(mtod(m, int *)); 298 m_freem(m); 299 } else { 300 error = EINVAL; 301 } 302 } else { 303 if (cm == 0) { 304 error = ECONNRESET; /* XXX */ 305 #ifdef notdef 306 break; 307 #endif 308 } 309 } 310 } while (cm == 0 && auio.uio_resid == len && !error); 311 312 if (cm == 0) 313 goto bad; 314 315 if (auio.uio_resid) { 316 error = 0; 317 #ifdef notdef 318 error = EMSGSIZE; 319 goto bad; 320 #endif 321 } 322 323 /* 324 * XXX: Break apart the control message, and retrieve the 325 * received file descriptor. Note that more than one descriptor 326 * may have been received, or that the rights chain may have more 327 * than a single mbuf in it. What to do? 328 */ 329 cmsg = mtod(cm, struct cmsghdr *); 330 newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int); 331 if (newfds == 0) { 332 error = ECONNREFUSED; 333 goto bad; 334 } 335 /* 336 * At this point the rights message consists of a control message 337 * header, followed by a data region containing a vector of 338 * integer file descriptors. The fds were allocated by the action 339 * of receiving the control message. 340 */ 341 ip = (int *) (cmsg + 1); 342 fd = *ip++; 343 if (newfds > 1) { 344 /* 345 * Close extra fds. 346 */ 347 int i; 348 printf("portal_open: %d extra fds\n", newfds - 1); 349 for (i = 1; i < newfds; i++) { 350 portal_closefd(p, *ip); 351 ip++; 352 } 353 } 354 355 /* 356 * Check that the mode the file is being opened for is a subset 357 * of the mode of the existing descriptor. 358 */ 359 fp = p->p_fd->fd_ofiles[fd]; 360 if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) { 361 portal_closefd(p, fd); 362 error = EACCES; 363 goto bad; 364 } 365 366 /* 367 * Save the dup fd in the proc structure then return the 368 * special error code (ENXIO) which causes magic things to 369 * happen in vn_open. The whole concept is, well, hmmm. 370 */ 371 p->p_dupfd = fd; 372 error = ENXIO; 373 374 bad:; 375 /* 376 * And discard the control message. 377 */ 378 if (cm) { 379 m_freem(cm); 380 } 381 382 if (so) { 383 soshutdown(so, 2); 384 soclose(so); 385 } 386 return (error); 387 } 388 389 int 390 portal_getattr(ap) 391 struct vop_getattr_args /* { 392 struct vnode *a_vp; 393 struct vattr *a_vap; 394 struct ucred *a_cred; 395 struct proc *a_p; 396 } */ *ap; 397 { 398 struct vnode *vp = ap->a_vp; 399 struct vattr *vap = ap->a_vap; 400 struct timeval tv; 401 402 bzero(vap, sizeof(*vap)); 403 vattr_null(vap); 404 vap->va_uid = 0; 405 vap->va_gid = 0; 406 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 407 vap->va_size = DEV_BSIZE; 408 vap->va_blocksize = DEV_BSIZE; 409 microtime(&tv); 410 TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime); 411 vap->va_mtime = vap->va_atime; 412 vap->va_ctime = vap->va_ctime; 413 vap->va_gen = 0; 414 vap->va_flags = 0; 415 vap->va_rdev = 0; 416 /* vap->va_qbytes = 0; */ 417 vap->va_bytes = 0; 418 /* vap->va_qsize = 0; */ 419 if (vp->v_flag & VROOT) { 420 vap->va_type = VDIR; 421 vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR| 422 S_IRGRP|S_IWGRP|S_IXGRP| 423 S_IROTH|S_IWOTH|S_IXOTH; 424 vap->va_nlink = 2; 425 vap->va_fileid = 2; 426 } else { 427 vap->va_type = VREG; 428 vap->va_mode = S_IRUSR|S_IWUSR| 429 S_IRGRP|S_IWGRP| 430 S_IROTH|S_IWOTH; 431 vap->va_nlink = 1; 432 vap->va_fileid = VTOPORTAL(vp)->pt_fileid; 433 } 434 return (0); 435 } 436 437 int 438 portal_setattr(ap) 439 struct vop_setattr_args /* { 440 struct vnode *a_vp; 441 struct vattr *a_vap; 442 struct ucred *a_cred; 443 struct proc *a_p; 444 } */ *ap; 445 { 446 447 /* 448 * Can't mess with the root vnode 449 */ 450 if (ap->a_vp->v_flag & VROOT) 451 return (EACCES); 452 453 return (0); 454 } 455 456 /* 457 * Fake readdir, just return empty directory. 458 * It is hard to deal with '.' and '..' so don't bother. 459 */ 460 int 461 portal_readdir(ap) 462 struct vop_readdir_args /* { 463 struct vnode *a_vp; 464 struct uio *a_uio; 465 struct ucred *a_cred; 466 int *a_eofflag; 467 u_long *a_cookies; 468 int a_ncookies; 469 } */ *ap; 470 { 471 472 /* 473 * We don't allow exporting portal mounts, and currently local 474 * requests do not need cookies. 475 */ 476 if (ap->a_ncookies) 477 panic("portal_readdir: not hungry"); 478 479 return (0); 480 } 481 482 int 483 portal_inactive(ap) 484 struct vop_inactive_args /* { 485 struct vnode *a_vp; 486 } */ *ap; 487 { 488 489 return (0); 490 } 491 492 int 493 portal_reclaim(ap) 494 struct vop_reclaim_args /* { 495 struct vnode *a_vp; 496 } */ *ap; 497 { 498 struct portalnode *pt = VTOPORTAL(ap->a_vp); 499 500 if (pt->pt_arg) { 501 free((caddr_t) pt->pt_arg, M_TEMP); 502 pt->pt_arg = 0; 503 } 504 FREE(ap->a_vp->v_data, M_TEMP); 505 ap->a_vp->v_data = 0; 506 507 return (0); 508 } 509 510 /* 511 * Return POSIX pathconf information applicable to special devices. 512 */ 513 portal_pathconf(ap) 514 struct vop_pathconf_args /* { 515 struct vnode *a_vp; 516 int a_name; 517 int *a_retval; 518 } */ *ap; 519 { 520 521 switch (ap->a_name) { 522 case _PC_LINK_MAX: 523 *ap->a_retval = LINK_MAX; 524 return (0); 525 case _PC_MAX_CANON: 526 *ap->a_retval = MAX_CANON; 527 return (0); 528 case _PC_MAX_INPUT: 529 *ap->a_retval = MAX_INPUT; 530 return (0); 531 case _PC_PIPE_BUF: 532 *ap->a_retval = PIPE_BUF; 533 return (0); 534 case _PC_CHOWN_RESTRICTED: 535 *ap->a_retval = 1; 536 return (0); 537 case _PC_VDISABLE: 538 *ap->a_retval = _POSIX_VDISABLE; 539 return (0); 540 default: 541 return (EINVAL); 542 } 543 /* NOTREACHED */ 544 } 545 546 /* 547 * Print out the contents of a Portal vnode. 548 */ 549 /* ARGSUSED */ 550 int 551 portal_print(ap) 552 struct vop_print_args /* { 553 struct vnode *a_vp; 554 } */ *ap; 555 { 556 557 printf("tag VT_PORTAL, portal vnode\n"); 558 return (0); 559 } 560 561 /*void*/ 562 int 563 portal_vfree(ap) 564 struct vop_vfree_args /* { 565 struct vnode *a_pvp; 566 ino_t a_ino; 567 int a_mode; 568 } */ *ap; 569 { 570 571 return (0); 572 } 573 574 575 /* 576 * Portal vnode unsupported operation 577 */ 578 int 579 portal_enotsupp() 580 { 581 582 return (EOPNOTSUPP); 583 } 584 585 /* 586 * Portal "should never get here" operation 587 */ 588 int 589 portal_badop() 590 { 591 592 panic("portal: bad op"); 593 /* NOTREACHED */ 594 } 595 596 /* 597 * Portal vnode null operation 598 */ 599 int 600 portal_nullop() 601 { 602 603 return (0); 604 } 605 606 #define portal_create ((int (*) __P((struct vop_create_args *)))portal_enotsupp) 607 #define portal_mknod ((int (*) __P((struct vop_mknod_args *)))portal_enotsupp) 608 #define portal_close ((int (*) __P((struct vop_close_args *)))nullop) 609 #define portal_access ((int (*) __P((struct vop_access_args *)))nullop) 610 #define portal_read ((int (*) __P((struct vop_read_args *)))portal_enotsupp) 611 #define portal_write ((int (*) __P((struct vop_write_args *)))portal_enotsupp) 612 #define portal_ioctl ((int (*) __P((struct vop_ioctl_args *)))portal_enotsupp) 613 #define portal_select ((int (*) __P((struct vop_select_args *)))portal_enotsupp) 614 #define portal_mmap ((int (*) __P((struct vop_mmap_args *)))portal_enotsupp) 615 #define portal_revoke vop_revoke 616 #define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 617 #define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop) 618 #define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp) 619 #define portal_link ((int (*) __P((struct vop_link_args *)))portal_enotsupp) 620 #define portal_rename ((int (*) __P((struct vop_rename_args *)))portal_enotsupp) 621 #define portal_mkdir ((int (*) __P((struct vop_mkdir_args *)))portal_enotsupp) 622 #define portal_rmdir ((int (*) __P((struct vop_rmdir_args *)))portal_enotsupp) 623 #define portal_symlink \ 624 ((int (*) __P((struct vop_symlink_args *)))portal_enotsupp) 625 #define portal_readlink \ 626 ((int (*) __P((struct vop_readlink_args *)))portal_enotsupp) 627 #define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) 628 #define portal_lock ((int (*) __P((struct vop_lock_args *)))nullop) 629 #define portal_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) 630 #define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop) 631 #define portal_strategy \ 632 ((int (*) __P((struct vop_strategy_args *)))portal_badop) 633 #define portal_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) 634 #define portal_advlock \ 635 ((int (*) __P((struct vop_advlock_args *)))portal_enotsupp) 636 #define portal_blkatoff \ 637 ((int (*) __P((struct vop_blkatoff_args *)))portal_enotsupp) 638 #define portal_valloc ((int(*) __P(( \ 639 struct vnode *pvp, \ 640 int mode, \ 641 struct ucred *cred, \ 642 struct vnode **vpp))) portal_enotsupp) 643 #define portal_truncate \ 644 ((int (*) __P((struct vop_truncate_args *)))portal_enotsupp) 645 #define portal_update ((int (*) __P((struct vop_update_args *)))portal_enotsupp) 646 #define portal_bwrite ((int (*) __P((struct vop_bwrite_args *)))portal_enotsupp) 647 648 int (**portal_vnodeop_p)(); 649 struct vnodeopv_entry_desc portal_vnodeop_entries[] = { 650 { &vop_default_desc, vn_default_error }, 651 { &vop_lookup_desc, portal_lookup }, /* lookup */ 652 { &vop_create_desc, portal_create }, /* create */ 653 { &vop_mknod_desc, portal_mknod }, /* mknod */ 654 { &vop_open_desc, portal_open }, /* open */ 655 { &vop_close_desc, portal_close }, /* close */ 656 { &vop_access_desc, portal_access }, /* access */ 657 { &vop_getattr_desc, portal_getattr }, /* getattr */ 658 { &vop_setattr_desc, portal_setattr }, /* setattr */ 659 { &vop_read_desc, portal_read }, /* read */ 660 { &vop_write_desc, portal_write }, /* write */ 661 { &vop_ioctl_desc, portal_ioctl }, /* ioctl */ 662 { &vop_select_desc, portal_select }, /* select */ 663 { &vop_mmap_desc, portal_mmap }, /* mmap */ 664 { &vop_revoke_desc, portal_revoke }, /* revoke */ 665 { &vop_fsync_desc, portal_fsync }, /* fsync */ 666 { &vop_seek_desc, portal_seek }, /* seek */ 667 { &vop_remove_desc, portal_remove }, /* remove */ 668 { &vop_link_desc, portal_link }, /* link */ 669 { &vop_rename_desc, portal_rename }, /* rename */ 670 { &vop_mkdir_desc, portal_mkdir }, /* mkdir */ 671 { &vop_rmdir_desc, portal_rmdir }, /* rmdir */ 672 { &vop_symlink_desc, portal_symlink }, /* symlink */ 673 { &vop_readdir_desc, portal_readdir }, /* readdir */ 674 { &vop_readlink_desc, portal_readlink }, /* readlink */ 675 { &vop_abortop_desc, portal_abortop }, /* abortop */ 676 { &vop_inactive_desc, portal_inactive }, /* inactive */ 677 { &vop_reclaim_desc, portal_reclaim }, /* reclaim */ 678 { &vop_lock_desc, portal_lock }, /* lock */ 679 { &vop_unlock_desc, portal_unlock }, /* unlock */ 680 { &vop_bmap_desc, portal_bmap }, /* bmap */ 681 { &vop_strategy_desc, portal_strategy }, /* strategy */ 682 { &vop_print_desc, portal_print }, /* print */ 683 { &vop_islocked_desc, portal_islocked }, /* islocked */ 684 { &vop_pathconf_desc, portal_pathconf }, /* pathconf */ 685 { &vop_advlock_desc, portal_advlock }, /* advlock */ 686 { &vop_blkatoff_desc, portal_blkatoff }, /* blkatoff */ 687 { &vop_valloc_desc, portal_valloc }, /* valloc */ 688 { &vop_vfree_desc, portal_vfree }, /* vfree */ 689 { &vop_truncate_desc, portal_truncate }, /* truncate */ 690 { &vop_update_desc, portal_update }, /* update */ 691 { &vop_bwrite_desc, portal_bwrite }, /* bwrite */ 692 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 693 }; 694 struct vnodeopv_desc portal_vnodeop_opv_desc = 695 { &portal_vnodeop_p, portal_vnodeop_entries }; 696