devip: implement source specific routing

This commit is contained in:
cinap_lenrek 2018-04-08 21:15:00 +02:00
parent dc8432d459
commit c2dd9b1da7
12 changed files with 1069 additions and 1003 deletions

View file

@ -74,7 +74,7 @@ freeblistchain(Block *bp)
}
/*
* create a new arp entry for an ip address.
* create a new arp entry for an ip address on ifc.
*/
static Arpent*
newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt)
@ -82,7 +82,6 @@ newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt)
uint t;
Block *xp;
Arpent *a, *e, *f, **l;
Medium *m = ifc->m;
int empty;
/* find oldest entry */
@ -128,10 +127,9 @@ newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt)
a->hash = *l;
*l = a;
memmove(a->ip, ip, sizeof(a->ip));
ipmove(a->ip, ip);
a->utime = NOW;
a->ctime = 0;
a->type = m;
a->rtime = NOW + ReTransTimer;
a->rxtsrem = MAX_MULTICAST_SOLICIT;
@ -172,8 +170,10 @@ cleanarpent(Arp *arp, Arpent *a)
a->utime = 0;
a->ctime = 0;
a->type = 0;
a->state = 0;
a->ifc = nil;
a->ifcid = 0;
/* take out of current chain */
l = &arp->hash[haship(a->ip)];
@ -198,7 +198,6 @@ cleanarpent(Arp *arp, Arpent *a)
a->hash = nil;
freeblistchain(a->hold);
a->hold = a->last = nil;
a->ifc = nil;
}
/*
@ -212,7 +211,6 @@ arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac)
{
int hash;
Arpent *a;
Medium *type = ifc->m;
uchar v6ip[IPaddrlen];
if(version == V4){
@ -223,11 +221,9 @@ arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac)
qlock(arp);
hash = haship(ip);
for(a = arp->hash[hash]; a != nil; a = a->hash){
if(ipcmp(ip, a->ip) == 0)
if(type == a->type)
if(a->ifc == ifc && a->ifcid == ifc->ifcid && ipcmp(ip, a->ip) == 0)
break;
}
if(a == nil){
a = newarp6(arp, ip, ifc, (version != V4));
a->state = AWAIT;
@ -245,7 +241,7 @@ arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac)
return a; /* return with arp qlocked */
}
memmove(mac, a->mac, a->type->maclen);
memmove(mac, a->mac, ifc->m->maclen);
/* remove old entries */
if(NOW - a->ctime > 15*60*1000)
@ -286,63 +282,53 @@ arpresolve(Arp *arp, Arpent *a, Medium *type, uchar *mac)
l = &f->nextrxt;
}
}
memmove(a->mac, mac, type->maclen);
a->type = type;
a->state = AOK;
a->utime = NOW;
bp = a->hold;
assert(bp->list == nil);
a->hold = a->last = nil;
qunlock(arp);
return bp;
}
void
arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
int
arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *src, int refresh)
{
Arp *arp;
Route *r;
Arpent *a, *f, **l;
Ipifc *ifc;
Medium *type;
Block *bp, *next;
Medium *m;
uchar v6ip[IPaddrlen];
arp = fs->arp;
if(n != 6)
return;
switch(version){
case V4:
r = v4lookup(fs, ip, nil);
r = v4lookup(fs, ip, src, nil);
v4tov6(v6ip, ip);
ip = v6ip;
break;
case V6:
r = v6lookup(fs, ip, nil);
r = v6lookup(fs, ip, src, nil);
break;
default:
panic("arpenter: version %d", version);
return; /* to supress warnings */
return -1; /* to supress warnings */
}
if(r == nil)
return;
ifc = r->ifc;
type = ifc->m;
if(r == nil || (ifc = r->ifc) == nil || (m = ifc->m) == nil || m->maclen != n || m->maclen == 0)
return -1;
qlock(arp);
for(a = arp->hash[haship(ip)]; a != nil; a = a->hash){
if(a->type != type || (a->state != AWAIT && a->state != AOK))
if(a->state != AWAIT && a->state != AOK)
continue;
if(a->ifc != ifc || a->ifcid != ifc->ifcid)
continue;
if(ipcmp(a->ip, ip) == 0){
a->state = AOK;
memmove(a->mac, mac, type->maclen);
memmove(a->mac, mac, n);
if(version == V6){
/* take out of re-transmit chain */
@ -356,8 +342,6 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
}
}
a->ifc = ifc;
a->ifcid = ifc->ifcid;
bp = a->hold;
a->hold = a->last = nil;
if(version == V4)
@ -367,46 +351,52 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
qunlock(arp);
while(bp != nil){
next = bp->list;
if(waserror()){
freeblistchain(next);
runlock(ifc);
nexterror();
if(!canrlock(ifc)){
freeblistchain(bp);
break;
}
rlock(ifc);
if(ifc->m != nil)
ifc->m->bwrite(ifc, concatblock(bp), version, ip);
else
freeblist(bp);
if(ifc->m != m){
runlock(ifc);
freeblistchain(bp);
break;
}
next = bp->list;
bp->list = nil;
if(waserror()){
runlock(ifc);
freeblistchain(next);
break;
}
m->bwrite(ifc, concatblock(bp), version, ip);
runlock(ifc);
poperror();
bp = next;
}
return;
return 1;
}
}
if(refresh == 0){
a = newarp6(arp, ip, ifc, 0);
a->state = AOK;
a->type = type;
a->ctime = NOW;
memmove(a->mac, mac, type->maclen);
memmove(a->mac, mac, n);
}
qunlock(arp);
return refresh == 0;
}
int
arpwrite(Fs *fs, char *s, int len)
{
int n;
Route *r;
Arp *arp;
Arpent *a;
Arpent *a, *x;
Medium *m;
char *f[4], buf[256];
uchar ip[IPaddrlen], mac[MAClen];
char *f[5], buf[256];
uchar ip[IPaddrlen], src[IPaddrlen], mac[MAClen];
arp = fs->arp;
@ -419,7 +409,7 @@ arpwrite(Fs *fs, char *s, int len)
if(len > 0 && buf[len-1] == '\n')
buf[len-1] = 0;
n = getfields(buf, f, 4, 1, " ");
n = getfields(buf, f, nelem(f), 1, " ");
if(strcmp(f[0], "flush") == 0){
qlock(arp);
for(a = arp->cache; a < &arp->cache[NCACHE]; a++){
@ -428,6 +418,8 @@ arpwrite(Fs *fs, char *s, int len)
a->hash = nil;
a->state = 0;
a->utime = 0;
a->ifc = nil;
a->ifcid = 0;
freeblistchain(a->hold);
a->hold = a->last = nil;
}
@ -442,47 +434,49 @@ arpwrite(Fs *fs, char *s, int len)
default:
error(Ebadarg);
case 3:
if (parseip(ip, f[1]) == -1)
if(parseip(ip, f[1]) == -1)
error(Ebadip);
if(isv4(ip))
r = v4lookup(fs, ip+IPv4off, nil);
else
r = v6lookup(fs, ip, nil);
if(r == nil)
error("Destination unreachable");
m = r->ifc->m;
n = parsemac(mac, f[2], m->maclen);
if((n = parsemac(mac, f[2], sizeof(mac))) <= 0)
error(Ebadarp);
findlocalip(fs, src, ip);
break;
case 4:
m = ipfindmedium(f[1]);
if(m == nil)
if(m == nil || m->maclen == 0)
error(Ebadarp);
if (parseip(ip, f[2]) == -1)
if(parseip(ip, f[2]) == -1)
error(Ebadip);
if((n = parsemac(mac, f[3], sizeof(mac))) != m->maclen)
error(Ebadarp);
findlocalip(fs, src, ip);
break;
case 5:
m = ipfindmedium(f[1]);
if(m == nil || m->maclen == 0)
error(Ebadarp);
if(parseip(ip, f[2]) == -1)
error(Ebadip);
if((n = parsemac(mac, f[3], sizeof(mac))) != m->maclen)
error(Ebadarp);
if(parseip(src, f[4]) == -1)
error(Ebadip);
n = parsemac(mac, f[3], m->maclen);
break;
}
if(m->ares == nil)
error(Ebadarp);
m->ares(fs, V6, ip, mac, n, 0);
if(arpenter(fs, V6, ip, mac, n, src, 0) <= 0)
error("destination unreachable");
} else if(strcmp(f[0], "del") == 0){
if(n != 2)
if (n != 2)
error(Ebadarg);
if (parseip(ip, f[1]) == -1)
error(Ebadip);
qlock(arp);
for(a = arp->hash[haship(ip)]; a != nil; a = a->hash)
if(memcmp(ip, a->ip, sizeof(a->ip)) == 0)
break;
if(a != nil){
cleanarpent(arp, a);
memset(a->ip, 0, sizeof(a->ip));
memset(a->mac, 0, sizeof(a->mac));
for(a = arp->hash[haship(ip)]; a != nil; a = x){
x = a->hash;
if(ipcmp(ip, a->ip) == 0){
cleanarpent(arp, a);
memset(a->ip, 0, sizeof(a->ip));
memset(a->mac, 0, sizeof(a->mac));
}
}
qunlock(arp);
} else
@ -491,13 +485,6 @@ arpwrite(Fs *fs, char *s, int len)
return len;
}
enum
{
Alinelen= 90,
};
char *aformat = "%-6.6s %-8.8s %-40.40I %-32.32s\n";
static void
convmac(char *p, uchar *mac, int n)
{
@ -506,34 +493,40 @@ convmac(char *p, uchar *mac, int n)
}
int
arpread(Arp *arp, char *p, ulong offset, int len)
arpread(Arp *arp, char *s, ulong offset, int len)
{
uchar ip[IPaddrlen], src[IPaddrlen];
char mac[2*MAClen+1], *p, *state;
Ipifc *ifc;
Arpent *a;
int n;
char mac[2*MAClen+1];
long n, o;
if(offset % Alinelen)
return 0;
offset = offset/Alinelen;
len = len/Alinelen;
n = 0;
p = s;
o = -offset;
for(a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++){
if(a->state == 0)
if(a->state == 0 || (ifc = a->ifc) == nil || a->ifcid != ifc->ifcid)
continue;
if(offset > 0){
offset--;
continue;
}
len--;
qlock(arp);
convmac(mac, a->mac, a->type->maclen);
n += sprint(p+n, aformat, a->type->name, arpstate[a->state], a->ip, mac);
state = arpstate[a->state];
ipmove(ip, a->ip);
convmac(mac, a->mac, ifc->m->maclen);
qunlock(arp);
ipv6local(ifc, src, ip);
n = snprint(p, len, "%-6.6s %-4.4s %-40.40I %-16.16s %I\n",
ifc->m->name, state, ip, mac, src);
if(o < 0) {
if(n > -o)
memmove(p, p-o, n+o);
o += n;
} else {
len -= n;
p += n;
}
}
return n;
return p - s;
}
void
@ -547,7 +540,7 @@ ndpsendsol(Fs *f, Ipifc *ifc, Arpent *a)
ipmove(src, ((Ip6hdr*)a->last->rp)->src);
arprelease(f->arp, a);
if(iplocalonifc(ifc, src) || ipproxyifc(f, ifc, src))
if(iplocalonifc(ifc, src) != nil || ipproxyifc(f, ifc, src))
goto send;
} else {
arprelease(f->arp, a);

View file

@ -848,7 +848,7 @@ setladdrport(Conv* c, char* str, int announcing)
else {
if(parseip(addr, str) == -1)
return Ebadip;
if(ipforme(c->p->f, addr) || ipismulticast(addr))
if(ipforme(c->p->f, addr) != 0 || ipismulticast(addr))
ipmove(c->laddr, addr);
else
return "not a local IP address";

View file

@ -33,9 +33,9 @@ static void etherunbind(Ipifc *ifc);
static void etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia);
static void etherremmulti(Ipifc *ifc, uchar *a, uchar *ia);
static void etherareg(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy);
static Block* multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac);
static void sendarp(Ipifc *ifc, Arpent *a);
static void sendgarp(Ipifc *ifc, uchar*);
static int multicastea(uchar *ea, uchar *ip);
static void recvarpproc(void*);
static void resolveaddr6(Ipifc *ifc, Arpent *a);
@ -53,8 +53,7 @@ Medium ethermedium =
.bwrite= etherbwrite,
.addmulti= etheraddmulti,
.remmulti= etherremmulti,
.ares= arpenter,
.areg= sendgarp,
.areg= etherareg,
.pref2addr= etherpref2addr,
};
@ -70,8 +69,7 @@ Medium gbemedium =
.bwrite= etherbwrite,
.addmulti= etheraddmulti,
.remmulti= etherremmulti,
.ares= arpenter,
.areg= sendgarp,
.areg= etherareg,
.pref2addr= etherpref2addr,
};
@ -271,7 +269,7 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
/* get mac address of destination */
a = arpget(er->f->arp, bp, version, ifc, ip, mac);
if(a){
if(a != nil){
/* check for broadcast or multicast */
bp = multicastarp(er->f, a, ifc->m, mac);
if(bp==nil){
@ -471,8 +469,8 @@ sendarp(Ipifc *ifc, Arpent *a)
arprelease(er->f->arp, a);
n = sizeof(Etherarp);
if(n < a->type->mintu)
n = a->type->mintu;
if(n < ifc->m->mintu)
n = ifc->m->mintu;
bp = allocb(n);
memset(bp->rp, 0, n);
e = (Etherarp*)bp->rp;
@ -536,10 +534,6 @@ sendgarp(Ipifc *ifc, uchar *ip)
Etherarp *e;
Etherrock *er = ifc->arg;
/* don't arp for our initial non address */
if(ipcmp(ip, IPnoaddr) == 0)
return;
n = sizeof(Etherarp);
if(n < ifc->m->mintu)
n = ifc->m->mintu;
@ -585,7 +579,7 @@ recvarp(Ipifc *ifc)
case ARPREPLY:
/* check for machine using my ip address */
v4tov6(ip, e->spa);
if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
if(iplocalonifc(ifc, ip) != nil || ipproxyifc(er->f, ifc, ip)){
if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
print("arprep: 0x%E/0x%E also has ip addr %V\n",
e->s, e->sha, e->spa);
@ -594,14 +588,13 @@ recvarp(Ipifc *ifc)
}
/* make sure we're not entering broadcast addresses */
if(ipcmp(ip, ipbroadcast) == 0 ||
!memcmp(e->sha, etherbroadcast, sizeof(e->sha))){
if(ipcmp(ip, ipbroadcast) == 0 || memcmp(e->sha, etherbroadcast, sizeof(e->sha)) == 0){
print("arprep: 0x%E/0x%E cannot register broadcast address %I\n",
e->s, e->sha, e->spa);
break;
}
arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0);
arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), e->tpa, 0);
break;
case ARPREQUEST:
@ -611,9 +604,9 @@ recvarp(Ipifc *ifc)
/* check for machine using my ip or ether address */
v4tov6(ip, e->spa);
if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
if(iplocalonifc(ifc, ip) != nil || ipproxyifc(er->f, ifc, ip)){
if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
if (memcmp(eprinted, e->spa, sizeof(e->spa))){
if(memcmp(eprinted, e->spa, sizeof(e->spa)) != 0){
/* print only once */
print("arpreq: 0x%E also has ip addr %V\n", e->sha, e->spa);
memmove(eprinted, e->spa, sizeof(e->spa));
@ -627,12 +620,11 @@ recvarp(Ipifc *ifc)
}
/* refresh what we know about sender */
arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 1);
arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), e->tpa, 1);
/* answer only requests for our address or systems we're proxying for */
v4tov6(ip, e->tpa);
if(!iplocalonifc(ifc, ip))
if(!ipproxyifc(er->f, ifc, ip))
if(iplocalonifc(ifc, ip) == nil && !ipproxyifc(er->f, ifc, ip))
break;
n = sizeof(Etherarp);
@ -742,7 +734,7 @@ ethermediumlink(void)
static void
etherpref2addr(uchar *pref, uchar *ea)
{
pref[8] = ea[0] | 0x2;
pref[8] = ea[0] ^ 0x2;
pref[9] = ea[1];
pref[10] = ea[2];
pref[11] = 0xFF;
@ -751,3 +743,31 @@ etherpref2addr(uchar *pref, uchar *ea)
pref[14] = ea[4];
pref[15] = ea[5];
}
static void
etherareg(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy)
{
static char tdad[] = "dad6";
uchar mcast[IPaddrlen];
if(ipcmp(ip, IPnoaddr) == 0)
return;
if(isv4(ip)){
sendgarp(ifc, ip);
return;
}
if(!iptentative(f, ip)){
icmpna(f, proxy, v6allnodesL, ip, ifc->mac, 1<<5);
return;
}
/* temporarily add route for duplicate address detection */
ipv62smcast(mcast, ip);
addroute(f, mcast, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
remroute(f, mcast, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
}

View file

@ -200,7 +200,7 @@ ip4reply(Fs *f, uchar ip4[4])
if(ipismulticast(addr))
return 0;
i = ipforme(f, addr);
return i == 0 || (i & Runi) != 0;
return i == 0 || i == Runi;
}
static int
@ -211,7 +211,7 @@ ip4me(Fs *f, uchar ip4[4])
v4tov6(addr, ip4);
if(ipismulticast(addr))
return 0;
return (ipforme(f, addr) & Runi) != 0;
return ipforme(f, addr) == Runi;
}
void
@ -401,7 +401,7 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
break;
case Unreachable:
if(p->code >= nelem(unreachcode)) {
snprint(m2, sizeof m2, "unreachable %V->%V code %d",
snprint(m2, sizeof m2, "unreachable %V -> %V code %d",
p->src, p->dst, p->code);
msg = m2;
} else
@ -452,7 +452,7 @@ raise:
freeblist(bp);
}
void
static void
icmpadvise(Proto *icmp, Block *bp, char *msg)
{
Conv **c, *s;
@ -478,7 +478,7 @@ icmpadvise(Proto *icmp, Block *bp, char *msg)
freeblist(bp);
}
int
static int
icmpstats(Proto *icmp, char *buf, int len)
{
Icmppriv *priv;

View file

@ -211,7 +211,7 @@ newIPICMP(int packetlen)
return nbp;
}
void
static void
icmpadvise6(Proto *icmp, Block *bp, char *msg)
{
ushort recid;
@ -223,7 +223,8 @@ icmpadvise6(Proto *icmp, Block *bp, char *msg)
for(c = icmp->conv; *c; c++) {
s = *c;
if(s->lport == recid && ipcmp(s->raddr, p->dst) == 0){
if(s->lport == recid)
if(ipcmp(s->laddr, p->dst) == 0 || ipcmp(s->raddr, p->dst) == 0){
if(s->ignoreadvice)
break;
qhangup(s->rq, msg);
@ -280,7 +281,7 @@ icmpkick6(void *x, Block *bp)
ipoput6(c->p->f, bp, 0, c->ttl, c->tos, nil);
}
char*
static char*
icmpctl6(Conv *c, char **argv, int argc)
{
Icmpcb6 *icb;
@ -311,10 +312,14 @@ goticmpkt6(Proto *icmp, Block *bp, int muxkey)
for(c = icmp->conv; *c; c++){
s = *c;
if(s->lport == recid && ipcmp(s->raddr, addr) == 0){
if(s->lport != recid)
continue;
if(ipcmp(s->laddr, addr) == 0){
qpass(s->rq, concatblock(bp));
return;
}
if(ipcmp(s->raddr, addr) == 0)
qpass(s->rq, copyblock(bp, blocklen(bp)));
}
freeblist(bp);
@ -416,7 +421,7 @@ icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
np->ttl = HOP_LIMIT;
np->vcf[0] = 0x06 << 4;
ipriv->out[NbrAdvert]++;
netlog(f, Logicmp, "sending neighbor advertisement %I\n", src);
netlog(f, Logicmp, "sending neighbor advertisement %I\n", targ);
ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
}
@ -692,26 +697,19 @@ targettype(Fs *f, Ipifc *ifc, uchar *target)
int t;
rlock(ifc);
if(ipproxyifc(f, ifc, target)) {
runlock(ifc);
return Tuniproxy;
}
for(lifc = ifc->lifc; lifc; lifc = lifc->next)
if(ipcmp(lifc->local, target) == 0) {
t = (lifc->tentative)? Tunitent: Tunirany;
runlock(ifc);
return t;
}
if((lifc = iplocalonifc(ifc, target)) != nil)
t = lifc->tentative? Tunitent: Tunirany;
else if(ipproxyifc(f, ifc, target))
t = Tuniproxy;
else
t = 0;
runlock(ifc);
return 0;
return t;
}
static void
icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
{
int refresh = 1;
char *msg, m2[128];
uchar pktflags;
uchar *packet = bp->rp;
@ -797,16 +795,12 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
/* fall through */
case Tuniproxy:
if(ipcmp(np->src, v6Unspecified) != 0) {
arpenter(icmp->f, V6, np->src, np->lnaddr,
8*np->olen-2, 0);
if(ipv6local(ipifc, lsrc, np->src)) {
arpenter(icmp->f, V6, np->src, np->lnaddr, 8*np->olen-2, lsrc, 0);
pktflags |= Sflag;
}
if(!ipv6local(ipifc, lsrc, np->src))
break;
icmpna(icmp->f, lsrc,
(ipcmp(np->src, v6Unspecified) == 0?
v6allnodesL: np->src),
} else
ipmove(lsrc, np->target);
icmpna(icmp->f, lsrc, (pktflags & Sflag) ? np->src : v6allnodesL,
np->target, ipifc->mac, pktflags);
break;
case Tunitent:
@ -830,9 +824,10 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
* the arp table.
*/
lifc = iplocalonifc(ipifc, np->target);
if(lifc && lifc->tentative)
refresh = 0;
arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, refresh);
if(lifc != nil && lifc->tentative)
arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, np->target, 0);
else if(ipv6local(ipifc, lsrc, np->target))
arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, lsrc, 1);
freeblist(bp);
break;
@ -846,7 +841,7 @@ raise:
freeblist(bp);
}
int
static int
icmpstats6(Proto *icmp6, char *buf, int len)
{
Icmppriv6 *priv;
@ -872,6 +867,14 @@ extern char* icmpannounce(Conv *c, char **argv, int argc);
extern char* icmpconnect(Conv *c, char **argv, int argc);
extern void icmpclose(Conv *c);
static void
icmpclose6(Conv *c)
{
Icmpcb6 *icb = (Icmpcb6*)c->ptcl;
icb->headers = 0;
icmpclose(c);
}
void
icmp6init(Fs *fs)
{
@ -883,7 +886,7 @@ icmp6init(Fs *fs)
icmp6->announce = icmpannounce;
icmp6->state = icmpstate;
icmp6->create = icmpcreate6;
icmp6->close = icmpclose;
icmp6->close = icmpclose6;
icmp6->rcv = icmpiput6;
icmp6->stats = icmpstats6;
icmp6->ctl = icmpctl6;

View file

@ -124,7 +124,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
Block *xp, *nb;
Ip4hdr *eh, *feh;
int lid, len, seglen, chunk, dlen, blklen, offset, medialen;
Route *r, *sr;
Route *r;
IP *ip;
int rv = 0;
@ -154,24 +154,16 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
goto free;
}
r = v4lookup(f, eh->dst, rh);
if(r == nil){
r = v4lookup(f, eh->dst, eh->src, rh);
if(r == nil || (ifc = r->ifc) == nil){
ip->stats[OutNoRoutes]++;
netlog(f, Logip, "no interface %V\n", eh->dst);
netlog(f, Logip, "no interface %V -> %V\n", eh->src, eh->dst);
rv = -1;
goto free;
}
ifc = r->ifc;
if(r->type & (Rifc|Runi))
if(r->type & (Rifc|Runi|Rbcast|Rmulti))
gate = eh->dst;
else
if(r->type & (Rbcast|Rmulti)) {
gate = eh->dst;
sr = v4lookup(f, eh->src, nil);
if(sr != nil && (sr->type & Runi))
ifc = sr->ifc;
}
else
gate = r->v4.gate;
@ -380,7 +372,7 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
/* don't forward to source's network */
rh.r = nil;
r = v4lookup(f, h->dst, &rh);
r = v4lookup(f, h->dst, h->src, &rh);
if(r == nil || r->ifc == ifc){
ip->stats[OutDiscards]++;
freeblist(bp);

View file

@ -39,7 +39,7 @@ enum
Maxproto= 20,
Maxincall= 10,
Nchans= 1024,
MAClen= 16, /* longest mac address */
MAClen= 8, /* longest mac address */
MAXTTL= 255,
DFLTTOS= 0,
@ -242,18 +242,8 @@ struct Medium
/* process packets written to 'data' */
void (*pktin)(Fs *f, Ipifc *ifc, Block *bp);
/* routes for router boards */
void (*addroute)(Ipifc *ifc, int, uchar*, uchar*, uchar*, int);
void (*remroute)(Ipifc *ifc, int, uchar*, uchar*);
void (*flushroutes)(Ipifc *ifc);
/* for routing multicast groups */
void (*joinmulti)(Ipifc *ifc, uchar *a, uchar *ia);
void (*leavemulti)(Ipifc *ifc, uchar *a, uchar *ia);
/* address resolution */
void (*ares)(Fs*, int, uchar*, uchar*, int, int); /* resolve */
void (*areg)(Ipifc*, uchar*); /* register */
void (*areg)(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy); /* register */
/* v6 address generation */
void (*pref2addr)(uchar *pref, uchar *ea);
@ -268,6 +258,7 @@ struct Iplifc
uchar mask[IPaddrlen];
uchar remote[IPaddrlen];
uchar net[IPaddrlen];
uchar type; /* ruoute type */
uchar tentative; /* =1 => v6 dup disc on, =0 => confirmed unique */
uchar onlink; /* =1 => onlink, =0 offlink. */
uchar autoflag; /* v6 autonomous flag */
@ -509,13 +500,11 @@ void ifclogclose(Fs*, Chan*);
* iproute.c
*/
typedef struct RouteTree RouteTree;
typedef struct Routewalk Routewalk;
typedef struct V4route V4route;
typedef struct V6route V6route;
enum
{
/* type bits */
Rv4= (1<<0), /* this is a version 4 route */
Rifc= (1<<1), /* this route is a directly connected interface */
@ -524,27 +513,18 @@ enum
Rbcast= (1<<4), /* a broadcast self address */
Rmulti= (1<<5), /* a multicast self address */
Rproxy= (1<<6), /* this route should be proxied */
};
struct Routewalk
{
int o;
int h;
char* p;
char* e;
void* state;
void (*walk)(Route*, Routewalk*);
Rsrc= (1<<7), /* source specific route */
};
struct RouteTree
{
Route* right;
Route* left;
Route* mid;
Route *mid;
Route *left;
Route *right;
Ipifc *ifc;
uchar ifcid; /* must match ifc->id */
uchar depth;
uchar type;
uchar ifcid; /* must match ifc->id */
Ipifc *ifc;
char tag[4];
int ref;
};
@ -553,6 +533,10 @@ struct V4route
{
ulong address;
ulong endaddress;
ulong source;
ulong endsource;
uchar gate[IPv4addrlen];
};
@ -560,6 +544,10 @@ struct V6route
{
ulong address[IPllen];
ulong endaddress[IPllen];
ulong source[IPllen];
ulong endsource[IPllen];
uchar gate[IPaddrlen];
};
@ -572,17 +560,14 @@ struct Route
V4route v4;
};
};
extern void v4addroute(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 v6delroute(Fs *f, uchar *a, uchar *mask, int dolock);
extern Route* v4lookup(Fs *f, uchar *a, Routehint *h);
extern Route* v6lookup(Fs *f, uchar *a, Routehint *h);
extern void addroute(Fs *f, uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, char *tag);
extern void remroute(Fs *f, uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, char *tag);
extern Route* v4lookup(Fs *f, uchar *a, uchar *s, Routehint *h);
extern Route* v6lookup(Fs *f, uchar *a, uchar *s, Routehint *h);
extern long routeread(Fs *f, char*, ulong, int);
extern long routewrite(Fs *f, Chan*, char*, int);
extern void routetype(int, char*);
extern void ipwalkroutes(Fs*, Routewalk*);
extern void convroute(Route*, uchar*, uchar*, uchar*, char*, int*);
extern void routetype(int type, char p[8]);
/*
* devip.c
@ -607,7 +592,6 @@ struct Arpent
{
uchar ip[IPaddrlen];
uchar mac[MAClen];
Medium *type; /* media type */
Arpent* hash;
Block* hold;
Block* last;
@ -627,7 +611,7 @@ extern int arpwrite(Fs*, char*, int);
extern Arpent* arpget(Arp*, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *h);
extern void arprelease(Arp*, Arpent *a);
extern Block* arpresolve(Arp*, Arpent *a, Medium *type, uchar *mac);
extern void arpenter(Fs*, int version, uchar *ip, uchar *mac, int len, int norefresh);
extern int arpenter(Fs*, int version, uchar *ip, uchar *mac, int n, uchar *src, int norefresh);
extern void ndpsendsol(Fs*, Ipifc*, Arpent*);
/*
@ -674,21 +658,16 @@ extern Medium* ipfindmedium(char *name);
extern void addipmedium(Medium *med);
extern int ipforme(Fs*, uchar *addr);
extern int iptentative(Fs*, uchar *addr);
extern int ipisbm(uchar *);
extern int ipismulticast(uchar *);
extern Ipifc* findipifc(Fs*, uchar *remote, int type);
extern int ipisbm(uchar *ip);
extern int ipismulticast(uchar *ip);
extern Ipifc* findipifc(Fs*, uchar *local, uchar *remote, int type);
extern Ipifc* findipifcstr(Fs *f, char *s);
extern void findlocalip(Fs*, uchar *local, uchar *remote);
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 Iplifc* ipremoteonifc(Ipifc *ifc, uchar *ip);
extern int ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip);
extern int ipismulticast(uchar *ip);
extern int ipisbooting(void);
extern int ipifccheckin(Ipifc *ifc, Medium *med);
extern void ipifccheckout(Ipifc *ifc);
extern int ipifcgrab(Ipifc *ifc);
extern void ipifcaddroute(Fs*, int, uchar*, uchar*, uchar*, int);
extern void ipifcremroute(Fs*, int, uchar*, uchar*);
extern void ipifcremmulti(Conv *c, uchar *ma, uchar *ia);
extern void ipifcaddmulti(Conv *c, uchar *ma, uchar *ia);
extern char* ipifcrem(Ipifc *ifc, char **argv, int argc);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
IP *ip;
Ip6hdr *eh;
Ipifc *ifc;
Route *r, *sr;
Route *r;
ip = f->ip;
@ -74,23 +74,16 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
goto free;
}
r = v6lookup(f, eh->dst, rh);
if(r == nil){
r = v6lookup(f, eh->dst, eh->src, rh);
if(r == nil || (r->type & Rv4) != 0 || (ifc = r->ifc) == nil){
ip->stats[OutNoRoutes]++;
netlog(f, Logip, "no interface %I\n", eh->dst);
netlog(f, Logip, "no interface %I -> %I\n", eh->src, eh->dst);
rv = -1;
goto free;
}
ifc = r->ifc;
if(r->type & (Rifc|Runi))
if(r->type & (Rifc|Runi|Rbcast|Rmulti))
gate = eh->dst;
else if(r->type & (Rbcast|Rmulti)) {
gate = eh->dst;
sr = v6lookup(f, eh->src, nil);
if(sr && (sr->type & Runi))
ifc = sr->ifc;
}
else
gate = r->v6.gate;
@ -226,7 +219,6 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
{
int hl, hop, tos, notforme, tentative;
uchar proto;
uchar v6dst[IPaddrlen];
IP *ip;
Ip6hdr *h;
Proto *p;
@ -251,10 +243,8 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
}
h = (Ip6hdr *)bp->rp;
memmove(&v6dst[0], &h->dst[0], IPaddrlen);
notforme = ipforme(f, v6dst) == 0;
tentative = iptentative(f, v6dst);
notforme = ipforme(f, h->dst) == 0;
tentative = iptentative(f, h->dst);
if(tentative && h->proto != ICMPv6) {
print("tentative addr, drop\n");
@ -290,8 +280,8 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
/* don't forward to source's network */
rh.r = nil;
r = v6lookup(f, h->dst, &rh);
if(r == nil || r->ifc == ifc){
r = v6lookup(f, h->dst, h->src, &rh);
if(r == nil || (r->type & Rv4) != 0 || r->ifc == ifc){
ip->stats[OutDiscards]++;
freeblist(bp);
return;

View file

@ -564,10 +564,10 @@ rudpiput(Proto *rudp, Ipifc *ifc, Block *bp)
c->rport = rport;
/* reply with the same ip address (if not broadcast) */
if(ipforme(f, laddr) == Runi)
ipmove(c->laddr, laddr);
else
if(ipforme(f, laddr) != Runi)
ipv6local(ifc, c->laddr, c->raddr);
else
ipmove(c->laddr, laddr);
}
break;
}

View file

@ -864,8 +864,7 @@ tcpmtu(Route *r, int version, uint *scale)
* otherwise, we use the default MSS which assumes a
* safe minimum MTU of 1280 bytes for V6.
*/
if(r != nil){
ifc = r->ifc;
if(r != nil && (ifc = r->ifc) != nil){
mtu = ifc->maxtu - ifc->m->hsize;
if(version == V4)
return mtu - (TCP4_PKT + TCP4_HDRSIZE);
@ -1314,7 +1313,7 @@ tcpsndsyn(Conv *s, Tcpctl *tcb)
tcb->sndsyntime = NOW;
/* set desired mss and scale */
tcb->mss = tcpmtu(v6lookup(s->p->f, s->raddr, s), s->ipversion, &tcb->scale);
tcb->mss = tcpmtu(v6lookup(s->p->f, s->raddr, s->laddr, s), s->ipversion, &tcb->scale);
tpriv = s->p->priv;
tpriv->stats[Mss] = tcb->mss;
}
@ -1492,7 +1491,7 @@ sndsynack(Proto *tcp, Limbo *lp)
seg.ack = lp->irs+1;
seg.flags = SYN|ACK;
seg.urg = 0;
seg.mss = tcpmtu(v6lookup(tcp->f, lp->raddr, nil), lp->version, &scale);
seg.mss = tcpmtu(v6lookup(tcp->f, lp->raddr, lp->laddr, nil), lp->version, &scale);
seg.wnd = QMAX;
/* if the other side set scale, we should too */
@ -1768,7 +1767,7 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
tcb->flags |= SYNACK;
/* set desired mss and scale */
tcb->mss = tcpmtu(v6lookup(s->p->f, src, s), version, &tcb->scale);
tcb->mss = tcpmtu(v6lookup(s->p->f, src, dst, s), version, &tcb->scale);
/* our sending max segment size cannot be bigger than what he asked for */
if(lp->mss != 0 && lp->mss < tcb->mss)