devip: pick source address for neighbor solicitations as of rfc4861 7.2.2, cleanup
rfc4861 7.2.2: If the source address of the packet prompting the solicitation is the same as one of the addresses assigned to the outgoing interface, that address SHOULD be placed in the IP Source Address of the outgoing solicitation. this change adds ndbsendsol() which handles the source address selection and also handles the arp table locking; avoiding access to the arp entry after the arp table is unlocked. cleanups: - use ipmove() instead of memmove(). - useless extern qualifiers
This commit is contained in:
parent
20cbb88e32
commit
547f60b4c5
5 changed files with 52 additions and 36 deletions
|
@ -47,7 +47,7 @@ char *Ebadarp = "bad arp";
|
|||
|
||||
#define haship(s) ((s)[IPaddrlen-1]%NHASH)
|
||||
|
||||
extern int ReTransTimer = RETRANS_TIMER;
|
||||
int ReTransTimer = RETRANS_TIMER;
|
||||
|
||||
static void rxmitproc(void *v);
|
||||
|
||||
|
@ -223,7 +223,7 @@ 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(memcmp(ip, a->ip, sizeof(a->ip)) == 0)
|
||||
if(ipcmp(ip, a->ip) == 0)
|
||||
if(type == a->type)
|
||||
break;
|
||||
}
|
||||
|
@ -536,13 +536,35 @@ arpread(Arp *arp, char *p, ulong offset, int len)
|
|||
return n;
|
||||
}
|
||||
|
||||
extern int
|
||||
void
|
||||
ndpsendsol(Fs *f, Ipifc *ifc, Arpent *a)
|
||||
{
|
||||
uchar targ[IPaddrlen], src[IPaddrlen];
|
||||
|
||||
ipmove(targ, a->ip);
|
||||
|
||||
if(a->last != nil){
|
||||
ipmove(src, ((Ip6hdr*)a->last->rp)->src);
|
||||
arprelease(f->arp, a);
|
||||
|
||||
if(iplocalonifc(ifc, src) || ipproxyifc(f, ifc, src))
|
||||
goto send;
|
||||
} else {
|
||||
arprelease(f->arp, a);
|
||||
}
|
||||
|
||||
if(!ipv6local(ifc, src, targ))
|
||||
return;
|
||||
send:
|
||||
icmpns(f, src, SRC_UNI, targ, TARG_MULTI, ifc->mac);
|
||||
}
|
||||
|
||||
int
|
||||
rxmitsols(Arp *arp)
|
||||
{
|
||||
Block *next, *xp;
|
||||
Arpent *a, *b, **l;
|
||||
Fs *f;
|
||||
uchar ipsrc[IPaddrlen];
|
||||
Ipifc *ifc = nil;
|
||||
long nrxt;
|
||||
|
||||
|
@ -579,10 +601,7 @@ rxmitsols(Arp *arp)
|
|||
if(a == nil)
|
||||
goto dodrops;
|
||||
|
||||
|
||||
qunlock(arp); /* for icmpns */
|
||||
if(ipv6local(ifc, ipsrc, a->ip))
|
||||
icmpns(f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac);
|
||||
ndpsendsol(f, ifc, a); /* unlocks arp */
|
||||
|
||||
runlock(ifc);
|
||||
qlock(arp);
|
||||
|
|
|
@ -498,7 +498,6 @@ resolveaddr6(Ipifc *ifc, Arpent *a)
|
|||
{
|
||||
Block *bp;
|
||||
Etherrock *er = ifc->arg;
|
||||
uchar ipsrc[IPaddrlen];
|
||||
|
||||
/* don't do anything if it's been less than a second since the last */
|
||||
if(NOW - a->ctime < ReTransTimer){
|
||||
|
@ -523,10 +522,7 @@ resolveaddr6(Ipifc *ifc, Arpent *a)
|
|||
}
|
||||
|
||||
a->rxtsrem--;
|
||||
arprelease(er->f->arp, a);
|
||||
|
||||
if(ipv6local(ifc, ipsrc, a->ip))
|
||||
icmpns(er->f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac);
|
||||
ndpsendsol(er->f, ifc, a); /* unlocks arp */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -610,7 +606,7 @@ recvarp(Ipifc *ifc)
|
|||
|
||||
case ARPREQUEST:
|
||||
/* don't answer arps till we know who we are */
|
||||
if(ifc->lifc == 0)
|
||||
if(ifc->lifc == nil)
|
||||
break;
|
||||
|
||||
/* check for machine using my ip or ether address */
|
||||
|
|
|
@ -113,7 +113,7 @@ icmpcreate(Conv *c)
|
|||
c->wq = qbypass(icmpkick, c);
|
||||
}
|
||||
|
||||
extern char*
|
||||
char*
|
||||
icmpconnect(Conv *c, char **argv, int argc)
|
||||
{
|
||||
char *e;
|
||||
|
@ -126,7 +126,7 @@ icmpconnect(Conv *c, char **argv, int argc)
|
|||
return nil;
|
||||
}
|
||||
|
||||
extern int
|
||||
int
|
||||
icmpstate(Conv *c, char *state, int n)
|
||||
{
|
||||
USED(c);
|
||||
|
@ -137,7 +137,7 @@ icmpstate(Conv *c, char *state, int n)
|
|||
);
|
||||
}
|
||||
|
||||
extern char*
|
||||
char*
|
||||
icmpannounce(Conv *c, char **argv, int argc)
|
||||
{
|
||||
char *e;
|
||||
|
@ -150,7 +150,7 @@ icmpannounce(Conv *c, char **argv, int argc)
|
|||
return nil;
|
||||
}
|
||||
|
||||
extern void
|
||||
void
|
||||
icmpclose(Conv *c)
|
||||
{
|
||||
qclose(c->rq);
|
||||
|
@ -214,7 +214,7 @@ ip4me(Fs *f, uchar ip4[4])
|
|||
return (ipforme(f, addr) & Runi) != 0;
|
||||
}
|
||||
|
||||
extern void
|
||||
void
|
||||
icmpttlexceeded(Fs *f, uchar *ia, Block *bp)
|
||||
{
|
||||
Block *nbp;
|
||||
|
@ -270,13 +270,13 @@ icmpunreachable(Fs *f, Block *bp, int code, int seq)
|
|||
ipoput4(f, nbp, 0, MAXTTL, DFLTTOS, nil);
|
||||
}
|
||||
|
||||
extern void
|
||||
void
|
||||
icmpnoconv(Fs *f, Block *bp)
|
||||
{
|
||||
icmpunreachable(f, bp, 3, 0);
|
||||
}
|
||||
|
||||
extern void
|
||||
void
|
||||
icmpcantfrag(Fs *f, Block *bp, int mtu)
|
||||
{
|
||||
icmpunreachable(f, bp, 4, mtu);
|
||||
|
|
|
@ -345,7 +345,7 @@ mkechoreply6(Block *bp, Ipifc *ifc)
|
|||
* tuni == TARG_MULTI => multicast for address resolution,
|
||||
* and tuni == TARG_UNI => neighbor reachability.
|
||||
*/
|
||||
extern void
|
||||
void
|
||||
icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
|
||||
{
|
||||
Block *nbp;
|
||||
|
@ -357,18 +357,18 @@ icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
|
|||
np = (Ndpkt*) nbp->rp;
|
||||
|
||||
if(suni == SRC_UNSPEC)
|
||||
memmove(np->src, v6Unspecified, IPaddrlen);
|
||||
ipmove(np->src, v6Unspecified);
|
||||
else
|
||||
memmove(np->src, src, IPaddrlen);
|
||||
ipmove(np->src, src);
|
||||
|
||||
if(tuni == TARG_UNI)
|
||||
memmove(np->dst, targ, IPaddrlen);
|
||||
ipmove(np->dst, targ);
|
||||
else
|
||||
ipv62smcast(np->dst, targ);
|
||||
|
||||
np->type = NbrSolicit;
|
||||
np->code = 0;
|
||||
memmove(np->target, targ, IPaddrlen);
|
||||
ipmove(np->target, targ);
|
||||
if(suni != SRC_UNSPEC) {
|
||||
np->otype = SRC_LLADDR;
|
||||
np->olen = 1; /* 1+1+6 = 8 = 1 8-octet */
|
||||
|
@ -388,7 +388,7 @@ icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
|
|||
/*
|
||||
* sends out an ICMPv6 neighbor advertisement. pktflags == RSO flags.
|
||||
*/
|
||||
extern void
|
||||
void
|
||||
icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
|
||||
{
|
||||
Block *nbp;
|
||||
|
@ -399,13 +399,13 @@ icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
|
|||
nbp = newIPICMP(NDPKTSZ);
|
||||
np = (Ndpkt*)nbp->rp;
|
||||
|
||||
memmove(np->src, src, IPaddrlen);
|
||||
memmove(np->dst, dst, IPaddrlen);
|
||||
ipmove(np->src, src);
|
||||
ipmove(np->dst, dst);
|
||||
|
||||
np->type = NbrAdvert;
|
||||
np->code = 0;
|
||||
np->icmpid[0] = flags;
|
||||
memmove(np->target, targ, IPaddrlen);
|
||||
ipmove(np->target, targ);
|
||||
|
||||
np->otype = TARGET_LLADDR;
|
||||
np->olen = 1;
|
||||
|
@ -420,7 +420,7 @@ icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
|
|||
ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
|
||||
}
|
||||
|
||||
extern void
|
||||
void
|
||||
icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
|
||||
{
|
||||
int osz = BLEN(bp);
|
||||
|
@ -449,7 +449,7 @@ icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
|
|||
goto freebl;
|
||||
}
|
||||
|
||||
memmove(np->dst, p->src, IPaddrlen);
|
||||
ipmove(np->dst, p->src);
|
||||
np->type = UnreachableV6;
|
||||
np->code = code;
|
||||
memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
|
||||
|
@ -468,7 +468,7 @@ freebl:
|
|||
freeblist(bp);
|
||||
}
|
||||
|
||||
extern void
|
||||
void
|
||||
icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
|
||||
{
|
||||
int osz = BLEN(bp);
|
||||
|
@ -496,7 +496,7 @@ icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
|
|||
return;
|
||||
}
|
||||
|
||||
memmove(np->dst, p->src, IPaddrlen);
|
||||
ipmove(np->dst, p->src);
|
||||
np->type = TimeExceedV6;
|
||||
np->code = 0;
|
||||
memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
|
||||
|
@ -507,7 +507,7 @@ icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
|
|||
ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
|
||||
}
|
||||
|
||||
extern void
|
||||
void
|
||||
icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
|
||||
{
|
||||
int osz = BLEN(bp);
|
||||
|
@ -535,7 +535,7 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
|
|||
return;
|
||||
}
|
||||
|
||||
memmove(np->dst, p->src, IPaddrlen);
|
||||
ipmove(np->dst, p->src);
|
||||
np->type = PacketTooBigV6;
|
||||
np->code = 0;
|
||||
hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize);
|
||||
|
|
|
@ -628,6 +628,7 @@ extern Arpent* arpget(Arp*, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar
|
|||
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 void ndpsendsol(Fs*, Ipifc*, Arpent*);
|
||||
|
||||
/*
|
||||
* ipaux.c
|
||||
|
|
Loading…
Reference in a new issue