⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfs_socket.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			mlen = hsiz;			/*		 * Loop through the mbuf list consolidating data.		 */		while (m) {			while (olen > 0) {				if (mlen == 0) {					m2->m_flags &= ~M_PKTHDR;					if (m2->m_flags & M_EXT)						m2->m_data = m2->m_ext.ext_buf;					else						m2->m_data = m2->m_dat;					m2->m_len = 0;					mlen = M_TRAILINGSPACE(m2);					tcp = mtod(m2, caddr_t);					mnew = m2;					m2 = m2->m_next;				}				siz = min(mlen, olen);				if (tcp != fcp)					bcopy(fcp, tcp, siz);				mnew->m_len += siz;				mlen -= siz;				olen -= siz;				tcp += siz;				fcp += siz;			}			m = m->m_next;			if (m) {				olen = m->m_len;				fcp = mtod(m, caddr_t);			}		}			/*		 * Finally, set m_len == 0 for any trailing mbufs that have		 * been copied out of.		 */		while (m2) {			m2->m_len = 0;			m2 = m2->m_next;		}		return;	    }	    m = m->m_next;	}}/* * Socket upcall routine for the nfsd sockets. * The caddr_t arg is a pointer to the "struct nfssvc_sock". * Essentially do as much as possible non-blocking, else punt and it will * be called with M_WAIT from an nfsd. */voidnfsrv_rcv(so, arg, waitflag)	struct socket *so;	caddr_t arg;	int waitflag;{	register struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;	register struct mbuf *m;	struct mbuf *mp, *nam;	struct uio auio;	int flags, error;	if ((slp->ns_flag & SLP_VALID) == 0)		return;#ifdef notdef	/*	 * Define this to test for nfsds handling this under heavy load.	 */	if (waitflag == M_DONTWAIT) {		slp->ns_flag |= SLP_NEEDQ; goto dorecs;	}#endif	auio.uio_procp = NULL;	if (so->so_type == SOCK_STREAM) {		/*		 * If there are already records on the queue, defer soreceive()		 * to an nfsd so that there is feedback to the TCP layer that		 * the nfs servers are heavily loaded.		 */		if (slp->ns_rec && waitflag == M_DONTWAIT) {			slp->ns_flag |= SLP_NEEDQ;			goto dorecs;		}		/*		 * Do soreceive().		 */		auio.uio_resid = 1000000000;		flags = MSG_DONTWAIT;		error = soreceive(so, &nam, &auio, &mp, (struct mbuf **)0, &flags);		if (error || mp == (struct mbuf *)0) {			if (error == EWOULDBLOCK)				slp->ns_flag |= SLP_NEEDQ;			else				slp->ns_flag |= SLP_DISCONN;			goto dorecs;		}		m = mp;		if (slp->ns_rawend) {			slp->ns_rawend->m_next = m;			slp->ns_cc += 1000000000 - auio.uio_resid;		} else {			slp->ns_raw = m;			slp->ns_cc = 1000000000 - auio.uio_resid;		}		while (m->m_next)			m = m->m_next;		slp->ns_rawend = m;		/*		 * Now try and parse record(s) out of the raw stream data.		 */		if (error = nfsrv_getstream(slp, waitflag)) {			if (error == EPERM)				slp->ns_flag |= SLP_DISCONN;			else				slp->ns_flag |= SLP_NEEDQ;		}	} else {		do {			auio.uio_resid = 1000000000;			flags = MSG_DONTWAIT;			error = soreceive(so, &nam, &auio, &mp,						(struct mbuf **)0, &flags);			if (mp) {				nfs_realign(mp, 10 * NFSX_UNSIGNED);				if (nam) {					m = nam;					m->m_next = mp;				} else					m = mp;				if (slp->ns_recend)					slp->ns_recend->m_nextpkt = m;				else					slp->ns_rec = m;				slp->ns_recend = m;				m->m_nextpkt = (struct mbuf *)0;			}			if (error) {				if ((so->so_proto->pr_flags & PR_CONNREQUIRED)					&& error != EWOULDBLOCK) {					slp->ns_flag |= SLP_DISCONN;					goto dorecs;				}			}		} while (mp);	}	/*	 * Now try and process the request records, non-blocking.	 */dorecs:	if (waitflag == M_DONTWAIT &&		(slp->ns_rec || (slp->ns_flag & (SLP_NEEDQ | SLP_DISCONN))))		nfsrv_wakenfsd(slp);}/* * Try and extract an RPC request from the mbuf data list received on a * stream socket. The "waitflag" argument indicates whether or not it * can sleep. */nfsrv_getstream(slp, waitflag)	register struct nfssvc_sock *slp;	int waitflag;{	register struct mbuf *m;	register char *cp1, *cp2;	register int len;	struct mbuf *om, *m2, *recm;	u_long recmark;	if (slp->ns_flag & SLP_GETSTREAM)		panic("nfs getstream");	slp->ns_flag |= SLP_GETSTREAM;	for (;;) {	    if (slp->ns_reclen == 0) {		if (slp->ns_cc < NFSX_UNSIGNED) {			slp->ns_flag &= ~SLP_GETSTREAM;			return (0);		}		m = slp->ns_raw;		if (m->m_len >= NFSX_UNSIGNED) {			bcopy(mtod(m, caddr_t), (caddr_t)&recmark, NFSX_UNSIGNED);			m->m_data += NFSX_UNSIGNED;			m->m_len -= NFSX_UNSIGNED;		} else {			cp1 = (caddr_t)&recmark;			cp2 = mtod(m, caddr_t);			while (cp1 < ((caddr_t)&recmark) + NFSX_UNSIGNED) {				while (m->m_len == 0) {					m = m->m_next;					cp2 = mtod(m, caddr_t);				}				*cp1++ = *cp2++;				m->m_data++;				m->m_len--;			}		}		slp->ns_cc -= NFSX_UNSIGNED;		slp->ns_reclen = ntohl(recmark) & ~0x80000000;		if (slp->ns_reclen < NFS_MINPACKET || slp->ns_reclen > NFS_MAXPACKET) {			slp->ns_flag &= ~SLP_GETSTREAM;			return (EPERM);		}	    }	    /*	     * Now get the record part.	     */	    if (slp->ns_cc == slp->ns_reclen) {		recm = slp->ns_raw;		slp->ns_raw = slp->ns_rawend = (struct mbuf *)0;		slp->ns_cc = slp->ns_reclen = 0;	    } else if (slp->ns_cc > slp->ns_reclen) {		len = 0;		m = slp->ns_raw;		om = (struct mbuf *)0;		while (len < slp->ns_reclen) {			if ((len + m->m_len) > slp->ns_reclen) {				m2 = m_copym(m, 0, slp->ns_reclen - len,					waitflag);				if (m2) {					if (om) {						om->m_next = m2;						recm = slp->ns_raw;					} else						recm = m2;					m->m_data += slp->ns_reclen - len;					m->m_len -= slp->ns_reclen - len;					len = slp->ns_reclen;				} else {					slp->ns_flag &= ~SLP_GETSTREAM;					return (EWOULDBLOCK);				}			} else if ((len + m->m_len) == slp->ns_reclen) {				om = m;				len += m->m_len;				m = m->m_next;				recm = slp->ns_raw;				om->m_next = (struct mbuf *)0;			} else {				om = m;				len += m->m_len;				m = m->m_next;			}		}		slp->ns_raw = m;		slp->ns_cc -= len;		slp->ns_reclen = 0;	    } else {		slp->ns_flag &= ~SLP_GETSTREAM;		return (0);	    }	    nfs_realign(recm, 10 * NFSX_UNSIGNED);	    if (slp->ns_recend)		slp->ns_recend->m_nextpkt = recm;	    else		slp->ns_rec = recm;	    slp->ns_recend = recm;	}}/* * Parse an RPC header. */nfsrv_dorec(slp, nd)	register struct nfssvc_sock *slp;	register struct nfsd *nd;{	register struct mbuf *m;	int error;	if ((slp->ns_flag & SLP_VALID) == 0 ||	    (m = slp->ns_rec) == (struct mbuf *)0)		return (ENOBUFS);	if (slp->ns_rec = m->m_nextpkt)		m->m_nextpkt = (struct mbuf *)0;	else		slp->ns_recend = (struct mbuf *)0;	if (m->m_type == MT_SONAME) {		nd->nd_nam = m;		nd->nd_md = nd->nd_mrep = m->m_next;		m->m_next = (struct mbuf *)0;	} else {		nd->nd_nam = (struct mbuf *)0;		nd->nd_md = nd->nd_mrep = m;	}	nd->nd_dpos = mtod(nd->nd_md, caddr_t);	if (error = nfs_getreq(nd, TRUE)) {		m_freem(nd->nd_nam);		return (error);	}	return (0);}/* * Parse an RPC request * - verify it * - fill in the cred struct. */nfs_getreq(nd, has_header)	register struct nfsd *nd;	int has_header;{	register int len, i;	register u_long *tl;	register long t1;	struct uio uio;	struct iovec iov;	caddr_t dpos, cp2;	u_long nfsvers, auth_type;	int error = 0, nqnfs = 0;	struct mbuf *mrep, *md;	mrep = nd->nd_mrep;	md = nd->nd_md;	dpos = nd->nd_dpos;	if (has_header) {		nfsm_dissect(tl, u_long *, 10*NFSX_UNSIGNED);		nd->nd_retxid = *tl++;		if (*tl++ != rpc_call) {			m_freem(mrep);			return (EBADRPC);		}	} else {		nfsm_dissect(tl, u_long *, 8*NFSX_UNSIGNED);	}	nd->nd_repstat = 0;	if (*tl++ != rpc_vers) {		nd->nd_repstat = ERPCMISMATCH;		nd->nd_procnum = NFSPROC_NOOP;		return (0);	}	nfsvers = nfs_vers;	if (*tl != nfs_prog) {		if (*tl == nqnfs_prog) {			nqnfs++;			nfsvers = nqnfs_vers;		} else {			nd->nd_repstat = EPROGUNAVAIL;			nd->nd_procnum = NFSPROC_NOOP;			return (0);		}	}	tl++;	if (*tl++ != nfsvers) {		nd->nd_repstat = EPROGMISMATCH;		nd->nd_procnum = NFSPROC_NOOP;		return (0);	}	nd->nd_procnum = fxdr_unsigned(u_long, *tl++);	if (nd->nd_procnum == NFSPROC_NULL)		return (0);	if (nd->nd_procnum >= NFS_NPROCS ||		(!nqnfs && nd->nd_procnum > NFSPROC_STATFS) ||		(*tl != rpc_auth_unix && *tl != rpc_auth_kerb)) {		nd->nd_repstat = EPROCUNAVAIL;		nd->nd_procnum = NFSPROC_NOOP;		return (0);	}	auth_type = *tl++;	len = fxdr_unsigned(int, *tl++);	if (len < 0 || len > RPCAUTH_MAXSIZ) {		m_freem(mrep);		return (EBADRPC);	}	/*	 * Handle auth_unix or auth_kerb.	 */	if (auth_type == rpc_auth_unix) {		len = fxdr_unsigned(int, *++tl);		if (len < 0 || len > NFS_MAXNAMLEN) {			m_freem(mrep);			return (EBADRPC);		}		nfsm_adv(nfsm_rndup(len));		nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);		nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);		nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);		len = fxdr_unsigned(int, *tl);		if (len < 0 || len > RPCAUTH_UNIXGIDS) {			m_freem(mrep);			return (EBADRPC);		}		nfsm_dissect(tl, u_long *, (len + 2)*NFSX_UNSIGNED);		for (i = 1; i <= len; i++)			if (i < NGROUPS)				nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);			else				tl++;		nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);	} else if (auth_type == rpc_auth_kerb) {		nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);		nd->nd_authlen = fxdr_unsigned(int, *tl);		uio.uio_resid = nfsm_rndup(nd->nd_authlen);		if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {			m_freem(mrep);			return (EBADRPC);		}		uio.uio_offset = 0;		uio.uio_iov = &iov;		uio.uio_iovcnt = 1;		uio.uio_segflg = UIO_SYSSPACE;		iov.iov_base = (caddr_t)nd->nd_authstr;		iov.iov_len = RPCAUTH_MAXSIZ;		nfsm_mtouio(&uio, uio.uio_resid);		nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);		nd->nd_flag |= NFSD_NEEDAUTH;	}	/*	 * Do we have any use for the verifier.	 * According to the "Remote Procedure Call Protocol Spec." it	 * should be AUTH_NULL, but some clients make it AUTH_UNIX?	 * For now, just skip over it	 */	len = fxdr_unsigned(int, *++tl);	if (len < 0 || len > RPCAUTH_MAXSIZ) {		m_freem(mrep);		return (EBADRPC);	}	if (len > 0) {		nfsm_adv(nfsm_rndup(len));	}	/*	 * For nqnfs, get piggybacked lease request.	 */	if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);		nd->nd_nqlflag = fxdr_unsigned(int, *tl);		if (nd->nd_nqlflag) {			nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);			nd->nd_duration = fxdr_unsigned(int, *tl);		} else			nd->nd_duration = NQ_MINLEASE;	} else {		nd->nd_nqlflag = NQL_NOVAL;		nd->nd_duration = NQ_MINLEASE;	}	nd->nd_md = md;	nd->nd_dpos = dpos;	return (0);nfsmout:	return (error);}/* * Search for a sleeping nfsd and wake it up. * SIDE EFFECT: If none found, set NFSD_CHECKSLP flag, so that one of the * running nfsds will go look for the work in the nfssvc_sock list. */voidnfsrv_wakenfsd(slp)	struct nfssvc_sock *slp;{	register struct nfsd *nd = nfsd_head.nd_next;	if ((slp->ns_flag & SLP_VALID) == 0)		return;	while (nd != (struct nfsd *)&nfsd_head) {		if (nd->nd_flag & NFSD_WAITING) {			nd->nd_flag &= ~NFSD_WAITING;			if (nd->nd_slp)				panic("nfsd wakeup");			slp->ns_sref++;			nd->nd_slp = slp;			wakeup((caddr_t)nd);			return;		}		nd = nd->nd_next;	}	slp->ns_flag |= SLP_DOREC;	nfsd_head.nd_flag |= NFSD_CHECKSLP;}nfs_msg(p, server, msg)	struct proc *p;	char *server, *msg;{	tpr_t tpr;	if (p)		tpr = tprintf_open(p);	else		tpr = NULL;	tprintf(tpr, "nfs server %s: %s\n", server, msg);	tprintf_close(tpr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -