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

📄 rmpproto.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	register char *src, *dst1, *dst2;	register u_char i;	/*	 *  If another connection already exists, delete it since we	 *  are obviously starting again.	 */	if ((oldconn = FindConn(rconn)) != NULL) {		syslog(LOG_WARNING, "%s: dropping existing connection",		       EnetStr(oldconn));		RemoveConn(oldconn);	}	rpl = &rconn->rmp;			/* cache ptr to RMP packet */	/*	 *  Set up assorted fields in reply packet.	 */	rpl->r_brpl.rmp_type = RMP_BOOT_REPL;	COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno);	rpl->r_brpl.rmp_session = GenSessID();	rpl->r_brpl.rmp_version = RMP_VERSION;	rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize;	/*	 *  Copy file name to `filepath' string, and into reply packet.	 */	src = &req->r_brq.rmp_flnm;	dst1 = filepath;	dst2 = &rpl->r_brpl.rmp_flnm;	for (i = 0; i < req->r_brq.rmp_flnmsize; i++)		*dst1++ = *dst2++ = *src++;	*dst1 = '\0';	/*	 *  If we are booting HP-UX machines, their secondary loader will	 *  ask for files like "/hp-ux".  As a security measure, we do not	 *  allow boot files to lay outside the boot directory (unless they	 *  are purposely link'd out.  So, make `filename' become the path-	 *  stripped file name and spoof the client into thinking that it	 *  really got what it wanted.	 */	filename = (filename = rindex(filepath,'/'))? ++filename: filepath;	/*	 *  Check that this is a valid boot file name.	 */	for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++)		if (STREQN(filename, filelist[i]))			goto match;	/*	 *  Invalid boot file name, set error and send reply packet.	 */	rpl->r_brpl.rmp_retcode = RMP_E_NOFILE;	retval = 0;	goto sendpkt;match:	/*	 *  This is a valid boot file.  Open the file and save the file	 *  descriptor associated with this connection and set success	 *  indication.  If the file couldnt be opened, set error:	 *  	"no such file or dir" - RMP_E_NOFILE	 *	"file table overflow" - RMP_E_BUSY	 *	"too many open files" - RMP_E_BUSY	 *	anything else         - RMP_E_OPENFILE	 */	if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) {		rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE:			(errno == EMFILE || errno == ENFILE)? RMP_E_BUSY:			RMP_E_OPENFILE;		retval = 0;	} else {		rpl->r_brpl.rmp_retcode = RMP_E_OKAY;		retval = 1;	}sendpkt:	syslog(LOG_INFO, "%s: request to boot %s (%s)",	       EnetStr(rconn), filename, retval? "granted": "denied");	rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize);	return (retval & SendPacket(rconn));}/***  SendReadRepl -- send a portion of the boot file to the requester.****	Parameters:**		rconn - the reply packet to be formatted.****	Returns:**		1 on success, 0 on failure.****	Side Effects:**		none.*/intSendReadRepl(rconn)	RMPCONN *rconn;{	int retval;	RMPCONN *oldconn;	register struct rmp_packet *rpl, *req;	register int size = 0;	int madeconn = 0;	/*	 *  Find the old connection.  If one doesnt exist, create one only	 *  to return the error code.	 */	if ((oldconn = FindConn(rconn)) == NULL) {		if ((oldconn = NewConn(rconn)) == NULL)			return(0);		syslog(LOG_ERR, "SendReadRepl: no active connection (%s)",		       EnetStr(rconn));		madeconn++;	}	req = &rconn->rmp;		/* cache ptr to request packet */	rpl = &oldconn->rmp;		/* cache ptr to reply packet */	if (madeconn) {			/* no active connection above; abort */		rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;		retval = 1;		goto sendpkt;	}	/*	 *  Make sure Session ID's match.	 */	if (req->r_rrq.rmp_session !=	    ((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session:	                                    rpl->r_rrpl.rmp_session)) {		syslog(LOG_ERR, "SendReadRepl: bad session id (%s)",		       EnetStr(rconn));		rpl->r_rrpl.rmp_retcode = RMP_E_BADSID;		retval = 1;		goto sendpkt;	}	/*	 *  If the requester asks for more data than we can fit,	 *  silently clamp the request size down to RMPREADDATA.	 *	 *  N.B. I do not know if this is "legal", however it seems	 *  to work.  This is necessary for bpfwrite() on machines	 *  with MCLBYTES less than 1514.	 */	if (req->r_rrq.rmp_size > RMPREADDATA)		req->r_rrq.rmp_size = RMPREADDATA;	/*	 *  Position read head on file according to info in request packet.	 */	GETWORD(req->r_rrq.rmp_offset, size);	if (lseek(oldconn->bootfd, (off_t)size, L_SET) < 0) {		syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)",		       EnetStr(rconn));		rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;		retval = 1;		goto sendpkt;	}	/*	 *  Read data directly into reply packet.	 */	if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data,	                 (int) req->r_rrq.rmp_size)) <= 0) {		if (size < 0) {			syslog(LOG_ERR, "SendReadRepl: read: %m (%s)",			       EnetStr(rconn));			rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;		} else {			rpl->r_rrpl.rmp_retcode = RMP_E_EOF;		}		retval = 1;		goto sendpkt;	}	/*	 *  Set success indication.	 */	rpl->r_rrpl.rmp_retcode = RMP_E_OKAY;sendpkt:	/*	 *  Set up assorted fields in reply packet.	 */	rpl->r_rrpl.rmp_type = RMP_READ_REPL;	COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset);	rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session;	oldconn->rmplen = RMPREADSIZE(size);	/* set size of packet */	retval &= SendPacket(oldconn);		/* send packet */	if (madeconn)				/* clean up after ourself */		FreeConn(oldconn);	return (retval);}/***  BootDone -- free up memory allocated for a connection.****	Parameters:**		rconn - incoming boot complete packet.****	Returns:**		1 on success, 0 on failure.****	Side Effects:**		none.*/intBootDone(rconn)	RMPCONN *rconn;{	RMPCONN *oldconn;	struct rmp_packet *rpl;	/*	 *  If we cant find the connection, ignore the request.	 */	if ((oldconn = FindConn(rconn)) == NULL) {		syslog(LOG_ERR, "BootDone: no existing connection (%s)",		       EnetStr(rconn));		return(0);	}	rpl = &oldconn->rmp;			/* cache ptr to RMP packet */	/*	 *  Make sure Session ID's match.	 */	if (rconn->rmp.r_rrq.rmp_session !=	    ((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session:	                                    rpl->r_rrpl.rmp_session)) {		syslog(LOG_ERR, "BootDone: bad session id (%s)",		       EnetStr(rconn));		return(0);	}	RemoveConn(oldconn);			/* remove connection */	syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn));	return(1);}/***  SendPacket -- send an RMP packet to a remote host.****	Parameters:**		rconn - packet to be sent.****	Returns:**		1 on success, 0 on failure.****	Side Effects:**		none.*/intSendPacket(rconn)	register RMPCONN *rconn;{	/*	 *  Set Ethernet Destination address to Source (BPF and the enet	 *  driver will take care of getting our source address set).	 */	bcopy((char *)&rconn->rmp.hp_hdr.saddr[0],	      (char *)&rconn->rmp.hp_hdr.daddr[0], RMP_ADDRLEN);	rconn->rmp.hp_hdr.len = rconn->rmplen - sizeof(struct hp_hdr);	/*	 *  Reverse 802.2/HP Extended Source & Destination Access Pts.	 */	rconn->rmp.hp_llc.dxsap = HPEXT_SXSAP;	rconn->rmp.hp_llc.sxsap = HPEXT_DXSAP;	/*	 *  Last time this connection was active.	 */	(void) gettimeofday(&rconn->tstamp, (struct timezone *)0);	if (DbgFp != NULL)			/* display packet */		DispPkt(rconn,DIR_SENT);	/*	 *  Send RMP packet to remote host.	 */	return(BpfWrite(rconn));}

⌨️ 快捷键说明

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