From 71f807873b43a4d2a2e2c9d1acbe1d97b5fdf18c Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 18 Mar 2018 07:50:48 +0100 Subject: [PATCH] devip: more v6 improvements ipv4local() and ipv6local() now take remote address argument, returning the closest local address to the source. this implements the standartized source address selection rules instead of just returning the first local v4 or v6 address. the source address selection was broken for esp, rudp an udp, blindly assuming ifc->lifc->local being a valid v4 address. use ipv6local() instead. the v6 routing code used to lookup source address route to decide to drop the packet instead of checking the interface on the destination route. factor out the route hint from Conv and put it in Routehint structure. avoiding stack bloat in v4 routing. implement the same trick for v6 avoiding second route lookup in ipoput6. fix memory leak in icmpv6 router solicitation handling. remove old unfinished handling of multiple v6 routers. should implement source specific routes instead. avoid duplication, use common convipvers() function. use isv4() instead of memcmp v4prefix. --- sys/src/9/ip/arp.c | 5 +- sys/src/9/ip/devip.c | 14 +- sys/src/9/ip/esp.c | 11 -- sys/src/9/ip/ethermedium.c | 7 +- sys/src/9/ip/icmp6.c | 42 +++--- sys/src/9/ip/ip.c | 23 ++-- sys/src/9/ip/ip.h | 40 +++--- sys/src/9/ip/ipaux.c | 9 ++ sys/src/9/ip/ipifc.c | 253 ++++++++++++++++--------------------- sys/src/9/ip/iproute.c | 36 +++--- sys/src/9/ip/ipv6.c | 18 +-- sys/src/9/ip/rudp.c | 2 +- sys/src/9/ip/udp.c | 46 +++---- 13 files changed, 208 insertions(+), 298 deletions(-) diff --git a/sys/src/9/ip/arp.c b/sys/src/9/ip/arp.c index 9d650a978..ba158cf29 100644 --- a/sys/src/9/ip/arp.c +++ b/sys/src/9/ip/arp.c @@ -539,7 +539,6 @@ arpread(Arp *arp, char *p, ulong offset, int len) extern int rxmitsols(Arp *arp) { - uint sflag; Block *next, *xp; Arpent *a, *b, **l; Fs *f; @@ -582,8 +581,8 @@ rxmitsols(Arp *arp) 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); diff --git a/sys/src/9/ip/devip.c b/sys/src/9/ip/devip.c index 2629c02ef..18dbf54ff 100644 --- a/sys/src/9/ip/devip.c +++ b/sys/src/9/ip/devip.c @@ -919,12 +919,7 @@ Fsstdconnect(Conv *c, char *argv[], int argc) 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 @@ ipwrite(Chan* ch, void *v, long n, vlong off) 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 @@ retry: c->lport = 0; c->rport = 0; c->restricted = 0; - c->maxfragsize = 0; c->ttl = MAXTTL; qreopen(c->rq); qreopen(c->wq); diff --git a/sys/src/9/ip/esp.c b/sys/src/9/ip/esp.c index 667090953..8fec0c766 100644 --- a/sys/src/9/ip/esp.c +++ b/sys/src/9/ip/esp.c @@ -266,17 +266,6 @@ espclose(Conv *c) memset(ecb, 0, sizeof(Espcb)); } -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) { diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c index 346093795..d8691b0e7 100644 --- a/sys/src/9/ip/ethermedium.c +++ b/sys/src/9/ip/ethermedium.c @@ -477,7 +477,7 @@ sendarp(Ipifc *ifc, Arpent *a) 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 @@ sendarp(Ipifc *ifc, Arpent *a) static void resolveaddr6(Ipifc *ifc, Arpent *a) { - int sflag; Block *bp; Etherrock *er = ifc->arg; uchar ipsrc[IPaddrlen]; @@ -526,8 +525,8 @@ resolveaddr6(Ipifc *ifc, Arpent *a) 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); } /* diff --git a/sys/src/9/ip/icmp6.c b/sys/src/9/ip/icmp6.c index 5557c6042..17d24d623 100644 --- a/sys/src/9/ip/icmp6.c +++ b/sys/src/9/ip/icmp6.c @@ -331,7 +331,7 @@ mkechoreply6(Block *bp, Ipifc *ifc) 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 @@ icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free) 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 @@ icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp) 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 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp) 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 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp) } 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 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp) 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 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp) 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; diff --git a/sys/src/9/ip/ip.c b/sys/src/9/ip/ip.c index 32b95b4b6..6c4d02992 100644 --- a/sys/src/9/ip/ip.c +++ b/sys/src/9/ip/ip.c @@ -63,8 +63,6 @@ ip_init_6(Fs *f) v6p->hp.rxmithost = 1000; /* v6 RETRANS_TIMER */ - v6p->cdrouter = -1; - f->v6p = v6p; } @@ -118,7 +116,7 @@ iprouting(Fs *f, int on) } 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 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) 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 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) 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 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp) int notforme; uchar *dp, v6dst[IPaddrlen]; IP *ip; - Route *r; - Conv conv; if(BLKIPVER(bp) != IP_VER4) { ipiput6(f, ifc, bp); @@ -377,15 +370,17 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp) /* route */ if(notforme) { + Route *r; + Routehint rh; + if(!ip->iprouting){ freeblist(bp); return; } /* 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 @@ if(r->ifc == nil) panic("nil route ifc"); 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; } diff --git a/sys/src/9/ip/ip.h b/sys/src/9/ip/ip.h index 7eb001ba8..84e776e4e 100644 --- a/sys/src/9/ip/ip.h +++ b/sys/src/9/ip/ip.h @@ -21,10 +21,10 @@ typedef struct Proto Proto; 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 @@ struct Ip4hdr 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 @@ struct Conv 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 @@ struct Conv void* ptcl; /* protocol specific stuff */ - Route *r; /* last route used */ - ulong rgen; /* routetable generation for *r */ + Routehint; }; struct Medium @@ -443,23 +446,10 @@ struct Fs 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 v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int 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 int isv4(uchar*); 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 ipisbm(uchar *); 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 void icmpttlexceeded(Fs*, uchar*, Block*); 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); diff --git a/sys/src/9/ip/ipaux.c b/sys/src/9/ip/ipaux.c index fd253dafe..e16249546 100644 --- a/sys/src/9/ip/ipaux.c +++ b/sys/src/9/ip/ipaux.c @@ -366,3 +366,12 @@ iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp) 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; +} diff --git a/sys/src/9/ip/ipifc.c b/sys/src/9/ip/ipifc.c index 84194a70e..3ed24fa60 100644 --- a/sys/src/9/ip/ipifc.c +++ b/sys/src/9/ip/ipifc.c @@ -1095,7 +1095,7 @@ iptentative(Fs *f, uchar *addr) * 0 - no match * Runi * Rbcast - * Rmcast + * Rmulti */ int ipforme(Fs *f, uchar *addr) @@ -1163,7 +1163,6 @@ findipifc(Fs *f, uchar *remote, int type) enum { unknownv6, /* UGH */ -// multicastv6, unspecifiedv6, linklocalv6, globalv6, @@ -1237,142 +1236,137 @@ findprimaryipv4(Fs *f, uchar *local) return; } } + ipmove(local, IPnoaddr); +} + +static int +comprefixlen(uchar *a, uchar *b, int n) +{ + int i, c; + + 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; + } + return i << 3; } /* - * find the local address 'closest' to the remote system, copy it to - * local and return the ifc for that address + * return v4 address associated with an interface close to remote + */ +int +ipv4local(Ipifc *ifc, uchar *local, uchar *remote) +{ + Iplifc *lifc; + int a, b; + + 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 b >= 0; +} + +/* + * return v6 address associated with an interface close to remote + */ +int +ipv6local(Ipifc *ifc, uchar *local, uchar *remote) +{ + struct { + int atype; + int deprecated; + int comprefixlen; + } a, b; + int atype; + Iplifc *lifc; + + 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 b.atype >= atype; +} + +/* + * find the local address 'closest' to the remote system, copy it to local */ void findlocalip(Fs *f, uchar *local, uchar *remote) { - int version, atype = unspecifiedv6, atypel = unknownv6; - int atyper, deprecated; - uchar gate[IPaddrlen], gnet[IPaddrlen]; - Ipifc *ifc; - Iplifc *lifc; Route *r; - 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); + if((r = v6lookup(f, remote, nil)) != nil){ + if(r->type & Runi){ + ipmove(local, remote); + goto out; } - - 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) + if((r->type & (Rifc|Rbcast|Rmulti|Rv4)) == Rv4){ + ipmove(local, v4prefix); + if(ipv4local(r->ifc, local+IPv4off, r->v4.gate)) goto out; - break; - default: - panic("findlocalip: version %d", version); } + if(ipv6local(r->ifc, local, remote)) + goto out; } - - switch(version){ - case V4: + if(isv4(remote)) findprimaryipv4(f, local); - break; - case V6: + else findprimaryipv6(f, local); - break; - default: - panic("findlocalip2: version %d", version); - } - out: qunlock(f->ipifc); } -/* - * return first v4 address associated with an interface - */ -int -ipv4local(Ipifc *ifc, uchar *addr) -{ - Iplifc *lifc; - - for(lifc = ifc->lifc; lifc; lifc = lifc->next){ - if(isv4(lifc->local)){ - memmove(addr, lifc->local+IPv4off, IPv4addrlen); - return 1; - } - } - return 0; -} - -/* - * return first v6 address associated with an interface - */ -int -ipv6local(Ipifc *ifc, uchar *addr) -{ - Iplifc *lifc; - - for(lifc = ifc->lifc; lifc; lifc = lifc->next){ - if(!isv4(lifc->local) && !(lifc->tentative)){ - ipmove(addr, lifc->local); - return 1; - } - } - return 0; -} - -int -ipv6anylocal(Ipifc *ifc, uchar *addr) -{ - Iplifc *lifc; - - for(lifc = ifc->lifc; lifc; lifc = lifc->next){ - if(!isv4(lifc->local)){ - ipmove(addr, lifc->local); - return SRC_UNI; - } - } - return SRC_UNSPEC; -} - /* * see if this address is bound to the interface */ @@ -1605,29 +1599,6 @@ ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip) } } - -/* 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) { diff --git a/sys/src/9/ip/iproute.c b/sys/src/9/ip/iproute.c index 518950309..f6a4be7f1 100644 --- a/sys/src/9/ip/iproute.c +++ b/sys/src/9/ip/iproute.c @@ -323,7 +323,6 @@ v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type) } #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 @@ v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type) 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,15 +475,15 @@ v6delroute(Fs *f, uchar *a, uchar *mask, int dolock) } Route* -v4lookup(Fs *f, uchar *a, Conv *c) +v4lookup(Fs *f, uchar *a, Routehint *rh) { Route *p, *q; ulong la; 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,16 +510,16 @@ v4lookup(Fs *f, uchar *a, Conv *c) q->ifcid = ifc->ifcid; } - if(c != nil){ - c->r = q; - c->rgen = v4routegeneration; + if(rh != nil){ + rh->r = q; + rh->rgen = v4routegeneration; } return q; } 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 @@ v6lookup(Fs *f, uchar *a, Conv *c) 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 @@ next: ; 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; diff --git a/sys/src/9/ip/ipv6.c b/sys/src/9/ip/ipv6.c index 8b50706f4..1fbfedc34 100644 --- a/sys/src/9/ip/ipv6.c +++ b/sys/src/9/ip/ipv6.c @@ -28,7 +28,7 @@ static Block* procxtns(IP *ip, Block *bp, int doreasm); 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 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) 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 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp) IP *ip; Ip6hdr *h; Proto *p; - Route *r, *sr; ip = f->ip; ip->stats[InReceives]++; @@ -274,6 +272,9 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp) /* route */ if(notforme) { + Route *r; + Routehint rh; + if(!ip->iprouting){ freeblist(bp); return; @@ -288,10 +289,9 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp) } /* 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 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp) 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; } diff --git a/sys/src/9/ip/rudp.c b/sys/src/9/ip/rudp.c index cc3da20f6..bbf779b02 100644 --- a/sys/src/9/ip/rudp.c +++ b/sys/src/9/ip/rudp.c @@ -567,7 +567,7 @@ rudpiput(Proto *rudp, Ipifc *ifc, Block *bp) if(ipforme(f, laddr) == Runi) ipmove(c->laddr, laddr); else - v4tov6(c->laddr, ifc->lifc->local); + ipv6local(ifc, c->laddr, c->raddr); } break; } diff --git a/sys/src/9/ip/udp.c b/sys/src/9/ip/udp.c index adaaac0df..fbaabd634 100644 --- a/sys/src/9/ip/udp.c +++ b/sys/src/9/ip/udp.c @@ -189,7 +189,7 @@ udpkick(void *x, Block *bp) Udppriv *upriv; Fs *f; int version; - Conv *rc; + Routehint *rh; upriv = c->p->priv; f = c->p->f; @@ -222,18 +222,12 @@ udpkick(void *x, Block *bp) } 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,14 +247,14 @@ udpkick(void *x, Block *bp) 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); 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 @@ udpkick(void *x, Block *bp) 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,14 +281,14 @@ udpkick(void *x, Block *bp) 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); 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 @@ udpkick(void *x, Block *bp) 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 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp) 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 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp) 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 @@ udpadvise(Proto *udp, Block *bp, char *msg) 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: