devip: fix ipv6 icmp unreachable handling, fix retransmit, fix ifc locking, remove tentative check

This commit is contained in:
cinap_lenrek 2018-04-22 18:54:13 +02:00
parent c80d94304d
commit 20b9326dad
7 changed files with 237 additions and 235 deletions

View file

@ -293,33 +293,38 @@ arpresolve(Arp *arp, Arpent *a, Medium *type, uchar *mac)
} }
int int
arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *src, int refresh) arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *ia, int refresh)
{ {
Arp *arp; Arp *arp;
Route *r; Route *r;
Arpent *a, *f, **l; Arpent *a, *f, **l;
Ipifc *ifc; Ipifc *ifc;
Block *bp, *next; Block *bp, *next;
Medium *m;
uchar v6ip[IPaddrlen]; uchar v6ip[IPaddrlen];
arp = fs->arp; arp = fs->arp;
switch(version){ switch(version){
case V4: case V4:
r = v4lookup(fs, ip, src, nil); r = v4lookup(fs, ip, ia, nil);
v4tov6(v6ip, ip); v4tov6(v6ip, ip);
ip = v6ip; ip = v6ip;
break; break;
case V6: case V6:
r = v6lookup(fs, ip, src, nil); r = v6lookup(fs, ip, ia, nil);
break; break;
default: default:
panic("arpenter: version %d", version); panic("arpenter: version %d", version);
return -1; /* to supress warnings */ return -1; /* to supress warnings */
} }
if(r == nil || (ifc = r->ifc) == nil || (m = ifc->m) == nil || m->maclen != n || m->maclen == 0) if(r == nil || (ifc = r->ifc) == nil)
return -1; return -1;
rlock(ifc);
if(ifc->m == nil || ifc->m->maclen != n || ifc->m->maclen == 0){
runlock(ifc);
return -1;
}
qlock(arp); qlock(arp);
for(a = arp->hash[haship(ip)]; a != nil; a = a->hash){ for(a = arp->hash[haship(ip)]; a != nil; a = a->hash){
if(a->state != AWAIT && a->state != AOK) if(a->state != AWAIT && a->state != AOK)
@ -351,28 +356,17 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *src, int refr
qunlock(arp); qunlock(arp);
while(bp != nil){ while(bp != nil){
if(!canrlock(ifc)){
freeblistchain(bp);
break;
}
if(ifc->m != m){
runlock(ifc);
freeblistchain(bp);
break;
}
next = bp->list; next = bp->list;
bp->list = nil; bp->list = nil;
if(waserror()){ if(waserror()){
runlock(ifc);
freeblistchain(next); freeblistchain(next);
break; break;
} }
m->bwrite(ifc, concatblock(bp), version, ip); ifc->m->bwrite(ifc, concatblock(bp), version, ip);
runlock(ifc);
poperror(); poperror();
bp = next; bp = next;
} }
runlock(ifc);
return 1; return 1;
} }
} }
@ -383,8 +377,9 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *src, int refr
a->ctime = NOW; a->ctime = NOW;
memmove(a->mac, mac, n); memmove(a->mac, mac, n);
} }
qunlock(arp); qunlock(arp);
runlock(ifc);
return refresh == 0; return refresh == 0;
} }
@ -396,7 +391,7 @@ arpwrite(Fs *fs, char *s, int len)
Arpent *a, *x; Arpent *a, *x;
Medium *m; Medium *m;
char *f[5], buf[256]; char *f[5], buf[256];
uchar ip[IPaddrlen], src[IPaddrlen], mac[MAClen]; uchar ip[IPaddrlen], ia[IPaddrlen], mac[MAClen];
arp = fs->arp; arp = fs->arp;
@ -438,7 +433,7 @@ arpwrite(Fs *fs, char *s, int len)
error(Ebadip); error(Ebadip);
if((n = parsemac(mac, f[2], sizeof(mac))) <= 0) if((n = parsemac(mac, f[2], sizeof(mac))) <= 0)
error(Ebadarp); error(Ebadarp);
findlocalip(fs, src, ip); findlocalip(fs, ia, ip);
break; break;
case 4: case 4:
m = ipfindmedium(f[1]); m = ipfindmedium(f[1]);
@ -448,7 +443,7 @@ arpwrite(Fs *fs, char *s, int len)
error(Ebadip); error(Ebadip);
if((n = parsemac(mac, f[3], sizeof(mac))) != m->maclen) if((n = parsemac(mac, f[3], sizeof(mac))) != m->maclen)
error(Ebadarp); error(Ebadarp);
findlocalip(fs, src, ip); findlocalip(fs, ia, ip);
break; break;
case 5: case 5:
m = ipfindmedium(f[1]); m = ipfindmedium(f[1]);
@ -458,11 +453,11 @@ arpwrite(Fs *fs, char *s, int len)
error(Ebadip); error(Ebadip);
if((n = parsemac(mac, f[3], sizeof(mac))) != m->maclen) if((n = parsemac(mac, f[3], sizeof(mac))) != m->maclen)
error(Ebadarp); error(Ebadarp);
if(parseip(src, f[4]) == -1) if(parseip(ia, f[4]) == -1)
error(Ebadip); error(Ebadip);
break; break;
} }
if(arpenter(fs, V6, ip, mac, n, src, 0) <= 0) if(arpenter(fs, V6, ip, mac, n, ia, 0) <= 0)
error("destination unreachable"); error("destination unreachable");
} else if(strcmp(f[0], "del") == 0){ } else if(strcmp(f[0], "del") == 0){
if (n != 2) if (n != 2)
@ -495,8 +490,8 @@ convmac(char *p, uchar *mac, int n)
int int
arpread(Arp *arp, char *s, ulong offset, int len) arpread(Arp *arp, char *s, ulong offset, int len)
{ {
uchar ip[IPaddrlen], src[IPaddrlen]; char mac[2*MAClen+1], *state, *mname, *p;
char mac[2*MAClen+1], *p, *state; uchar ip[IPaddrlen], ia[IPaddrlen];
Ipifc *ifc; Ipifc *ifc;
Arpent *a; Arpent *a;
long n, o; long n, o;
@ -504,18 +499,25 @@ arpread(Arp *arp, char *s, ulong offset, int len)
p = s; p = s;
o = -offset; o = -offset;
for(a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++){ for(a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++){
if(a->state == 0 || (ifc = a->ifc) == nil || a->ifcid != ifc->ifcid) if(a->state == 0 || (ifc = a->ifc) == nil)
continue; continue;
rlock(ifc);
qlock(arp); qlock(arp);
state = arpstate[a->state]; state = arpstate[a->state];
ipmove(ip, a->ip); ipmove(ip, a->ip);
if(ifc->m == nil || a->ifcid != ifc->ifcid || !ipv6local(ifc, ia, ip)){
qunlock(arp);
runlock(ifc);
continue;
}
mname = ifc->m->name;
convmac(mac, a->mac, ifc->m->maclen); convmac(mac, a->mac, ifc->m->maclen);
qunlock(arp); qunlock(arp);
runlock(ifc);
ipv6local(ifc, src, ip);
n = snprint(p, len, "%-6.6s %-4.4s %-40.40I %-16.16s %I\n", n = snprint(p, len, "%-6.6s %-4.4s %-40.40I %-16.16s %I\n",
ifc->m->name, state, ip, mac, src); mname, state, ip, mac, ia);
if(o < 0) { if(o < 0) {
if(n > -o) if(n > -o)
memmove(p, p-o, n+o); memmove(p, p-o, n+o);
@ -549,17 +551,20 @@ ndpsendsol(Fs *f, Ipifc *ifc, Arpent *a)
if(!ipv6local(ifc, src, targ)) if(!ipv6local(ifc, src, targ))
return; return;
send: send:
icmpns(f, src, SRC_UNI, targ, TARG_MULTI, ifc->mac); if(!waserror()){
icmpns(f, src, SRC_UNI, targ, TARG_MULTI, ifc->mac);
poperror();
}
} }
int long
rxmitsols(Arp *arp) rxmitsols(Arp *arp)
{ {
Block *next, *xp; Block *next, *xp;
Arpent *a, *b, **l; Arpent *a, *b, **l;
Fs *f; Ipifc *ifc;
Ipifc *ifc = nil;
long nrxt; long nrxt;
Fs *f;
qlock(arp); qlock(arp);
f = arp->f; f = arp->f;
@ -573,6 +578,7 @@ rxmitsols(Arp *arp)
if(nrxt > 3*ReTransTimer/4) if(nrxt > 3*ReTransTimer/4)
goto dodrops; /* return nrxt; */ goto dodrops; /* return nrxt; */
ifc = nil;
for(; a != nil; a = a->nextrxt){ for(; a != nil; a = a->nextrxt){
ifc = a->ifc; ifc = a->ifc;
if(a->rxtsrem > 0 && ifc != nil && canrlock(ifc)){ if(a->rxtsrem > 0 && ifc != nil && canrlock(ifc)){
@ -628,8 +634,19 @@ dodrops:
qunlock(arp); qunlock(arp);
for(; xp != nil; xp = next){ for(; xp != nil; xp = next){
Ip6hdr *eh;
Route *r;
next = xp->list; next = xp->list;
icmphostunr6(f, ifc, xp, Icmp6_adr_unreach, 1); eh = (Ip6hdr*)xp->rp;
r = v6lookup(f, eh->src, eh->dst, nil);
if(r != nil && (ifc = r->ifc) != nil && canrlock(ifc)){
if(!waserror()){
icmphostunr6(f, ifc, xp, Icmp6_adr_unreach, (r->type & Runi) != 0);
poperror();
}
runlock(ifc);
}
freeblist(xp); freeblist(xp);
} }

View file

@ -472,7 +472,7 @@ espiput(Proto *esp, Ipifc*, Block *bp)
ecb = c->ptcl; ecb = c->ptcl;
/* too hard to do decryption/authentication on block lists */ /* too hard to do decryption/authentication on block lists */
if(bp->next) if(bp->next != nil)
bp = concatblock(bp); bp = concatblock(bp);
if(BLEN(bp) < vers.hdrlen + ecb->espivlen + Esptaillen + ecb->ahlen) { if(BLEN(bp) < vers.hdrlen + ecb->espivlen + Esptaillen + ecb->ahlen) {

View file

@ -33,7 +33,7 @@ static void etherunbind(Ipifc *ifc);
static void etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip); static void etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia); static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia);
static void etherremmulti(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 void etherareg(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *ip);
static Block* multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac); static Block* multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac);
static void sendarp(Ipifc *ifc, Arpent *a); static void sendarp(Ipifc *ifc, Arpent *a);
static int multicastea(uchar *ea, uchar *ip); static int multicastea(uchar *ea, uchar *ip);
@ -219,8 +219,8 @@ etherbind(Ipifc *ifc, int argc, char **argv)
poperror(); poperror();
kproc("etherread4", etherread4, ifc); kproc("etherread4", etherread4, ifc);
kproc("recvarpproc", recvarpproc, ifc);
kproc("etherread6", etherread6, ifc); kproc("etherread6", etherread6, ifc);
kproc("recvarpproc", recvarpproc, ifc);
} }
/* /*
@ -231,27 +231,27 @@ etherunbind(Ipifc *ifc)
{ {
Etherrock *er = ifc->arg; Etherrock *er = ifc->arg;
if(er->read4p) if(er->read4p != nil)
postnote(er->read4p, 1, "unbind", 0); postnote(er->read4p, 1, "unbind", 0);
if(er->read6p) if(er->read6p != nil)
postnote(er->read6p, 1, "unbind", 0); postnote(er->read6p, 1, "unbind", 0);
if(er->arpp) if(er->arpp != nil)
postnote(er->arpp, 1, "unbind", 0); postnote(er->arpp, 1, "unbind", 0);
/* wait for readers to die */ /* wait for readers to die */
while(er->arpp != 0 || er->read4p != 0 || er->read6p != 0) while(er->arpp != nil || er->read4p != nil || er->read6p != nil)
tsleep(&up->sleep, return0, 0, 300); tsleep(&up->sleep, return0, 0, 300);
if(er->mchan4 != nil) if(er->mchan4 != nil)
cclose(er->mchan4); cclose(er->mchan4);
if(er->achan != nil)
cclose(er->achan);
if(er->cchan4 != nil) if(er->cchan4 != nil)
cclose(er->cchan4); cclose(er->cchan4);
if(er->mchan6 != nil) if(er->mchan6 != nil)
cclose(er->mchan6); cclose(er->mchan6);
if(er->cchan6 != nil) if(er->cchan6 != nil)
cclose(er->cchan6); cclose(er->cchan6);
if(er->achan != nil)
cclose(er->achan);
free(er); free(er);
} }
@ -329,7 +329,7 @@ etherread4(void *a)
er = ifc->arg; er = ifc->arg;
er->read4p = up; /* hide identity under a rock for unbind */ er->read4p = up; /* hide identity under a rock for unbind */
if(waserror()){ if(waserror()){
er->read4p = 0; er->read4p = nil;
pexit("hangup", 1); pexit("hangup", 1);
} }
for(;;){ for(;;){
@ -369,7 +369,7 @@ etherread6(void *a)
er = ifc->arg; er = ifc->arg;
er->read6p = up; /* hide identity under a rock for unbind */ er->read6p = up; /* hide identity under a rock for unbind */
if(waserror()){ if(waserror()){
er->read6p = 0; er->read6p = nil;
pexit("hangup", 1); pexit("hangup", 1);
} }
for(;;){ for(;;){
@ -571,6 +571,11 @@ recvarp(Ipifc *ifc)
if(ebp == nil) if(ebp == nil)
return; return;
if(!canrlock(ifc)){
freeb(ebp);
return;
}
e = (Etherarp*)ebp->rp; e = (Etherarp*)ebp->rp;
switch(nhgets(e->op)) { switch(nhgets(e->op)) {
default: default:
@ -647,8 +652,14 @@ recvarp(Ipifc *ifc)
memmove(r->s, ifc->mac, sizeof(r->s)); memmove(r->s, ifc->mac, sizeof(r->s));
rbp->wp += n; rbp->wp += n;
runlock(ifc);
freeb(ebp);
devtab[er->achan->type]->bwrite(er->achan, rbp, 0); devtab[er->achan->type]->bwrite(er->achan, rbp, 0);
return;
} }
runlock(ifc);
freeb(ebp); freeb(ebp);
} }
@ -660,7 +671,7 @@ recvarpproc(void *v)
er->arpp = up; er->arpp = up;
if(waserror()){ if(waserror()){
er->arpp = 0; er->arpp = nil;
pexit("hangup", 1); pexit("hangup", 1);
} }
for(;;) for(;;)
@ -745,10 +756,10 @@ etherpref2addr(uchar *pref, uchar *ea)
} }
static void static void
etherareg(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy) etherareg(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *ip)
{ {
static char tdad[] = "dad6"; static char tdad[] = "dad6";
uchar mcast[IPaddrlen]; uchar a[IPaddrlen];
if(ipcmp(ip, IPnoaddr) == 0) if(ipcmp(ip, IPnoaddr) == 0)
return; return;
@ -758,16 +769,25 @@ etherareg(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy)
return; return;
} }
if(!iptentative(f, ip)){ if((lifc->type&Rv4) != 0)
icmpna(f, proxy, v6allnodesL, ip, ifc->mac, 1<<5); return;
if(!lifc->tentative){
icmpna(f, lifc->local, v6allnodesL, ip, ifc->mac, 1<<5);
return; return;
} }
if(ipcmp(lifc->local, ip) != 0)
return;
/* temporarily add route for duplicate address detection */ /* temporarily add route for duplicate address detection */
ipv62smcast(mcast, ip); ipv62smcast(a, ip);
addroute(f, mcast, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad); addroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
if(waserror()){
remroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
nexterror();
}
icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac); icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
poperror();
remroute(f, mcast, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad); remroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
} }

View file

@ -99,6 +99,7 @@ ip_init(Fs *f)
IP *ip; IP *ip;
ip = smalloc(sizeof(IP)); ip = smalloc(sizeof(IP));
ip->stats[DefaultTTL] = MAXTTL;
initfrag(ip, 100); initfrag(ip, 100);
f->ip = ip; f->ip = ip;
@ -362,7 +363,7 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
if(notforme) { if(notforme) {
Route *r; Route *r;
Routehint rh; Routehint rh;
Ipifc *toifc; Ipifc *nifc;
if(!ip->iprouting) if(!ip->iprouting)
goto drop; goto drop;
@ -370,8 +371,8 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
/* don't forward to source's network */ /* don't forward to source's network */
rh.r = nil; rh.r = nil;
r = v4lookup(f, h->dst, h->src, &rh); r = v4lookup(f, h->dst, h->src, &rh);
if(r == nil || (toifc = r->ifc) == nil if(r == nil || (nifc = r->ifc) == nil
|| (toifc == ifc && !ifc->reflect)){ || (nifc == ifc && !ifc->reflect)){
ip->stats[OutDiscards]++; ip->stats[OutDiscards]++;
goto drop; goto drop;
} }
@ -385,7 +386,7 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
} }
/* reassemble if the interface expects it */ /* reassemble if the interface expects it */
if(toifc->reassemble){ if(nifc->reassemble){
frag = nhgets(h->frag); frag = nhgets(h->frag);
if(frag & ~IP_DF) { if(frag & ~IP_DF) {
h->tos = 0; h->tos = 0;
@ -441,8 +442,6 @@ ipstats(Fs *f, char *buf, int len)
int i; int i;
ip = f->ip; ip = f->ip;
ip->stats[DefaultTTL] = MAXTTL;
p = buf; p = buf;
e = p+len; e = p+len;
for(i = 0; i < Nipstats; i++) for(i = 0; i < Nipstats; i++)
@ -467,7 +466,7 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih)
/* /*
* block lists are too hard, pullupblock into a single block * block lists are too hard, pullupblock into a single block
*/ */
if(bp->next){ if(bp->next != nil){
bp = pullupblock(bp, blocklen(bp)); bp = pullupblock(bp, blocklen(bp));
ih = (Ip4hdr*)(bp->rp); ih = (Ip4hdr*)(bp->rp);
} }
@ -477,7 +476,7 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih)
/* /*
* find a reassembly queue for this fragment * find a reassembly queue for this fragment
*/ */
for(f = ip->flisthead4; f; f = fnext){ for(f = ip->flisthead4; f != nil; f = fnext){
fnext = f->next; /* because ipfragfree4 changes the list */ fnext = f->next; /* because ipfragfree4 changes the list */
if(f->src == src && f->dst == dst && f->id == id) if(f->src == src && f->dst == dst && f->id == id)
break; break;
@ -536,7 +535,7 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih)
} }
/* Check overlap of a previous fragment - trim away as necessary */ /* Check overlap of a previous fragment - trim away as necessary */
if(prev) { if(prev != nil) {
ovlap = BKFG(prev)->foff + BKFG(prev)->flen - BKFG(bp)->foff; ovlap = BKFG(prev)->foff + BKFG(prev)->flen - BKFG(bp)->foff;
if(ovlap > 0) { if(ovlap > 0) {
if(ovlap >= BKFG(bp)->flen) { if(ovlap >= BKFG(bp)->flen) {
@ -553,11 +552,11 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih)
*l = bp; *l = bp;
/* Check to see if succeeding segments overlap */ /* Check to see if succeeding segments overlap */
if(bp->next) { if(bp->next != nil) {
l = &bp->next; l = &bp->next;
fend = BKFG(bp)->foff + BKFG(bp)->flen; fend = BKFG(bp)->foff + BKFG(bp)->flen;
/* Take completely covered segments out */ /* Take completely covered segments out */
while(*l) { while(*l != nil) {
ovlap = fend - BKFG(*l)->foff; ovlap = fend - BKFG(*l)->foff;
if(ovlap <= 0) if(ovlap <= 0)
break; break;
@ -581,7 +580,7 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih)
* without IP_MF set, we're done. * without IP_MF set, we're done.
*/ */
pktposn = 0; pktposn = 0;
for(bl = f->blist; bl; bl = bl->next) { for(bl = f->blist; bl != nil; bl = bl->next) {
if(BKFG(bl)->foff != pktposn) if(BKFG(bl)->foff != pktposn)
break; break;
if((BLKIP(bl)->frag[0]&(IP_MF>>8)) == 0) { if((BLKIP(bl)->frag[0]&(IP_MF>>8)) == 0) {
@ -592,7 +591,7 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih)
/* Pullup all the fragment headers and /* Pullup all the fragment headers and
* return a complete packet * return a complete packet
*/ */
for(bl = bl->next; bl; bl = bl->next) { for(bl = bl->next; bl != nil; bl = bl->next) {
fragsize = BKFG(bl)->flen; fragsize = BKFG(bl)->flen;
len += fragsize; len += fragsize;
bl->rp += IP4HDR; bl->rp += IP4HDR;
@ -622,7 +621,7 @@ ipfragfree4(IP *ip, Fragment4 *frag)
{ {
Fragment4 *fl, **l; Fragment4 *fl, **l;
if(frag->blist) if(frag->blist != nil)
freeblist(frag->blist); freeblist(frag->blist);
frag->src = 0; frag->src = 0;
@ -630,7 +629,7 @@ ipfragfree4(IP *ip, Fragment4 *frag)
frag->blist = nil; frag->blist = nil;
l = &ip->flisthead4; l = &ip->flisthead4;
for(fl = *l; fl; fl = fl->next) { for(fl = *l; fl != nil; fl = fl->next) {
if(fl == frag) { if(fl == frag) {
*l = frag->next; *l = frag->next;
break; break;
@ -653,7 +652,7 @@ ipfragallo4(IP *ip)
while(ip->fragfree4 == nil) { while(ip->fragfree4 == nil) {
/* free last entry on fraglist */ /* free last entry on fraglist */
for(f = ip->flisthead4; f->next; f = f->next) for(f = ip->flisthead4; f->next != nil; f = f->next)
; ;
ipfragfree4(ip, f); ipfragfree4(ip, f);
} }

View file

@ -243,7 +243,7 @@ struct Medium
void (*pktin)(Fs *f, Ipifc *ifc, Block *bp); void (*pktin)(Fs *f, Ipifc *ifc, Block *bp);
/* address resolution */ /* address resolution */
void (*areg)(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy); /* register */ void (*areg)(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *ip);
/* v6 address generation */ /* v6 address generation */
void (*pref2addr)(uchar *pref, uchar *ea); void (*pref2addr)(uchar *pref, uchar *ea);
@ -608,7 +608,7 @@ extern int arpwrite(Fs*, char*, int);
extern Arpent* arpget(Arp*, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *h); extern Arpent* arpget(Arp*, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *h);
extern void arprelease(Arp*, Arpent *a); extern void arprelease(Arp*, Arpent *a);
extern Block* arpresolve(Arp*, Arpent *a, Medium *type, uchar *mac); extern Block* arpresolve(Arp*, Arpent *a, Medium *type, uchar *mac);
extern int arpenter(Fs*, int version, uchar *ip, uchar *mac, int n, uchar *src, int norefresh); extern int arpenter(Fs*, int version, uchar *ip, uchar *mac, int n, uchar *ia, int norefresh);
extern void ndpsendsol(Fs*, Ipifc*, Arpent*); extern void ndpsendsol(Fs*, Ipifc*, Arpent*);
/* /*
@ -654,8 +654,6 @@ extern Medium pktmedium;
extern Medium* ipfindmedium(char *name); extern Medium* ipfindmedium(char *name);
extern void addipmedium(Medium *med); extern void addipmedium(Medium *med);
extern int ipforme(Fs*, uchar *addr); extern int ipforme(Fs*, uchar *addr);
extern int iptentative(Fs*, uchar *addr);
extern int ipisbm(uchar *ip);
extern int ipismulticast(uchar *ip); extern int ipismulticast(uchar *ip);
extern Ipifc* findipifc(Fs*, uchar *local, uchar *remote, int type); extern Ipifc* findipifc(Fs*, uchar *local, uchar *remote, int type);
extern Ipifc* findipifcstr(Fs *f, char *s); extern Ipifc* findipifcstr(Fs *f, char *s);

View file

@ -61,6 +61,7 @@ static char tifc[] = "ifc ";
static void addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type); static void addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type);
static void remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a); static void remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a);
static void ipifcregisteraddr(Fs*, Ipifc*, uchar *, uchar *);
static void ipifcregisterproxy(Fs*, Ipifc*, uchar*, int); static void ipifcregisterproxy(Fs*, Ipifc*, uchar*, int);
static char* ipifcremlifc(Ipifc*, Iplifc**); static char* ipifcremlifc(Ipifc*, Iplifc**);
@ -218,10 +219,6 @@ ipifcunbind(Ipifc *ifc)
/* disassociate logical interfaces (before zeroing ifc->arg) */ /* disassociate logical interfaces (before zeroing ifc->arg) */
while(ifc->lifc != nil){ while(ifc->lifc != nil){
err = ipifcremlifc(ifc, &ifc->lifc); err = ipifcremlifc(ifc, &ifc->lifc);
/*
* note: err non-zero means lifc not found,
* which can't happen in this case.
*/
if(err != nil) if(err != nil)
error(err); error(err);
} }
@ -273,7 +270,7 @@ ipifcstate(Conv *c, char *state, int n)
ifc->in, ifc->out, ifc->inerr, ifc->outerr); ifc->in, ifc->out, ifc->inerr, ifc->outerr);
rlock(ifc); rlock(ifc);
for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next) for(lifc = ifc->lifc; lifc != nil && n > m; lifc = lifc->next)
m += snprint(state+m, n - m, slineformat, lifc->local, m += snprint(state+m, n - m, slineformat, lifc->local,
lifc->mask, lifc->remote, lifc->validlt, lifc->preflt); lifc->mask, lifc->remote, lifc->validlt, lifc->preflt);
if(ifc->lifc == nil) if(ifc->lifc == nil)
@ -291,9 +288,8 @@ ipifclocal(Conv *c, char *state, int n)
int m; int m;
ifc = (Ipifc*)c->ptcl; ifc = (Ipifc*)c->ptcl;
m = 0;
rlock(ifc); rlock(ifc);
m = 0;
for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
m += snprint(state+m, n - m, "%-40.40I ->", lifc->local); m += snprint(state+m, n - m, "%-40.40I ->", lifc->local);
for(link = lifc->link; link != nil; link = link->lifclink) for(link = lifc->link; link != nil; link = link->lifclink)
@ -405,14 +401,9 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp)
uchar bcast[IPaddrlen], net[IPaddrlen]; uchar bcast[IPaddrlen], net[IPaddrlen];
Iplifc *lifc, **l; Iplifc *lifc, **l;
int i, type, mtu; int i, type, mtu;
Medium *m;
Fs *f; Fs *f;
if((m = ifc->m) == nil) mtu = 0;
return "ipifc not yet bound to device";
f = ifc->conv->p->f;
type = Rifc; type = Rifc;
memset(ip, 0, IPaddrlen); memset(ip, 0, IPaddrlen);
memset(mask, 0, IPaddrlen); memset(mask, 0, IPaddrlen);
@ -424,8 +415,6 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp)
/* fall through */ /* fall through */
case 5: case 5:
mtu = strtoul(argv[4], 0, 0); mtu = strtoul(argv[4], 0, 0);
if(mtu >= m->mintu && mtu <= m->maxtu)
ifc->maxtu = mtu;
/* fall through */ /* fall through */
case 4: case 4:
if (parseip(ip, argv[1]) == -1 || parseip(rem, argv[3]) == -1) if (parseip(ip, argv[1]) == -1 || parseip(rem, argv[3]) == -1)
@ -462,11 +451,18 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp)
} }
wlock(ifc); wlock(ifc);
if(ifc->m == nil)
return "ipifc not yet bound to device";
f = ifc->conv->p->f;
if(waserror()){ if(waserror()){
wunlock(ifc); wunlock(ifc);
nexterror(); return up->errstr;
} }
if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu)
ifc->maxtu = mtu;
/* ignore if this is already a local address for this ifc */ /* ignore if this is already a local address for this ifc */
if((lifc = iplocalonifc(ifc, ip)) != nil){ if((lifc = iplocalonifc(ifc, ip)) != nil){
if(lifcp != nil) { if(lifcp != nil) {
@ -576,9 +572,7 @@ done:
wunlock(ifc); wunlock(ifc);
poperror(); poperror();
/* register the address on this network for address resolution */ ipifcregisteraddr(f, ifc, ip, ip);
if(m->areg != nil)
(*m->areg)(f, ifc, ip, ip);
return nil; return nil;
} }
@ -701,7 +695,7 @@ ipifcconnect(Conv* c, char **argv, int argc)
wunlock(ifc); wunlock(ifc);
err = ipifcadd(ifc, argv, argc, 0, nil); err = ipifcadd(ifc, argv, argc, 0, nil);
if(err) if(err != nil)
return err; return err;
Fsconnected(c, nil); Fsconnected(c, nil);
@ -1069,18 +1063,6 @@ ipselftabread(Fs *f, char *cp, ulong offset, int n)
return m; return m;
} }
int
iptentative(Fs *f, uchar *addr)
{
Ipself *p;
for(p = f->self->hash[hashipa(addr)]; p != nil; p = p->next)
if(ipcmp(addr, p->a) == 0)
return p->link->lifc->tentative;
return 0;
}
/* /*
* returns * returns
* 0 - no match * 0 - no match
@ -1112,27 +1094,26 @@ Ipifc*
findipifc(Fs *f, uchar *local, uchar *remote, int type) findipifc(Fs *f, uchar *local, uchar *remote, int type)
{ {
uchar gnet[IPaddrlen]; uchar gnet[IPaddrlen];
int spec, xspec;
Ipifc *ifc, *x; Ipifc *ifc, *x;
Iplifc *lifc; Iplifc *lifc;
Conv **cp, **e; Conv **cp;
int spec, xspec;
x = nil; x = nil;
xspec = 0; xspec = 0;
for(cp = f->ipifc->conv; *cp != nil; cp++){
/* find most specific match */
e = &f->ipifc->conv[f->ipifc->nc];
for(cp = f->ipifc->conv; cp < e; cp++){
if(*cp == nil)
continue;
ifc = (Ipifc*)(*cp)->ptcl; ifc = (Ipifc*)(*cp)->ptcl;
rlock(ifc);
for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
if(type & Runi){ if(type & Runi){
if(ipcmp(remote, lifc->local) == 0) if(ipcmp(remote, lifc->local) == 0){
Found:
runlock(ifc);
return ifc; return ifc;
}
} else if(type & (Rbcast|Rmulti)) { } else if(type & (Rbcast|Rmulti)) {
if(ipcmp(local, lifc->local) == 0) if(ipcmp(local, lifc->local) == 0)
return ifc; goto Found;
} }
maskip(remote, lifc->mask, gnet); maskip(remote, lifc->mask, gnet);
if(ipcmp(gnet, lifc->net) == 0){ if(ipcmp(gnet, lifc->net) == 0){
@ -1143,6 +1124,7 @@ findipifc(Fs *f, uchar *local, uchar *remote, int type)
} }
} }
} }
runlock(ifc);
} }
return x; return x;
} }
@ -1159,7 +1141,7 @@ findipifcstr(Fs *f, char *s)
if(p > s && *p == '\0'){ if(p > s && *p == '\0'){
if(x < 0) if(x < 0)
return nil; return nil;
if(x < f->ipifc->nc && (c = f->ipifc->conv[x]) != nil) if(x < f->ipifc->nc && (c = f->ipifc->conv[x]) != nil && ipifcinuse(c))
return (Ipifc*)c->ptcl; return (Ipifc*)c->ptcl;
} }
if(parseip(ip, s) != -1) if(parseip(ip, s) != -1)
@ -1167,35 +1149,36 @@ findipifcstr(Fs *f, char *s)
return nil; return nil;
} }
/*
* find "best" (global > link local > unspecified)
* local address; address must be current.
*/
static void static void
findprimaryipv6(Fs *f, uchar *local) findprimaryipv6(Fs *f, uchar *local)
{ {
int atype, atypel; int atype, atypel;
Conv **cp, **e;
Ipifc *ifc;
Iplifc *lifc; Iplifc *lifc;
Ipifc *ifc;
Conv **cp;
ipmove(local, v6Unspecified); ipmove(local, v6Unspecified);
atype = unspecifiedv6; atype = unspecifiedv6;
/* for(cp = f->ipifc->conv; *cp != nil; cp++){
* find "best" (global > link local > unspecified)
* local address; address must be current.
*/
e = &f->ipifc->conv[f->ipifc->nc];
for(cp = f->ipifc->conv; cp < e; cp++){
if(*cp == nil)
continue;
ifc = (Ipifc*)(*cp)->ptcl; ifc = (Ipifc*)(*cp)->ptcl;
rlock(ifc);
for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
atypel = v6addrtype(lifc->local); atypel = v6addrtype(lifc->local);
if(atypel > atype && v6addrcurr(lifc)) { if(atypel > atype && v6addrcurr(lifc)) {
ipmove(local, lifc->local); ipmove(local, lifc->local);
atype = atypel; atype = atypel;
if(atype == globalv6) if(atype == globalv6){
runlock(ifc);
return; return;
}
} }
} }
runlock(ifc);
} }
} }
@ -1205,20 +1188,22 @@ findprimaryipv6(Fs *f, uchar *local)
static void static void
findprimaryipv4(Fs *f, uchar *local) findprimaryipv4(Fs *f, uchar *local)
{ {
Conv **cp, **e;
Ipifc *ifc;
Iplifc *lifc; Iplifc *lifc;
Ipifc *ifc;
Conv **cp;
/* find first ifc local address */ /* find first ifc local address */
e = &f->ipifc->conv[f->ipifc->nc]; for(cp = f->ipifc->conv; *cp != nil; cp++){
for(cp = f->ipifc->conv; cp < e; cp++){
if(*cp == nil)
continue;
ifc = (Ipifc*)(*cp)->ptcl; ifc = (Ipifc*)(*cp)->ptcl;
if((lifc = ifc->lifc) != nil && (lifc->type & Rv4) != 0){ rlock(ifc);
ipmove(local, lifc->local); for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
return; if((lifc->type & Rv4) != 0){
ipmove(local, lifc->local);
runlock(ifc);
return;
}
} }
runlock(ifc);
} }
ipmove(local, IPnoaddr); ipmove(local, IPnoaddr);
} }
@ -1310,41 +1295,47 @@ void
findlocalip(Fs *f, uchar *local, uchar *remote) findlocalip(Fs *f, uchar *local, uchar *remote)
{ {
Route *r; Route *r;
Ipifc *ifc;
Iplifc *lifc; Iplifc *lifc;
Conv **cp, **e; Ipifc *ifc, *nifc;
Conv **cp;
qlock(f->ipifc); for(cp = f->ipifc->conv; *cp != nil; cp++){
e = &f->ipifc->conv[f->ipifc->nc];
for(cp = f->ipifc->conv; cp < e; cp++){
if(*cp == nil)
continue;
ifc = (Ipifc*)(*cp)->ptcl; ifc = (Ipifc*)(*cp)->ptcl;
rlock(ifc);
for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
if(lifc->tentative) if(lifc->tentative)
continue; continue;
r = v6lookup(f, remote, lifc->local, nil); r = v6lookup(f, remote, lifc->local, nil);
if(r == nil || (ifc = r->ifc) == nil) if(r == nil || (nifc = r->ifc) == nil)
continue; continue;
if(r->type & Runi){ if(r->type & Runi){
ipmove(local, remote); ipmove(local, remote);
goto out; runlock(ifc);
return;
} }
if(nifc != ifc) rlock(nifc);
if((r->type & (Rifc|Rbcast|Rmulti|Rv4)) == Rv4){ if((r->type & (Rifc|Rbcast|Rmulti|Rv4)) == Rv4){
ipmove(local, v4prefix); ipmove(local, v4prefix);
if(ipv4local(ifc, local+IPv4off, r->v4.gate)) if(ipv4local(nifc, local+IPv4off, r->v4.gate)){
goto out; if(nifc != ifc) runlock(nifc);
runlock(ifc);
return;
}
} }
if(ipv6local(ifc, local, remote)) if(ipv6local(nifc, local, remote)){
goto out; if(nifc != ifc) runlock(nifc);
runlock(ifc);
return;
}
if(nifc != ifc) runlock(nifc);
} }
runlock(ifc);
} }
if(isv4(remote)) if(isv4(remote))
findprimaryipv4(f, local); findprimaryipv4(f, local);
else else
findprimaryipv6(f, local); findprimaryipv6(f, local);
out:
qunlock(f->ipifc);
} }
@ -1408,20 +1399,6 @@ ipismulticast(uchar *ip)
return V6; return V6;
return 0; return 0;
} }
int
ipisbm(uchar *ip)
{
if(isv4(ip)){
if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
return V4;
else if(ipcmp(ip, IPv4bcast) == 0)
return V4;
}
else if(ip[0] == 0xff)
return V6;
return 0;
}
/* /*
* add a multicast address to an interface, called with c->car locked * add a multicast address to an interface, called with c->car locked
@ -1430,13 +1407,10 @@ void
ipifcaddmulti(Conv *c, uchar *ma, uchar *ia) ipifcaddmulti(Conv *c, uchar *ma, uchar *ia)
{ {
Ipmulti *multi, **l; Ipmulti *multi, **l;
Conv **cp, **e;
Iplifc *lifc; Iplifc *lifc;
Ipifc *ifc; Ipifc *ifc;
Fs *f; Fs *f;
f = c->p->f;
for(l = &c->multi; *l != nil; l = &(*l)->next) for(l = &c->multi; *l != nil; l = &(*l)->next)
if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0) if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0)
return; /* it's already there */ return; /* it's already there */
@ -1446,11 +1420,8 @@ ipifcaddmulti(Conv *c, uchar *ma, uchar *ia)
ipmove(multi->ia, ia); ipmove(multi->ia, ia);
multi->next = nil; multi->next = nil;
e = &f->ipifc->conv[f->ipifc->nc]; f = c->p->f;
for(cp = f->ipifc->conv; cp < e; cp++){ if((ifc = findipifc(f, ia, ma, Rmulti)) != nil){
if((*cp) == nil || (*cp)->inuse == 0)
continue;
ifc = (Ipifc*)(*cp)->ptcl;
wlock(ifc); wlock(ifc);
if(waserror()){ if(waserror()){
wunlock(ifc); wunlock(ifc);
@ -1471,13 +1442,10 @@ void
ipifcremmulti(Conv *c, uchar *ma, uchar *ia) ipifcremmulti(Conv *c, uchar *ma, uchar *ia)
{ {
Ipmulti *multi, **l; Ipmulti *multi, **l;
Conv **cp, **e;
Iplifc *lifc; Iplifc *lifc;
Ipifc *ifc; Ipifc *ifc;
Fs *f; Fs *f;
f = c->p->f;
for(l = &c->multi; *l != nil; l = &(*l)->next) for(l = &c->multi; *l != nil; l = &(*l)->next)
if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0) if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0)
break; break;
@ -1487,12 +1455,10 @@ ipifcremmulti(Conv *c, uchar *ma, uchar *ia)
return; /* we don't have it open */ return; /* we don't have it open */
*l = multi->next; *l = multi->next;
free(multi);
e = &f->ipifc->conv[f->ipifc->nc]; f = c->p->f;
for(cp = f->ipifc->conv; cp < e; cp++){ if((ifc = findipifc(f, ia, ma, Rmulti)) != nil){
if((*cp) == nil || (*cp)->inuse == 0)
continue;
ifc = (Ipifc*)(*cp)->ptcl;
wlock(ifc); wlock(ifc);
if(waserror()){ if(waserror()){
wunlock(ifc); wunlock(ifc);
@ -1504,46 +1470,63 @@ ipifcremmulti(Conv *c, uchar *ma, uchar *ia)
poperror(); poperror();
} }
free(multi); }
/* register the address on this network for address resolution */
static void
ipifcregisteraddr(Fs *f, Ipifc *ifc, uchar *ia, uchar *ip)
{
Iplifc *lifc;
rlock(ifc);
if(waserror()){
runlock(ifc);
print("ipifcregisteraddr %s %I %I: %s\n", ifc->dev, ia, ip, up->errstr);
return;
}
lifc = iplocalonifc(ifc, ia);
if(lifc != nil && ifc->m != nil && ifc->m->areg != nil)
(*ifc->m->areg)(f, ifc, lifc, ip);
runlock(ifc);
poperror();
} }
static void static void
ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip, int add) ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip, int add)
{ {
uchar proxy[IPaddrlen]; uchar a[IPaddrlen];
Conv **cp, **e;
Iplifc *lifc; Iplifc *lifc;
Ipifc *nifc; Ipifc *nifc;
Medium *m; Conv **cp;
/* register the address on any interface that will proxy for the ip */ /* register the address on any interface that will proxy for the ip */
e = &f->ipifc->conv[f->ipifc->nc]; for(cp = f->ipifc->conv; *cp != nil; cp++){
for(cp = f->ipifc->conv; cp < e; cp++){ nifc = (Ipifc*)(*cp)->ptcl;
if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc) if(nifc == ifc)
continue; continue;
wlock(nifc); wlock(nifc);
m = nifc->m; if(nifc->m == nil
if(m == nil || m->areg == nil || waserror()){ || (lifc = ipremoteonifc(nifc, ip)) == nil
|| (lifc->type & Rptpt) != 0
|| waserror()){
wunlock(nifc); wunlock(nifc);
continue; continue;
} }
if((lifc = ipremoteonifc(nifc, ip)) != nil){ if((lifc->type & Rv4) == 0){
if((lifc->type & Rv4) == 0){ /* add solicited-node multicast addr */
/* add solicited-node multicast addr */ ipv62smcast(a, ip);
ipv62smcast(proxy, ip); if(add)
if(add) addselfcache(f, nifc, lifc, a, Rmulti);
addselfcache(f, nifc, lifc, proxy, Rmulti); else
else remselfcache(f, nifc, lifc, a);
remselfcache(f, nifc, lifc, proxy);
}
ipmove(proxy, lifc->local);
} }
ipmove(a, lifc->local);
wunlock(nifc); wunlock(nifc);
poperror(); poperror();
if(add && lifc != nil) if(add)
(*m->areg)(f, nifc, ip, proxy); ipifcregisteraddr(f, nifc, a, ip);
} }
} }

View file

@ -31,7 +31,7 @@ int
ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh) 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;
uchar *gate, nexthdr; uchar *gate, nexthdr;
Block *xp, *nb; Block *xp, *nb;
Fraghdr6 fraghdr; Fraghdr6 fraghdr;
@ -50,13 +50,6 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
/* Number of uchars in data and ip header to write */ /* Number of uchars in data and ip header to write */
len = blocklen(bp); len = blocklen(bp);
tentative = iptentative(f, eh->src);
if(tentative){
netlog(f, Logip, "reject tx of packet with tentative src address %I\n",
eh->src);
goto free;
}
if(gating){ if(gating){
chunk = nhgets(eh->ploadlen); chunk = nhgets(eh->ploadlen);
if(chunk > len){ if(chunk > len){
@ -217,7 +210,7 @@ free:
void void
ipiput6(Fs *f, Ipifc *ifc, Block *bp) ipiput6(Fs *f, Ipifc *ifc, Block *bp)
{ {
int hl, hop, tos, notforme, tentative; int hl, hop, tos;
uchar proto; uchar proto;
IP *ip; IP *ip;
Ip6hdr *h; Ip6hdr *h;
@ -242,16 +235,8 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
return; return;
} }
h = (Ip6hdr *)bp->rp;
notforme = ipforme(f, h->dst) == 0;
tentative = iptentative(f, h->dst);
if(tentative && h->proto != ICMPv6) {
print("tentative addr, drop\n");
goto drop;
}
/* Check header version */ /* Check header version */
h = (Ip6hdr *)bp->rp;
if(BLKIPVER(bp) != IP_VER6) { if(BLKIPVER(bp) != IP_VER6) {
ip->stats[InHdrErrors]++; ip->stats[InHdrErrors]++;
netlog(f, Logip, "ip: bad version %ux\n", (h->vcf[0]&0xF0)>>2); netlog(f, Logip, "ip: bad version %ux\n", (h->vcf[0]&0xF0)>>2);
@ -259,10 +244,10 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
} }
/* route */ /* route */
if(notforme) { if(ipforme(f, h->dst) == 0) {
Route *r; Route *r;
Routehint rh; Routehint rh;
Ipifc *toifc; Ipifc *nifc;
if(!ip->iprouting) if(!ip->iprouting)
goto drop; goto drop;
@ -277,8 +262,8 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
/* don't forward to source's network */ /* don't forward to source's network */
rh.r = nil; rh.r = nil;
r = v6lookup(f, h->dst, h->src, &rh); r = v6lookup(f, h->dst, h->src, &rh);
if(r == nil || (toifc = r->ifc) == nil || (r->type & Rv4) != 0 if(r == nil || (nifc = r->ifc) == nil || (r->type & Rv4) != 0
|| (toifc == ifc && !ifc->reflect)){ || (nifc == ifc && !ifc->reflect)){
ip->stats[OutDiscards]++; ip->stats[OutDiscards]++;
goto drop; goto drop;
} }
@ -292,7 +277,7 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
} }
/* process headers & reassemble if the interface expects it */ /* process headers & reassemble if the interface expects it */
bp = procxtns(ip, bp, toifc->reassemble); bp = procxtns(ip, bp, nifc->reassemble);
if(bp == nil) if(bp == nil)
return; return;
@ -312,7 +297,7 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
h = (Ip6hdr *) (bp->rp); h = (Ip6hdr *) (bp->rp);
proto = h->proto; proto = h->proto;
p = Fsrcvpcol(f, proto); p = Fsrcvpcol(f, proto);
if(p && p->rcv) { if(p != nil && p->rcv != nil) {
ip->stats[InDelivers]++; ip->stats[InDelivers]++;
(*p->rcv)(p, ifc, bp); (*p->rcv)(p, ifc, bp);
return; return;
@ -455,7 +440,7 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih)
/* /*
* block lists are too hard, pullupblock into a single block * block lists are too hard, pullupblock into a single block
*/ */
if(bp->next){ if(bp->next != nil){
bp = pullupblock(bp, blocklen(bp)); bp = pullupblock(bp, blocklen(bp));
ih = (Ip6hdr *)bp->rp; ih = (Ip6hdr *)bp->rp;
} }
@ -465,7 +450,7 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih)
/* /*
* find a reassembly queue for this fragment * find a reassembly queue for this fragment
*/ */
for(f = ip->flisthead6; f; f = fnext){ for(f = ip->flisthead6; f != nil; f = fnext){
fnext = f->next; fnext = f->next;
if(ipcmp(f->src, src)==0 && ipcmp(f->dst, dst)==0 && f->id == id) if(ipcmp(f->src, src)==0 && ipcmp(f->dst, dst)==0 && f->id == id)
break; break;
@ -524,7 +509,7 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih)
} }
/* Check overlap of a previous fragment - trim away as necessary */ /* Check overlap of a previous fragment - trim away as necessary */
if(prev) { if(prev != nil) {
ovlap = BKFG(prev)->foff + BKFG(prev)->flen - BKFG(bp)->foff; ovlap = BKFG(prev)->foff + BKFG(prev)->flen - BKFG(bp)->foff;
if(ovlap > 0) { if(ovlap > 0) {
if(ovlap >= BKFG(bp)->flen) { if(ovlap >= BKFG(bp)->flen) {
@ -541,12 +526,12 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih)
*l = bp; *l = bp;
/* Check to see if succeeding segments overlap */ /* Check to see if succeeding segments overlap */
if(bp->next) { if(bp->next != nil) {
l = &bp->next; l = &bp->next;
fend = BKFG(bp)->foff + BKFG(bp)->flen; fend = BKFG(bp)->foff + BKFG(bp)->flen;
/* Take completely covered segments out */ /* Take completely covered segments out */
while(*l) { while(*l != nil) {
ovlap = fend - BKFG(*l)->foff; ovlap = fend - BKFG(*l)->foff;
if(ovlap <= 0) if(ovlap <= 0)
break; break;
@ -570,7 +555,7 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih)
* with the trailing bit of fraghdr->offsetRM[1] set, we're done. * with the trailing bit of fraghdr->offsetRM[1] set, we're done.
*/ */
pktposn = 0; pktposn = 0;
for(bl = f->blist; bl && BKFG(bl)->foff == pktposn; bl = bl->next) { for(bl = f->blist; bl != nil && BKFG(bl)->foff == pktposn; bl = bl->next) {
fraghdr = (Fraghdr6 *)(bl->rp + uflen); fraghdr = (Fraghdr6 *)(bl->rp + uflen);
if((fraghdr->offsetRM[1] & 1) == 0) { if((fraghdr->offsetRM[1] & 1) == 0) {
bl = f->blist; bl = f->blist;
@ -584,7 +569,7 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih)
* Pullup all the fragment headers and * Pullup all the fragment headers and
* return a complete packet * return a complete packet
*/ */
for(bl = bl->next; bl; bl = bl->next) { for(bl = bl->next; bl != nil; bl = bl->next) {
fragsize = BKFG(bl)->flen; fragsize = BKFG(bl)->flen;
len += fragsize; len += fragsize;
bl->rp += uflen + IP6FHDR; bl->rp += uflen + IP6FHDR;