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:
cinap_lenrek 2018-03-19 01:11:08 +01:00
parent 20cbb88e32
commit 547f60b4c5
5 changed files with 52 additions and 36 deletions

View file

@ -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);

View file

@ -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 */

View file

@ -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);

View file

@ -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);

View file

@ -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