~kris/9p

9hist

b0329a43e9223778376a326de32ab87a47f33df9 — David du Colombier 34 years ago 38e1a3e
Plan 9 from Bell Labs 1992-06-26
6 files changed, 284 insertions(+), 236 deletions(-)

M port/devip.c
M port/ipdat.h
M port/stil.c
M port/stip.c
M port/tcpinput.c
M port/tcptimer.c
M port/devip.c => port/devip.c +185 -118
@@ 13,15 13,15 @@ enum
{
	Nrprotocol	= 3,	/* Number of protocols supported by this driver */
	Nipsubdir	= 4,	/* Number of subdirectory entries per connection */
	Nfrag		= 32,	/* Ip reassembly queue entries */
	Nifc		= 4,	/* max interfaces */
};

int 	udpsum = 1;
Queue	*Ipoutput;			/* Control message stream for tcp/il */
Ipifc	*ipifc;				/* IP protocol interfaces for stip */
Ipconv	*ipconv[Nrprotocol];		/* Connections for each protocol */
Network	*ipnet[Nrprotocol];		/* User level interface for protocol */
Ipifc	*ipifc[Nrprotocol+1];
QLock	ipalloc;			/* Protocol port allocation lock */
Ipconv	*tcpbase;			/* Base tcp connection */
Ipconv	**tcpbase;

Streamput   udpstiput, udpstoput, tcpstiput, tcpstoput, iliput, iloput, bsdiput, bsdoput;
Streamopen  udpstopen, tcpstopen, ilopen, bsdopen;


@@ 35,46 35,39 @@ Qinfo bsdinfo = { bsdiput,   bsdoput,	bsdopen,   bsdclose,   "bsd", 0, 1 };
Qinfo *protocols[] = { &tcpinfo, &udpinfo, &ilinfo, 0 };

void
ipinitnet(Network *np, Qinfo *stproto, Ipconv *cp)
ipinitifc(Ipifc *ifc, Qinfo *stproto)
{
	int j;

	for(j = 0; j < conf.ip; j++, cp++){
		cp->stproto = stproto;
		cp->net = np;
		netadd(np, cp, j);
	}
	np->name = stproto->name;
	np->nconv = conf.ip;
	np->devp = &ipinfo;
	np->protop = stproto;
	ifc->conv = xalloc(Nipconv * sizeof(Ipconv*));
	ifc->protop = stproto;
	ifc->nconv = Nipconv;
	ifc->devp = &ipinfo;
	if(stproto != &udpinfo)
		np->listen = iplisten;
	np->clone = ipclonecon;
	np->ninfo = 3;
	np->info[0].name = "remote";
	np->info[0].fill = ipremotefill;
	np->info[1].name = "local";
	np->info[1].fill = iplocalfill;
	np->info[2].name = "status";
	np->info[2].fill = ipstatusfill;
		ifc->listen = iplisten;
	ifc->clone = ipclonecon;
	ifc->ninfo = 3;
	ifc->info[0].name = "remote";
	ifc->info[0].fill = ipremotefill;
	ifc->info[1].name = "local";
	ifc->info[1].fill = iplocalfill;
	ifc->info[2].name = "status";
	ifc->info[2].fill = ipstatusfill;
	ifc->name = stproto->name;
}

void
ipreset(void)
{
	int i, j;

	ipifc = (Ipifc *)xalloc(sizeof(Ipifc) * conf.ip);
	int i;

	for(i = 0; protocols[i]; i++) {
		ipconv[i] = (Ipconv *)xalloc(sizeof(Ipconv) * conf.ip);
		ipnet[i] = (Network *)xalloc(sizeof(Network));
		ipinitnet(ipnet[i], protocols[i], ipconv[i]);
		ipifc[i] = xalloc(sizeof(Ipifc));
		ipinitifc(ipifc[i], protocols[i]);
		newqinfo(protocols[i]);
	}

	initfrag(conf.frag);
	initfrag(Nfrag);
}

void


@@ 114,40 107,79 @@ ipclone(Chan *c, Chan *nc)
int
ipwalk(Chan *c, char *name)
{
	return netwalk(c, name, ipnet[c->dev]);
	return netwalk(c, name, ipifc[c->dev]);
}

void
ipstat(Chan *c, char *db)
{
	netstat(c, db, ipnet[c->dev]);
	netstat(c, db, ipifc[c->dev]);
}

Chan *
ipopen(Chan *c, int omode)
{
	return netopen(c, omode, ipnet[c->dev]);
	return netopen(c, omode, ipifc[c->dev]);
}

int
ipclonecon(Chan *c)
{
	Ipconv *new, *base;
	Ipconv *new;

	base = ipconv[c->dev];
	new = ipincoming(base, 0);
	new = ipincoming(ipifc[c->dev], 0);
	if(new == 0)
		error(Enodev);
	return new - base;
	return new->id;
}

Ipconv *
ipincoming(Ipconv *base, Ipconv *from)
/*
 *  create a new conversation structure if none exists for this conversation slot
 */
Ipconv*
ipcreateconv(Ipifc *ifc, int id)
{
	Ipconv *new, *etab;
	Ipconv **p;
	Ipconv *new;

	p = &ifc->conv[id];
	if(*p)
		return *p;
	qlock(ifc);
	p = &ifc->conv[id];
	if(*p){
		qunlock(ifc);
		return *p;
	}
	if(waserror()){
		qunlock(ifc);
		nexterror();
	}
	new = smalloc(sizeof(Ipconv));
	new->ifc = ifc;
	netadd(ifc, new, p - ifc->conv);
	new->ref = 1;
	*p = new;
	qunlock(ifc);
	poperror();
	return new;
}

	etab = &base[conf.ip];
	for(new = base; new < etab; new++) {
/*
 *  allocate a conversation structure.
 */
Ipconv*
ipincoming(Ipifc *ifc, Ipconv *from)
{
	Ipconv **p, **etab;
	Ipconv *new;

	/* look for an unused existing conversation */
	etab = &ifc->conv[Nipconv];
	for(p = ifc->conv; p < etab; p++) {
		new = *p;
		if(new == 0)
			break;
		if(new->ref == 0 && canqlock(new)) {
			if(new->ref || ipconbusy(new)) {
				qunlock(new);


@@ 163,7 195,35 @@ ipincoming(Ipconv *base, Ipconv *from)
			return new;
		}	
	}
	return 0;

	/* create one */
	qlock(ifc);
	etab = &ifc->conv[Nipconv];
	for(p = ifc->conv; ; p++){
		if(p == etab){
			qunlock(ifc);
			return 0;
		}
		if(*p == 0)
			break;
	}
	if(waserror()){
		qunlock(ifc);
		nexterror();
	}
	new = smalloc(sizeof(Ipconv));
	new->ifc = ifc;
	netadd(ifc, new, p - ifc->conv);
	qlock(new);
	*p = new;
	qunlock(ifc);
	if(from)	/* copy ownership from listening channel */
		netown(new, from->owner, 0);
	else		/* current user becomes owner */
		netown(new, u->p->user, 0);
	new->ref = 1;
	qunlock(new);
	return new;
}

void


@@ 183,7 243,7 @@ ipremove(Chan *c)
void
ipwstat(Chan *c, char *dp)
{
	netwstat(c, dp, ipnet[c->dev]);
	netwstat(c, dp, ipifc[c->dev]);
}

void


@@ 196,7 256,7 @@ ipclose(Chan *c)
long
ipread(Chan *c, void *a, long n, ulong offset)
{
	return netread(c, a, n, offset, ipnet[c->dev]);
	return netread(c, a, n, offset, ipifc[c->dev]);
}

long


@@ 214,7 274,7 @@ ipwrite(Chan *c, char *a, long n, ulong offset)
	if (type != Sctlqid)
		error(Eperm);

	cp = &ipconv[c->dev][STREAMID(c->qid.path)];
	cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path));

	m = n;
	if(m > sizeof(buf)-1)


@@ 251,13 311,13 @@ ipwrite(Chan *c, char *a, long n, ulong offset)
		/* If we have no local port assign one */
		if(cp->psrc == 0){
			qlock(&ipalloc);
			cp->psrc = nextport(ipconv[c->dev], priv);
			cp->psrc = nextport(ipifc[c->dev], priv);
			qunlock(&ipalloc);
		}

		if(cp->stproto == &tcpinfo)
		if(cp->ifc->protop == &tcpinfo)
			tcpstart(cp, TCP_ACTIVE, Streamhi, 0);
		else if(cp->stproto == &ilinfo)
		else if(cp->ifc->protop == &ilinfo)
			ilstart(cp, IL_ACTIVE, 20);

		/*


@@ 274,7 334,7 @@ ipwrite(Chan *c, char *a, long n, ulong offset)
		}
	}
	else if(strcmp(field[0], "disconnect") == 0) {
		if(cp->stproto != &udpinfo)
		if(cp->ifc->protop != &udpinfo)
			error(Eperm);

		cp->dst = 0;


@@ 291,7 351,7 @@ ipwrite(Chan *c, char *a, long n, ulong offset)

		if(port){
			qlock(&ipalloc);
			if(portused(ipconv[c->dev], port)) {
			if(portused(ipifc[c->dev], port)) {
				qunlock(&ipalloc);	
				error(Einuse);
			}


@@ 299,14 359,14 @@ ipwrite(Chan *c, char *a, long n, ulong offset)
			qunlock(&ipalloc);
		} else if(*field[1] != '*'){
			qlock(&ipalloc);
			cp->psrc = nextport(ipconv[c->dev], 0);
			cp->psrc = nextport(ipifc[c->dev], 0);
			qunlock(&ipalloc);
		} else
			cp->psrc = 0;

		if(cp->stproto == &tcpinfo)
		if(cp->ifc->protop == &tcpinfo)
			tcpstart(cp, TCP_PASSIVE, Streamhi, 0);
		else if(cp->stproto == &ilinfo)
		else if(cp->ifc->protop == &ilinfo)
			ilstart(cp, IL_PASSIVE, 10);

		if(cp->backlog == 0)


@@ 331,11 391,11 @@ ipwrite(Chan *c, char *a, long n, ulong offset)
int
ipconbusy(Ipconv  *cp)
{
	if(cp->stproto == &tcpinfo)
	if(cp->ifc->protop == &tcpinfo)
	if(cp->tcpctl.state != Closed)
		return 1;

	if(cp->stproto == &ilinfo)
	if(cp->ifc->protop == &ilinfo)
	if(cp->ilctl.state != Ilclosed)
		return 1;



@@ 352,9 412,9 @@ udpstiput(Queue *q, Block *bp)
 * udprcvmsg - called by stip to multiplex udp ports onto conversations
 */
void
udprcvmsg(Ipconv *muxed, Block *bp)
udprcvmsg(Ipifc *ifc, Block *bp)
{
	Ipconv *ifc, *etab;
	Ipconv *cp, **p, **etab;
	Udphdr *uh;
	Port   dport, sport;
	ushort sum, len;


@@ 383,11 443,14 @@ udprcvmsg(Ipconv *muxed, Block *bp)
	sport = nhgets(uh->udpsport);

	/* Look for a conversation structure for this port */
	etab = &muxed[conf.ip];
	for(ifc = muxed; ifc < etab; ifc++) {
		if(ifc->ref)
		if(ifc->psrc == dport)
		if(ifc->pdst == 0 || ifc->pdst == sport) {
	etab = &ifc->conv[Nipconv];
	for(p = ifc->conv; p < etab; p++) {
		cp = *p;
		if(cp == 0)
			break;
		if(cp->ref)
		if(cp->psrc == dport)
		if(cp->pdst == 0 || cp->pdst == sport) {
			/* Trim the packet down to data size */
			len = len - (UDP_HDRSIZE-UDP_PHDRSIZE);
			bp = btrim(bp, UDP_EHSIZE+UDP_HDRSIZE, len);


@@ 395,9 458,9 @@ udprcvmsg(Ipconv *muxed, Block *bp)
				return;

			/* Stuff the src address into the remote file */
		 	ifc->dst = addr;
			ifc->pdst = sport;
			PUTNEXT(ifc->readq, bp);
		 	cp->dst = addr;
			cp->pdst = sport;
			PUTNEXT(cp->readq, bp);
			return;
		}
	}


@@ 476,8 539,6 @@ udpstclose(Queue *q)
	ipc->psrc = 0;
	ipc->pdst = 0;
	ipc->dst = 0;

	closeipifc(ipc->ipinterface);
}

void


@@ 485,13 546,12 @@ udpstopen(Queue *q, Stream *s)
{
	Ipconv *ipc;

	ipc = &ipconv[s->dev][s->id];
	ipc->ipinterface = newipifc(IP_UDPPROTO, udprcvmsg, ipconv[s->dev],
			            1500, 512, ETHER_HDR, "UDP");
	ipc = ipcreateconv(ipifc[s->dev], s->id);
	initipifc(ipifc[s->dev], IP_UDPPROTO, udprcvmsg, 1500, 512, ETHER_HDR, "UDP");

	ipc->readq = RD(q);	
	RD(q)->ptr = (void *)ipc;
	WR(q)->next->ptr = (void *)ipc->ipinterface;
	WR(q)->next->ptr = (void *)ipc->ifc;
	WR(q)->ptr = (void *)ipc;
}



@@ 564,6 624,7 @@ void
tcpstopen(Queue *q, Stream *s)
{
	Ipconv *ipc;
	Ipifc *ifc;
	Tcpctl *tcb;
	Block *bp;	
	static int tcpkprocs;


@@ 578,22 639,22 @@ tcpstopen(Queue *q, Stream *s)
	if(tcpkprocs == 0) {
		tcpkprocs = 1;
		kproc("tcpack", tcpackproc, 0);
		kproc("tcpflow", tcpflow, &ipconv[s->dev]);
		kproc("tcpflow", tcpflow, ipifc[s->dev]);

	}

	if(tcpbase == 0)
		tcpbase = ipconv[s->dev];
	ipc = &ipconv[s->dev][s->id];
	ipc->ipinterface = newipifc(IP_TCPPROTO, tcp_input, ipconv[s->dev], 
			            1500, 512, ETHER_HDR, "TCP");
		tcpbase = ipifc[s->dev]->conv;
	ifc = ipifc[s->dev];
	initipifc(ifc, IP_TCPPROTO, tcp_input, 1500, 512, ETHER_HDR, "TCP");
	ipc = ipcreateconv(ifc, s->id);

	ipc->readq = RD(q);
	ipc->readq->rp = &tcpflowr;
	ipc->err = 0;

	RD(q)->ptr = (void *)ipc;
	WR(q)->next->ptr = (void *)ipc->ipinterface;
	WR(q)->next->ptr = (void *)ipc->ifc;
	WR(q)->ptr = (void *)ipc;

	/* pass any waiting data upstream */


@@ 607,22 668,18 @@ tcpstopen(Queue *q, Stream *s)
void
ipremotefill(Chan *c, char *buf, int len)
{
	int connection;
	Ipconv *cp;

	connection = STREAMID(c->qid.path);
	cp = &ipconv[c->dev][connection];
	cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path));
	sprint(buf, "%d.%d.%d.%d %d\n", fmtaddr(cp->dst), cp->pdst);
}

void
iplocalfill(Chan *c, char *buf, int len)
{
	int connection;
	Ipconv *cp;

	connection = STREAMID(c->qid.path);
	cp = &ipconv[c->dev][connection];
	cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path));
	sprint(buf, "%d.%d.%d.%d %d\n", fmtaddr(Myip[Myself]), cp->psrc);
}



@@ 633,17 690,17 @@ ipstatusfill(Chan *c, char *buf, int len)
	Ipconv *cp;

	connection = STREAMID(c->qid.path);
	cp = &ipconv[c->dev][connection];
	if(cp->stproto == &tcpinfo)
	cp = ipcreateconv(ipifc[c->dev], connection);
	if(cp->ifc->protop == &tcpinfo)
		sprint(buf, "tcp/%d %d %s %s\n", connection, cp->ref,
			tcpstate[cp->tcpctl.state],
			cp->tcpctl.flags & CLONE ? "listen" : "connect");
	else if(cp->stproto == &ilinfo)
	else if(cp->ifc->protop == &ilinfo)
		sprint(buf, "il/%d %d %s rtt %d ms %d csum\n", connection, cp->ref,
			ilstate[cp->ilctl.state], cp->ilctl.rtt,
			cp->ipinterface ? cp->ipinterface->chkerrs : 0);
			cp->ifc ? cp->ifc->chkerrs : 0);
	else
		sprint(buf, "%s/%d %d\n", cp->stproto->name, connection, cp->ref);
		sprint(buf, "%s/%d %d\n", cp->ifc->protop->name, connection, cp->ref);
}

int


@@ 655,20 712,19 @@ iphavecon(Ipconv *s)
int
iplisten(Chan *c)
{
	Ipconv *etab, *new;
	Ipconv *s, *base;
	Ipconv **p, **etab, *new;
	Ipconv *s;
	int connection;
	Ipconv *cp;

	connection = STREAMID(c->qid.path);
	s = &ipconv[c->dev][connection];
	base = ipconv[c->dev];
	s = ipcreateconv(ipifc[c->dev], connection);

	if(s->stproto == &tcpinfo)
	if(s->ifc->protop == &tcpinfo)
	if(s->tcpctl.state != Listen)
		error(Enolisten);

	if(s->stproto == &ilinfo)
	if(s->ifc->protop == &ilinfo)
	if(s->ilctl.state != Illistening)
		error(Enolisten);



@@ 680,15 736,18 @@ iplisten(Chan *c)
		}
		sleep(&s->listenr, iphavecon, s);
		poperror();
		new = base;
 		for(etab = &base[conf.ip]; new < etab; new++) {
		etab = &ipifc[c->dev]->conv[Nipconv];
 		for(p = ipifc[c->dev]->conv; p < etab; p++) {
			new = *p;
			if(new == 0)
				break;
			if(new->newcon == s) {
				qlock(s);
				s->curlog--;
				qunlock(s);
				new->newcon = 0;
				qunlock(&s->listenq);
				return new - base;
				return new->id;
			}
		}
		qunlock(&s->listenq);


@@ 701,7 760,7 @@ void
tcpstclose(Queue *q)
{
	Ipconv *s;
	Ipconv *etab, *ifc;
	Ipconv **etab, **p;
	Tcpctl *tcb;

	s = (Ipconv *)(q->ptr);


@@ 720,11 779,11 @@ tcpstclose(Queue *q)
		qlock(s);
		s->backlog = 0;
		s->curlog = 0;
		etab = &tcpbase[conf.ip];
		for(ifc = tcpbase; ifc < etab; ifc++){
			if(ifc->newcon == s) {
				ifc->newcon = 0;
				tcpflushincoming(ifc);
		etab = &tcpbase[Nipconv];
		for(p = tcpbase; p < etab && *p; p++){
			if((*p)->newcon == s) {
				(*p)->newcon = 0;
				tcpflushincoming(*p);
			}
		}
		qunlock(s);


@@ 921,17 980,22 @@ btrim(Block *bp, int offset, int len)
}

Ipconv *
portused(Ipconv *ic, Port port)
portused(Ipifc *ifc, Port port)
{
	Ipconv *ifc, *etab;
	Ipconv **p, **etab;
	Ipconv *cp;

	if(port == 0)
		return 0;

	etab = &ic[conf.ip];
	for(ifc = ic; ifc < etab; ifc++)
		if(ifc->psrc == port) 
			return ifc;
	etab = &ifc->conv[Nipconv];
	for(p = ifc->conv; p < etab; p++){
		cp = *p;
		if(cp == 0)
			break;
		if(cp->psrc == port) 
			return cp;
	}

	return 0;
}


@@ 939,7 1003,7 @@ portused(Ipconv *ic, Port port)
static Port lastport[2] = { PORTALLOC-1, PRIVPORTALLOC-1 };

Port
nextport(Ipconv *ic, int priv)
nextport(Ipifc *ifc, int priv)
{
	Port base;
	Port max;


@@ 957,10 1021,10 @@ nextport(Ipconv *ic, int priv)
	}
	
	for(i = *p + 1; i < max; i++)
		if(!portused(ic, i))
		if(!portused(ifc, i))
			return(*p = i);
	for(i = base ; i <= *p; i++)
		if(!portused(ic, i))
		if(!portused(ifc, i))
			return(*p = i);

	return(0);


@@ 968,14 1032,17 @@ nextport(Ipconv *ic, int priv)

/* NEEDS HASHING ! */

Ipconv *
ip_conn(Ipconv *ic, Port dst, Port src, Ipaddr dest, char proto)
Ipconv*
ip_conn(Ipifc *ifc, Port dst, Port src, Ipaddr dest, char proto)
{
	Ipconv *s, *etab;
	Ipconv **p, *s, **etab;

	/* Look for a conversation structure for this port */
	etab = &ic[conf.ip];
	for(s = ic; s < etab; s++) {
	etab = &ifc->conv[Nipconv];
	for(p = ifc->conv; p < etab; p++) {
		s = *p;
		if(s == 0)
			break;
		if(s->psrc == dst)
		if(s->pdst == src)
		if(s->dst == dest || dest == 0)

M port/ipdat.h => port/ipdat.h +23 -18
@@ 280,13 280,11 @@ struct Ipconv
	QLock;			/* Ref count lock */
	Netprot;		/* stat info */
	int 	ref;
	Qinfo	*stproto;	/* Stream protocol for this device */
	Network	*net;		/* user level network interface */
	Ipaddr	dst;		/* Destination from connect */
	Port	psrc;		/* Source port */
	Port	pdst;		/* Destination port */

	Ipifc	*ipinterface;	/* Ip protocol interface */
	Ipifc	*ifc;	/* Ip protocol interface */
	Queue	*readq;		/* Pointer to upstream read q */
	QLock	listenq;	/* List of people waiting incoming cons */
	Rendez	listenr;	/* Some where to sleep while waiting */


@@ 360,24 358,31 @@ enum				/* Tcp connection states */
	Time_wait
};

enum
{
	Nipconv=	512,		/* max conversations per interface */
};

/*
 * Ip interface structure. We have one for each active protocol driver
 */
struct Ipifc 
{
	QLock;
	int 		ref;
	Network;				/* user level network interface */
	Ipifc		*next;
	int 		inited;
	uchar		protocol;		/* Ip header protocol number */
	char		name[NAMELEN];		/* Protocol name */
	void (*iprcv)	(Ipconv *, Block *);	/* Receive demultiplexor */
	Ipconv		*connections;		/* Connection list */
	void (*iprcv)	(Ipifc*, Block*);	/* Receive demultiplexor */
	int		maxmtu;			/* Maximum transfer unit */
	int		minmtu;			/* Minumum tranfer unit */
	int		hsize;			/* Media header size */	
	ulong		chkerrs;		/* checksum errors */
	Lock;	
	Lock;
	Ipconv		**conv;			/* conversations */
};


struct Fragq
{
	QLock;


@@ 423,7 428,6 @@ int	arp_lookup(uchar*, uchar*);
int	backoff(int);
Block*	btrim(Block*, int, int);
void	close_self(Ipconv *, char []);
void	closeipifc(Ipifc*);
int	dupb(Block **, Block *, int, int);
void	extract_oob(Block **, Block **, Tcp *);
void	get_reseq(Tcpctl *, char *, Tcp *, Block **, ushort *);


@@ 436,15 440,17 @@ void	ilstart(Ipconv *, int, int);
int	inb_window(Tcpctl *, int);
void	init_tcpctl(Ipconv *);
void	initfrag(int);
Ipconv*	ip_conn(Ipconv *, Port, Port, Ipaddr dest, char proto);
void	initipifc(Ipifc*, uchar, void (*)(Ipifc*, Block*), int, int, int, char*);
Ipconv*	ip_conn(Ipifc*, Port, Port, Ipaddr dest, char proto);
ushort	ip_csum(uchar*);
Block*	ip_reassemble(int, Block*, Etherhdr*);
int	ipclonecon(Chan *);
int	ipconbusy(Ipconv*);
Ipconv*	ipcreateconv(Ipifc*, int);
int	ipforme(uchar*);
Fragq*	ipfragallo(void);
void	ipfragfree(Fragq*, int);
Ipconv*	ipincoming(Ipconv*, Ipconv*);
Ipconv*	ipincoming(Ipifc*, Ipconv*);
int	iplisten(Chan *);
void	iplocalfill(Chan*, char*, int);
void	ipmkdir(Qinfo *, Dirtab *, Ipconv *);


@@ 453,13 459,12 @@ void	ipremotefill(Chan*, char*, int);
void	iproute(uchar*, uchar*);
void	ipsetaddrs(void);
void	ipstatusfill(Chan*, char*, int);
Ipifc*	newipifc(uchar, void (*)(Ipconv *, Block*), Ipconv *, int, int, int, char*);
Port	nextport(Ipconv *, int);
ulong	nhgetl(uchar*);
Port	nextport(Ipifc*, int);
ushort	nhgets(uchar*);
ulong	nhgetl(uchar*);
int	ntohtcp(Tcp *, Block **);
int	ntohtcp(Tcp*, Block**);
Ipconv*	portused(Ipconv *, Port);
Ipconv*	portused(Ipifc*, Port);
void	ppkt(Block*);
void	proc_syn(Ipconv*, char, Tcp*);
ushort	ptcl_csum(Block*bp, int, int);


@@ 478,7 483,7 @@ void	start_timer(Timer *);
void	state_upcall(Ipconv*, char oldstate, char newstate);
void	stop_timer(Timer *);
void	tcp_acktimer(void *);
void	tcp_input(Ipconv *, Block *);
void	tcp_input(Ipifc*, Block *);
void	tcp_output(Ipconv*);
void	tcp_timeout(void *);
void	tcpackproc(void*);


@@ 487,7 492,7 @@ void	tcpflushincoming(Ipconv*);
void	tcprcvwin(Ipconv *);
void	tcpstart(Ipconv *, int, ushort, char);
int	trim(Tcpctl *, Tcp *, Block **, ushort *);
void	udprcvmsg(Ipconv *, Block*);
void	udprcvmsg(Ipifc*, Block*);
void	update(Ipconv *, Tcp *);

#define	fmtaddr(xx)	(xx>>24)&0xff,(xx>>16)&0xff,(xx>>8)&0xff,xx&0xff


@@ 501,7 506,7 @@ extern Ipaddr Myip[7];
extern Ipaddr Mymask;
extern Ipaddr Mynetmask;
extern Ipaddr classmask[4];
extern Ipconv *ipconv[];
extern Ipifc *ipifc[];
extern char *tcpstate[];
extern char *ilstate[];
extern Rendez tcpflowr;

M port/stil.c => port/stil.c +29 -19
@@ 44,7 44,7 @@ enum
			 (s)->fasttime = (Fasttime*(s)->rtt)/Iltickms; \
			 (s)->slowtime = (Slowtime*(s)->rtt)/Iltickms; }

void	ilrcvmsg(Ipconv*, Block*);
void	ilrcvmsg(Ipifc*, Block*);
void	ilackproc(void*);
void	ilsendctl(Ipconv*, Ilhdr*, int, ulong, ulong);
void	ilackq(Ilcb*, Block*);


@@ 69,16 69,15 @@ ilopen(Queue *q, Stream *s)

	if(ilkproc == 0) {
		ilkproc = 1;
		kproc("ilack", ilackproc, ipconv[s->dev]);
		kproc("ilack", ilackproc, ipifc[s->dev]);
	}

	ipc = &ipconv[s->dev][s->id];
	ipc->ipinterface = newipifc(IP_ILPROTO, ilrcvmsg, ipconv[s->dev],
			            1500, 60, ETHER_HDR, "IL");
	ipc = ipcreateconv(ipifc[s->dev], s->id);
	initipifc(ipc->ifc, IP_ILPROTO, ilrcvmsg, 1500, 60, ETHER_HDR, "IL");

	ipc->readq = RD(q);	
	RD(q)->ptr = (void *)ipc;
	WR(q)->next->ptr = (void *)ipc->ipinterface;
	WR(q)->next->ptr = (void *)ipc->ifc;
	WR(q)->ptr = (void *)ipc;
}



@@ 259,12 258,12 @@ iliput(Queue *q, Block *bp)
}

void
ilrcvmsg(Ipconv *ipc, Block *bp)
ilrcvmsg(Ipifc *ifc, Block *bp)
{
	Ilhdr *ih;
	Ilcb *ic;
	int plen, illen;
	Ipconv *s, *etab, *new;
	Ipconv *s, **p, **etab, *new;
	short sp, dp;
	Ipaddr dst;
	char *st;


@@ 283,39 282,46 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
	dst = nhgetl(ih->src);

	if(ilcksum && ptcl_csum(bp, IL_EHSIZE, illen) != 0) {
		ipc->ipinterface->chkerrs++;
		ifc->chkerrs++;
/*		st = (ih->iltype < 0 || ih->iltype > Ilclose) ? "?" : iltype[ih->iltype];
		print("il: cksum error, pkt(%s id %lud ack %lud %d.%d.%d.%d/%d->%d)\n",
			st, nhgetl(ih->ilid), nhgetl(ih->ilack), fmtaddr(dst), sp, dp); /**/
		goto drop;
	}

	etab = &ipc[conf.ip];
	for(s = ipc; s < etab; s++)
	etab = &ifc->conv[Nipconv];
	for(p = ifc->conv; p < etab; p++) {
		s = *p;
		if(s == 0)
			break;
		if(s->psrc == sp)
		if(s->pdst == dp)
		if(s->dst == dst) {
			ilprocess(s, ih, bp);
			return;
		}
	}

	if(ih->iltype != Ilsync)
		goto drop;

	/* Look for a listener */
	for(s = ipc; s < etab; s++) {
	for(p = ifc->conv; p < etab; p++) {
		s = *p;
		if(s == 0)
			break;
		if(s->ilctl.state == Illistening)
		if(s->pdst == 0)
		if(s->dst == 0) {
			if(s->curlog > s->backlog)
				goto reset;

			new = ipincoming(ipc, s);
			new = ipincoming(ifc, s);
			if(new == 0)
				goto reset;

			new->newcon = s;
			new->ipinterface = s->ipinterface;
			new->ifc = s->ifc;
			new->psrc = sp;
			new->pdst = dp;
			new->dst = nhgetl(ih->src);


@@ 334,7 340,6 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
			ic->window = Defaultwin;
			ilprocess(new, ih, bp);

			s->ipinterface->ref++;
			s->curlog++;
			wakeup(&s->listenr);
			return;


@@ 549,6 554,7 @@ ilhangup(Ipconv *s, char *msg)
	ic = &s->ilctl;
	callout = ic->state == Ilsyncer;
	ic->state = Ilclosed;
	qlock(s);
	if(s->readq) {
		if(msg) {
			l = strlen(msg);


@@ 562,6 568,7 @@ ilhangup(Ipconv *s, char *msg)
		nb->flags |= S_DELIM;
		PUTNEXT(s->readq, nb);
	}
	qunlock(s);
	if(callout)
		wakeup(&ic->syncer);
	s->psrc = 0;


@@ 703,16 710,19 @@ ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, ulong id, ulong ack)
void
ilackproc(void *a)
{
	Ipconv *base, *end, *s;
	Ipifc *ifc;
	Ipconv **base, **p, **end, *s;
	Ilcb *ic;
	Block *bp, *np;

	base = (Ipconv*)a;
	end = &base[conf.ip];
	ifc = (Ipifc*)a;
	base = ifc->conv;
	end = &base[Nipconv];

	for(;;) {
		tsleep(&ilackr, return0, 0, Iltickms);
		for(s = base; s < end; s++) {
		for(p = base; p < end && *p; p++) {
			s = *p;
			ic = &s->ilctl;
			ic->timeout += Iltickms;
			switch(ic->state) {

M port/stip.c => port/stip.c +22 -57
@@ 17,7 17,6 @@
#define DPRINT if(pip)print
int pip = 0;
int ipcksum = 1;
extern Ipifc *ipifc;
int Id = 1;

Fragq		*flisthead;


@@ 81,7 80,7 @@ ipetheropen(Queue *q, Stream *s)
		s->inuse++;
		ipsetaddrs();
	} else {
		ipc = &ipconv[s->dev][s->id];
		ipc = ipcreateconv(ipifc[s->dev], s->id);
		RD(q)->ptr = (void *)ipc;
		WR(q)->ptr = (void *)ipc;
		ipc->ref = 1;


@@ 92,50 91,27 @@ ipetheropen(Queue *q, Stream *s)
}

/*
 * newipifc - Attach to or Create a new protocol interface
 *  initipifc - set parameters of an ip protocol interface
 */

Ipifc *
newipifc(uchar ptcl, void (*recvfun)(Ipconv *, Block *bp),
	 Ipconv *con, int max, int min, int hdrsize, char *name)
void
initipifc(Ipifc *ifc, uchar ptcl, void (*recvfun)(Ipifc*, Block *bp), int max,
	int min, int hdrsize, char *name)
{
	Ipifc *ifc, *free;
 
	free = 0;
	for(ifc = ipifc; ifc < &ipifc[conf.ipif]; ifc++) {
		qlock(ifc);
		if(ifc->protocol == ptcl) {
			ifc->ref++;
			qunlock(ifc);
			return(ifc);
		}
		if(!free && ifc->ref == 0) {
			ifc->ref = 1;
			free = ifc;
		}
		else
			qunlock(ifc);
	}

	if(!free)
		error(Enoifc);

	free->iprcv = recvfun;
	qlock(ifc);
	ifc->iprcv = recvfun;

	/* If media supports large transfer units limit maxmtu
	 * to max ip size */
	if(max > IP_MAX)
		max = IP_MAX;
	free->maxmtu = max;
	free->minmtu = min;
	free->hsize = hdrsize;
	free->connections = con;
	ifc->maxmtu = max;
	ifc->minmtu = min;
	ifc->hsize = hdrsize;

	free->protocol = ptcl;
	strncpy(free->name, name, NAMELEN);
	ifc->protocol = ptcl;
	ifc->inited = 1;

	qunlock(free);
	return(free);
	qunlock(ifc);
}

static void


@@ 150,20 126,6 @@ ipetherclose(Queue *q)
	}
}

void
closeipifc(Ipifc *ifc)
{
	/* If this is the last reference to the protocol multiplexor
	 * cancel upcalls from this stream
	 */
	qlock(ifc);
	if(--ifc->ref == 0) {
		ifc->protocol = 0;
		ifc->name[0] = 0;
	}
	qunlock(ifc);
}

static void
ipetheroput(Queue *q, Block *bp)
{


@@ 301,7 263,7 @@ drop:
static void
ipetheriput(Queue *q, Block *bp)
{
	Ipifc 	 *ep, *ifp;
	Ipifc 	 *ifc, **ifp;
	Etherhdr *h;
	ushort   frag;



@@ 345,13 307,16 @@ ipetheriput(Queue *q, Block *bp)
	/*
 	 * Look for an ip interface attached to this protocol
	 */
	ep = &ipifc[conf.ipif];
	for(ifp = ipifc; ifp < ep; ifp++)
		if(ifp->protocol == h->proto) {
			(*ifp->iprcv)(ifp->connections, bp);
	for(ifp = ipifc; ; ifp++){
		ifc = *ifp;
		if(ifc == 0)
			break;
		if(ifc->protocol == h->proto) {
			(*ifc->iprcv)(ifc, bp);
			return;
		}
			
	}

drop:
	freeb(bp);
}

M port/tcpinput.c => port/tcpinput.c +11 -12
@@ 92,7 92,7 @@ tcpmove(struct Tctl *to, struct Tctl *from)
}

Ipconv*
tcpincoming(Ipconv *ipc, Ipconv *s, Tcp *segp, Ipaddr source)
tcpincoming(Ipifc *ifc, Ipconv *s, Tcp *segp, Ipaddr source)
{
	Ipconv *new;



@@ 102,7 102,7 @@ tcpincoming(Ipconv *ipc, Ipconv *s, Tcp *segp, Ipaddr source)
		return 0;
	}

	new = ipincoming(ipc, s);
	new = ipincoming(ifc, s);
	if(new == 0){
		qunlock(s);
		return 0;


@@ 120,17 120,15 @@ tcpincoming(Ipconv *ipc, Ipconv *s, Tcp *segp, Ipaddr source)
	new->tcpctl.acktimer.arg = new;
	new->tcpctl.acktimer.state = TIMER_STOP;
	new->newcon = s;
	new->ipinterface = s->ipinterface;

	s->ipinterface->ref++;
	wakeup(&s->listenr);
	return new;
}

void
tcp_input(Ipconv *ipc, Block *bp)
tcp_input(Ipifc *ifc, Block *bp)
{
	Ipconv *s, *e;
	Ipconv *s, **p, **etab;
	Ipconv *spec, *gen;
	Tcpctl *tcb;		
	Tcphdr *h;


@@ 164,7 162,7 @@ tcp_input(Ipconv *ipc, Block *bp)
		return;
	
	/* Look for a connection, failing that attempt to establish a listen */
	s = ip_conn(ipc, seg.dest, seg.source, source, IP_TCPPROTO);
	s = ip_conn(ifc, seg.dest, seg.source, source, IP_TCPPROTO);
	if (s == 0) {
		if(seg.flags & SYN){
			/*


@@ 173,8 171,9 @@ tcp_input(Ipconv *ipc, Block *bp)
			 */
			spec = 0;
			gen = 0;
			e = &ipc[conf.ip];
			for(s = ipc; s < e; s++) {
			etab = &ifc->conv[Nipconv];
			for(p = ifc->conv; p < etab && *p; p++) {
				s = *p;
				if(s->tcpctl.state == Listen)
				if(s->pdst == 0)
				if(s->dst == 0) {


@@ 187,9 186,9 @@ tcp_input(Ipconv *ipc, Block *bp)
				}
			}
			if(spec)
				s = tcpincoming(ipc, spec, &seg, source);
				s = tcpincoming(ifc, spec, &seg, source);
			else if(gen)
				s = tcpincoming(ipc, gen, &seg, source);
				s = tcpincoming(ifc, gen, &seg, source);
			else
				s = 0;
		}


@@ 583,7 582,7 @@ proc_syn(Ipconv *s, char tos, Tcp *seg)
		tcb->mss = seg->mss;

	tcb->max_snd = seg->wnd;
	if((mtu = s->ipinterface->maxmtu) != 0) {
	if((mtu = s->ifc->maxmtu) != 0) {
		mtu -= TCP_HDRSIZE + TCP_EHSIZE + TCP_PHDRSIZE; 
		tcb->cwind = tcb->mss = MIN(mtu, tcb->mss);
	}

M port/tcptimer.c => port/tcptimer.c +14 -12
@@ 108,23 108,25 @@ stop_timer(Timer *t)
}

void
tcpflow(void *conv)
tcpflow(void *x)
{
	Ipconv *base, *ifc, *etab;
	Ipifc *ifc;
	Ipconv *cp, **p, **etab;

	base = (Ipconv*)conv;

	etab = &base[conf.ip];
	ifc = x;
	etab = &ifc->conv[Nipconv];
	for(;;) {
		sleep(&tcpflowr, return0, 0);

		for(ifc = base; ifc < etab; ifc++) {
			if(ifc->readq)
			if(ifc->ref != 0)
			if(ifc->stproto == &tcpinfo)
			if(!QFULL(ifc->readq->next)) {
				tcprcvwin(ifc);
				tcp_acktimer(ifc);
		for(p = ifc->conv; p < etab; p++) {
			cp = *p;
			if(cp == 0)
				break;
			if(cp->readq)
			if(cp->ref != 0)
			if(!QFULL(cp->readq->next)) {
				tcprcvwin(cp);
				tcp_acktimer(cp);
			}
		}
	}