~kris/9p

9hist

0fb1379c9e77672723371e235624c17c3216afcf — David du Colombier 24 years ago 64a6cbb
Plan 9 from Bell Labs 2002-06-01
10 files changed, 262 insertions(+), 215 deletions(-)

M ip/arp.c
M ip/devip.c
M ip/ethermedium.c
M ip/icmp.c
M ip/icmp6.c
M ip/il.c
M ip/ip.h
M ip/ipifc.c
M ip/tcp.c
M ip/udp.c
M ip/arp.c => ip/arp.c +24 -65
@@ 60,56 60,9 @@ arpinit(Fs *f)
	kproc("rxmitproc", rxmitproc, f->arp);
}

static Arpent*
newarp(Arp *arp, uchar *ip, Medium *m)
{
	uint t;
	Block *next, *xp;
	Arpent *a, *e, *f, **l;

	/* find oldest entry */
	e = &arp->cache[NCACHE];
	a = arp->cache;
	t = a->used;
	for(f = a; f < e; f++){
		if(f->used < t){
			t = f->used;
			a = f;
		}
	}

	/* dump waiting packets */
	xp = a->hold;
	a->hold = nil;

	while(xp){
		next = xp->list;
		freeblist(xp);
		xp = next;
	}

	/* take out of current chain */
	l = &arp->hash[haship(a->ip)];
	for(f = *l; f; f = f->hash){
		if(f == a){
			*l = a->hash;
			break;
		}
		l = &f->hash;
	}

	/* insert into new chain */
	l = &arp->hash[haship(ip)];
	a->hash = *l;
	*l = a;
	memmove(a->ip, ip, sizeof(a->ip));
	a->used = msec;
	a->time = 0;
	a->type = m;

	return a;
}

/*
 *  create a new arp entry for an ip address.
 */
static Arpent*
newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt)
{


@@ 243,6 196,12 @@ cleanarpent(Arp *arp, Arpent *a)
	a->ifc = nil;
}

/*
 *  fill in the media address if we have it.  Otherwise return an
 *  Arpent that represents the state of the address resolution FSM
 *  for ip.  Add the packet to be sent onto the list of packets
 *  waiting for ip->mac to be resolved.
 */
Arpent*
arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac)
{


@@ 265,11 224,7 @@ arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac)
	}

	if(a == nil){
		//a = newarp6(arp, ip, ifc, (version != V4));
		if(version == V4)
			a = newarp(arp, ip, type);
		else 
			a = newarp6(arp, ip, ifc, 1);
		a = newarp6(arp, ip, ifc, (version != V4));
		a->state = AWAIT;
	}
	a->used = msec;


@@ 300,6 255,9 @@ arprelease(Arp *arp, Arpent*)
}

/*
 * Copy out the mac address from the Arpent.  Return the
 * block waiting to get sent to this mac address.
 *
 * called with arp locked
 */
Block*


@@ 348,13 306,19 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
		return;
	}

	if(version == V4){
	switch(version){
	case V4:
		r = v4lookup(fs, ip);
		v4tov6(v6ip, ip);
		ip = v6ip;
	}
	else
		break;
	case V6:
		r = v6lookup(fs, ip);
		break;
	default:
		panic("arpenter: version %d", version);
		return;	/* to supress warnings */
	}

	if(r == nil){
//		print("arp: no route for entry\n");


@@ 417,12 381,7 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
	}

	if(refresh == 0){
		//a = newarp6(arp, ip, ifc, 0);
		if(version == 4)
			a = newarp(arp, ip, type);
		else 
			a = newarp6(arp, ip, ifc, 0);

		a = newarp6(arp, ip, ifc, 0);
		a->state = AOK;
		a->type = type;
		memmove(a->mac, mac, type->maclen);


@@ 672,7 631,7 @@ rxmitproc(void *v)
	long wakeupat;

	arp->rxmitp = up;
	print("arp rxmitproc started\n");
	//print("arp rxmitproc started\n");
	if(waserror()){
		arp->rxmitp = 0;
		pexit("hangup", 1);

M ip/devip.c => ip/devip.c +14 -2
@@ 878,8 878,18 @@ Fsstdconnect(Conv *c, char *argv[], int argc)
		p = setraddrport(c, argv[1]);
		if(p != nil)
			return p;
		return setladdrport(c, argv[2], 0);
		p = setladdrport(c, argv[2], 0);
		if(p != nil)
			return p;
	}

	if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
		memcmp(c->laddr, v4prefix, IPv4off) == 0)
		|| ipcmp(c->raddr, IPnoaddr) == 0)
		c->ipversion = V4;
	else
		c->ipversion = V6;

	return nil;
}
/*


@@ 1308,7 1318,7 @@ Fsrcvpcolx(Fs *f, uchar proto)
 *  called with protocol locked
 */
Conv*
Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport)
Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version)
{
	Conv *nc;
	Conv **l;


@@ 1336,6 1346,8 @@ Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport)
	nc->next = nil;
	*l = nc;
	nc->state = Connected;
	nc->ipversion = version;

	qunlock(c);

	wakeup(&c->listenr);

M ip/ethermedium.c => ip/ethermedium.c +32 -11
@@ 252,10 252,16 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
		/* check for broadcast or multicast */
		bp = multicastarp(er->f, a, ifc->m, mac);
		if(bp==nil){
			if(version == V4) 
			switch(version){
			case V4:
				sendarp(ifc, a);
			else 
				break;
			case V6: 
				resolveaddr6(ifc, a);
				break;
			default:
				panic("etherbwrite: version %d", version);
			}
			return;
		}
	}


@@ 283,6 289,8 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
		eh->t[1] = 0xDD;
		devtab[er->mchan6->type]->bwrite(er->mchan6, bp, 0);
		break;
	default:
		panic("etherbwrite2: version %d", version);
	}
	ifc->out++;
}


@@ 371,14 379,20 @@ etheraddmulti(Ipifc *ifc, uchar *a, uchar *)
	uchar mac[6];
	char buf[64];
	Etherrock *er = ifc->arg;
	int type;
	int version;

	type = multicastea(mac, a);
	version = multicastea(mac, a);
	sprint(buf, "addmulti %E", mac);
	if(type == V4) 
	switch(version){
	case V4:
		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
	else if(type == V6) 
		break;
	case V6:
		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
		break;
	default:
		panic("etheraddmulti: version %d", version);
	}
}

static void


@@ 387,14 401,20 @@ etherremmulti(Ipifc *ifc, uchar *a, uchar *)
	uchar mac[6];
	char buf[64];
	Etherrock *er = ifc->arg;
	int type;
	int version;

	type = multicastea(mac, a);
	version = multicastea(mac, a);
	sprint(buf, "remmulti %E", mac);
	if(type == V4) 
	switch(version){
	case V4:
		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
	else if(type == V6) 
		break;
	case V6:
		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
		break;
	default:
		panic("etherremmulti: version %d", version);
	}
}

/*


@@ 659,7 679,8 @@ multicastea(uchar *ea, uchar *ip)

/*
 *  fill in an arp entry for broadcast or multicast
 *  addresses
 *  addresses.  Return the first queued packet for the
 *  IP address.
 */
static Block*
multicastarp(Fs *f, Arpent *a, Medium *medium, uchar *mac)

M ip/icmp.c => ip/icmp.c +3 -1
@@ 110,9 110,11 @@ icmpconnect(Conv *c, char **argv, int argc)
	char *e;

	e = Fsstdconnect(c, argv, argc);
	if(e != nil)
		return e;
	Fsconnected(c, e);

	return e;
	return nil;
}

extern int

M ip/icmp6.c => ip/icmp6.c +2 -15
@@ 196,18 196,6 @@ newIPICMP(int packetlen)
	return nbp;
}


char*
icmpconnect6(Conv *c, char **argv, int argc)
{
	char *e;

	e = Fsstdconnect(c, argv, argc);
	Fsconnected(c, e);

	return e;
}

void
icmpadvise6(Proto *icmp, Block *bp, char *msg)
{


@@ 245,7 233,6 @@ icmpkick6(Conv *c)

	if(icb->headers==6) {
		/* get user specified addresses */
//print("icmpkick6: headers\n");
		bp = pullupblock(bp, ICMP_USEAD6);
		if(bp == nil)
			return;


@@ 275,7 262,6 @@ icmpkick6(Conv *c)
	p->vcf[0] = 0x06 << 4;
	if(p->type <= Maxtype6)	
		ipriv->out[p->type]++;
//print("icmpkick6: src %I dst %I\n", p->src, p->dst);
	ipoput6(c->p->f, bp, 0, c->ttl, c->tos);
}



@@ 893,6 879,7 @@ icmpstats6(Proto *icmp6, char *buf, int len)
// need to import from icmp.c
extern int	icmpstate(Conv *c, char *state, int n);
extern char*	icmpannounce(Conv *c, char **argv, int argc);
extern char*	icmpconnect(Conv *c, char **argv, int argc);
extern void	icmpcreate(Conv *c);
extern void	icmpclose(Conv *c);



@@ 904,7 891,7 @@ icmp6init(Fs *fs)
	icmp6->priv = smalloc(sizeof(Icmppriv6));
	icmp6->name = "icmpv6";
	icmp6->kick = icmpkick6;
	icmp6->connect = icmpconnect6;
	icmp6->connect = icmpconnect;
	icmp6->announce = icmpannounce;
	icmp6->state = icmpstate;
	icmp6->create = icmpcreate;

M ip/il.c => ip/il.c +1 -1
@@ 597,7 597,7 @@ iliput(Proto *il, Ipifc*, Block *bp)
			goto raise;
		}

		new = Fsnewcall(s, raddr, dp, laddr, sp);
		new = Fsnewcall(s, raddr, dp, laddr, sp, V4);
		if(new == nil){
			qunlock(il);
			netlog(il->f, Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp);

M ip/ip.h => ip/ip.h +2 -1
@@ 84,6 84,7 @@ struct Conv
	ushort	rport;			/* remote port number */
	uint	ttl;			/* max time to live */
	uint	tos;			/* type of service */
	uchar	ipversion;		/* IPv4 or IPv6 */

	char	*owner;			/* protections */
	int	perm;


@@ 360,7 361,7 @@ struct v6params


int	Fsconnected(Conv*, char*);
Conv*	Fsnewcall(Conv*, uchar*, ushort, uchar*, ushort);
Conv*	Fsnewcall(Conv*, uchar*, ushort, uchar*, ushort, uchar);
int	Fspcolstats(char*, int);
int	Fsproto(Fs*, Proto*);
int	Fsbuiltinproto(Fs*, uchar);

M ip/ipifc.c => ip/ipifc.c +16 -7
@@ 1278,7 1278,7 @@ findlocalip(Fs *f, uchar *local, uchar *remote)
	USED(atypel);
	qlock(f->ipifc);
	r = v6lookup(f, remote);
 	version = (memcmp(remote, v4prefix, IPv4off) == 0) ? 4 : 6;
 	version = (memcmp(remote, v4prefix, IPv4off) == 0) ? V4 : V6;
	
	if(r != nil){
		ifc = r->ifc;


@@ 1290,7 1290,8 @@ findlocalip(Fs *f, uchar *local, uchar *remote)
		}

		/* find ifc address closest to the gateway to use */
		if(version == 4) {
		switch(version) {
		case V4:
			for(lifc = ifc->lifc; lifc; lifc = lifc->next){
				maskip(gate, lifc->mask, gnet);
				if(ipcmp(gnet, lifc->net) == 0){


@@ 1298,8 1299,8 @@ findlocalip(Fs *f, uchar *local, uchar *remote)
					goto out;
				}
			}
		}
		else {
			break;
		case V6:
			for(lifc = ifc->lifc; lifc; lifc = lifc->next){
				atypel = v6addrtype(lifc->local);
				maskip(gate, lifc->mask, gnet);


@@ 1314,14 1315,22 @@ findlocalip(Fs *f, uchar *local, uchar *remote)
			}
			if(atype > unspecifiedv6)
				goto out;
			break;
		default:
			panic("findlocalip: version %d", version);
		}
	}

	if(version == 4)
	switch(version){
	case V4:
		findprimaryip(f, local);
	else
		break;
	case V6:
		findprimaryip6(f, local);

		break;
	default:
		panic("findlocalip2: version %d", version);
	}

out:
	qunlock(f->ipifc);

M ip/tcp.c => ip/tcp.c +109 -74
@@ 676,15 676,22 @@ tcpmtu(Conv *s)
{
	Ipifc *ifc;
	int mtu;
	int version = (isv4(s->raddr) && isv4(s->laddr)) ? 4 : 6;
	uchar version;

	version = s->ipversion;
	mtu = 0;
	ifc = findipifc(s->p->f, s->raddr, 0);
	if(ifc != nil) {
		if(version == 4)
		switch(version){
		case V4:
			mtu = ifc->maxmtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE);
		else
			break;
		case V6:
			mtu = ifc->maxmtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE);
			break;
		default:
			panic("tcpmtu: version %d", version);
		}
	}

	if(mtu < 32) {


@@ 698,6 705,9 @@ void
inittcpctl(Conv *s, int mode)
{
	Tcpctl *tcb;
	Tcp4hdr* h4;
	Tcp6hdr* h6;

	tcb = (Tcpctl*)s->ptcl;

	memset(tcb, 0, sizeof(Tcpctl));


@@ 719,28 729,32 @@ inittcpctl(Conv *s, int mode)
	tcb->katimer.arg = s;

	/* create a prototype(pseudo) header */
	if(mode != TCP_LISTEN)
	if(ipcmp(s->laddr, IPnoaddr) == 0)
		findlocalip(s->p->f, s->laddr, s->raddr);

//	if(isv4(s->raddr)) {
	if(memcmp(s->raddr, v4prefix, IPv4off) == 0 &&
		memcmp(s->laddr, v4prefix, IPv4off) == 0) {
		Tcp4hdr* h4 = &tcb->protohdr.tcp4hdr;
		memset(h4, 0, sizeof(*h4));
		h4->proto = IP_TCPPROTO;
		hnputs(h4->tcpsport, s->lport);
		hnputs(h4->tcpdport, s->rport);
		v6tov4(h4->tcpsrc, s->laddr);
		v6tov4(h4->tcpdst, s->raddr);
	} else {
		Tcp6hdr* h6 = &tcb->protohdr.tcp6hdr;
		memset(h6, 0, sizeof(*h6));
		h6->proto = IP_TCPPROTO;
		hnputs(h6->tcpsport, s->lport);
		hnputs(h6->tcpdport, s->rport);
		ipmove(h6->tcpsrc, s->laddr);
		ipmove(h6->tcpdst, s->raddr);
	if(mode != TCP_LISTEN){
		if(ipcmp(s->laddr, IPnoaddr) == 0)
			findlocalip(s->p->f, s->laddr, s->raddr);

		switch(s->ipversion){
		case V4:
			h4 = &tcb->protohdr.tcp4hdr;
			memset(h4, 0, sizeof(*h4));
			h4->proto = IP_TCPPROTO;
			hnputs(h4->tcpsport, s->lport);
			hnputs(h4->tcpdport, s->rport);
			v6tov4(h4->tcpsrc, s->laddr);
			v6tov4(h4->tcpdst, s->raddr);
			break;
		case V6:
			h6 = &tcb->protohdr.tcp6hdr;
			memset(h6, 0, sizeof(*h6));
			h6->proto = IP_TCPPROTO;
			hnputs(h6->tcpsport, s->lport);
			hnputs(h6->tcpdport, s->rport);
			ipmove(h6->tcpsrc, s->laddr);
			ipmove(h6->tcpdst, s->raddr);
			break;
		default:
			panic("inittcpctl: version %d", s->ipversion);
		}
	}

	tcb->mss = tcb->cwind = tcpmtu(s);


@@ 1062,7 1076,7 @@ tcpsndsyn(Tcpctl *tcb)
}

void
sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, int version)
sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, uchar version)
{
	Block *hbp;
	uchar rflags;


@@ 1076,7 1090,8 @@ sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, int vers
		return;

	/* make pseudo header */
	if(version == 4) {
	switch(version) {
	case V4:
		memset(&ph4, 0, sizeof(ph4));
		ph4.vihl = IP_VER4;
		v6tov4(ph4.tcpsrc, dest);


@@ 1085,8 1100,8 @@ sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, int vers
		hnputs(ph4.tcplen, TCP4_HDRSIZE);
		hnputs(ph4.tcpsport, seg->dest);
		hnputs(ph4.tcpdport, seg->source);
	}
	else {
		break;
	case V6:
		memset(&ph6, 0, sizeof(ph6));
		ph6.vcf[0] = IP_VER6;
		ipmove(ph6.tcpsrc, dest);


@@ 1095,6 1110,9 @@ sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, int vers
		hnputs(ph6.ploadlen, TCP6_HDRSIZE);
		hnputs(ph6.tcpsport, seg->dest);
		hnputs(ph6.tcpdport, seg->source);
		break;
	default:
		panic("sndrst: version %d", version);
	}

	tpriv->stats[OutRsts]++;


@@ 1119,17 1137,21 @@ sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, int vers
	seg->wnd = 0;
	seg->urg = 0;
	seg->mss = 0;
	if(version == 4) {
	switch(version) {
	case V4:
		hbp = htontcp4(seg, nil, &ph4, nil);
		if(hbp == nil)
			return;
		ipoput4(tcp->f, hbp, 0, MAXTTL, DFLTTOS);
	}
	else {
		break;
	case V6:
		hbp = htontcp6(seg, nil, &ph6, nil);
		if(hbp == nil)
			return;
		ipoput6(tcp->f, hbp, 0, MAXTTL, DFLTTOS);
		break;
	default:
		panic("sndrst2: version %d", version);
	}
}



@@ 1148,7 1170,6 @@ tcphangup(Conv *s)
	if(waserror())
		return commonerror();
	if(s->raddr != 0) {
		int version = isv4(s->raddr) ? 4 : 6;
		seg.flags = RST | ACK;
		seg.ack = tcb->rcv.nxt;
		seg.seq = tcb->snd.ptr;


@@ 1156,15 1177,19 @@ tcphangup(Conv *s)
		seg.urg = 0;
		seg.mss = 0;
		tcb->last_ack = tcb->rcv.nxt;
		if(version == 4) {
		switch(s->ipversion) {
		case V4:
			tcb->protohdr.tcp4hdr.vihl = IP_VER4;
			hbp = htontcp4(&seg, nil, &tcb->protohdr.tcp4hdr, tcb);
			ipoput4(s->p->f, hbp, 0, s->ttl, s->tos);
		}
		else {
			break;
		case V6:
			tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
			hbp = htontcp6(&seg, nil, &tcb->protohdr.tcp6hdr, tcb);
			ipoput6(s->p->f, hbp, 0, s->ttl, s->tos);
			break;
		default:
			panic("tcphangup: version %d", s->ipversion);
		}
	}
	localclose(s, nil);


@@ 1172,14 1197,16 @@ tcphangup(Conv *s)
	return nil;
}

Conv*
tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst)
static Conv*
tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
{
	Conv *new;
	Tcpctl *tcb;
	Tcppriv *tpriv;
	Tcp4hdr *h4;
	Tcp6hdr *h6;

	new = Fsnewcall(s, src, segp->source, dst, segp->dest);
	new = Fsnewcall(s, src, segp->source, dst, segp->dest, version);
	if(new == nil)
		return nil;



@@ 1195,23 1222,27 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst)
	tcb->rtt_timer.arg = new;
	tcb->rtt_timer.state = TcptimerOFF;

	if(isv4(src)) {
		Tcp4hdr *h = &tcb->protohdr.tcp4hdr;
		memset(h, 0, sizeof(*h));
		h->proto = IP_TCPPROTO;
		hnputs(h->tcpsport, new->lport);
		hnputs(h->tcpdport, new->rport);
		v6tov4(h->tcpsrc, dst);
		v6tov4(h->tcpdst, src);
	}
	else {
		Tcp6hdr *h = &tcb->protohdr.tcp6hdr;
		memset(h, 0, sizeof(*h));
		h->proto = IP_TCPPROTO;
		hnputs(h->tcpsport, new->lport);
		hnputs(h->tcpdport, new->rport);
		ipmove(h->tcpsrc, dst);
		ipmove(h->tcpdst, src);
	switch(version){
	case V4:
		h4 = &tcb->protohdr.tcp4hdr;
		memset(h4, 0, sizeof(*h4));
		h4->proto = IP_TCPPROTO;
		hnputs(h4->tcpsport, new->lport);
		hnputs(h4->tcpdport, new->rport);
		v6tov4(h4->tcpsrc, dst);
		v6tov4(h4->tcpdst, src);
		break;
	case V6:
		h6 = &tcb->protohdr.tcp6hdr;
		memset(h6, 0, sizeof(*h6));
		h6->proto = IP_TCPPROTO;
		hnputs(h6->tcpsport, new->lport);
		hnputs(h6->tcpdport, new->rport);
		ipmove(h6->tcpsrc, dst);
		ipmove(h6->tcpdst, src);
		break;
	default:
		panic("tcpincoming: version %d", new->ipversion);
	}

	tpriv = new->p->priv;


@@ 1442,7 1473,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp)
	Conv *s;
	Fs *f;
	Tcppriv *tpriv;
	int version;
	uchar version;

	f = tcp->f;
	tpriv = tcp->priv;


@@ 1453,7 1484,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp)
	h6 = (Tcp6hdr*)(bp->rp);

	if((h4->vihl&0xF0)==IP_VER4) {
		version = 4;
		version = V4;
		length = nhgets(h4->length);
		v4tov6(dest, h4->tcpdst);
		v4tov6(source, h4->tcpsrc);


@@ 1491,7 1522,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp)
		int ttl = h6->ttl;
		int proto = h6->proto;

		version = 6;
		version = V6;
		length = nhgets(h6->ploadlen);
		ipmove(dest, h6->tcpdst);
		ipmove(source, h6->tcpsrc);


@@ 1554,7 1585,7 @@ reset:
		if((seg.flags & SYN) == 0 || (seg.flags & ACK) != 0)
			goto reset;

		s = tcpincoming(s, &seg, source, dest);
		s = tcpincoming(s, &seg, source, dest, version);
		if(s == nil)
			goto reset;
	}


@@ 1893,18 1924,11 @@ tcpoutput(Conv *s)
	ulong ssize, dsize, usable, sent;
	Fs *f;
	Tcppriv *tpriv;
	//int version = isv4(s->raddr) ? 4 : 6;
	int version;

	if( (memcmp(s->raddr, v4prefix, IPv4off) == 0 &&
		memcmp(s->laddr, v4prefix, IPv4off) == 0)
		|| ipcmp(s->raddr, IPnoaddr) == 0)
		version = 4;
	else
		version = 6;
	uchar version;

	f = s->p->f;
	tpriv = s->p->priv;
	version = s->ipversion;

	for(msgs = 0; msgs < 100; msgs++) {
		tcb = (Tcpctl*)s->ptcl;


@@ 2033,21 2057,26 @@ tcpoutput(Conv *s)
			tcb->snd.nxt = tcb->snd.ptr;

		/* Build header, link data and compute cksum */
		if(version == 4) {
		switch(version){
		case V4:
			tcb->protohdr.tcp4hdr.vihl = IP_VER4;
			hbp = htontcp4(&seg, bp, &tcb->protohdr.tcp4hdr, tcb);
			if(hbp == nil) {
				freeblist(bp);
				return;
			}
		}
		else {
			break;
		case V6:
			tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
			hbp = htontcp6(&seg, bp, &tcb->protohdr.tcp6hdr, tcb);
			if(hbp == nil) {
				freeblist(bp);
				return;
			}
			break;
		default:
			hbp = nil;	/* to suppress a warning */
			panic("tcpoutput: version %d", version);
		}

		/* Start the transmission timers if there is new data and we


@@ 2076,10 2105,16 @@ tcpoutput(Conv *s)
			qlock(s);
			nexterror();
		}
		if(version == 4)
		switch(version){
		case V4:
			ipoput4(f, hbp, 0, s->ttl, s->tos);
		else
			break;
		case V6:
			ipoput6(f, hbp, 0, s->ttl, s->tos);
			break;
		default:
			panic("tcpoutput2: version %d", version);
		}
		qlock(s);
		poperror();
	}

M ip/udp.c => ip/udp.c +59 -38
@@ 250,18 250,14 @@ udpkick(Conv *c)
	}

	dlen = blocklen(bp);
	/* Make space to fit udp & ip header */
	if(version == 4)
		bp = padblock(bp, UDP4_IPHDR_SZ+UDP_UDPHDR_SZ);
	else
		bp = padblock(bp, UDP6_IPHDR_SZ+UDP_UDPHDR_SZ);

	if(bp == nil)
		return;

	/* fill in pseudo header and compute checksum */
	if(version == 4) 
	{
	switch(version){
	case V4:
		bp = padblock(bp, UDP4_IPHDR_SZ+UDP_UDPHDR_SZ);
		if(bp == nil)
			return;

		uh4 = (Udp4hdr *)(bp->rp);
		ptcllen = dlen + UDP_UDPHDR_SZ;
		uh4->Unused = 0;


@@ 288,8 284,13 @@ udpkick(Conv *c)
		       ptclcsum(bp, UDP4_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ));
		uh4->vihl = IP_VER4;
		ipoput4(f, bp, 0, c->ttl, c->tos);
	}
	else {
		break;

	case V6:
		bp = padblock(bp, UDP6_IPHDR_SZ+UDP_UDPHDR_SZ);
		if(bp == nil)
			return;

		// using the v6 ip header to create pseudo header 
		// first then reset it to the normal ip header
		uh6 = (Udp6hdr *)(bp->rp);


@@ 318,22 319,15 @@ udpkick(Conv *c)
		uh6->viclfl[0] = IP_VER6;
		hnputs(uh6->len, ptcllen);
		uh6->nextheader = IP_UDPPROTO;

		ipoput6(f, bp, 0, c->ttl, c->tos);
		break;

	default:
		panic("udpkick: version %d", version);
	}
	upriv->ustats.udpOutDatagrams++;
}

Conv*
udpincoming(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport)
{
	Conv *new;

	new = Fsnewcall(c, raddr, rport, laddr, lport);
	if(new == nil)
		return nil;
}

void
udpiput(Proto *udp, Ipifc *ifc, Block *bp)
{


@@ 347,6 341,7 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp)
	Udppriv *upriv;
	Fs *f;
	int version;
	int ottl, oviclfl, olen;

	upriv = udp->priv;
	f = udp->f;


@@ 357,8 352,8 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp)

	/* Put back pseudo header for checksum 
	 * (remember old values for icmpnoconv()) */
	if(version == 4) {
		int ottl, olen;
	switch(version) {
	case V4:
		ottl = uh4->Unused;
		uh4->Unused = 0;
		len = nhgets(uh4->udplen);


@@ 381,9 376,8 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp)
		}
		uh4->Unused = ottl;
		hnputs(uh4->udpplen, olen);
	}
	else {
		int ottl, oviclfl, olen;
		break;
	case V6:
		uh6 = (Udp6hdr*)(bp->rp);
		len = nhgets(uh6->udplen);
		oviclfl = nhgetl(uh6->viclfl);


@@ 407,6 401,10 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp)
		hnputs(uh6->len, olen);
		uh6->nextheader = IP_UDPPROTO;
		uh6->hoplimit = ottl;
		break;
	default:
		panic("udpiput: version %d", version);
		return;	/* to avoid a warning */
	}

	qlock(udp);


@@ 419,11 417,15 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp)
		netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
		       laddr, lport);

		if(version == 4) 
		switch(version){
		case V4:
			icmpnoconv(f, bp);
		else {
print("udpiput: no conv %I!%d -> %I!%d\n", raddr, rport, laddr, lport);
			break;
		case V6:
			icmphostunr(f, ifc, bp, icmp6_port_unreach, 0);
			break;
		default:
			panic("udpiput2: version %d", version);
		}

		freeblist(bp);


@@ 435,12 437,18 @@ print("udpiput: no conv %I!%d -> %I!%d\n", raddr, rport, laddr, lport);
		if(ucb->headers == 0){
			/* create a new conversation */
			if(ipforme(f, laddr) != Runi) {
				if(version == 4)
				switch(version){
				case V4:
					v4tov6(laddr, ifc->lifc->local);
				else
					break;
				case V6:
					ipmove(laddr, ifc->lifc->local);
					break;
				default:
					panic("udpiput3: version %d", version);
				}
			}
			c = Fsnewcall(c, raddr, rport, laddr, lport);
			c = Fsnewcall(c, raddr, rport, laddr, lport, version);
			if(c == nil){
				qunlock(udp);
				freeblist(bp);


@@ 458,10 466,17 @@ print("udpiput: no conv %I!%d -> %I!%d\n", raddr, rport, laddr, lport);
	 * Trim the packet down to data size
	 */
	len -= UDP_UDPHDR_SZ;
	if(version == 4)
	switch(version){
	case V4:
		bp = trimblock(bp, UDP4_IPHDR_SZ+UDP_UDPHDR_SZ, len);
	else
		break;
	case V6:
		bp = trimblock(bp, UDP6_IPHDR_SZ+UDP_UDPHDR_SZ, len);
		break;
	default:
		bp = nil;
		panic("udpiput4: version %d", version);
	}
	if(bp == nil){
		qunlock(c);
		netlog(f, Logudp, "udp: len err %I.%d -> %I.%d\n", raddr, rport,


@@ 545,17 560,23 @@ udpadvise(Proto *udp, Block *bp, char *msg)
	h4 = (Udp4hdr*)(bp->rp);
	version = ((h4->vihl&0xF0)==IP_VER6) ? 6 : 4;

	if(version == 4) {
	switch(version) {
	case V4:
		v4tov6(dest, h4->udpdst);
		v4tov6(source, h4->udpsrc);
		psource = nhgets(h4->udpsport);
		pdest = nhgets(h4->udpdport);
	} else {
		break;
	case V6:
		h6 = (Udp6hdr*)(bp->rp);
		ipmove(dest, h6->udpdst);
		ipmove(source, h6->udpsrc);
		psource = nhgets(h6->udpsport);
		pdest = nhgets(h6->udpdport);
		break;
	default:
		panic("udpadvise: version %d", version);
		return;  /* to avoid a warning */
	}

	/* Look for a connection */