This commit is contained in:
cinap_lenrek 2018-03-18 07:53:10 +01:00
commit 20cbb88e32
14 changed files with 208 additions and 299 deletions

View file

@ -539,7 +539,6 @@ arpread(Arp *arp, char *p, ulong offset, int len)
extern int extern int
rxmitsols(Arp *arp) rxmitsols(Arp *arp)
{ {
uint sflag;
Block *next, *xp; Block *next, *xp;
Arpent *a, *b, **l; Arpent *a, *b, **l;
Fs *f; Fs *f;
@ -582,8 +581,8 @@ rxmitsols(Arp *arp)
qunlock(arp); /* for icmpns */ qunlock(arp); /* for icmpns */
if((sflag = ipv6anylocal(ifc, ipsrc)) != SRC_UNSPEC) if(ipv6local(ifc, ipsrc, a->ip))
icmpns(f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac); icmpns(f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac);
runlock(ifc); runlock(ifc);
qlock(arp); qlock(arp);

View file

@ -919,12 +919,7 @@ Fsstdconnect(Conv *c, char *argv[], int argc)
return p; return p;
} }
if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 && c->ipversion = convipvers(c);
memcmp(c->laddr, v4prefix, IPv4off) == 0)
|| ipcmp(c->raddr, IPnoaddr) == 0)
c->ipversion = V4;
else
c->ipversion = V6;
return nil; return nil;
} }
@ -1150,12 +1145,6 @@ ipwrite(Chan* ch, void *v, long n, vlong off)
if (parseip(ia, cb->f[1]) == -1) if (parseip(ia, cb->f[1]) == -1)
error(Ebadip); error(Ebadip);
ipifcremmulti(c, c->raddr, ia); 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) { } else if(x->ctl != nil) {
p = x->ctl(c, cb->f, cb->nf); p = x->ctl(c, cb->f, cb->nf);
if(p != nil) if(p != nil)
@ -1329,7 +1318,6 @@ retry:
c->lport = 0; c->lport = 0;
c->rport = 0; c->rport = 0;
c->restricted = 0; c->restricted = 0;
c->maxfragsize = 0;
c->ttl = MAXTTL; c->ttl = MAXTTL;
qreopen(c->rq); qreopen(c->rq);
qreopen(c->wq); qreopen(c->wq);

View file

@ -266,17 +266,6 @@ espclose(Conv *c)
memset(ecb, 0, sizeof(Espcb)); 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 static int
pktipvers(Fs *f, Block **bpp) pktipvers(Fs *f, Block **bpp)
{ {

View file

@ -477,7 +477,7 @@ sendarp(Ipifc *ifc, Arpent *a)
memset(bp->rp, 0, n); memset(bp->rp, 0, n);
e = (Etherarp*)bp->rp; e = (Etherarp*)bp->rp;
memmove(e->tpa, a->ip+IPv4off, sizeof(e->tpa)); 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)); memmove(e->sha, ifc->mac, sizeof(e->sha));
memset(e->d, 0xff, sizeof(e->d)); /* ethernet broadcast */ memset(e->d, 0xff, sizeof(e->d)); /* ethernet broadcast */
memmove(e->s, ifc->mac, sizeof(e->s)); memmove(e->s, ifc->mac, sizeof(e->s));
@ -496,7 +496,6 @@ sendarp(Ipifc *ifc, Arpent *a)
static void static void
resolveaddr6(Ipifc *ifc, Arpent *a) resolveaddr6(Ipifc *ifc, Arpent *a)
{ {
int sflag;
Block *bp; Block *bp;
Etherrock *er = ifc->arg; Etherrock *er = ifc->arg;
uchar ipsrc[IPaddrlen]; uchar ipsrc[IPaddrlen];
@ -526,8 +525,8 @@ resolveaddr6(Ipifc *ifc, Arpent *a)
a->rxtsrem--; a->rxtsrem--;
arprelease(er->f->arp, a); arprelease(er->f->arp, a);
if(sflag = ipv6anylocal(ifc, ipsrc)) if(ipv6local(ifc, ipsrc, a->ip))
icmpns(er->f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac); icmpns(er->f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac);
} }
/* /*

View file

@ -331,7 +331,7 @@ mkechoreply6(Block *bp, Ipifc *ifc)
ipmove(addr, p->src); ipmove(addr, p->src);
if(!isv6mcast(p->dst)) if(!isv6mcast(p->dst))
ipmove(p->src, p->dst); ipmove(p->src, p->dst);
else if (!ipv6anylocal(ifc, p->src)) else if (!ipv6local(ifc, p->src, addr))
return nil; return nil;
ipmove(p->dst, addr); ipmove(p->dst, addr);
p->type = EchoReplyV6; p->type = EchoReplyV6;
@ -440,7 +440,7 @@ icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
np = (IPICMP *)nbp->rp; np = (IPICMP *)nbp->rp;
rlock(ifc); 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); netlog(f, Logicmp, "send icmphostunr -> src %I dst %I\n", p->src, p->dst);
else { else {
netlog(f, Logicmp, "icmphostunr fail -> src %I dst %I\n", p->src, p->dst); 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); nbp = newIPICMP(sz);
np = (IPICMP *) nbp->rp; 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", netlog(f, Logicmp, "send icmpttlexceeded6 -> src %I dst %I\n",
p->src, p->dst); p->src, p->dst);
else { else {
@ -526,7 +526,7 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
nbp = newIPICMP(sz); nbp = newIPICMP(sz);
np = (IPICMP *)nbp->rp; 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", netlog(f, Logicmp, "send icmppkttoobig6 -> src %I dst %I\n",
p->src, p->dst); p->src, p->dst);
else { else {
@ -778,18 +778,11 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
} }
bp->rp -= IPICMPSZ; bp->rp -= IPICMPSZ;
} }
goticmpkt6(icmp, bp, 0); goticmpkt6(icmp, bp, 0);
break; break;
case RouterAdvert: case RouterAdvert:
case RouterSolicit: 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); goticmpkt6(icmp, bp, p->type);
break; break;
@ -809,21 +802,21 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
8*np->olen-2, 0); 8*np->olen-2, 0);
pktflags |= Sflag; pktflags |= Sflag;
} }
if(ipv6local(ipifc, lsrc)) if(!ipv6local(ipifc, lsrc, np->src))
icmpna(icmp->f, lsrc, break;
(ipcmp(np->src, v6Unspecified) == 0? icmpna(icmp->f, lsrc,
v6allnodesL: np->src), (ipcmp(np->src, v6Unspecified) == 0?
np->target, ipifc->mac, pktflags); v6allnodesL: np->src),
else np->target, ipifc->mac, pktflags);
freeblist(bp);
break; break;
case Tunitent: case Tunitent:
/* not clear what needs to be done. send up /*
* an icmp mesg saying don't use this address? */ * not clear what needs to be done. send up
default: * an icmp mesg saying don't use this address?
freeblist(bp); */
break;
} }
freeblist(bp);
break; break;
case NbrAdvert: case NbrAdvert:
@ -839,8 +832,7 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
lifc = iplocalonifc(ipifc, np->target); lifc = iplocalonifc(ipifc, np->target);
if(lifc && lifc->tentative) if(lifc && lifc->tentative)
refresh = 0; refresh = 0;
arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, refresh);
refresh);
freeblist(bp); freeblist(bp);
break; break;

View file

@ -63,8 +63,6 @@ ip_init_6(Fs *f)
v6p->hp.rxmithost = 1000; /* v6 RETRANS_TIMER */ v6p->hp.rxmithost = 1000; /* v6 RETRANS_TIMER */
v6p->cdrouter = -1;
f->v6p = v6p; f->v6p = v6p;
} }
@ -118,7 +116,7 @@ iprouting(Fs *f, int on)
} }
int 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; Ipifc *ifc;
uchar *gate; uchar *gate;
@ -156,7 +154,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c)
goto free; goto free;
} }
r = v4lookup(f, eh->dst, c); r = v4lookup(f, eh->dst, rh);
if(r == nil){ if(r == nil){
ip->stats[OutNoRoutes]++; ip->stats[OutNoRoutes]++;
netlog(f, Logip, "no interface %V\n", eh->dst); 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; goto raise;
/* If we dont need to fragment just send it */ /* If we dont need to fragment just send it */
if(c && c->maxfragsize && c->maxfragsize < ifc->maxtu) medialen = ifc->maxtu - ifc->m->hsize;
medialen = c->maxfragsize - ifc->m->hsize;
else
medialen = ifc->maxtu - ifc->m->hsize;
if(len <= medialen) { if(len <= medialen) {
if(!gating) if(!gating)
hnputs(eh->id, incref(&ip->id4)); hnputs(eh->id, incref(&ip->id4));
@ -315,8 +310,6 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
int notforme; int notforme;
uchar *dp, v6dst[IPaddrlen]; uchar *dp, v6dst[IPaddrlen];
IP *ip; IP *ip;
Route *r;
Conv conv;
if(BLKIPVER(bp) != IP_VER4) { if(BLKIPVER(bp) != IP_VER4) {
ipiput6(f, ifc, bp); ipiput6(f, ifc, bp);
@ -377,15 +370,17 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
/* route */ /* route */
if(notforme) { if(notforme) {
Route *r;
Routehint rh;
if(!ip->iprouting){ if(!ip->iprouting){
freeblist(bp); freeblist(bp);
return; return;
} }
/* don't forward to source's network */ /* don't forward to source's network */
memmove(&conv, ifc->conv, sizeof conv); rh.r = nil;
conv.r = nil; r = v4lookup(f, h->dst, &rh);
r = v4lookup(f, h->dst, &conv);
if(r == nil || r->ifc == ifc){ if(r == nil || r->ifc == ifc){
ip->stats[OutDiscards]++; ip->stats[OutDiscards]++;
freeblist(bp); freeblist(bp);
@ -419,7 +414,7 @@ if(r->ifc == nil) panic("nil route ifc");
ip->stats[ForwDatagrams]++; ip->stats[ForwDatagrams]++;
tos = h->tos; tos = h->tos;
hop = h->ttl; hop = h->ttl;
ipoput4(f, bp, 1, hop - 1, tos, &conv); ipoput4(f, bp, 1, hop - 1, tos, &rh);
return; return;
} }

View file

@ -21,10 +21,10 @@ typedef struct Proto Proto;
typedef struct Arpent Arpent; typedef struct Arpent Arpent;
typedef struct Arp Arp; typedef struct Arp Arp;
typedef struct Route Route; typedef struct Route Route;
typedef struct Routehint Routehint;
typedef struct Routerparams Routerparams; typedef struct Routerparams Routerparams;
typedef struct Hostparams Hostparams; typedef struct Hostparams Hostparams;
typedef struct v6router v6router;
typedef struct v6params v6params; typedef struct v6params v6params;
#pragma incomplete Arp #pragma incomplete Arp
@ -164,6 +164,12 @@ struct Ip4hdr
uchar dst[4]; /* IP destination */ uchar dst[4]; /* IP destination */
}; };
struct Routehint
{
Route *r; /* last route used */
ulong rgen; /* routetable generation for *r */
};
/* /*
* one per conversation directory * one per conversation directory
*/ */
@ -191,8 +197,6 @@ struct Conv
int length; int length;
int state; int state;
int maxfragsize; /* If set, used for fragmentation */
/* udp specific */ /* udp specific */
int headers; /* data src/dst headers in udp */ int headers; /* data src/dst headers in udp */
int reliable; /* true if reliable udp */ int reliable; /* true if reliable udp */
@ -217,8 +221,7 @@ struct Conv
void* ptcl; /* protocol specific stuff */ void* ptcl; /* protocol specific stuff */
Route *r; /* last route used */ Routehint;
ulong rgen; /* routetable generation for *r */
}; };
struct Medium struct Medium
@ -443,23 +446,10 @@ struct Fs
long ndbmtime; 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 struct v6params
{ {
Routerparams rp; /* v6 params, one copy per node now */ Routerparams rp; /* v6 params, one copy per node now */
Hostparams hp; 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 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 v4delroute(Fs *f, uchar *a, uchar *mask, int dolock);
extern void v6delroute(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* v4lookup(Fs *f, uchar *a, Routehint *h);
extern Route* v6lookup(Fs *f, uchar *a, Conv *c); extern Route* v6lookup(Fs *f, uchar *a, Routehint *h);
extern long routeread(Fs *f, char*, ulong, int); extern long routeread(Fs *f, char*, ulong, int);
extern long routewrite(Fs *f, Chan*, char*, int); extern long routewrite(Fs *f, Chan*, char*, int);
extern void routetype(int, char*); extern void routetype(int, char*);
@ -654,6 +644,7 @@ extern int isv4(uchar*);
extern void v4tov6(uchar *v6, uchar *v4); extern void v4tov6(uchar *v6, uchar *v4);
extern int v6tov4(uchar *v4, uchar *v6); extern int v6tov4(uchar *v4, uchar *v6);
extern int eipfmt(Fmt*); extern int eipfmt(Fmt*);
extern int convipvers(Conv *c);
#define ipmove(x, y) memmove(x, y, IPaddrlen) #define ipmove(x, y) memmove(x, y, IPaddrlen)
#define ipcmp(x, y) ( (x)[IPaddrlen-1] != (y)[IPaddrlen-1] || memcmp(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 int ipismulticast(uchar *);
extern Ipifc* findipifc(Fs*, uchar *remote, int type); extern Ipifc* findipifc(Fs*, uchar *remote, int type);
extern void findlocalip(Fs*, uchar *local, uchar *remote); extern void findlocalip(Fs*, uchar *local, uchar *remote);
extern int ipv4local(Ipifc *ifc, uchar *addr); extern int ipv4local(Ipifc *ifc, uchar *local, uchar *remote);
extern int ipv6local(Ipifc *ifc, uchar *addr); extern int ipv6local(Ipifc *ifc, uchar *local, uchar *remote);
extern int ipv6anylocal(Ipifc *ifc, uchar *addr);
extern Iplifc* iplocalonifc(Ipifc *ifc, uchar *ip); extern Iplifc* iplocalonifc(Ipifc *ifc, uchar *ip);
extern int ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip); extern int ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip);
extern int ipismulticast(uchar *ip); extern int ipismulticast(uchar *ip);
@ -714,8 +704,8 @@ extern void icmpttlexceeded(Fs*, uchar*, Block*);
extern ushort ipcsum(uchar*); extern ushort ipcsum(uchar*);
extern void ipiput4(Fs*, Ipifc*, Block*); extern void ipiput4(Fs*, Ipifc*, Block*);
extern void ipiput6(Fs*, Ipifc*, Block*); extern void ipiput6(Fs*, Ipifc*, Block*);
extern int ipoput4(Fs*, Block*, int, int, int, Conv*); extern int ipoput4(Fs*, Block*, int, int, int, Routehint*);
extern int ipoput6(Fs*, Block*, int, int, int, Conv*); extern int ipoput6(Fs*, Block*, int, int, int, Routehint*);
extern int ipstats(Fs*, char*, int); extern int ipstats(Fs*, char*, int);
extern ushort ptclbsum(uchar*, int); extern ushort ptclbsum(uchar*, int);
extern ushort ptclcsum(Block*, int, int); extern ushort ptclcsum(Block*, int, int);

View file

@ -366,3 +366,12 @@ iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp)
unlock(ht); unlock(ht);
return nil; return nil;
} }
int
convipvers(Conv *c)
{
if(isv4(c->raddr) && isv4(c->laddr) || ipcmp(c->raddr, IPnoaddr) == 0)
return V4;
else
return V6;
}

View file

@ -1095,7 +1095,7 @@ iptentative(Fs *f, uchar *addr)
* 0 - no match * 0 - no match
* Runi * Runi
* Rbcast * Rbcast
* Rmcast * Rmulti
*/ */
int int
ipforme(Fs *f, uchar *addr) ipforme(Fs *f, uchar *addr)
@ -1163,7 +1163,6 @@ findipifc(Fs *f, uchar *remote, int type)
enum { enum {
unknownv6, /* UGH */ unknownv6, /* UGH */
// multicastv6,
unspecifiedv6, unspecifiedv6,
linklocalv6, linklocalv6,
globalv6, globalv6,
@ -1237,142 +1236,137 @@ findprimaryipv4(Fs *f, uchar *local)
return; 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 * return v4 address associated with an interface close to remote
* local and return the ifc for that address */
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 void
findlocalip(Fs *f, uchar *local, uchar *remote) 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; Route *r;
USED(atype);
USED(atypel);
qlock(f->ipifc); qlock(f->ipifc);
r = v6lookup(f, remote, nil); if((r = v6lookup(f, remote, nil)) != nil){
version = (memcmp(remote, v4prefix, IPv4off) == 0)? V4: V6; if(r->type & Runi){
ipmove(local, remote);
if(r != nil){ goto out;
ifc = r->ifc;
if(r->type & Rv4)
v4tov6(gate, r->v4.gate);
else {
ipmove(gate, r->v6.gate);
ipmove(local, v6Unspecified);
} }
if((r->type & (Rifc|Rbcast|Rmulti|Rv4)) == Rv4){
switch(version) { ipmove(local, v4prefix);
case V4: if(ipv4local(r->ifc, local+IPv4off, r->v4.gate))
/* 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; goto out;
break;
default:
panic("findlocalip: version %d", version);
} }
if(ipv6local(r->ifc, local, remote))
goto out;
} }
if(isv4(remote))
switch(version){
case V4:
findprimaryipv4(f, local); findprimaryipv4(f, local);
break; else
case V6:
findprimaryipv6(f, local); findprimaryipv6(f, local);
break;
default:
panic("findlocalip2: version %d", version);
}
out: out:
qunlock(f->ipifc); 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 * 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* char*
ipifcadd6(Ipifc *ifc, char**argv, int argc) ipifcadd6(Ipifc *ifc, char**argv, int argc)
{ {

View file

@ -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 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 void
v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type) 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; ulong x, y;
int h, eh; int h, eh;
/*
if(ISDFLT(a, mask, tag))
f->v6p->cdrouter = -1;
*/
for(h = 0; h < IPllen; h++){ for(h = 0; h < IPllen; h++){
x = nhgetl(a+4*h); x = nhgetl(a+4*h);
y = nhgetl(mask+4*h); y = nhgetl(mask+4*h);
@ -482,15 +475,15 @@ v6delroute(Fs *f, uchar *a, uchar *mask, int dolock)
} }
Route* Route*
v4lookup(Fs *f, uchar *a, Conv *c) v4lookup(Fs *f, uchar *a, Routehint *rh)
{ {
Route *p, *q; Route *p, *q;
ulong la; ulong la;
uchar gate[IPaddrlen]; uchar gate[IPaddrlen];
Ipifc *ifc; Ipifc *ifc;
if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v4routegeneration) if(rh != nil && rh->r != nil && rh->r->ifc != nil && rh->rgen == v4routegeneration)
return c->r; return rh->r;
la = nhgetl(a); la = nhgetl(a);
q = nil; q = nil;
@ -517,16 +510,16 @@ v4lookup(Fs *f, uchar *a, Conv *c)
q->ifcid = ifc->ifcid; q->ifcid = ifc->ifcid;
} }
if(c != nil){ if(rh != nil){
c->r = q; rh->r = q;
c->rgen = v4routegeneration; rh->rgen = v4routegeneration;
} }
return q; return q;
} }
Route* Route*
v6lookup(Fs *f, uchar *a, Conv *c) v6lookup(Fs *f, uchar *a, Routehint *rh)
{ {
Route *p, *q; Route *p, *q;
ulong la[IPllen]; ulong la[IPllen];
@ -536,18 +529,18 @@ v6lookup(Fs *f, uchar *a, Conv *c)
Ipifc *ifc; Ipifc *ifc;
if(memcmp(a, v4prefix, IPv4off) == 0){ if(memcmp(a, v4prefix, IPv4off) == 0){
q = v4lookup(f, a+IPv4off, c); q = v4lookup(f, a+IPv4off, rh);
if(q != nil) if(q != nil)
return q; return q;
} }
if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v6routegeneration) if(rh != nil && rh->r != nil && rh->r->ifc != nil && rh->rgen == v6routegeneration)
return c->r; return rh->r;
for(h = 0; h < IPllen; h++) for(h = 0; h < IPllen; h++)
la[h] = nhgetl(a+4*h); la[h] = nhgetl(a+4*h);
q = 0; q = nil;
for(p=f->v6root[V6H(la)]; p;){ for(p=f->v6root[V6H(la)]; p;){
for(h = 0; h < IPllen; h++){ for(h = 0; h < IPllen; h++){
x = la[h]; x = la[h];
@ -588,9 +581,10 @@ next: ;
q->ifc = ifc; q->ifc = ifc;
q->ifcid = ifc->ifcid; q->ifcid = ifc->ifcid;
} }
if(c != nil){
c->r = q; if(rh != nil){
c->rgen = v6routegeneration; rh->r = q;
rh->rgen = v6routegeneration;
} }
return q; return q;

View file

@ -28,7 +28,7 @@ static Block* procxtns(IP *ip, Block *bp, int doreasm);
int unfraglen(Block *bp, uchar *nexthdr, int setfh); int unfraglen(Block *bp, uchar *nexthdr, int setfh);
int 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 medialen, len, chunk, uflen, flen, seglen, lid, offset, fragoff;
int morefrags, blklen, rv = 0, tentative; 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; goto free;
} }
r = v6lookup(f, eh->dst, c); r = v6lookup(f, eh->dst, rh);
if(r == nil){ if(r == nil){
// print("no route for %I, src %I free\n", eh->dst, eh->src);
ip->stats[OutNoRoutes]++; ip->stats[OutNoRoutes]++;
netlog(f, Logip, "no interface %I\n", eh->dst); netlog(f, Logip, "no interface %I\n", eh->dst);
rv = -1; rv = -1;
@ -231,7 +230,6 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
IP *ip; IP *ip;
Ip6hdr *h; Ip6hdr *h;
Proto *p; Proto *p;
Route *r, *sr;
ip = f->ip; ip = f->ip;
ip->stats[InReceives]++; ip->stats[InReceives]++;
@ -274,6 +272,9 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
/* route */ /* route */
if(notforme) { if(notforme) {
Route *r;
Routehint rh;
if(!ip->iprouting){ if(!ip->iprouting){
freeblist(bp); freeblist(bp);
return; return;
@ -288,10 +289,9 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
} }
/* don't forward to source's network */ /* don't forward to source's network */
sr = v6lookup(f, h->src, nil); rh.r = nil;
r = v6lookup(f, h->dst, nil); r = v6lookup(f, h->dst, &rh);
if(r == nil || r->ifc == ifc){
if(r == nil || sr == r){
ip->stats[OutDiscards]++; ip->stats[OutDiscards]++;
freeblist(bp); freeblist(bp);
return; return;
@ -315,7 +315,7 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
h = (Ip6hdr *)bp->rp; h = (Ip6hdr *)bp->rp;
tos = IPV6CLASS(h); tos = IPV6CLASS(h);
hop = h->ttl; hop = h->ttl;
ipoput6(f, bp, 1, hop-1, tos, nil); ipoput6(f, bp, 1, hop-1, tos, &rh);
return; return;
} }

View file

@ -567,7 +567,7 @@ rudpiput(Proto *rudp, Ipifc *ifc, Block *bp)
if(ipforme(f, laddr) == Runi) if(ipforme(f, laddr) == Runi)
ipmove(c->laddr, laddr); ipmove(c->laddr, laddr);
else else
v4tov6(c->laddr, ifc->lifc->local); ipv6local(ifc, c->laddr, c->raddr);
} }
break; break;
} }

View file

@ -189,7 +189,7 @@ udpkick(void *x, Block *bp)
Udppriv *upriv; Udppriv *upriv;
Fs *f; Fs *f;
int version; int version;
Conv *rc; Routehint *rh;
upriv = c->p->priv; upriv = c->p->priv;
f = c->p->f; f = c->p->f;
@ -222,18 +222,12 @@ udpkick(void *x, Block *bp)
} }
if(ucb->headers) { if(ucb->headers) {
if(memcmp(laddr, v4prefix, IPv4off) == 0 if(isv4(laddr) || ipcmp(laddr, IPnoaddr) == 0)
|| ipcmp(laddr, IPnoaddr) == 0) version = V4;
version = 4;
else else
version = 6; version = V6;
} else { } else {
if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 && version = convipvers(c);
memcmp(c->laddr, v4prefix, IPv4off) == 0)
|| ipcmp(c->raddr, IPnoaddr) == 0)
version = 4;
else
version = 6;
} }
dlen = blocklen(bp); dlen = blocklen(bp);
@ -253,14 +247,14 @@ udpkick(void *x, Block *bp)
v6tov4(uh4->udpdst, raddr); v6tov4(uh4->udpdst, raddr);
hnputs(uh4->udpdport, rport); hnputs(uh4->udpdport, rport);
v6tov4(uh4->udpsrc, laddr); v6tov4(uh4->udpsrc, laddr);
rc = nil; rh = nil;
} else { } else {
v6tov4(uh4->udpdst, c->raddr); v6tov4(uh4->udpdst, c->raddr);
hnputs(uh4->udpdport, c->rport); hnputs(uh4->udpdport, c->rport);
if(ipcmp(c->laddr, IPnoaddr) == 0) if(ipcmp(c->laddr, IPnoaddr) == 0)
findlocalip(f, c->laddr, c->raddr); findlocalip(f, c->laddr, c->raddr);
v6tov4(uh4->udpsrc, c->laddr); v6tov4(uh4->udpsrc, c->laddr);
rc = c; rh = c;
} }
hnputs(uh4->udpsport, c->lport); hnputs(uh4->udpsport, c->lport);
hnputs(uh4->udplen, ptcllen); hnputs(uh4->udplen, ptcllen);
@ -269,7 +263,7 @@ udpkick(void *x, Block *bp)
hnputs(uh4->udpcksum, hnputs(uh4->udpcksum,
ptclcsum(bp, UDP4_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ)); ptclcsum(bp, UDP4_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ));
uh4->vihl = IP_VER4; uh4->vihl = IP_VER4;
ipoput4(f, bp, 0, c->ttl, c->tos, rc); ipoput4(f, bp, 0, c->ttl, c->tos, rh);
break; break;
case V6: case V6:
@ -287,14 +281,14 @@ udpkick(void *x, Block *bp)
ipmove(uh6->udpdst, raddr); ipmove(uh6->udpdst, raddr);
hnputs(uh6->udpdport, rport); hnputs(uh6->udpdport, rport);
ipmove(uh6->udpsrc, laddr); ipmove(uh6->udpsrc, laddr);
rc = nil; rh = nil;
} else { } else {
ipmove(uh6->udpdst, c->raddr); ipmove(uh6->udpdst, c->raddr);
hnputs(uh6->udpdport, c->rport); hnputs(uh6->udpdport, c->rport);
if(ipcmp(c->laddr, IPnoaddr) == 0) if(ipcmp(c->laddr, IPnoaddr) == 0)
findlocalip(f, c->laddr, c->raddr); findlocalip(f, c->laddr, c->raddr);
ipmove(uh6->udpsrc, c->laddr); ipmove(uh6->udpsrc, c->laddr);
rc = c; rh = c;
} }
hnputs(uh6->udpsport, c->lport); hnputs(uh6->udpsport, c->lport);
hnputs(uh6->udplen, ptcllen); hnputs(uh6->udplen, ptcllen);
@ -306,7 +300,7 @@ udpkick(void *x, Block *bp)
uh6->viclfl[0] = IP_VER6; uh6->viclfl[0] = IP_VER6;
hnputs(uh6->len, ptcllen); hnputs(uh6->len, ptcllen);
uh6->nextheader = IP_UDPPROTO; uh6->nextheader = IP_UDPPROTO;
ipoput6(f, bp, 0, c->ttl, c->tos, rc); ipoput6(f, bp, 0, c->ttl, c->tos, rh);
break; break;
default: default:
@ -336,7 +330,7 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp)
upriv->ustats.udpInDatagrams++; upriv->ustats.udpInDatagrams++;
uh4 = (Udp4hdr*)(bp->rp); 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 /* Put back pseudo header for checksum
* (remember old values for icmpnoconv()) */ * (remember old values for icmpnoconv()) */
@ -424,18 +418,8 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp)
if(c->state == Announced){ if(c->state == Announced){
if(ucb->headers == 0){ if(ucb->headers == 0){
/* create a new conversation */ /* create a new conversation */
if(ipforme(f, laddr) != Runi) { if(ipforme(f, laddr) != Runi)
switch(version){ ipv6local(ifc, laddr, raddr);
case V4:
v4tov6(laddr, ifc->lifc->local);
break;
case V6:
ipmove(laddr, ifc->lifc->local);
break;
default:
panic("udpiput3: version %d", version);
}
}
c = Fsnewcall(c, raddr, rport, laddr, lport, version); c = Fsnewcall(c, raddr, rport, laddr, lport, version);
if(c == nil){ if(c == nil){
qunlock(udp); qunlock(udp);
@ -533,7 +517,7 @@ udpadvise(Proto *udp, Block *bp, char *msg)
int version; int version;
h4 = (Udp4hdr*)(bp->rp); h4 = (Udp4hdr*)(bp->rp);
version = ((h4->vihl&0xF0)==IP_VER6) ? 6 : 4; version = ((h4->vihl&0xF0)==IP_VER6) ? V6 : V4;
switch(version) { switch(version) {
case V4: case V4:

View file

@ -468,7 +468,6 @@ static void
recvrarouter(uchar buf[], int pktlen) recvrarouter(uchar buf[], int pktlen)
{ {
USED(buf, pktlen); USED(buf, pktlen);
ralog("i am a router and got a router advert");
} }
/* host receiving a router advertisement calls this */ /* host receiving a router advertisement calls this */