shithub: riscv

Download patch

ref: 20cbb88e32ece30dd984ab658c365f574790d6ba
parent: 87df80019e3676583f2d60d500179ddcfabab584
parent: 71f807873b43a4d2a2e2c9d1acbe1d97b5fdf18c
author: cinap_lenrek <[email protected]>
date: Sun Mar 18 03:53:10 EDT 2018

merge

--- a/sys/src/9/ip/arp.c
+++ b/sys/src/9/ip/arp.c
@@ -539,7 +539,6 @@
 extern int
 rxmitsols(Arp *arp)
 {
-	uint sflag;
 	Block *next, *xp;
 	Arpent *a, *b, **l;
 	Fs *f;
@@ -582,8 +581,8 @@
 
 
 	qunlock(arp);	/* for icmpns */
-	if((sflag = ipv6anylocal(ifc, ipsrc)) != SRC_UNSPEC) 
-		icmpns(f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac); 
+	if(ipv6local(ifc, ipsrc, a->ip)) 
+		icmpns(f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac); 
 
 	runlock(ifc);
 	qlock(arp);	
--- a/sys/src/9/ip/devip.c
+++ b/sys/src/9/ip/devip.c
@@ -919,12 +919,7 @@
 			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;
+	c->ipversion = convipvers(c);
 
 	return nil;
 }
@@ -1150,12 +1145,6 @@
 			if (parseip(ia, cb->f[1]) == -1)
 				error(Ebadip);
 			ipifcremmulti(c, c->raddr, ia);
-		} else if(strcmp(cb->f[0], "maxfragsize") == 0){
-			if(cb->nf < 2)
-				error("maxfragsize needs size");
-
-			c->maxfragsize = (int)strtol(cb->f[1], nil, 0);
-			
 		} else if(x->ctl != nil) {
 			p = x->ctl(c, cb->f, cb->nf);
 			if(p != nil)
@@ -1329,7 +1318,6 @@
 	c->lport = 0;
 	c->rport = 0;
 	c->restricted = 0;
-	c->maxfragsize = 0;
 	c->ttl = MAXTTL;
 	qreopen(c->rq);
 	qreopen(c->wq);
--- a/sys/src/9/ip/esp.c
+++ b/sys/src/9/ip/esp.c
@@ -267,17 +267,6 @@
 }
 
 static int
-convipvers(Conv *c)
-{
-	if((memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
-	    memcmp(c->laddr, v4prefix, IPv4off) == 0) ||
-	    ipcmp(c->raddr, IPnoaddr) == 0)
-		return V4;
-	else
-		return V6;
-}
-
-static int
 pktipvers(Fs *f, Block **bpp)
 {
 	if (*bpp == nil || BLEN(*bpp) == 0) {
--- a/sys/src/9/ip/ethermedium.c
+++ b/sys/src/9/ip/ethermedium.c
@@ -477,7 +477,7 @@
 	memset(bp->rp, 0, n);
 	e = (Etherarp*)bp->rp;
 	memmove(e->tpa, a->ip+IPv4off, sizeof(e->tpa));
-	ipv4local(ifc, e->spa);
+	ipv4local(ifc, e->spa, e->tpa);
 	memmove(e->sha, ifc->mac, sizeof(e->sha));
 	memset(e->d, 0xff, sizeof(e->d));		/* ethernet broadcast */
 	memmove(e->s, ifc->mac, sizeof(e->s));
@@ -496,7 +496,6 @@
 static void
 resolveaddr6(Ipifc *ifc, Arpent *a)
 {
-	int sflag;
 	Block *bp;
 	Etherrock *er = ifc->arg;
 	uchar ipsrc[IPaddrlen];
@@ -526,8 +525,8 @@
 	a->rxtsrem--;
 	arprelease(er->f->arp, a);
 
-	if(sflag = ipv6anylocal(ifc, ipsrc))
-		icmpns(er->f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);
+	if(ipv6local(ifc, ipsrc, a->ip))
+		icmpns(er->f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac);
 }
 
 /*
--- a/sys/src/9/ip/icmp6.c
+++ b/sys/src/9/ip/icmp6.c
@@ -331,7 +331,7 @@
 	ipmove(addr, p->src);
 	if(!isv6mcast(p->dst))
 		ipmove(p->src, p->dst);
-	else if (!ipv6anylocal(ifc, p->src))
+	else if (!ipv6local(ifc, p->src, addr))
 		return nil;
 	ipmove(p->dst, addr);
 	p->type = EchoReplyV6;
@@ -440,7 +440,7 @@
 	np = (IPICMP *)nbp->rp;
 
 	rlock(ifc);
-	if(ipv6anylocal(ifc, np->src))
+	if(ipv6local(ifc, np->src, p->src))
 		netlog(f, Logicmp, "send icmphostunr -> src %I dst %I\n", p->src, p->dst);
 	else {
 		netlog(f, Logicmp, "icmphostunr fail -> src %I dst %I\n", p->src, p->dst);
@@ -487,7 +487,7 @@
 	nbp = newIPICMP(sz);
 	np = (IPICMP *) nbp->rp;
 
-	if(ipv6anylocal(ifc, np->src))
+	if(ipv6local(ifc, np->src, p->src))
 		netlog(f, Logicmp, "send icmpttlexceeded6 -> src %I dst %I\n",
 			p->src, p->dst);
 	else {
@@ -526,7 +526,7 @@
 	nbp = newIPICMP(sz);
 	np = (IPICMP *)nbp->rp;
 
-	if(ipv6anylocal(ifc, np->src))
+	if(ipv6local(ifc, np->src, p->src))
 		netlog(f, Logicmp, "send icmppkttoobig6 -> src %I dst %I\n",
 			p->src, p->dst);
 	else {
@@ -778,18 +778,11 @@
 			}
 			bp->rp -= IPICMPSZ;
 		}
-
 		goticmpkt6(icmp, bp, 0);
 		break;
 
 	case RouterAdvert:
 	case RouterSolicit:
-		/* using lsrc as a temp, munge hdr for goticmp6 */
-		if (0) {
-			memmove(lsrc, p->src, IPaddrlen);
-			memmove(p->src, p->dst, IPaddrlen);
-			memmove(p->dst, lsrc, IPaddrlen);
-		}
 		goticmpkt6(icmp, bp, p->type);
 		break;
 
@@ -809,21 +802,21 @@
 					8*np->olen-2, 0);
 				pktflags |= Sflag;
 			}
-			if(ipv6local(ipifc, lsrc))
-				icmpna(icmp->f, lsrc,
-					(ipcmp(np->src, v6Unspecified) == 0?
-						v6allnodesL: np->src),
-					np->target, ipifc->mac, pktflags);
-			else
-				freeblist(bp);
+			if(!ipv6local(ipifc, lsrc, np->src))
+				break;
+			icmpna(icmp->f, lsrc,
+				(ipcmp(np->src, v6Unspecified) == 0?
+					v6allnodesL: np->src),
+				np->target, ipifc->mac, pktflags);
 			break;
-
 		case Tunitent:
-			/* not clear what needs to be done. send up
-			 * an icmp mesg saying don't use this address? */
-		default:
-			freeblist(bp);
+			/*
+			 * not clear what needs to be done. send up
+			 * an icmp mesg saying don't use this address?
+			 */
+			break;
 		}
+		freeblist(bp);
 		break;
 
 	case NbrAdvert:
@@ -839,8 +832,7 @@
 		lifc = iplocalonifc(ipifc, np->target);
 		if(lifc && lifc->tentative)
 			refresh = 0;
-		arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2,
-			refresh);
+		arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, refresh);
 		freeblist(bp);
 		break;
 
--- a/sys/src/9/ip/ip.c
+++ b/sys/src/9/ip/ip.c
@@ -63,8 +63,6 @@
 
 	v6p->hp.rxmithost	= 1000;		/* v6 RETRANS_TIMER */
 
-	v6p->cdrouter 		= -1;
-
 	f->v6p			= v6p;
 }
 
@@ -118,7 +116,7 @@
 }
 
 int
-ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c)
+ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
 {
 	Ipifc *ifc;
 	uchar *gate;
@@ -156,7 +154,7 @@
 		goto free;
 	}
 
-	r = v4lookup(f, eh->dst, c);
+	r = v4lookup(f, eh->dst, rh);
 	if(r == nil){
 		ip->stats[OutNoRoutes]++;
 		netlog(f, Logip, "no interface %V\n", eh->dst);
@@ -193,10 +191,7 @@
 		goto raise;
 
 	/* If we dont need to fragment just send it */
-	if(c && c->maxfragsize && c->maxfragsize < ifc->maxtu)
-		medialen = c->maxfragsize - ifc->m->hsize;
-	else
-		medialen = ifc->maxtu - ifc->m->hsize;
+	medialen = ifc->maxtu - ifc->m->hsize;
 	if(len <= medialen) {
 		if(!gating)
 			hnputs(eh->id, incref(&ip->id4));
@@ -315,8 +310,6 @@
 	int notforme;
 	uchar *dp, v6dst[IPaddrlen];
 	IP *ip;
-	Route *r;
-	Conv conv;
 
 	if(BLKIPVER(bp) != IP_VER4) {
 		ipiput6(f, ifc, bp);
@@ -377,6 +370,9 @@
 
 	/* route */
 	if(notforme) {
+		Route *r;
+		Routehint rh;
+
 		if(!ip->iprouting){
 			freeblist(bp);
 			return;
@@ -383,9 +379,8 @@
 		}
 
 		/* don't forward to source's network */
-		memmove(&conv, ifc->conv, sizeof conv);
-		conv.r = nil;
-		r = v4lookup(f, h->dst, &conv);
+		rh.r = nil;
+		r = v4lookup(f, h->dst, &rh);
 		if(r == nil || r->ifc == ifc){
 			ip->stats[OutDiscards]++;
 			freeblist(bp);
@@ -419,7 +414,7 @@
 		ip->stats[ForwDatagrams]++;
 		tos = h->tos;
 		hop = h->ttl;
-		ipoput4(f, bp, 1, hop - 1, tos, &conv);
+		ipoput4(f, bp, 1, hop - 1, tos, &rh);
 		return;
 	}
 
--- a/sys/src/9/ip/ip.h
+++ b/sys/src/9/ip/ip.h
@@ -21,10 +21,10 @@
 typedef struct	Arpent	Arpent;
 typedef struct	Arp Arp;
 typedef struct	Route	Route;
+typedef struct	Routehint Routehint;
 
 typedef struct	Routerparams	Routerparams;
 typedef struct 	Hostparams	Hostparams;
-typedef struct 	v6router	v6router;
 typedef struct	v6params	v6params;
 
 #pragma incomplete Arp
@@ -164,6 +164,12 @@
 	uchar	dst[4];		/* IP destination */
 };
 
+struct Routehint
+{
+	Route	*r;			/* last route used */
+	ulong	rgen;			/* routetable generation for *r */
+};
+
 /*
  *  one per conversation directory
  */
@@ -191,8 +197,6 @@
 	int	length;
 	int	state;
 
-	int	maxfragsize;		/* If set, used for fragmentation */
-
 	/* udp specific */
 	int	headers;		/* data src/dst headers in udp */
 	int	reliable;		/* true if reliable udp */
@@ -217,8 +221,7 @@
 
 	void*	ptcl;			/* protocol specific stuff */
 
-	Route	*r;			/* last route used */
-	ulong	rgen;			/* routetable generation for *r */
+	Routehint;
 };
 
 struct Medium
@@ -443,23 +446,10 @@
 	long	ndbmtime;
 };
 
-/* one per default router known to host */
-struct v6router {
-	uchar	inuse;
-	Ipifc	*ifc;
-	int	ifcid;
-	uchar	routeraddr[IPaddrlen];
-	long	ltorigin;
-	Routerparams	rp;
-};
-
 struct v6params
 {
 	Routerparams	rp;		/* v6 params, one copy per node now */
 	Hostparams	hp;
-	v6router	v6rlist[3];	/* max 3 default routers, currently */
-	int		cdrouter;	/* uses only v6rlist[cdrouter] if   */
-					/* cdrouter >= 0. */
 };
 
 
@@ -586,8 +576,8 @@
 extern void	v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type);
 extern void	v4delroute(Fs *f, uchar *a, uchar *mask, int dolock);
 extern void	v6delroute(Fs *f, uchar *a, uchar *mask, int dolock);
-extern Route*	v4lookup(Fs *f, uchar *a, Conv *c);
-extern Route*	v6lookup(Fs *f, uchar *a, Conv *c);
+extern Route*	v4lookup(Fs *f, uchar *a, Routehint *h);
+extern Route*	v6lookup(Fs *f, uchar *a, Routehint *h);
 extern long	routeread(Fs *f, char*, ulong, int);
 extern long	routewrite(Fs *f, Chan*, char*, int);
 extern void	routetype(int, char*);
@@ -654,6 +644,7 @@
 extern void	v4tov6(uchar *v6, uchar *v4);
 extern int	v6tov4(uchar *v4, uchar *v6);
 extern int	eipfmt(Fmt*);
+extern int	convipvers(Conv *c);
 
 #define	ipmove(x, y) memmove(x, y, IPaddrlen)
 #define	ipcmp(x, y) ( (x)[IPaddrlen-1] != (y)[IPaddrlen-1] || memcmp(x, y, IPaddrlen) )
@@ -686,9 +677,8 @@
 extern int	ipismulticast(uchar *);
 extern Ipifc*	findipifc(Fs*, uchar *remote, int type);
 extern void	findlocalip(Fs*, uchar *local, uchar *remote);
-extern int	ipv4local(Ipifc *ifc, uchar *addr);
-extern int	ipv6local(Ipifc *ifc, uchar *addr);
-extern int	ipv6anylocal(Ipifc *ifc, uchar *addr);
+extern int	ipv4local(Ipifc *ifc, uchar *local, uchar *remote);
+extern int	ipv6local(Ipifc *ifc, uchar *local, uchar *remote);
 extern Iplifc*	iplocalonifc(Ipifc *ifc, uchar *ip);
 extern int	ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip);
 extern int	ipismulticast(uchar *ip);
@@ -714,8 +704,8 @@
 extern ushort	ipcsum(uchar*);
 extern void	ipiput4(Fs*, Ipifc*, Block*);
 extern void	ipiput6(Fs*, Ipifc*, Block*);
-extern int	ipoput4(Fs*, Block*, int, int, int, Conv*);
-extern int	ipoput6(Fs*, Block*, int, int, int, Conv*);
+extern int	ipoput4(Fs*, Block*, int, int, int, Routehint*);
+extern int	ipoput6(Fs*, Block*, int, int, int, Routehint*);
 extern int	ipstats(Fs*, char*, int);
 extern ushort	ptclbsum(uchar*, int);
 extern ushort	ptclcsum(Block*, int, int);
--- a/sys/src/9/ip/ipaux.c
+++ b/sys/src/9/ip/ipaux.c
@@ -366,3 +366,12 @@
 	unlock(ht);
 	return nil;
 }
+
+int
+convipvers(Conv *c)
+{
+	if(isv4(c->raddr) && isv4(c->laddr) || ipcmp(c->raddr, IPnoaddr) == 0)
+		return V4;
+	else
+		return V6;
+}
--- a/sys/src/9/ip/ipifc.c
+++ b/sys/src/9/ip/ipifc.c
@@ -1095,7 +1095,7 @@
  *	0		- no match
  *	Runi
  *	Rbcast
- *	Rmcast
+ *	Rmulti
  */
 int
 ipforme(Fs *f, uchar *addr)
@@ -1163,7 +1163,6 @@
 
 enum {
 	unknownv6,		/* UGH */
-//	multicastv6,
 	unspecifiedv6,
 	linklocalv6,
 	globalv6,
@@ -1237,140 +1236,135 @@
 			return;
 		}
 	}
+	ipmove(local, IPnoaddr);
 }
 
-/*
- *  find the local address 'closest' to the remote system, copy it to
- *  local and return the ifc for that address
- */
-void
-findlocalip(Fs *f, uchar *local, uchar *remote)
+static int
+comprefixlen(uchar *a, uchar *b, int n)
 {
-	int version, atype = unspecifiedv6, atypel = unknownv6;
-	int atyper, deprecated;
-	uchar gate[IPaddrlen], gnet[IPaddrlen];
-	Ipifc *ifc;
-	Iplifc *lifc;
-	Route *r;
+	int i, c;
 
-	USED(atype);
-	USED(atypel);
-	qlock(f->ipifc);
-	r = v6lookup(f, remote, nil);
- 	version = (memcmp(remote, v4prefix, IPv4off) == 0)? V4: V6;
-
-	if(r != nil){
-		ifc = r->ifc;
-		if(r->type & Rv4)
-			v4tov6(gate, r->v4.gate);
-		else {
-			ipmove(gate, r->v6.gate);
-			ipmove(local, v6Unspecified);
-		}
-
-		switch(version) {
-		case V4:
-			/* find ifc address closest to the gateway to use */
-			for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-				maskip(gate, lifc->mask, gnet);
-				if(ipcmp(gnet, lifc->net) == 0){
-					ipmove(local, lifc->local);
-					goto out;
-				}
-			}
-			break;
-		case V6:
-			/* find ifc address with scope matching the destination */
-			atyper = v6addrtype(remote);
-			deprecated = 0;
-			for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-				atypel = v6addrtype(lifc->local);
-				/* prefer appropriate scope */
-				if(atypel > atype && atype < atyper ||
-				   atypel < atype && atype > atyper){
-					ipmove(local, lifc->local);
-					deprecated = !v6addrcurr(lifc);
-					atype = atypel;
-				} else if(atypel == atype){
-					/* avoid deprecated addresses */
-					if(deprecated && v6addrcurr(lifc)){
-						ipmove(local, lifc->local);
-						atype = atypel;
-						deprecated = 0;
-					}
-				}
-				if(atype == atyper && !deprecated)
-					goto out;
-			}
-			if(atype >= atyper)
-				goto out;
-			break;
-		default:
-			panic("findlocalip: version %d", version);
-		}
+	for(i = 0; i < n; i++){
+		if((c = a[i] ^ b[i]) == 0)
+			continue;
+		for(i <<= 3; (c & 0x80) == 0; i++)
+			c <<= 1;
+		return i;
 	}
-
-	switch(version){
-	case V4:
-		findprimaryipv4(f, local);
-		break;
-	case V6:
-		findprimaryipv6(f, local);
-		break;
-	default:
-		panic("findlocalip2: version %d", version);
-	}
-
-out:
-	qunlock(f->ipifc);
+	return i << 3;
 }
 
 /*
- *  return first v4 address associated with an interface
+ *  return v4 address associated with an interface close to remote
  */
 int
-ipv4local(Ipifc *ifc, uchar *addr)
+ipv4local(Ipifc *ifc, uchar *local, uchar *remote)
 {
 	Iplifc *lifc;
+	int a, b;
 
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-		if(isv4(lifc->local)){
-			memmove(addr, lifc->local+IPv4off, IPv4addrlen);
-			return 1;
+	b = -1;
+	for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
+		if(!isv4(lifc->local))
+			continue;
+		a = comprefixlen(lifc->local+IPv4off, remote, IPv4addrlen);
+		if(a > b){
+			b = a;
+			memmove(local, lifc->local+IPv4off, IPv4addrlen);
 		}
 	}
-	return 0;
+	return b >= 0;
 }
 
 /*
- *  return first v6 address associated with an interface
+ *  return v6 address associated with an interface close to remote
  */
 int
-ipv6local(Ipifc *ifc, uchar *addr)
+ipv6local(Ipifc *ifc, uchar *local, uchar *remote)
 {
+	struct {
+		int	atype;
+		int	deprecated;
+		int	comprefixlen;
+	} a, b;
+	int atype;
 	Iplifc *lifc;
 
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-		if(!isv4(lifc->local) && !(lifc->tentative)){
-			ipmove(addr, lifc->local);
-			return 1;
+	if(isv4(remote)){
+		ipmove(local, v4prefix);
+		return ipv4local(ifc, local+IPv4off, remote+IPv4off);
+	}
+
+	atype = v6addrtype(remote);
+	ipmove(local, v6Unspecified);
+	b.atype = unknownv6;
+	b.deprecated = 1;
+	b.comprefixlen = 0;
+
+	for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
+		if(lifc->tentative)
+			continue;
+
+		a.atype = v6addrtype(lifc->local);
+		a.deprecated = !v6addrcurr(lifc);
+		a.comprefixlen = comprefixlen(lifc->local, remote, IPaddrlen);
+
+		/* prefer appropriate scope */
+		if(a.atype != b.atype){
+			if(a.atype > b.atype && b.atype < atype ||
+			   a.atype < b.atype && b.atype > atype)
+				goto Good;
+			continue;
 		}
+		/* prefer non-deprecated addresses */
+		if(a.deprecated != b.deprecated){
+			if(b.deprecated)
+				goto Good;
+			continue;
+		}
+		/* prefer longer common prefix */
+		if(a.comprefixlen != b.comprefixlen){
+			if(a.comprefixlen > b.comprefixlen)
+				goto Good;
+			continue;
+		}
+		continue;
+	Good:
+		b = a;
+		ipmove(local, lifc->local);
 	}
-	return 0;
+
+	return b.atype >= atype;
 }
 
-int
-ipv6anylocal(Ipifc *ifc, uchar *addr)
+/*
+ *  find the local address 'closest' to the remote system, copy it to local
+ */
+void
+findlocalip(Fs *f, uchar *local, uchar *remote)
 {
-	Iplifc *lifc;
+	Route *r;
 
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-		if(!isv4(lifc->local)){
-			ipmove(addr, lifc->local);
-			return SRC_UNI;
+	qlock(f->ipifc);
+	if((r = v6lookup(f, remote, nil)) != nil){
+		if(r->type & Runi){
+			ipmove(local, remote);
+			goto out;
 		}
+		if((r->type & (Rifc|Rbcast|Rmulti|Rv4)) == Rv4){
+			ipmove(local, v4prefix);
+			if(ipv4local(r->ifc, local+IPv4off, r->v4.gate))
+				goto out;
+		}
+		if(ipv6local(r->ifc, local, remote))
+			goto out;
 	}
-	return SRC_UNSPEC;
+	if(isv4(remote))
+		findprimaryipv4(f, local);
+	else
+		findprimaryipv6(f, local);
+out:
+	qunlock(f->ipifc);
 }
 
 /*
@@ -1604,29 +1598,6 @@
 		}
 	}
 }
-
-
-/* added for new v6 mesg types */
-static void
-adddefroute6(Fs *f, uchar *gate, int force)
-{
-	Route *r;
-
-	r = v6lookup(f, v6Unspecified, nil);
-	/*
-	 * route entries generated by all other means take precedence
-	 * over router announcements.
-	 */
-	if (r && !force && strcmp(r->tag, "ra") != 0)
-		return;
-
-	v6delroute(f, v6Unspecified, v6Unspecified, 1);
-	v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0);
-}
-
-enum {
-	Ngates = 3,
-};
 
 char*
 ipifcadd6(Ipifc *ifc, char**argv, int argc)
--- a/sys/src/9/ip/iproute.c
+++ b/sys/src/9/ip/iproute.c
@@ -323,7 +323,6 @@
 }
 
 #define	V6H(a)	(((a)[IPllen-1] & 0x07ffffff)>>(32-Lroot-5))
-#define ISDFLT(a, mask, tag) ((ipcmp((a),v6Unspecified)==0) && (ipcmp((mask),v6Unspecified)==0) && (strcmp((tag), "ra")!=0))
 
 void
 v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type)
@@ -333,12 +332,6 @@
 	ulong x, y;
 	int h, eh;
 
-	/*
-	if(ISDFLT(a, mask, tag))
-		f->v6p->cdrouter = -1;
-	*/
-
-
 	for(h = 0; h < IPllen; h++){
 		x = nhgetl(a+4*h);
 		y = nhgetl(mask+4*h);
@@ -482,7 +475,7 @@
 }
 
 Route*
-v4lookup(Fs *f, uchar *a, Conv *c)
+v4lookup(Fs *f, uchar *a, Routehint *rh)
 {
 	Route *p, *q;
 	ulong la;
@@ -489,8 +482,8 @@
 	uchar gate[IPaddrlen];
 	Ipifc *ifc;
 
-	if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v4routegeneration)
-		return c->r;
+	if(rh != nil && rh->r != nil && rh->r->ifc != nil && rh->rgen == v4routegeneration)
+		return rh->r;
 
 	la = nhgetl(a);
 	q = nil;
@@ -517,9 +510,9 @@
 		q->ifcid = ifc->ifcid;
 	}
 
-	if(c != nil){
-		c->r = q;
-		c->rgen = v4routegeneration;
+	if(rh != nil){
+		rh->r = q;
+		rh->rgen = v4routegeneration;
 	}
 
 	return q;
@@ -526,7 +519,7 @@
 }
 
 Route*
-v6lookup(Fs *f, uchar *a, Conv *c)
+v6lookup(Fs *f, uchar *a, Routehint *rh)
 {
 	Route *p, *q;
 	ulong la[IPllen];
@@ -536,18 +529,18 @@
 	Ipifc *ifc;
 
 	if(memcmp(a, v4prefix, IPv4off) == 0){
-		q = v4lookup(f, a+IPv4off, c);
+		q = v4lookup(f, a+IPv4off, rh);
 		if(q != nil)
 			return q;
 	}
 
-	if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v6routegeneration)
-		return c->r;
+	if(rh != nil && rh->r != nil && rh->r->ifc != nil && rh->rgen == v6routegeneration)
+		return rh->r;
 
 	for(h = 0; h < IPllen; h++)
 		la[h] = nhgetl(a+4*h);
 
-	q = 0;
+	q = nil;
 	for(p=f->v6root[V6H(la)]; p;){
 		for(h = 0; h < IPllen; h++){
 			x = la[h];
@@ -588,9 +581,10 @@
 		q->ifc = ifc;
 		q->ifcid = ifc->ifcid;
 	}
-	if(c != nil){
-		c->r = q;
-		c->rgen = v6routegeneration;
+
+	if(rh != nil){
+		rh->r = q;
+		rh->rgen = v6routegeneration;
 	}
 	
 	return q;
--- a/sys/src/9/ip/ipv6.c
+++ b/sys/src/9/ip/ipv6.c
@@ -28,7 +28,7 @@
 int		unfraglen(Block *bp, uchar *nexthdr, int setfh);
 
 int
-ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c)
+ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
 {
 	int medialen, len, chunk, uflen, flen, seglen, lid, offset, fragoff;
 	int morefrags, blklen, rv = 0, tentative;
@@ -74,9 +74,8 @@
 		goto free;
 	}
 
-	r = v6lookup(f, eh->dst, c);
+	r = v6lookup(f, eh->dst, rh);
 	if(r == nil){
-//		print("no route for %I, src %I free\n", eh->dst, eh->src);
 		ip->stats[OutNoRoutes]++;
 		netlog(f, Logip, "no interface %I\n", eh->dst);
 		rv = -1;
@@ -231,7 +230,6 @@
 	IP *ip;
 	Ip6hdr *h;
 	Proto *p;
-	Route *r, *sr;
 
 	ip = f->ip;
 	ip->stats[InReceives]++;
@@ -274,6 +272,9 @@
 
 	/* route */
 	if(notforme) {
+		Route *r;
+		Routehint rh;
+
 		if(!ip->iprouting){
 			freeblist(bp);
 			return;
@@ -288,10 +289,9 @@
 		}
 			
 		/* don't forward to source's network */
-		sr = v6lookup(f, h->src, nil);
-		r  = v6lookup(f, h->dst, nil);
-
-		if(r == nil || sr == r){
+		rh.r = nil;
+		r  = v6lookup(f, h->dst, &rh);
+		if(r == nil || r->ifc == ifc){
 			ip->stats[OutDiscards]++;
 			freeblist(bp);
 			return;
@@ -315,7 +315,7 @@
 		h = (Ip6hdr *)bp->rp;
 		tos = IPV6CLASS(h);
 		hop = h->ttl;
-		ipoput6(f, bp, 1, hop-1, tos, nil);
+		ipoput6(f, bp, 1, hop-1, tos, &rh);
 		return;
 	}
 
--- a/sys/src/9/ip/rudp.c
+++ b/sys/src/9/ip/rudp.c
@@ -567,7 +567,7 @@
 			if(ipforme(f, laddr) == Runi)
 				ipmove(c->laddr, laddr);
 			else
-				v4tov6(c->laddr, ifc->lifc->local);
+				ipv6local(ifc, c->laddr, c->raddr);
 		}
 		break;
 	}
--- a/sys/src/9/ip/udp.c
+++ b/sys/src/9/ip/udp.c
@@ -189,7 +189,7 @@
 	Udppriv *upriv;
 	Fs *f;
 	int version;
-	Conv *rc;
+	Routehint *rh;
 
 	upriv = c->p->priv;
 	f = c->p->f;
@@ -222,18 +222,12 @@
 	}
 
 	if(ucb->headers) {
-		if(memcmp(laddr, v4prefix, IPv4off) == 0
-		|| ipcmp(laddr, IPnoaddr) == 0)
-			version = 4;
+		if(isv4(laddr) || ipcmp(laddr, IPnoaddr) == 0)
+			version = V4;
 		else
-			version = 6;
+			version = V6;
 	} else {
-		if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
-			memcmp(c->laddr, v4prefix, IPv4off) == 0)
-			|| ipcmp(c->raddr, IPnoaddr) == 0)
-			version = 4;
-		else
-			version = 6;
+		version = convipvers(c);
 	}
 
 	dlen = blocklen(bp);
@@ -253,7 +247,7 @@
 			v6tov4(uh4->udpdst, raddr);
 			hnputs(uh4->udpdport, rport);
 			v6tov4(uh4->udpsrc, laddr);
-			rc = nil;
+			rh = nil;
 		} else {
 			v6tov4(uh4->udpdst, c->raddr);
 			hnputs(uh4->udpdport, c->rport);
@@ -260,7 +254,7 @@
 			if(ipcmp(c->laddr, IPnoaddr) == 0)
 				findlocalip(f, c->laddr, c->raddr);
 			v6tov4(uh4->udpsrc, c->laddr);
-			rc = c;
+			rh = c;
 		}
 		hnputs(uh4->udpsport, c->lport);
 		hnputs(uh4->udplen, ptcllen);
@@ -269,7 +263,7 @@
 		hnputs(uh4->udpcksum,
 		       ptclcsum(bp, UDP4_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ));
 		uh4->vihl = IP_VER4;
-		ipoput4(f, bp, 0, c->ttl, c->tos, rc);
+		ipoput4(f, bp, 0, c->ttl, c->tos, rh);
 		break;
 
 	case V6:
@@ -287,7 +281,7 @@
 			ipmove(uh6->udpdst, raddr);
 			hnputs(uh6->udpdport, rport);
 			ipmove(uh6->udpsrc, laddr);
-			rc = nil;
+			rh = nil;
 		} else {
 			ipmove(uh6->udpdst, c->raddr);
 			hnputs(uh6->udpdport, c->rport);
@@ -294,7 +288,7 @@
 			if(ipcmp(c->laddr, IPnoaddr) == 0)
 				findlocalip(f, c->laddr, c->raddr);
 			ipmove(uh6->udpsrc, c->laddr);
-			rc = c;
+			rh = c;
 		}
 		hnputs(uh6->udpsport, c->lport);
 		hnputs(uh6->udplen, ptcllen);
@@ -306,7 +300,7 @@
 		uh6->viclfl[0] = IP_VER6;
 		hnputs(uh6->len, ptcllen);
 		uh6->nextheader = IP_UDPPROTO;
-		ipoput6(f, bp, 0, c->ttl, c->tos, rc);
+		ipoput6(f, bp, 0, c->ttl, c->tos, rh);
 		break;
 
 	default:
@@ -336,7 +330,7 @@
 	upriv->ustats.udpInDatagrams++;
 
 	uh4 = (Udp4hdr*)(bp->rp);
-	version = ((uh4->vihl&0xF0)==IP_VER6) ? 6 : 4;
+	version = ((uh4->vihl&0xF0)==IP_VER6) ? V6 : V4;
 
 	/* Put back pseudo header for checksum
 	 * (remember old values for icmpnoconv()) */
@@ -424,18 +418,8 @@
 	if(c->state == Announced){
 		if(ucb->headers == 0){
 			/* create a new conversation */
-			if(ipforme(f, laddr) != Runi) {
-				switch(version){
-				case V4:
-					v4tov6(laddr, ifc->lifc->local);
-					break;
-				case V6:
-					ipmove(laddr, ifc->lifc->local);
-					break;
-				default:
-					panic("udpiput3: version %d", version);
-				}
-			}
+			if(ipforme(f, laddr) != Runi)
+				ipv6local(ifc, laddr, raddr);
 			c = Fsnewcall(c, raddr, rport, laddr, lport, version);
 			if(c == nil){
 				qunlock(udp);
@@ -533,7 +517,7 @@
 	int version;
 
 	h4 = (Udp4hdr*)(bp->rp);
-	version = ((h4->vihl&0xF0)==IP_VER6) ? 6 : 4;
+	version = ((h4->vihl&0xF0)==IP_VER6) ? V6 : V4;
 
 	switch(version) {
 	case V4:
--- a/sys/src/cmd/ip/ipconfig/ipv6.c
+++ b/sys/src/cmd/ip/ipconfig/ipv6.c
@@ -468,7 +468,6 @@
 recvrarouter(uchar buf[], int pktlen)
 {
 	USED(buf, pktlen);
-	ralog("i am a router and got a router advert");
 }
 
 /* host receiving a router advertisement calls this */