Example #1
0
/* Checks the checksum of the modbus message given by *buff 
 * length should be the length of the modbus data buffer INCLUDING the
 * two byte checksum.  Returns 1 if checksum matches */
int
crc16check(u_int8_t *buff, int length)
{
    u_int16_t crcLocal, crcRemote;
    if(length < 2) return 0; /* Otherwise a bad pointer will go to crc16 */
    crcLocal = crc16(buff, length-2);
    COPYWORD(&crcRemote, &buff[length-2]);
    if(crcLocal == crcRemote) return 1;
    else return 0;
};
Example #2
0
/*
**  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.
*/
int
SendReadRepl(RMPCONN *rconn)
{
	int retval = 0;
	RMPCONN *oldconn;
	struct rmp_packet *rpl, *req;
	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 (ntohs(req->r_rrq.rmp_session) !=
	    ((rpl->r_type == RMP_BOOT_REPL)? ntohs(rpl->r_brpl.rmp_session):
	                                     ntohs(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 (ntohs(req->r_rrq.rmp_size) > RMPREADDATA)
		req->r_rrq.rmp_size = htons(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, SEEK_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) ntohs(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);
}
Example #3
0
/*
**  SendBootRepl -- open boot file and respond to boot request.
**
**	Parameters:
**		req - RMP BOOT packet containing the request.
**		rconn - the reply packet to be formatted.
**		filelist - list of files available to the requester.
**
**	Returns:
**		1 on success, 0 on failure.
**
**	Side Effects:
**		none.
*/
int
SendBootRepl(struct rmp_packet *req, RMPCONN *rconn, char *filelist[])
{
	int retval;
	char *filename, filepath[RMPBOOTDATA+1];
	RMPCONN *oldconn;
	struct rmp_packet *rpl;
	char *src, *dst1, *dst2;
	u_int8_t 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 = htons(GenSessID());
	rpl->r_brpl.rmp_version = htons(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 = strrchr(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));
}