/* 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); }
static int __P(sncp_request(struct proc *p, struct sncp_request_args *uap)){ int error = 0, rqsize; struct ncp_conn *conn; struct ncp_handle *handle; DECLARE_RQ; error = ncp_conn_findhandle(uap->connHandle,p,&handle); if (error) return error; conn = handle->nh_conn; if (uap->fn == NCP_CONN) return ncp_conn_handler(p, uap, conn, handle); error = copyin(&uap->ncpbuf->rqsize, &rqsize, sizeof(int)); if (error) return(error); error = ncp_conn_lock(conn,p,p->p_ucred,NCPM_EXECUTE); if (error) return(error); ncp_rq_head(rqp,NCP_REQUEST,uap->fn,p,p->p_ucred); if (rqsize) error = ncp_rq_usermem(rqp,(caddr_t)uap->ncpbuf->packet, rqsize); if (!error) { error = ncp_request(conn, rqp); if (error == 0 && rqp->rpsize) ncp_rp_usermem(rqp, (caddr_t)uap->ncpbuf->packet, rqp->rpsize); copyout(&rqp->cs, &uap->ncpbuf->cs, sizeof(rqp->cs)); copyout(&rqp->cc, &uap->ncpbuf->cc, sizeof(rqp->cc)); copyout(&rqp->rpsize, &uap->ncpbuf->rpsize, sizeof(rqp->rpsize)); } ncp_rq_done(rqp); ncp_conn_unlock(conn,p); return error; }
static int __P(sncp_conn_scan(struct proc *p, struct sncp_conn_scan_args *uap)){ int connHandle = 0, error; struct ncp_conn_args li, *lip; struct ncp_conn *conn; struct ncp_handle *hp; char *user = NULL, *password = NULL; if (uap->li) { if (copyin(uap->li,&li,sizeof(li))) return EFAULT; lip = &li; } else { lip = NULL; } if (lip != NULL) { lip->server[sizeof(lip->server)-1]=0; /* just to make sure */ ncp_str_upper(lip->server); if (lip->user) { user = ncp_str_dup(lip->user); if (user == NULL) return EINVAL; ncp_str_upper(user); } if (lip->password) { password = ncp_str_dup(lip->password); if (password == NULL) { if (user) free(user, M_NCPDATA); return EINVAL; } ncp_str_upper(password); } lip->user = user; lip->password = password; } error = ncp_conn_getbyli(lip,p,p->p_ucred,NCPM_EXECUTE,&conn); if (!error) { /* already have this login */ ncp_conn_gethandle(conn, p, &hp); connHandle = hp->nh_id; ncp_conn_unlock(conn,p); copyout(&connHandle,uap->connHandle,sizeof(connHandle)); } if (user) free(user, M_NCPDATA); if (password) free(password, M_NCPDATA); p->p_retval[0] = error; return error; }
void ncp_at_exit(struct proc *p) { struct ncp_conn *ncp, *nncp; if (ncp_conn_putprochandles(p) == 0) return; ncp_conn_locklist(LK_EXCLUSIVE, p); for (ncp = conn_list.slh_first; ncp; ncp = nncp) { nncp = ncp->nc_next.sle_next; if (ncp->ref_cnt != 0) continue; if (ncp_conn_lock(ncp, p, p->p_ucred,NCPM_READ|NCPM_EXECUTE|NCPM_WRITE)) continue; if (ncp_disconnect(ncp) != 0) ncp_conn_unlock(ncp,p); } ncp_conn_unlocklist(p); return; }
void ncp_done(void) { struct ncp_conn *ncp, *nncp; struct proc *p = curproc; untimeout(ncp_timer,NULL,ncp_timer_handle); rm_at_exit(ncp_at_exit); ncp_conn_locklist(LK_EXCLUSIVE, p); for (ncp = conn_list.slh_first; ncp; ncp = nncp) { nncp = ncp->nc_next.sle_next; ncp->ref_cnt = 0; if (ncp_conn_lock(ncp, p, p->p_ucred,NCPM_READ|NCPM_EXECUTE|NCPM_WRITE)) { NCPFATAL("Can't lock connection !\n"); continue; } if (ncp_disconnect(ncp) != 0) ncp_conn_unlock(ncp,p); } ncp_conn_unlocklist(p); }
/* * nwfs_ioctl(struct vnode *a_vp, u_long a_command, caddr_t a_data, * int a_fflag, struct ucred *a_cred) */ int nwfs_ioctl(struct vop_ioctl_args *ap) { int error; struct thread *td = curthread; /* XXX */ struct ucred *cred = ap->a_cred; struct vnode *vp = ap->a_vp; struct nwnode *np = VTONW(vp); struct nwmount *nmp = VTONWFS(vp); struct ncp_conn *conn = NWFSTOCONN(nmp); struct ncp_handle *hp; struct nw_entry_info *fap; void *data = ap->a_data; switch (ap->a_command) { case NWFSIOC_GETCONN: error = ncp_conn_lock(conn, td, cred, NCPM_READ); if (error) break; error = ncp_conn_gethandle(conn, td, &hp); ncp_conn_unlock(conn, td); if (error) break; *(int*)data = hp->nh_id; break; case NWFSIOC_GETEINFO: if ((error = VOP_EACCESS(vp, VEXEC, cred))) break; fap = data; error = ncp_obtain_info(nmp, np->n_fid.f_id, 0, NULL, fap, td, ap->a_cred); strcpy(fap->entryName, np->n_name); fap->nameLen = np->n_nmlen; break; case NWFSIOC_GETNS: if ((error = VOP_EACCESS(vp, VEXEC, cred))) break; *(int*)data = nmp->name_space; break; default: error = EINVAL; } return (error); }
static int __P(sncp_connect(struct proc *p, struct sncp_connect_args *uap)){ int connHandle = 0, error; struct ncp_conn *conn; struct ncp_handle *handle; struct ncp_conn_args li; checkbad(copyin(uap->li,&li,sizeof(li))); checkbad(copyout(&connHandle,uap->connHandle,sizeof(connHandle))); /* check before */ li.password = li.user = NULL; error = ncp_conn_getattached(&li, p, p->p_ucred, NCPM_WRITE | NCPM_EXECUTE, &conn); if (error) { error = ncp_connect(&li, p, p->p_ucred, &conn); } if (!error) { error = ncp_conn_gethandle(conn, p, &handle); copyout(&handle->nh_id, uap->connHandle, sizeof(uap->connHandle)); ncp_conn_unlock(conn,p); } bad: p->p_retval[0]=error; return error; }
int ncp_request(struct ncp_rq *rqp) { struct ncp_conn *ncp = rqp->nr_conn; int error, rcnt; error = ncp_conn_lock(ncp, rqp->nr_td, rqp->nr_cred, NCPM_EXECUTE); if (error) goto out; rcnt = NCP_RESTORE_COUNT; for(;;) { if (ncp->flags & NCPFL_ATTACHED) { error = ncp_request_int(rqp); if (ncp->flags & NCPFL_ATTACHED) break; } if (rcnt-- == 0) { error = ECONNRESET; break; } /* * Do not attempt to restore connection recursively */ if (ncp->flags & NCPFL_RESTORING) { error = ENOTCONN; break; } error = ncp_restore_login(ncp); if (error) continue; } ncp_conn_unlock(ncp, rqp->nr_td); out: if (error && (rqp->nr_flags & NCPR_DONTFREEONERR) == 0) ncp_rq_done(rqp); 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; }
/* * 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; }
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; }