예제 #1
0
/* 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);
}
예제 #2
0
/*
 * 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;
}
예제 #3
0
/*
 * 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;
}
예제 #4
0
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;
}