/* Unmount the filesystem described by mp. */ static int nwfs_unmount(struct mount *mp, int mntflags) { struct nwmount *nmp = VFSTONWFS(mp); struct ncp_conn *conn; int error, flags; NCPVODEBUG("nwfs_unmount: flags=%04x\n",mntflags); flags = 0; if (mntflags & MNT_FORCE) flags |= FORCECLOSE; /* There is 1 extra root vnode reference from nwfs_mount(). */ error = vflush(mp, 1, flags); if (error) return (error); conn = NWFSTOCONN(nmp); ncp_conn_puthandle(nmp->connh,NULL,0); if (ncp_conn_lock(conn, curthread, proc0.p_ucred, NCPM_WRITE | NCPM_EXECUTE) == 0) { if(ncp_disconnect(conn)) ncp_conn_unlock(conn, curthread); } mp->mnt_data = (qaddr_t)0; if (nmp->m.flags & NWFS_MOUNT_HAVE_NLS) kfree(nmp->m.nls.to_lower, M_NWFSDATA); kfree(nmp, M_NWFSDATA); mp->mnt_flag &= ~MNT_LOCAL; return (error); }
/* * mp - path - addr in user space of mount point (ie /usr or whatever) * data - addr in user space of mount params */ static int nwfs_mount(struct mount *mp) { struct nwfs_args args; /* will hold data from mount request */ int error; struct nwmount *nmp = NULL; struct ncp_conn *conn = NULL; struct ncp_handle *handle = NULL; struct vnode *vp; struct thread *td; char *pc,*pe; td = curthread; if (mp->mnt_flag & MNT_ROOTFS) return (EOPNOTSUPP); if (mp->mnt_flag & MNT_UPDATE) { nwfs_printf("MNT_UPDATE not implemented"); return (EOPNOTSUPP); } error = vfs_copyopt(mp->mnt_optnew, "nwfs_args", &args, sizeof args); if (error) return (error); if (args.version != NWFS_VERSION) { nwfs_printf("mount version mismatch: kernel=%d, mount=%d\n",NWFS_VERSION,args.version); return (1); } error = ncp_conn_getbyref(args.connRef, td , td->td_ucred,NCPM_EXECUTE,&conn); if (error) { nwfs_printf("invalid connection refernce %d\n",args.connRef); return (error); } error = ncp_conn_gethandle(conn, NULL, &handle); if (error) { nwfs_printf("can't get connection handle\n"); return (error); } ncp_conn_unlock(conn, td); /* we keep the ref */ mp->mnt_stat.f_iosize = conn->buffer_size; /* We must malloc our own mount info */ nmp = malloc(sizeof(struct nwmount),M_NWFSDATA, M_WAITOK | M_USE_RESERVE | M_ZERO); if (nmp == NULL) { nwfs_printf("could not alloc nwmount\n"); error = ENOMEM; goto bad; } mp->mnt_data = nmp; nmp->connh = handle; nmp->n_root = NULL; nmp->n_id = nwfsid++; nmp->m = args; nmp->m.file_mode = (nmp->m.file_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG; nmp->m.dir_mode = (nmp->m.dir_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR; if ((error = nwfs_initnls(nmp)) != 0) goto bad; pc = mp->mnt_stat.f_mntfromname; pe = pc+sizeof(mp->mnt_stat.f_mntfromname); bzero(pc, MNAMELEN); *(pc++) = '/'; pc = index(strncpy(pc, conn->li.server, pe-pc-2),0); if (pc < pe-1) { *(pc++) = ':'; pc=index(strncpy(pc, conn->li.user, pe-pc-2),0); if (pc < pe-1) { *(pc++) = '/'; strncpy(pc, nmp->m.mounted_vol, pe-pc-2); } } /* protect against invalid mount points */ nmp->m.mount_point[sizeof(nmp->m.mount_point)-1] = '\0'; vfs_getnewfsid(mp); error = nwfs_root(mp, LK_EXCLUSIVE, &vp); if (error) goto bad; /* * Lose the lock but keep the ref. */ VOP_UNLOCK(vp, 0); NCPVODEBUG("rootvp.vrefcnt=%d\n",vrefcnt(vp)); return error; bad: if (nmp) free(nmp, M_NWFSDATA); if (handle) ncp_conn_puthandle(handle, NULL, 0); return error; }
/* * mp - path - addr in user space of mount point (ie /usr or whatever) * data - addr in user space of mount params */ static int nwfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) { struct nwfs_args args; /* will hold data from mount request */ int error; struct nwmount *nmp = NULL; struct ncp_conn *conn = NULL; struct ncp_handle *handle = NULL; struct vnode *vp; char *pc,*pe; if (data == NULL) { nwfs_printf("missing data argument\n"); return 1; } if (mp->mnt_flag & MNT_UPDATE) { nwfs_printf("MNT_UPDATE not implemented"); return (EOPNOTSUPP); } error = copyin(data, (caddr_t)&args, sizeof(struct nwfs_args)); if (error) return (error); if (args.version != NWFS_VERSION) { nwfs_printf("mount version mismatch: kernel=%d, mount=%d\n",NWFS_VERSION,args.version); return (1); } error = ncp_conn_getbyref(args.connRef,curthread,cred,NCPM_EXECUTE,&conn); if (error) { nwfs_printf("invalid connection reference %d\n",args.connRef); return (error); } error = ncp_conn_gethandle(conn, NULL, &handle); if (error) { nwfs_printf("can't get connection handle\n"); return (error); } ncp_conn_unlock(conn,curthread); /* we keep the ref */ mp->mnt_stat.f_iosize = conn->buffer_size; /* We must malloc our own mount info */ nmp = kmalloc(sizeof(struct nwmount), M_NWFSDATA, M_WAITOK | M_USE_RESERVE | M_ZERO); mp->mnt_data = (qaddr_t)nmp; nmp->connh = handle; nmp->n_root = NULL; nmp->n_id = nwfsid++; nmp->m = args; nmp->m.file_mode = (nmp->m.file_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG; nmp->m.dir_mode = (nmp->m.dir_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR; if ((error = nwfs_initnls(nmp)) != 0) goto bad; pc = mp->mnt_stat.f_mntfromname; pe = pc+sizeof(mp->mnt_stat.f_mntfromname); bzero(pc, MNAMELEN); *(pc++) = '/'; pc = index(strncpy(pc, conn->li.server, pe-pc-2),0); if (pc < pe-1) { *(pc++) = ':'; pc=index(strncpy(pc, conn->li.user, pe-pc-2),0); if (pc < pe-1) { *(pc++) = '/'; strncpy(pc, nmp->m.mounted_vol, pe-pc-2); } } /* protect against invalid mount points */ nmp->m.mount_point[sizeof(nmp->m.mount_point)-1] = '\0'; vfs_add_vnodeops(mp, &nwfs_vnode_vops, &mp->mnt_vn_norm_ops); vfs_getnewfsid(mp); error = nwfs_root(mp, &vp); if (error) goto bad; /* * Lose the lock but keep the ref. */ vn_unlock(vp); NCPVODEBUG("rootvp.vrefcnt=%d\n",vp->v_sysref.refcnt); return error; bad: if (nmp) kfree(nmp, M_NWFSDATA); if (handle) ncp_conn_puthandle(handle, NULL, 0); return error; }
static int ncp_conn_handler(struct proc *p, struct sncp_request_args *uap, struct ncp_conn *conn, struct ncp_handle *hp) { int error=0, rqsize, subfn; struct ucred *cred; char *pdata; cred = p->p_ucred; error = copyin(&uap->ncpbuf->rqsize, &rqsize, sizeof(int)); if (error) return(error); error = 0; pdata = uap->ncpbuf->packet; subfn = *(pdata++) & 0xff; rqsize--; switch (subfn) { case NCP_CONN_READ: case NCP_CONN_WRITE: { struct ncp_rw rwrq; struct uio auio; struct iovec iov; if (rqsize != sizeof(rwrq)) return (EBADRPC); error = copyin(pdata,&rwrq,rqsize); if (error) return (error); iov.iov_base = rwrq.nrw_base; iov.iov_len = rwrq.nrw_cnt; auio.uio_iov = &iov; auio.uio_iovcnt = 1; auio.uio_offset = rwrq.nrw_offset; auio.uio_resid = rwrq.nrw_cnt; auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = (subfn == NCP_CONN_READ) ? UIO_READ : UIO_WRITE; auio.uio_procp = p; error = ncp_conn_lock(conn,p,cred,NCPM_EXECUTE); if (error) return(error); if (subfn == NCP_CONN_READ) error = ncp_read(conn, &rwrq.nrw_fh, &auio, cred); else error = ncp_write(conn, &rwrq.nrw_fh, &auio, cred); rwrq.nrw_cnt -= auio.uio_resid; ncp_conn_unlock(conn,p); p->p_retval[0] = rwrq.nrw_cnt; break; } /* case int_read/write */ case NCP_CONN_SETFLAGS: { u_int16_t mask, flags; error = copyin(pdata,&mask, sizeof(mask)); if (error) return error; pdata += sizeof(mask); error = copyin(pdata,&flags,sizeof(flags)); if (error) return error; error = ncp_conn_lock(conn,p,cred,NCPM_WRITE); if (error) return error; if (mask & NCPFL_PERMANENT) { conn->flags &= ~NCPFL_PERMANENT; conn->flags |= (flags & NCPFL_PERMANENT); } if (mask & NCPFL_PRIMARY) { error = ncp_conn_setprimary(conn, flags & NCPFL_PRIMARY); if (error) { ncp_conn_unlock(conn,p); break; } } ncp_conn_unlock(conn,p); break; } case NCP_CONN_LOGIN: { struct ncp_conn_login la; if (rqsize != sizeof(la)) return (EBADRPC); if ((error = copyin(pdata,&la,rqsize)) != 0) break; error = ncp_conn_lock(conn, p, cred, NCPM_EXECUTE | NCPM_WRITE); if (error) return error; error = ncp_login(conn, la.username, la.objtype, la.password, p, p->p_ucred); ncp_conn_unlock(conn, p); p->p_retval[0] = error; break; } case NCP_CONN_GETINFO: { struct ncp_conn_stat ncs; int len = sizeof(ncs); error = ncp_conn_lock(conn, p, p->p_ucred, NCPM_READ); if (error) return error; ncp_conn_getinfo(conn, &ncs); copyout(&len, &uap->ncpbuf->rpsize, sizeof(int)); error = copyout(&ncs, &uap->ncpbuf->packet, len); ncp_conn_unlock(conn, p); break; } case NCP_CONN_GETUSER: { int len; error = ncp_conn_lock(conn, p, p->p_ucred, NCPM_READ); if (error) return error; len = (conn->li.user) ? strlen(conn->li.user) + 1 : 0; copyout(&len, &uap->ncpbuf->rpsize, sizeof(int)); if (len) { error = copyout(conn->li.user, &uap->ncpbuf->packet, len); } ncp_conn_unlock(conn, p); break; } case NCP_CONN_CONN2REF: { int len = sizeof(int); error = ncp_conn_lock(conn, p, p->p_ucred, NCPM_READ); if (error) return error; copyout(&len, &uap->ncpbuf->rpsize, sizeof(int)); if (len) { error = copyout(&conn->nc_id, &uap->ncpbuf->packet, len); } ncp_conn_unlock(conn, p); break; } case NCP_CONN_FRAG: { struct ncp_conn_frag nf; if (rqsize != sizeof(nf)) return (EBADRPC); if ((error = copyin(pdata, &nf, rqsize)) != 0) break; error = ncp_conn_lock(conn, p, cred, NCPM_EXECUTE); if (error) return error; error = ncp_conn_frag_rq(conn, p, &nf); ncp_conn_unlock(conn, p); copyout(&nf, &pdata, sizeof(nf)); p->p_retval[0] = error; break; } case NCP_CONN_DUP: { struct ncp_handle *newhp; int len = sizeof(NWCONN_HANDLE); error = ncp_conn_lock(conn, p, cred, NCPM_READ); if (error) break; copyout(&len, &uap->ncpbuf->rpsize, len); error = ncp_conn_gethandle(conn, p, &newhp); if (!error) error = copyout(&newhp->nh_id, uap->ncpbuf->packet, len); ncp_conn_unlock(conn,p); break; } case NCP_CONN_CONNCLOSE: { error = ncp_conn_lock(conn, p, cred, NCPM_EXECUTE); if (error) break; ncp_conn_puthandle(hp, p, 0); error = ncp_disconnect(conn); if (error) ncp_conn_unlock(conn, p); break; } default: error = EOPNOTSUPP; } return error; }