BBN-Vax-TCP/bbnnet/netmain.c
#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);
}