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) #define haship(s) ((s)[IPaddrlen-1]%NHASH)
extern int ReTransTimer = RETRANS_TIMER; int ReTransTimer = RETRANS_TIMER;
static void rxmitproc(void *v); static void rxmitproc(void *v);
@ -223,7 +223,7 @@ arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac)
qlock(arp); qlock(arp);
hash = haship(ip); hash = haship(ip);
for(a = arp->hash[hash]; a != nil; a = a->hash){ 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) if(type == a->type)
break; break;
} }
@ -536,13 +536,35 @@ arpread(Arp *arp, char *p, ulong offset, int len)
return n; 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) rxmitsols(Arp *arp)
{ {
Block *next, *xp; Block *next, *xp;
Arpent *a, *b, **l; Arpent *a, *b, **l;
Fs *f; Fs *f;
uchar ipsrc[IPaddrlen];
Ipifc *ifc = nil; Ipifc *ifc = nil;
long nrxt; long nrxt;
@ -579,10 +601,7 @@ rxmitsols(Arp *arp)
if(a == nil) if(a == nil)
goto dodrops; goto dodrops;
ndpsendsol(f, ifc, a); /* unlocks arp */
qunlock(arp); /* for icmpns */
if(ipv6local(ifc, ipsrc, a->ip))
icmpns(f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac);
runlock(ifc); runlock(ifc);
qlock(arp); qlock(arp);

View file

@ -498,7 +498,6 @@ resolveaddr6(Ipifc *ifc, Arpent *a)
{ {
Block *bp; Block *bp;
Etherrock *er = ifc->arg; Etherrock *er = ifc->arg;
uchar ipsrc[IPaddrlen];
/* don't do anything if it's been less than a second since the last */ /* don't do anything if it's been less than a second since the last */
if(NOW - a->ctime < ReTransTimer){ if(NOW - a->ctime < ReTransTimer){
@ -523,10 +522,7 @@ resolveaddr6(Ipifc *ifc, Arpent *a)
} }
a->rxtsrem--; a->rxtsrem--;
arprelease(er->f->arp, a); ndpsendsol(er->f, ifc, a); /* unlocks arp */
if(ipv6local(ifc, ipsrc, a->ip))
icmpns(er->f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac);
} }
/* /*
@ -610,7 +606,7 @@ recvarp(Ipifc *ifc)
case ARPREQUEST: case ARPREQUEST:
/* don't answer arps till we know who we are */ /* don't answer arps till we know who we are */
if(ifc->lifc == 0) if(ifc->lifc == nil)
break; break;
/* check for machine using my ip or ether address */ /* check for machine using my ip or ether address */

View file

@ -113,7 +113,7 @@ icmpcreate(Conv *c)
c->wq = qbypass(icmpkick, c); c->wq = qbypass(icmpkick, c);
} }
extern char* char*
icmpconnect(Conv *c, char **argv, int argc) icmpconnect(Conv *c, char **argv, int argc)
{ {
char *e; char *e;
@ -126,7 +126,7 @@ icmpconnect(Conv *c, char **argv, int argc)
return nil; return nil;
} }
extern int int
icmpstate(Conv *c, char *state, int n) icmpstate(Conv *c, char *state, int n)
{ {
USED(c); USED(c);
@ -137,7 +137,7 @@ icmpstate(Conv *c, char *state, int n)
); );
} }
extern char* char*
icmpannounce(Conv *c, char **argv, int argc) icmpannounce(Conv *c, char **argv, int argc)
{ {
char *e; char *e;
@ -150,7 +150,7 @@ icmpannounce(Conv *c, char **argv, int argc)
return nil; return nil;
} }
extern void void
icmpclose(Conv *c) icmpclose(Conv *c)
{ {
qclose(c->rq); qclose(c->rq);
@ -214,7 +214,7 @@ ip4me(Fs *f, uchar ip4[4])
return (ipforme(f, addr) & Runi) != 0; return (ipforme(f, addr) & Runi) != 0;
} }
extern void void
icmpttlexceeded(Fs *f, uchar *ia, Block *bp) icmpttlexceeded(Fs *f, uchar *ia, Block *bp)
{ {
Block *nbp; Block *nbp;
@ -270,13 +270,13 @@ icmpunreachable(Fs *f, Block *bp, int code, int seq)
ipoput4(f, nbp, 0, MAXTTL, DFLTTOS, nil); ipoput4(f, nbp, 0, MAXTTL, DFLTTOS, nil);
} }
extern void void
icmpnoconv(Fs *f, Block *bp) icmpnoconv(Fs *f, Block *bp)
{ {
icmpunreachable(f, bp, 3, 0); icmpunreachable(f, bp, 3, 0);
} }
extern void void
icmpcantfrag(Fs *f, Block *bp, int mtu) icmpcantfrag(Fs *f, Block *bp, int mtu)
{ {
icmpunreachable(f, bp, 4, mtu); icmpunreachable(f, bp, 4, mtu);

View file

@ -345,7 +345,7 @@ mkechoreply6(Block *bp, Ipifc *ifc)
* tuni == TARG_MULTI => multicast for address resolution, * tuni == TARG_MULTI => multicast for address resolution,
* and tuni == TARG_UNI => neighbor reachability. * and tuni == TARG_UNI => neighbor reachability.
*/ */
extern void void
icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac) icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
{ {
Block *nbp; Block *nbp;
@ -357,18 +357,18 @@ icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
np = (Ndpkt*) nbp->rp; np = (Ndpkt*) nbp->rp;
if(suni == SRC_UNSPEC) if(suni == SRC_UNSPEC)
memmove(np->src, v6Unspecified, IPaddrlen); ipmove(np->src, v6Unspecified);
else else
memmove(np->src, src, IPaddrlen); ipmove(np->src, src);
if(tuni == TARG_UNI) if(tuni == TARG_UNI)
memmove(np->dst, targ, IPaddrlen); ipmove(np->dst, targ);
else else
ipv62smcast(np->dst, targ); ipv62smcast(np->dst, targ);
np->type = NbrSolicit; np->type = NbrSolicit;
np->code = 0; np->code = 0;
memmove(np->target, targ, IPaddrlen); ipmove(np->target, targ);
if(suni != SRC_UNSPEC) { if(suni != SRC_UNSPEC) {
np->otype = SRC_LLADDR; np->otype = SRC_LLADDR;
np->olen = 1; /* 1+1+6 = 8 = 1 8-octet */ 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. * 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) icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
{ {
Block *nbp; Block *nbp;
@ -399,13 +399,13 @@ icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
nbp = newIPICMP(NDPKTSZ); nbp = newIPICMP(NDPKTSZ);
np = (Ndpkt*)nbp->rp; np = (Ndpkt*)nbp->rp;
memmove(np->src, src, IPaddrlen); ipmove(np->src, src);
memmove(np->dst, dst, IPaddrlen); ipmove(np->dst, dst);
np->type = NbrAdvert; np->type = NbrAdvert;
np->code = 0; np->code = 0;
np->icmpid[0] = flags; np->icmpid[0] = flags;
memmove(np->target, targ, IPaddrlen); ipmove(np->target, targ);
np->otype = TARGET_LLADDR; np->otype = TARGET_LLADDR;
np->olen = 1; 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); ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
} }
extern void void
icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free) icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
{ {
int osz = BLEN(bp); int osz = BLEN(bp);
@ -449,7 +449,7 @@ icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
goto freebl; goto freebl;
} }
memmove(np->dst, p->src, IPaddrlen); ipmove(np->dst, p->src);
np->type = UnreachableV6; np->type = UnreachableV6;
np->code = code; np->code = code;
memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ); memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
@ -468,7 +468,7 @@ freebl:
freeblist(bp); freeblist(bp);
} }
extern void void
icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp) icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
{ {
int osz = BLEN(bp); int osz = BLEN(bp);
@ -496,7 +496,7 @@ icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
return; return;
} }
memmove(np->dst, p->src, IPaddrlen); ipmove(np->dst, p->src);
np->type = TimeExceedV6; np->type = TimeExceedV6;
np->code = 0; np->code = 0;
memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ); 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); ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
} }
extern void void
icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp) icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
{ {
int osz = BLEN(bp); int osz = BLEN(bp);
@ -535,7 +535,7 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
return; return;
} }
memmove(np->dst, p->src, IPaddrlen); ipmove(np->dst, p->src);
np->type = PacketTooBigV6; np->type = PacketTooBigV6;
np->code = 0; np->code = 0;
hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize); 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 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 void arpenter(Fs*, int version, uchar *ip, uchar *mac, int len, int norefresh); extern void arpenter(Fs*, int version, uchar *ip, uchar *mac, int len, int norefresh);
extern void ndpsendsol(Fs*, Ipifc*, Arpent*);
/* /*
* ipaux.c * ipaux.c