BBN-Vax-TCP/bbnnet/netmain.c

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

#include "../h/param.h"
#include "../h/inode.h"
#include "../bbnnet/mbuf.h"
#include "../bbnnet/net.h"
#include "../bbnnet/ifcb.h"
#include "../h/buf.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/proc.h"

extern struct user u;
char netbugf[] = "/etc/net/tcpdebug";
char gatefile[] = "/etc/net/gateway.bin";

/*
 * This is the mainline of the network input process.  First, we
 * fork off as a separate process within the kernel, initialize the
 * net buffer manager, local net interfaces, and timers.  Then, we
 * loop forever, sleeping on net input.  Once awakened by a local net
 * driver, we dispatch to each local interface in turn, to process the
 * input message(s).  After handling the interfaces, we adjust the net
 * buffer allocation, call on the tcp processor to handle any outstanding
 * timer or user events, and...
 */
netmain()
{
	register struct inode *ip;
	register struct proc *p;
	register struct ifcb *lp;
	int schar();
	int fid;

	fid = u.u_r.r_val1;
	fork();		/* returns twice - once in old and once in new  */
	u.u_r.r_val1 = fid;
	if (!u.u_error
              && u.u_r.r_val2) {	/* if child then */

		netcb.n_proc = p = u.u_procp;	/* -> proc table entry */
		p->p_flag |= SSYS;
		netcb.n_iss = 1;
		netcb.n_ip_cnt = 0;

		/* set up debugging file */

		netcb.n_debug = NULL;
		u.u_dirp = &netbugf[0]; 
		ip = namei(schar, 0);
		if (ip != NULL) 
			if ((ip->i_mode & IFMT) != IFREG) 
				iput(ip);
			else {
				netcb.n_debug = ip;
				prele(ip);
			}

		mbufinit();     /* init buf mgmt system */
		gatinit();	/* read gateway file and init table */

		/* initialize all local net i/fs */

		for (lp=ifcb; lp < &ifcb[nifcb]; lp++) { 
			(*lp->if_init)(lp);
		}

		/* start timers */

		tcp_timeo();
		ip_timeo();

		for (;;) {      /* body of input process */

			/*
			 * reset local i/f if necessary, otherwise
			 * just handle net input
			 */
			for (lp=ifcb; lp < &ifcb[nifcb]; lp++) {
				if (lp->if_needinit || lp->if_error) 
					netreset(lp);
				else if (lp->if_avail)
					(*lp->if_rcv)(lp);
			
			/* call TCP processor to handle any user or
			   timer events. */

				tcp_input(NULL, NULL);
				
			/*
			 * expand or shrink the buffer freelist as needed
			 */
	        		if (netcb.n_bufs < netcb.n_lowat)
	        			m_expand();
	        		else if (netcb.n_bufs > netcb.n_hiwat)
	        			m_relse();
			}
	
			/* 
			 * wait for net input (awakened by drivers)
			 */
			sleep((caddr_t)&ifcb[0], PZERO-15); 
		}
	}
}

/*
 * Generic local net reset:  clear input and output queues and call driver
 * init routine.
 */
netreset(ip)
register struct ifcb *ip;
{
	register struct mbuf *m, *n;
	int s;	

	s = spl5();
	ip->if_avail = FALSE;

	/*
	 * clear all i/f queues
	 */
	for (m=ip->if_inq_hd; m != NULL; m=n) {
		n = m->m_act;
		m_freem(m);
	}
	ip->if_inq_hd = NULL;
	ip->if_inq_tl = NULL;

	for (m=ip->if_outq_hd; m != NULL; m=n) {
		n = m->m_act;
		m_freem(m);
	}
	ip->if_outq_hd = NULL;
	ip->if_outq_tl = NULL;

	if (ip->if_inq_msg != NULL) {
		m_freem(ip->if_inq_msg);
		ip->if_inq_msg = NULL;
		ip->if_inq_cur = NULL;
	}

	if (ip->if_outq_cur != NULL) {
		m_freem(ip->if_outq_cur);
		ip->if_outq_cur = NULL;
	}

	h_reset(ip->if_net);
	splx(s);
	printf("dev %d/%d: netreset\n", major(ip->if_dev), minor(ip->if_dev));
	
	/* 
	 * now call net driver specific init routine to reinit
	 */
	(*ip->if_init)(ip);
}

/*
 * Read the binary format gateway file into the gateway table.  The file
 * contains gateway structure entries produced from the ASCII gateway
 * table.  Called from netmain or netioctl, returns number of entries
 * successfully read or -1 if error
 */
gatinit()
{
	register i;
	register struct inode *ip;
	register struct ifcb *lp;
	register struct gway *gp;
	struct gway gatent;
	net_t gatnet;
	int schar();

	/* set up to read the gateway file */

	u.u_dirp = gatefile;
	if ((ip = namei(schar, 0)) == NULL) 
		return(-1);

	if ((ip->i_mode & IFMT) != IFREG) {
		iput(ip);
		printf("bad format gateway file: %s\n", gatefile);
		return(-1);
	}
	u.u_offset = 0;
	u.u_segflg = 1;
	u.u_error = 0;

	/* read entries from the file into the table */

	for (gp=gateway, i=NGATE; i > 0; i--, gp++) {
		u.u_base = (caddr_t)&gatent;
		u.u_count = sizeof gatent;
		readi(ip);
		if (u.u_error != 0) {
			printf("error %d reading gateway file: %s\n",
				u.u_error, gatefile);
			goto out;
		}
		if (u.u_count == sizeof gatent) 	/* check EOF */
			break;
		if (u.u_count != 0 || !gatent.g_flags & GWFORMAT) {
			printf("invalid gateway file entry, read %d entries\n",
				NGATE-i+1);
			goto out;
		}

		/* look for i/f corresponding to gateway local net addr */

		gatnet = iptonet(gatent.g_local);
		for (lp=ifcb; lp < &ifcb[nifcb]; lp++)
			if (lp->if_net == gatnet) {
				gatent.g_ifcb = lp;
				goto gotif;
			}
		printf("invalid gateway addr %X, entry %d ignored\n",
			gatent.g_local.s_addr, NGATE-i+1);
		gp--;
gotif:
		*gp = gatent;
	}
	if (u.u_offset < ip->i_size)
		tablefull("gateway");
out:
	gatewayNGATE = gp;
	prele(ip);
	iput(ip);
	return(NGATE-i+1);
}

/*
 * Save anomolous packets for debugging purposes.  If limit is non-zero,
 * save up to limit packets.  Otherwise just free.
 */
netlog(mp)
register struct mbuf *mp;
{
	register struct mbuf *m;
		
	if (netcb.n_loglim > 0) {

		/* free all but header */

		if (mp->m_next != NULL) {
			m_freem(mp->m_next);
			mp->m_next = NULL;
		}

		/* add to end */

		mp->m_act = NULL;
		if (netcb.n_log_hd != NULL)
			netcb.n_log_tl->m_act = mp;
		else
			netcb.n_log_hd = mp;
		netcb.n_log_tl = mp;
		netcb.n_logct++;
		
		/* if limit exceeded, remove from head */

		while (netcb.n_logct > netcb.n_loglim && 
		    (m = netcb.n_log_hd) != NULL) {
			netcb.n_log_hd = m->m_act;
			m_free(m);
			netcb.n_logct--;
		}
	} else
		m_freem(mp);
}