diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-04-22 18:54:13 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-04-22 18:54:13 +0200 |
commit | 20b9326daddd52ffe534a968fb596af1674f53cc (patch) | |
tree | dd78be5dc993adf3af0c18e910ffb94414b0bb27 /sys/src | |
parent | c80d94304d0b9946c822e073b637760a0894522a (diff) |
devip: fix ipv6 icmp unreachable handling, fix retransmit, fix ifc locking, remove tentative check
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/9/ip/arp.c | 85 | ||||
-rw-r--r-- | sys/src/9/ip/esp.c | 2 | ||||
-rw-r--r-- | sys/src/9/ip/ethermedium.c | 60 | ||||
-rw-r--r-- | sys/src/9/ip/ip.c | 31 | ||||
-rw-r--r-- | sys/src/9/ip/ip.h | 6 | ||||
-rw-r--r-- | sys/src/9/ip/ipifc.c | 241 | ||||
-rw-r--r-- | sys/src/9/ip/ipv6.c | 47 |
7 files changed, 237 insertions, 235 deletions
diff --git a/sys/src/9/ip/arp.c b/sys/src/9/ip/arp.c index 72e71a9f2..42c1ce262 100644 --- a/sys/src/9/ip/arp.c +++ b/sys/src/9/ip/arp.c @@ -293,32 +293,37 @@ arpresolve(Arp *arp, Arpent *a, Medium *type, uchar *mac) } 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; Route *r; Arpent *a, *f, **l; Ipifc *ifc; Block *bp, *next; - Medium *m; uchar v6ip[IPaddrlen]; arp = fs->arp; switch(version){ case V4: - r = v4lookup(fs, ip, src, nil); + r = v4lookup(fs, ip, ia, nil); v4tov6(v6ip, ip); ip = v6ip; break; case V6: - r = v6lookup(fs, ip, src, nil); + r = v6lookup(fs, ip, ia, nil); break; default: panic("arpenter: version %d", version); 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; + + rlock(ifc); + if(ifc->m == nil || ifc->m->maclen != n || ifc->m->maclen == 0){ + runlock(ifc); return -1; + } qlock(arp); for(a = arp->hash[haship(ip)]; a != nil; a = a->hash){ @@ -351,28 +356,17 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *src, int refr qunlock(arp); while(bp != nil){ - if(!canrlock(ifc)){ - freeblistchain(bp); - break; - } - 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); + ifc->m->bwrite(ifc, concatblock(bp), version, ip); poperror(); bp = next; } - + runlock(ifc); return 1; } } @@ -383,8 +377,9 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *src, int refr a->ctime = NOW; memmove(a->mac, mac, n); } - qunlock(arp); + runlock(ifc); + return refresh == 0; } @@ -396,7 +391,7 @@ arpwrite(Fs *fs, char *s, int len) Arpent *a, *x; Medium *m; char *f[5], buf[256]; - uchar ip[IPaddrlen], src[IPaddrlen], mac[MAClen]; + uchar ip[IPaddrlen], ia[IPaddrlen], mac[MAClen]; arp = fs->arp; @@ -438,7 +433,7 @@ arpwrite(Fs *fs, char *s, int len) error(Ebadip); if((n = parsemac(mac, f[2], sizeof(mac))) <= 0) error(Ebadarp); - findlocalip(fs, src, ip); + findlocalip(fs, ia, ip); break; case 4: m = ipfindmedium(f[1]); @@ -448,7 +443,7 @@ arpwrite(Fs *fs, char *s, int len) error(Ebadip); if((n = parsemac(mac, f[3], sizeof(mac))) != m->maclen) error(Ebadarp); - findlocalip(fs, src, ip); + findlocalip(fs, ia, ip); break; case 5: m = ipfindmedium(f[1]); @@ -458,11 +453,11 @@ arpwrite(Fs *fs, char *s, int len) error(Ebadip); if((n = parsemac(mac, f[3], sizeof(mac))) != m->maclen) error(Ebadarp); - if(parseip(src, f[4]) == -1) + if(parseip(ia, f[4]) == -1) error(Ebadip); break; } - if(arpenter(fs, V6, ip, mac, n, src, 0) <= 0) + if(arpenter(fs, V6, ip, mac, n, ia, 0) <= 0) error("destination unreachable"); } else if(strcmp(f[0], "del") == 0){ if (n != 2) @@ -495,8 +490,8 @@ convmac(char *p, uchar *mac, int n) int arpread(Arp *arp, char *s, ulong offset, int len) { - uchar ip[IPaddrlen], src[IPaddrlen]; - char mac[2*MAClen+1], *p, *state; + char mac[2*MAClen+1], *state, *mname, *p; + uchar ip[IPaddrlen], ia[IPaddrlen]; Ipifc *ifc; Arpent *a; long n, o; @@ -504,18 +499,25 @@ arpread(Arp *arp, char *s, ulong offset, int len) p = s; o = -offset; 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; + rlock(ifc); qlock(arp); state = arpstate[a->state]; 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); qunlock(arp); + runlock(ifc); - 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); + mname, state, ip, mac, ia); if(o < 0) { if(n > -o) memmove(p, p-o, n+o); @@ -549,17 +551,20 @@ ndpsendsol(Fs *f, Ipifc *ifc, Arpent *a) if(!ipv6local(ifc, src, targ)) return; 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) { Block *next, *xp; Arpent *a, *b, **l; - Fs *f; - Ipifc *ifc = nil; + Ipifc *ifc; long nrxt; + Fs *f; qlock(arp); f = arp->f; @@ -573,6 +578,7 @@ rxmitsols(Arp *arp) if(nrxt > 3*ReTransTimer/4) goto dodrops; /* return nrxt; */ + ifc = nil; for(; a != nil; a = a->nextrxt){ ifc = a->ifc; if(a->rxtsrem > 0 && ifc != nil && canrlock(ifc)){ @@ -628,8 +634,19 @@ dodrops: qunlock(arp); for(; xp != nil; xp = next){ + Ip6hdr *eh; + Route *r; + 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); } diff --git a/sys/src/9/ip/esp.c b/sys/src/9/ip/esp.c index 8fec0c766..1d8a86201 100644 --- a/sys/src/9/ip/esp.c +++ b/sys/src/9/ip/esp.c @@ -472,7 +472,7 @@ espiput(Proto *esp, Ipifc*, Block *bp) ecb = c->ptcl; /* too hard to do decryption/authentication on block lists */ - if(bp->next) + if(bp->next != nil) bp = concatblock(bp); if(BLEN(bp) < vers.hdrlen + ecb->espivlen + Esptaillen + ecb->ahlen) { diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c index 0532457de..245959eb5 100644 --- a/sys/src/9/ip/ethermedium.c +++ b/sys/src/9/ip/ethermedium.c @@ -33,7 +33,7 @@ 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 void etherareg(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *ip); static Block* multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac); static void sendarp(Ipifc *ifc, Arpent *a); static int multicastea(uchar *ea, uchar *ip); @@ -219,8 +219,8 @@ etherbind(Ipifc *ifc, int argc, char **argv) poperror(); kproc("etherread4", etherread4, ifc); - kproc("recvarpproc", recvarpproc, ifc); kproc("etherread6", etherread6, ifc); + kproc("recvarpproc", recvarpproc, ifc); } /* @@ -231,27 +231,27 @@ etherunbind(Ipifc *ifc) { Etherrock *er = ifc->arg; - if(er->read4p) + if(er->read4p != nil) postnote(er->read4p, 1, "unbind", 0); - if(er->read6p) + if(er->read6p != nil) postnote(er->read6p, 1, "unbind", 0); - if(er->arpp) + if(er->arpp != nil) postnote(er->arpp, 1, "unbind", 0); /* 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); if(er->mchan4 != nil) cclose(er->mchan4); - if(er->achan != nil) - cclose(er->achan); if(er->cchan4 != nil) cclose(er->cchan4); if(er->mchan6 != nil) cclose(er->mchan6); if(er->cchan6 != nil) cclose(er->cchan6); + if(er->achan != nil) + cclose(er->achan); free(er); } @@ -329,7 +329,7 @@ etherread4(void *a) er = ifc->arg; er->read4p = up; /* hide identity under a rock for unbind */ if(waserror()){ - er->read4p = 0; + er->read4p = nil; pexit("hangup", 1); } for(;;){ @@ -369,7 +369,7 @@ etherread6(void *a) er = ifc->arg; er->read6p = up; /* hide identity under a rock for unbind */ if(waserror()){ - er->read6p = 0; + er->read6p = nil; pexit("hangup", 1); } for(;;){ @@ -571,6 +571,11 @@ recvarp(Ipifc *ifc) if(ebp == nil) return; + if(!canrlock(ifc)){ + freeb(ebp); + return; + } + e = (Etherarp*)ebp->rp; switch(nhgets(e->op)) { default: @@ -647,8 +652,14 @@ recvarp(Ipifc *ifc) memmove(r->s, ifc->mac, sizeof(r->s)); rbp->wp += n; + runlock(ifc); + freeb(ebp); + devtab[er->achan->type]->bwrite(er->achan, rbp, 0); + return; } + + runlock(ifc); freeb(ebp); } @@ -660,7 +671,7 @@ recvarpproc(void *v) er->arpp = up; if(waserror()){ - er->arpp = 0; + er->arpp = nil; pexit("hangup", 1); } for(;;) @@ -745,10 +756,10 @@ etherpref2addr(uchar *pref, uchar *ea) } static void -etherareg(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy) +etherareg(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *ip) { static char tdad[] = "dad6"; - uchar mcast[IPaddrlen]; + uchar a[IPaddrlen]; if(ipcmp(ip, IPnoaddr) == 0) return; @@ -758,16 +769,25 @@ etherareg(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy) return; } - if(!iptentative(f, ip)){ - icmpna(f, proxy, v6allnodesL, ip, ifc->mac, 1<<5); + if((lifc->type&Rv4) != 0) + return; + + if(!lifc->tentative){ + icmpna(f, lifc->local, 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); + if(ipcmp(lifc->local, ip) != 0) + return; + /* temporarily add route for duplicate address detection */ + ipv62smcast(a, ip); + 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); - - remroute(f, mcast, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad); + poperror(); + remroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad); } diff --git a/sys/src/9/ip/ip.c b/sys/src/9/ip/ip.c index 948125737..7166619dd 100644 --- a/sys/src/9/ip/ip.c +++ b/sys/src/9/ip/ip.c @@ -99,6 +99,7 @@ ip_init(Fs *f) IP *ip; ip = smalloc(sizeof(IP)); + ip->stats[DefaultTTL] = MAXTTL; initfrag(ip, 100); f->ip = ip; @@ -362,7 +363,7 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp) if(notforme) { Route *r; Routehint rh; - Ipifc *toifc; + Ipifc *nifc; if(!ip->iprouting) goto drop; @@ -370,8 +371,8 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp) /* don't forward to source's network */ rh.r = nil; r = v4lookup(f, h->dst, h->src, &rh); - if(r == nil || (toifc = r->ifc) == nil - || (toifc == ifc && !ifc->reflect)){ + if(r == nil || (nifc = r->ifc) == nil + || (nifc == ifc && !ifc->reflect)){ ip->stats[OutDiscards]++; goto drop; } @@ -385,7 +386,7 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp) } /* reassemble if the interface expects it */ - if(toifc->reassemble){ + if(nifc->reassemble){ frag = nhgets(h->frag); if(frag & ~IP_DF) { h->tos = 0; @@ -441,8 +442,6 @@ ipstats(Fs *f, char *buf, int len) int i; ip = f->ip; - ip->stats[DefaultTTL] = MAXTTL; - p = buf; e = p+len; 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 */ - if(bp->next){ + if(bp->next != nil){ bp = pullupblock(bp, blocklen(bp)); ih = (Ip4hdr*)(bp->rp); } @@ -477,7 +476,7 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih) /* * 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 */ if(f->src == src && f->dst == dst && f->id == id) break; @@ -536,7 +535,7 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih) } /* 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; if(ovlap > 0) { if(ovlap >= BKFG(bp)->flen) { @@ -553,11 +552,11 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih) *l = bp; /* Check to see if succeeding segments overlap */ - if(bp->next) { + if(bp->next != nil) { l = &bp->next; fend = BKFG(bp)->foff + BKFG(bp)->flen; /* Take completely covered segments out */ - while(*l) { + while(*l != nil) { ovlap = fend - BKFG(*l)->foff; if(ovlap <= 0) break; @@ -581,7 +580,7 @@ ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih) * without IP_MF set, we're done. */ pktposn = 0; - for(bl = f->blist; bl; bl = bl->next) { + for(bl = f->blist; bl != nil; bl = bl->next) { if(BKFG(bl)->foff != pktposn) break; 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 * 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; len += fragsize; bl->rp += IP4HDR; @@ -622,7 +621,7 @@ ipfragfree4(IP *ip, Fragment4 *frag) { Fragment4 *fl, **l; - if(frag->blist) + if(frag->blist != nil) freeblist(frag->blist); frag->src = 0; @@ -630,7 +629,7 @@ ipfragfree4(IP *ip, Fragment4 *frag) frag->blist = nil; l = &ip->flisthead4; - for(fl = *l; fl; fl = fl->next) { + for(fl = *l; fl != nil; fl = fl->next) { if(fl == frag) { *l = frag->next; break; @@ -653,7 +652,7 @@ ipfragallo4(IP *ip) while(ip->fragfree4 == nil) { /* 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); } diff --git a/sys/src/9/ip/ip.h b/sys/src/9/ip/ip.h index 6047acb2a..10428afdf 100644 --- a/sys/src/9/ip/ip.h +++ b/sys/src/9/ip/ip.h @@ -243,7 +243,7 @@ struct Medium void (*pktin)(Fs *f, Ipifc *ifc, Block *bp); /* 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 */ 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 void arprelease(Arp*, Arpent *a); 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*); /* @@ -654,8 +654,6 @@ extern Medium pktmedium; 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 *ip); extern int ipismulticast(uchar *ip); extern Ipifc* findipifc(Fs*, uchar *local, uchar *remote, int type); extern Ipifc* findipifcstr(Fs *f, char *s); diff --git a/sys/src/9/ip/ipifc.c b/sys/src/9/ip/ipifc.c index 371812127..af5c1606f 100644 --- a/sys/src/9/ip/ipifc.c +++ b/sys/src/9/ip/ipifc.c @@ -61,6 +61,7 @@ static char tifc[] = "ifc "; 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 ipifcregisteraddr(Fs*, Ipifc*, uchar *, uchar *); static void ipifcregisterproxy(Fs*, Ipifc*, uchar*, int); static char* ipifcremlifc(Ipifc*, Iplifc**); @@ -218,10 +219,6 @@ ipifcunbind(Ipifc *ifc) /* disassociate logical interfaces (before zeroing ifc->arg) */ while(ifc->lifc != nil){ err = ipifcremlifc(ifc, &ifc->lifc); - /* - * note: err non-zero means lifc not found, - * which can't happen in this case. - */ if(err != nil) error(err); } @@ -273,7 +270,7 @@ ipifcstate(Conv *c, char *state, int n) ifc->in, ifc->out, ifc->inerr, ifc->outerr); 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, lifc->mask, lifc->remote, lifc->validlt, lifc->preflt); if(ifc->lifc == nil) @@ -291,9 +288,8 @@ ipifclocal(Conv *c, char *state, int n) int m; ifc = (Ipifc*)c->ptcl; - m = 0; - rlock(ifc); + m = 0; for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ m += snprint(state+m, n - m, "%-40.40I ->", lifc->local); 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]; Iplifc *lifc, **l; int i, type, mtu; - Medium *m; Fs *f; - if((m = ifc->m) == nil) - return "ipifc not yet bound to device"; - - f = ifc->conv->p->f; - + mtu = 0; type = Rifc; memset(ip, 0, IPaddrlen); memset(mask, 0, IPaddrlen); @@ -424,8 +415,6 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) /* fall through */ case 5: mtu = strtoul(argv[4], 0, 0); - if(mtu >= m->mintu && mtu <= m->maxtu) - ifc->maxtu = mtu; /* fall through */ case 4: 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); + if(ifc->m == nil) + return "ipifc not yet bound to device"; + + f = ifc->conv->p->f; if(waserror()){ 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 */ if((lifc = iplocalonifc(ifc, ip)) != nil){ if(lifcp != nil) { @@ -576,9 +572,7 @@ done: wunlock(ifc); poperror(); - /* register the address on this network for address resolution */ - if(m->areg != nil) - (*m->areg)(f, ifc, ip, ip); + ipifcregisteraddr(f, ifc, ip, ip); return nil; } @@ -701,7 +695,7 @@ ipifcconnect(Conv* c, char **argv, int argc) wunlock(ifc); err = ipifcadd(ifc, argv, argc, 0, nil); - if(err) + if(err != nil) return err; Fsconnected(c, nil); @@ -1069,18 +1063,6 @@ ipselftabread(Fs *f, char *cp, ulong offset, int n) 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 * 0 - no match @@ -1112,27 +1094,26 @@ Ipifc* findipifc(Fs *f, uchar *local, uchar *remote, int type) { uchar gnet[IPaddrlen]; + int spec, xspec; Ipifc *ifc, *x; Iplifc *lifc; - Conv **cp, **e; - int spec, xspec; + Conv **cp; x = nil; xspec = 0; - - /* find most specific match */ - e = &f->ipifc->conv[f->ipifc->nc]; - for(cp = f->ipifc->conv; cp < e; cp++){ - if(*cp == nil) - continue; + for(cp = f->ipifc->conv; *cp != nil; cp++){ ifc = (Ipifc*)(*cp)->ptcl; + rlock(ifc); for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ if(type & Runi){ - if(ipcmp(remote, lifc->local) == 0) + if(ipcmp(remote, lifc->local) == 0){ + Found: + runlock(ifc); return ifc; + } } else if(type & (Rbcast|Rmulti)) { if(ipcmp(local, lifc->local) == 0) - return ifc; + goto Found; } maskip(remote, lifc->mask, gnet); if(ipcmp(gnet, lifc->net) == 0){ @@ -1143,6 +1124,7 @@ findipifc(Fs *f, uchar *local, uchar *remote, int type) } } } + runlock(ifc); } return x; } @@ -1159,7 +1141,7 @@ findipifcstr(Fs *f, char *s) if(p > s && *p == '\0'){ if(x < 0) 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; } if(parseip(ip, s) != -1) @@ -1167,35 +1149,36 @@ findipifcstr(Fs *f, char *s) return nil; } +/* + * find "best" (global > link local > unspecified) + * local address; address must be current. + */ static void findprimaryipv6(Fs *f, uchar *local) { int atype, atypel; - Conv **cp, **e; - Ipifc *ifc; Iplifc *lifc; + Ipifc *ifc; + Conv **cp; ipmove(local, v6Unspecified); atype = unspecifiedv6; - /* - * 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; + for(cp = f->ipifc->conv; *cp != nil; cp++){ ifc = (Ipifc*)(*cp)->ptcl; + rlock(ifc); for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ atypel = v6addrtype(lifc->local); if(atypel > atype && v6addrcurr(lifc)) { ipmove(local, lifc->local); atype = atypel; - if(atype == globalv6) + if(atype == globalv6){ + runlock(ifc); return; + } } } + runlock(ifc); } } @@ -1205,20 +1188,22 @@ findprimaryipv6(Fs *f, uchar *local) static void findprimaryipv4(Fs *f, uchar *local) { - Conv **cp, **e; - Ipifc *ifc; Iplifc *lifc; + Ipifc *ifc; + Conv **cp; /* find first ifc local address */ - e = &f->ipifc->conv[f->ipifc->nc]; - for(cp = f->ipifc->conv; cp < e; cp++){ - if(*cp == nil) - continue; + for(cp = f->ipifc->conv; *cp != nil; cp++){ ifc = (Ipifc*)(*cp)->ptcl; - if((lifc = ifc->lifc) != nil && (lifc->type & Rv4) != 0){ - ipmove(local, lifc->local); - return; + rlock(ifc); + for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ + if((lifc->type & Rv4) != 0){ + ipmove(local, lifc->local); + runlock(ifc); + return; + } } + runlock(ifc); } ipmove(local, IPnoaddr); } @@ -1310,41 +1295,47 @@ void findlocalip(Fs *f, uchar *local, uchar *remote) { Route *r; - Ipifc *ifc; Iplifc *lifc; - Conv **cp, **e; + Ipifc *ifc, *nifc; + Conv **cp; - qlock(f->ipifc); - e = &f->ipifc->conv[f->ipifc->nc]; - for(cp = f->ipifc->conv; cp < e; cp++){ - if(*cp == nil) - continue; + for(cp = f->ipifc->conv; *cp != nil; cp++){ ifc = (Ipifc*)(*cp)->ptcl; + rlock(ifc); for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ if(lifc->tentative) continue; + r = v6lookup(f, remote, lifc->local, nil); - if(r == nil || (ifc = r->ifc) == nil) + if(r == nil || (nifc = r->ifc) == nil) continue; if(r->type & Runi){ ipmove(local, remote); - goto out; + runlock(ifc); + return; } + if(nifc != ifc) rlock(nifc); if((r->type & (Rifc|Rbcast|Rmulti|Rv4)) == Rv4){ ipmove(local, v4prefix); - if(ipv4local(ifc, local+IPv4off, r->v4.gate)) - goto out; + if(ipv4local(nifc, local+IPv4off, r->v4.gate)){ + if(nifc != ifc) runlock(nifc); + runlock(ifc); + return; + } + } + if(ipv6local(nifc, local, remote)){ + if(nifc != ifc) runlock(nifc); + runlock(ifc); + return; } - if(ipv6local(ifc, local, remote)) - goto out; + if(nifc != ifc) runlock(nifc); } + runlock(ifc); } if(isv4(remote)) findprimaryipv4(f, local); else findprimaryipv6(f, local); -out: - qunlock(f->ipifc); } @@ -1408,20 +1399,6 @@ ipismulticast(uchar *ip) return V6; 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 @@ -1430,13 +1407,10 @@ void ipifcaddmulti(Conv *c, uchar *ma, uchar *ia) { Ipmulti *multi, **l; - Conv **cp, **e; Iplifc *lifc; Ipifc *ifc; Fs *f; - f = c->p->f; - for(l = &c->multi; *l != nil; l = &(*l)->next) if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0) return; /* it's already there */ @@ -1446,11 +1420,8 @@ ipifcaddmulti(Conv *c, uchar *ma, uchar *ia) ipmove(multi->ia, ia); multi->next = nil; - e = &f->ipifc->conv[f->ipifc->nc]; - for(cp = f->ipifc->conv; cp < e; cp++){ - if((*cp) == nil || (*cp)->inuse == 0) - continue; - ifc = (Ipifc*)(*cp)->ptcl; + f = c->p->f; + if((ifc = findipifc(f, ia, ma, Rmulti)) != nil){ wlock(ifc); if(waserror()){ wunlock(ifc); @@ -1471,13 +1442,10 @@ void ipifcremmulti(Conv *c, uchar *ma, uchar *ia) { Ipmulti *multi, **l; - Conv **cp, **e; Iplifc *lifc; Ipifc *ifc; Fs *f; - f = c->p->f; - for(l = &c->multi; *l != nil; l = &(*l)->next) if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0) break; @@ -1487,12 +1455,10 @@ ipifcremmulti(Conv *c, uchar *ma, uchar *ia) return; /* we don't have it open */ *l = multi->next; + free(multi); - e = &f->ipifc->conv[f->ipifc->nc]; - for(cp = f->ipifc->conv; cp < e; cp++){ - if((*cp) == nil || (*cp)->inuse == 0) - continue; - ifc = (Ipifc*)(*cp)->ptcl; + f = c->p->f; + if((ifc = findipifc(f, ia, ma, Rmulti)) != nil){ wlock(ifc); if(waserror()){ wunlock(ifc); @@ -1504,46 +1470,63 @@ ipifcremmulti(Conv *c, uchar *ma, uchar *ia) 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 ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip, int add) { - uchar proxy[IPaddrlen]; - Conv **cp, **e; + uchar a[IPaddrlen]; Iplifc *lifc; Ipifc *nifc; - Medium *m; + Conv **cp; /* 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 < e; cp++){ - if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc) + for(cp = f->ipifc->conv; *cp != nil; cp++){ + nifc = (Ipifc*)(*cp)->ptcl; + if(nifc == ifc) continue; wlock(nifc); - m = nifc->m; - if(m == nil || m->areg == nil || waserror()){ + if(nifc->m == nil + || (lifc = ipremoteonifc(nifc, ip)) == nil + || (lifc->type & Rptpt) != 0 + || waserror()){ wunlock(nifc); continue; } - if((lifc = ipremoteonifc(nifc, ip)) != nil){ - if((lifc->type & Rv4) == 0){ - /* add solicited-node multicast addr */ - ipv62smcast(proxy, ip); - if(add) - addselfcache(f, nifc, lifc, proxy, Rmulti); - else - remselfcache(f, nifc, lifc, proxy); - } - ipmove(proxy, lifc->local); + if((lifc->type & Rv4) == 0){ + /* add solicited-node multicast addr */ + ipv62smcast(a, ip); + if(add) + addselfcache(f, nifc, lifc, a, Rmulti); + else + remselfcache(f, nifc, lifc, a); } + ipmove(a, lifc->local); wunlock(nifc); poperror(); - if(add && lifc != nil) - (*m->areg)(f, nifc, ip, proxy); + if(add) + ipifcregisteraddr(f, nifc, a, ip); } } diff --git a/sys/src/9/ip/ipv6.c b/sys/src/9/ip/ipv6.c index a2836d7ae..aab473c87 100644 --- a/sys/src/9/ip/ipv6.c +++ b/sys/src/9/ip/ipv6.c @@ -31,7 +31,7 @@ int ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh) { int medialen, len, chunk, uflen, flen, seglen, lid, offset, fragoff; - int morefrags, blklen, rv = 0, tentative; + int morefrags, blklen, rv = 0; uchar *gate, nexthdr; Block *xp, *nb; 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 */ 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){ chunk = nhgets(eh->ploadlen); if(chunk > len){ @@ -217,7 +210,7 @@ free: void ipiput6(Fs *f, Ipifc *ifc, Block *bp) { - int hl, hop, tos, notforme, tentative; + int hl, hop, tos; uchar proto; IP *ip; Ip6hdr *h; @@ -242,16 +235,8 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp) 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 */ + h = (Ip6hdr *)bp->rp; if(BLKIPVER(bp) != IP_VER6) { ip->stats[InHdrErrors]++; 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 */ - if(notforme) { + if(ipforme(f, h->dst) == 0) { Route *r; Routehint rh; - Ipifc *toifc; + Ipifc *nifc; if(!ip->iprouting) goto drop; @@ -277,8 +262,8 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp) /* don't forward to source's network */ rh.r = nil; r = v6lookup(f, h->dst, h->src, &rh); - if(r == nil || (toifc = r->ifc) == nil || (r->type & Rv4) != 0 - || (toifc == ifc && !ifc->reflect)){ + if(r == nil || (nifc = r->ifc) == nil || (r->type & Rv4) != 0 + || (nifc == ifc && !ifc->reflect)){ ip->stats[OutDiscards]++; goto drop; } @@ -292,7 +277,7 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp) } /* process headers & reassemble if the interface expects it */ - bp = procxtns(ip, bp, toifc->reassemble); + bp = procxtns(ip, bp, nifc->reassemble); if(bp == nil) return; @@ -312,7 +297,7 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp) h = (Ip6hdr *) (bp->rp); proto = h->proto; p = Fsrcvpcol(f, proto); - if(p && p->rcv) { + if(p != nil && p->rcv != nil) { ip->stats[InDelivers]++; (*p->rcv)(p, ifc, bp); return; @@ -455,7 +440,7 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih) /* * block lists are too hard, pullupblock into a single block */ - if(bp->next){ + if(bp->next != nil){ bp = pullupblock(bp, blocklen(bp)); ih = (Ip6hdr *)bp->rp; } @@ -465,7 +450,7 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih) /* * 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; if(ipcmp(f->src, src)==0 && ipcmp(f->dst, dst)==0 && f->id == id) break; @@ -524,7 +509,7 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih) } /* 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; if(ovlap > 0) { if(ovlap >= BKFG(bp)->flen) { @@ -541,12 +526,12 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih) *l = bp; /* Check to see if succeeding segments overlap */ - if(bp->next) { + if(bp->next != nil) { l = &bp->next; fend = BKFG(bp)->foff + BKFG(bp)->flen; /* Take completely covered segments out */ - while(*l) { + while(*l != nil) { ovlap = fend - BKFG(*l)->foff; if(ovlap <= 0) 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. */ 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); if((fraghdr->offsetRM[1] & 1) == 0) { bl = f->blist; @@ -584,7 +569,7 @@ ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih) * Pullup all the fragment headers and * 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; len += fragsize; bl->rp += uflen + IP6FHDR; |