SRI-NOSC/ncpd/send_pro.c

Compare this file to the similar file:
Show the results in this format:

#

/*	send_pro.c	*/

/*	globals declared in this file:
		x_retries
		rst_buf

	functions declared in this file:
		mak_ldr
		send_pro
		rst_all
		chk_host
		qup_pro
		hw_s2b
		hw_rfc
		hw_cls
		hw_all
		hw_err
		hw_dwn
		pr_flush
*/

#include	"files.h"
#include	"hstlnk.h"
#include	"kwrite.h"
#include	"globvar.h"
#include	"probuf.h"
#include	"hhi.h"
#include	"leader.h"
#include	"kread.h"
#include	"socket.h"
#include	"io_buf.h"

/* SCCS PROGRAM IDENTIFICATION STRING */
char id_send_pro[] "~|^`send_pro.c\tV4.0E1\t7Jul78\n";

int	x_retries	1;	/* number of retries on protocol xmission */


/*name:
	mak_ldr

function:
	constructs the common protions of the kernel, im, and host leaders
	for a "send" write to the kernel.

algorithm:
	clears all the leader bytes to zero.
	fills in kernel opcode, host, and byte size.

parameters:
	none.

returns:
	nothing.

globals:
	kw_buf=
	host

calls:
	nothing.

called by:
	send_pro
	rst_all
	fi_ssn

history:
	initial coding 12/09/74 by G. R. Grossman.

*/

mak_ldr()
{
	register char	*byte_p;	/* used in clearing all leader bytes */

	for(	byte_p= &kw_buf;	/* clear leader bytes to zero */
		byte_p != kw_buf.kw_data->l_data;
		*byte_p++ = 0
	   );

	kw_buf.kw_op = kwi_send;	/* kernel write opcode */
	kw_buf.kw_data->l_host = host;	/* imp leader host field */
	kw_buf.kw_data->l_bysz = 8;	/* host leader byte size field */
}

/*name:
	send_pro

function:
	if appropriate, accumulates up to 120 bytes of integral host_host
	protocol commands and sends them via the kernel "send" write
	instruction, setting appropriate flags and counters.

algorithm:
	if there is a rfnm outstanding for the current host, return.
	set up leader via mak_ldr.
	copy the minimum of: (120) (number of bytes of available integral
	host-host command bytes) from probuf's in host's h_pb_q into
	kw_buf, incrementing h_pb_sent[host] for each probuf copied.
	set byte count in host leader.
	if host's h_pb_rtry = 0, set to x_retries.
	write kw_buf to the kernel.
	set host's rfnm bit in rfnm_bm.

parameters:
	none.

returns:
	nothing.

globals:
	h_pb_sent=
	h_pb_q
	h_pb_rtry=
	rfnm_bm=
	pro2send=
	host
	kw_buf=
	x_retries

calls:
	mak_ldr
	kw_write
	set_bit
	log_time
	printf

called by:
	main
	chk_host

history:
	initial coding 12/10/74 by G. R. Grossman.
	modified to check for something in proto queue and reset
	pro2send  S. F. Holmgren 1/20/76

*/

send_pro()
{
	register char	*byte_p,	/* for copying into kw_buf */
			*pb_bp;		/* for copying out of probufs */
	register int	n;		/* count for copying out of
					   probufs */
	int		byte_cnt;	/* counts down total bytes copied
					   from 120 */
	struct probuf	*pb_p,		/* for running thru host's probuf
					   queue */
			*stop;		/* stopper for above */


	/* check rfnm bit, return if set */
	if ( bit_on(&rfnm_bm[0],host) )		/* rfnm outstanding for host? */
		return;

	/* set up leader and initialize pointers */
	mak_ldr();
	byte_cnt = 120;		/* maximun bytes of integral commands we
				   may send */
	byte_p = kw_buf.kw_data->l_data;	/* point at data field in
						   buffer */
	if( h_pb_q[host] == 0 )
	{
		log_time();
		printf("Send_proto and no proto to send to host :%d\n",host);
		return;
	}
	pb_p = stop = h_pb_q[host]->pb_link; /* point at 1st probuf in
						hosts's q */

	/* main loop: copy probufs into kw_buf */
	do
	{
		if ( (byte_cnt =- pb_p->pb_count) >= 0) /* can we send this
							   probuf? */
		{
			pb_bp = pb_p->pb_text;	/* point at text in probuf */
			n = pb_p->pb_count;	/* byte count for copy */
			if( n <= 0 )
			{
				log_err("send_pro: probuf with zero count \n");
				return;
			}
			do	/* copy loop */
			{
				*byte_p++ = *pb_bp++;	/* copy a byte */
			}
			while (--n);	/* do it (byte count) times */
			h_pb_sent[host]++;	/* inc probufs sent count */
		}	/* end of probuf ok branch */
		else	/* otherwise quit */
			break;
	}
	while ( (pb_p = pb_p->pb_link) != stop );	/* loop til back
							   at beginning
							   of probuf q */

	/* finish leader */
	kw_buf.kw_data->l_bycnt = swab(byte_p - kw_buf.kw_data->l_data);
		/* host byte count is end of data - beginning of data */

	/* set retry count if appropriate */
	if ( h_pb_rtry[host] == 0 )	/* retries zero means they haven't been
					   set */
		h_pb_rtry[host] = x_retries;	/* so set them */

	/* write buffer to kernel */
	kw_write(byte_p - &kw_buf.lo_byte);

	/* set rfnm bit */
	set_bit(&rfnm_bm[0],host);
	/* reset pro2send */
	pro2send = 0;

}

/*name:
	rst_all

function:
	sends host-host resets to all possible (or only known) hosts 
	on the network.

algorithm:
	if there is protocol to send for the current host, sent it,
		cause we're going to change the host number
	if init_host zero
		if compile option RSTKNOWN is set
			open and scan the host name file, setting the
			known bit for each host we find
		else
			set the known bit for all hosts.

	do:
		find the next host; return if there are no more
		if there is protocol to send, send it so that
			it isn't forgotten when we change host number.
	while chk_host does not reset this new host;
parameters:
	none.

returns:
	nothing.

globals:
	init_host=
	host=

calls:
	chk_host
	fopen	(lib)
	getl	(lib)
	bit_on
	set_bit
	log_asc

called by:
	ir_reset
	ir_rfnm
	ir_re_x

history:
	initial coding 12/10/74 by G. R. Grossman.
	modifications for shutting off debugging and logging 1/9/75
	by G. R. Grossman.
	modified to send prior protocol by Greg Noel on 8/31/77
	modified to scan /usr/net/hnames file for known hosts (under
		compiletime switch) 25Jan78 by J.S.Goldberg at ill-nts
	modified to clean code and prevent the clobbering of the global host
	from causing the daemon to forget about queued up protocol.
		1978/Jul/14 R. Balocca and B. Greiner


notes:
	when the compiletime switch RSTKNOWN is defined, rst_all will
	scan the list of host names (/usr/net/hnames) and set a bit map
	if hosts that are known according to that scan.  otherwise, the
	bitmap is completely filled with ones, to force reset attempts 
	on all hosts.  if the open of the file fails, all hosts are
	assumed to be known (e.g. the map is filled with ones).

*/

	/* if RSTKNOWN is defined, only those hosts that are listed	*/
	/* in /usr/net/hnames will get a reset sent to them.		*/
	/* else, all hosts get one.					*/
#define RSTKNOWN	on

#define NUMHOSTS 256			/* move to probuf.h */
#ifdef RSTKNOWN
rst_all() {
    register
    char   *cp				/* ptr for hnames parsing	 */
           ;
    register
    int     h				/* for host number, and countr	 */
           ;
    struct io_buf   fbuf[1];
    char    line[100]			/* generous line buffer		 */
           ;
    static char h_kno_bm[NUMHOSTS / 8]      /* map of known hosts		 */
               ;			/* N.B.	could be external if other	 */
					/* routines have need of the bitmap	 */


    if (init_host == 0) {		/* assumes initial value of 0	 */
	if (fopen("/usr/net/hnames", fbuf) < 0) {
	    log_asc("rst_all: can't open /usr/net/hnames");
	    for (h = 0; h < NUMHOSTS / 8; h_kno_bm[h++] = 0377);
	}
	else {
	    for (h = 0; h < NUMHOSTS / 8; h_kno_bm[h++] = 0);
	    while ((h = getl(line, fbuf)) > 0) {
		line[h] = '\0';
		cp = line;
					/* skip hostname, till get white space	 */
		while (*cp != ' ' && *cp != '\t' && *cp)
		    cp++;
		if (*cp == '\0') {      /* paranoid of editable files	 */
		    log_asc("rst_all: bad line in hnames, viz:");
		    log_asc(line);
		    continue;
		}
		if ((h = atoi(cp)) & ~0377) {
					/* host num too big		 */
		    log_asc("rst_all: bad host# in hnames, viz:");
		    log_asc(line);
		    continue;
		}
		set_bit(h_kno_bm, h);
	    }
	    close(fbuf -> fid);
	}
    }					/* endof if( init_host == 0 )				 */
					/* look for next host, while the host number is legal		 */
    for (; ++init_host < NUMHOSTS;) {
	if (bit_on(h_kno_bm, init_host)) {
	    if (pro2send)
		send_pro();		/* send any queued protocol */
	    host = (init_host & 0377);  /* set host this host */
	    if (!chk_host())		/* host down? */
		return;
	}
    }
}
#endif
#ifndef RSTKNOWN
rst_all() {

 /* look for next host, while the host number is legal		 */
    for (; ++init_host < NUMHOSTS;) {
	if (pro2send)
	    send_pro();			/* send any queued protocol */
	host = (init_host & 0377);      /* set host this host */
	if (!chk_host())		/* host down? */
	    return;
    }
}
#endif

/*name:
	chk_host

function:
	checks if host is marked as up or if we are awaiting rfnm from host
	and, if neither is the case, sends a reset to the host.

algorithm:
	save result of or'ing results of examining the host's up and rfnm
	bits; if = 0:
              send rst via qup_pro
	return result.

parameters:
	none.

returns:
	0	if it sends a reset to the host.
	!=0	otherwise.

globals:
	host
	h_up_bm
	rfnm_bm

calls:
	bit_on
	qup_pro
	send_pro

called by:
	kr_odrct
	rst_all
	kr_ouicp

history:
	initial coding 1/17/75 by G. R. Grossman

*/

char	rst_buf[]{hhi_rst};	/* buffer containing a host-host rst */

chk_host()
{
	register int	h;		/* will hold host number */
	register int	res;		/* holds result of test for return */

	h = host;
	if ( (res = (bit_on(&h_up_bm[0],h) | bit_on(&rfnm_bm[0],h))) == 0 )
		/* neither up nor awaiting rfnm? */
	{
		qup_pro(&rst_buf[0],1);		/* send rst */
  send_pro();
	}
	return(res);				/* tell caller what we did */
}

/*name:
	qup_pro

function:
	queues up host-host protocol for sending.

algorithm:
	an attempt is made to get a probuf from pb_fr_q via q_dlink;
	if this fails:
		allocate a new probuf via alloc.
		increment n_pb, which counts the existing probufs.
	set count in probuf to the size of the command.
	copy the command into the probuf.
	enter the probuf in the host's h_pb_q via q_enter.
	set pro2send to cause transmission at end of current major cycle.

parameters:
	cmd_p	pointer to char[] containing the command.
	n	size of command in bytes.

returns:
	nothing.

globals:
	pb_fr_q=
	n_pb=
	pb_size
	h_pb_q=
	host

calls:
	q_dlink
	q_enter
	alloc	(sys)

called by:
	hw_rfc
	hw_cls
	hw_all
	hw_err
	hr_rfc
	hr_eco
	hr_rst

history:
	initial coding 12/29/74 by G. R. Grossman

*/

qup_pro(cmd_p,n)
char	*cmd_p;
int	n;
{
	register struct probuf	*pb_p;	/* will point to the probuf we use */
	register char	*sbp,		/* source pointer for copying cmd */
			*dbp;		/* dest      "     "     "     "  */

	if ( (pb_p = q_dlink(&pb_fr_q)) == 0 )	/* fail to get probuf? */
	{
		pb_p = alloc(pb_size);	/* get a new one */
		++n_pb;			/* increment informational counter */
	}
	pb_p->pb_count = n;		/* set byte count in probuf */
	dbp = &pb_p->pb_text[0];	/* destination for copy is text
					   field of probuf */
	for ( sbp = cmd_p;		/* source is command */
	      n > 0;			/* loop for n bytes */
	      n--	)
		*dbp++ = *sbp++;	/* copy a byte */
	q_enter(&h_pb_q[host],pb_p);	/* enter probuf in host's probuf q */
	pro2send = 1;			/* set send flag */
}

/*name:
	hw_s2b

function:
	copies socket numbers from socket struct to hw_buf for hw_rfc
	and hw_cls.

algorithm:
	the source byte pointer is pointed at the local socket field in
	the socket struct.
	the destination byte pointer is pointed at the 2nd byte of hw_buf.
	two zero bytes are put in the destination to serve as the first
	two bytes of the local socket.
	the local and foreign sockets are copied from the socket struct.

parameters:
	skt_p	pointer to the socket struct containing the socket
		numbers to be copied.

returns:
	nothing.

globals:
	hw_buf=

calls:
	nothing.

called by:
	hw_rfc
	hw_cls

history:
	initial coding 12/30/74 by G. R. Grossman

*/

hw_s2b(skt_p)
struct socket	*skt_p;
{
	register char	*sbp,	/* source byte pointer for copying */
			*dbp;	/*  dest   "      "     "     "    */
	register int	n;	/* counter for copying */

	sbp = &skt_p->s_lskt[0];	/* source is local socket field */
	dbp = &hw_buf[1];		/* dest is 2nd byte of command */
	*dbp++ = 0;			/* 1st byte of local socket */
	*dbp++ = 0;			/* "nd  "   "    "     "    */
	for (n = 6 ; n > 0 ; n-- )	/* now copy six bytes */
		*dbp++ = *sbp++;	/* one at a time */
}
/*name:
	hw_rfc

function:
	queues for sending the rfc appropriate to the socket struct
	specified.

algorithm:
	if the socket represents a send connection:
		set opcode to str.
		set last byte of command to byte size of connection.
	otherwise (receive connection):
		set op code to rts.
		set last byte to link number.
	copy socket numbers via hw_s2b.
	queue for sending via qup_pro.

parameters:
	skt_p	points to the socket struct defining the rfc to be sent.

returns:
	nothing.

globals:
	hw_buf=
	hhi_rts
	hhi_str

calls:
	hw_s2b
	qup_pro

called by:
	lsint_q
	rfc_slsn
	so_uinit

history:
	initial coding 12/30/74 by G. R. Grossman

*/

hw_rfc(skt_p)
struct socket	*skt_p;
{
	register struct socket	*s_p;	/* points to socket struct */

	s_p = skt_p;
	if ( s_p->s_lskt[1] & 1 )	/* send connection? */
	{
		hw_buf[0] = hhi_str;	/* op code is str */
		hw_buf[9] = s_p->s_bysz;	/* last byte is byte size */
	}
	else				/* receive connection */
	{
		hw_buf[0] = hhi_rts;	/* op code is rts */
		hw_buf[9] = s_p->s_hstlnk.hl_link;	/* last byte is link */
	}
	hw_s2b(s_p);			/* copy socket numbers */
	qup_pro(&hw_buf[0],10);		/* queue command for sending */
}

/*name:
	hw_cls

function:
	queues for sending the cls appropriate to the socket struct
	specified.

algorithm:
	set op code to cls.
	copy socket numbers via hw_s2b.
	queue for sending via qup_pro.

parameters:
	skt_p	pointer to socket struct defining the cls.

returns:
	nothing.

globals:
	hw_buf=
	hhi_cls

calls:
	hw_s2b
	qup_pro

called by:
	cls_rfcw
	cls_q
	clo_rfop
	clo_c2cw
	su_ut3
	tmo_q

history:
	initial coding 12/30/74 by G. R. Grossman

*/

hw_cls(skt_p)
struct socket	*skt_p;
{
	hw_buf[0] = hhi_cls;		/* set op code */
	hw_s2b(skt_p);			/* copy socket numbers */
	qup_pro(&hw_buf[0],9);		/* queue for sending */
}

/*name:
	hw_all

function:
	queues for sending the all command determined by the socket
	struct specified and the speified number of messages and bits.

algorithm:
	set op code to all.
	set link # from socket struct.
	copy message count, swapping bytes.
	set 1st 2 bytes of bits field to zero.
	copy 2nd word of bits field, swapping bytes.

parameters:
	skt_p	points to the socket struct descriibg the connection
		for which the all is being sent.
	msgs	number of messages to be allocated.
	bits	number of bits to be allocated.

returns:
	nothing.

globals:
	hw_buf=
	hhi_all

calls:
	qup_pro

called by:
	fi_sopn

history:
	initial coding 12/30/74 by G. R. Grossman

*/

hw_all(skt_p,msgs,bits)
struct socket	*skt_p;
int	msgs,bits;
{
	register char	*bp;	/* byte pointer for constructing command */
	register char	*BUG;	/* to avoid compiler bug in optimization */

	BUG =	/* compiler incorrectly uses bp below, so we save copy */
	bp = &hw_buf[0];	/* point at beginning of assembly buffer */
	*bp++ = hhi_all;	/* op code */
	*bp++ = skt_p->s_hstlnk.hl_link;	/* link number */
	*bp++ = msgs.hi_byte;	/* copy messages, swapping bytes */
	*bp++ = msgs.lo_byte;
	*bp++ = 0;		/* 1st 2 bytes of bits are zero */
	*bp++ = 0;
	*bp++ = bits.hi_byte;	/* copy bits, swapping bytes */
	*bp++ = bits.lo_byte;
	qup_pro( BUG,8 );	/* compiler uses bp instead of recalculating
	qup_pro( &hw_buf[0],8 );	/* queue for sending */
}

/*name:
	hw_err

function:
	queues for sending an err command with the specified code and
	containing the command bytes specified; also logs the received
	message containing the erroneous command and the err command
	sent.

algorithm:
	the op code is set to err.
	the error code is set as specified by the parameters.
	the specified command bytes are copied into the err command.
	if there were less than 10 command bytes, pad with zeroes.
	queue for sending via qup_pro.
	log the entire received message containing the ostensible error.
	log the err command just queued for sending.

parameters:
	code	the err code as specified by the host-host protocol.
	byte_p	pointer to the command bytes to be included in the
		err.
	n_bytes	number of command bytes to be included.

returns:
	nothing.

globals:
	hw_buf=
	hhi_err
	kr_buf
	kr_bytes
	kr_p

calls:
	qup_pro
	log_bin

called by:
	hr_rfc
	hr_cls

history:
	initial coding 12/30/74 by G. R. Grossman

*/

hw_err(code,byte_p,n_bytes)
int	code,n_bytes;
char	*byte_p;
{
	register char	*sbp,		/* source pointer for copying */
			*dbp;		/*  dest     "     "     "    */
	register int	n;		/* counter         "     "    */

	dbp = &hw_buf[0];		/* point at assembly buffer */
	*dbp++ = hhi_err;		/* set op code */
	*dbp++ = code;			/* set err code */
	sbp = byte_p;			/* pointer to command bytes to be
					   copied */
	for (	n = n_bytes;		/* set counter */
		n-- > 0 ;		/* done when counter is zero */
		*dbp++ = *sbp++		/* copy a byte each time */
	    );
	while ( n_bytes++ < 10 )	/* pad with zero until have 10 bytes */
		*dbp++ = 0;
	qup_pro(&hw_buf[0],12);		/* queue for sending */
	log_bin("hw_err: hh err detected;message",	/* log bad message */
		&kr_buf.krr_type,	/* start at type field */
		kr_p + kr_bytes - &kr_buf.krr_type );	/* size is current
							   pointer + bytes
							   left - start */
	log_bin(".... err sent was",&hw_buf[0],12);	/* log err sent */
}

/*name:
	hw_dwn

function:
	send an imp to host type 2 ( host going down ) message to
	the imp

algorithm:
	clean up the buffer with mak_ldr
	stick in a type 2 message
	say we wont know when will be up
	this is an emergency restart

parameters:
	none

returns:
	nothing

globals:
	kw_buf=

calls:
	mak_ldr
	kwrite

called by:
	daemon_dwn

history:
	initial coding 6/23/76 by S. F. Holmgren

*/
hw_dwn()
{
	register char *p;

	/* clean up hw_buf */
	mak_ldr();

	/* build a host going down message */
	p = &kw_buf.kw_data[0];
	*p++ = 2;		/* host down op code */
	*p++ = 0;		/* no destination */
	*p++ = 0377;		/* we dont know when coming back */
	*p++ = 0350;		/* this is an emergency restart */

	kw_write( p - &kw_buf.lo_byte );
}

/*name:
	pr_flush

function:
	flushes the protocol buffer queue for the current host.

algorithm:
	while q_dlink yields a non-zero pointer on delinking a probuf
	from the host's h_pb_q, enter the probuf in the free probuf q,
	pb_fr_q.
      indicate that there is no protocol in flight

parameters:
	none.

returns:
	nothing.

globals:
	host
	pro2send=
	h_pb_q[host]=
	pb_fr_q=
      h_pb_sent[host]=

calls:
	q_dlink
	q_enter

called by:
	h_dead

history:
	initial coding 1/2/75 by G. R. Grossman
	modified to reset pro2send by S. F. Holmgren 1/20/76
      modified to step on h_pb_sent by Greg Noel 8/31/77

*/

pr_flush()
{
	register struct probuf	*p;	/* holds pointer to probuf between
					   its being delinked from host's
					   h_pb_q and linked into pb_fr_q */

	while ( p = q_dlink(&h_pb_q[host]) )	/* was q non-empty? */
		q_enter(&pb_fr_q,p);		/* put probuf in free q */
	pro2send = 0;				/* say no protocol to send */
      h_pb_sent[host] = 0;
}