devip: various icmp stuff

no need to rlock ifc in targetttype() as we are called from icmpiput6(),
which the ifc rlocked.

for icmpadvise, the lport, destination *AND* source have to match.

a connection gets a packet when the packets destination matches the source
*OR* the packets source matches the destination.
This commit is contained in:
cinap_lenrek 2018-04-22 18:47:19 +02:00
parent 575398eb9b
commit 26aca332bb
2 changed files with 39 additions and 49 deletions

View file

@ -288,22 +288,20 @@ icmpcantfrag(Fs *f, Block *bp, int mtu)
static void static void
goticmpkt(Proto *icmp, Block *bp) goticmpkt(Proto *icmp, Block *bp)
{ {
ushort recid;
uchar dst[IPaddrlen], src[IPaddrlen];
Conv **c, *s; Conv **c, *s;
Icmp *p; Icmp *p;
uchar dst[IPaddrlen];
ushort recid;
p = (Icmp *) bp->rp; p = (Icmp *) bp->rp;
v4tov6(dst, p->src); v4tov6(dst, p->dst);
v4tov6(src, p->src);
recid = nhgets(p->icmpid); recid = nhgets(p->icmpid);
for(c = icmp->conv; *c; c++) { for(c = icmp->conv; (s = *c) != nil; c++){
s = *c;
if(s->lport == recid) if(s->lport == recid)
if(ipcmp(s->raddr, dst) == 0){ if(ipcmp(s->laddr, dst) == 0 || ipcmp(s->raddr, src) == 0)
qpass(s->rq, concatblock(bp)); qpass(s->rq, copyblock(bp, blocklen(bp)));
return;
}
} }
freeblist(bp); freeblist(bp);
} }
@ -317,6 +315,7 @@ mkechoreply(Block *bp, Fs *f)
q = (Icmp *)bp->rp; q = (Icmp *)bp->rp;
if(!ip4me(f, q->dst) || !ip4reply(f, q->src)) if(!ip4me(f, q->dst) || !ip4reply(f, q->src))
return nil; return nil;
q->vihl = IP_VER4; q->vihl = IP_VER4;
memmove(ip, q->src, sizeof(q->dst)); memmove(ip, q->src, sizeof(q->dst));
memmove(q->src, q->dst, sizeof(q->src)); memmove(q->src, q->dst, sizeof(q->src));
@ -392,9 +391,9 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
switch(p->type) { switch(p->type) {
case EchoRequest: case EchoRequest:
if (iplen < n) if(iplen < n)
bp = trimblock(bp, 0, iplen); bp = trimblock(bp, 0, iplen);
if(bp->next) if(bp->next != nil)
bp = concatblock(bp); bp = concatblock(bp);
r = mkechoreply(bp, icmp->f); r = mkechoreply(bp, icmp->f);
if(r == nil) if(r == nil)
@ -458,18 +457,19 @@ raise:
static void static void
icmpadvise(Proto *icmp, Block *bp, char *msg) icmpadvise(Proto *icmp, Block *bp, char *msg)
{ {
ushort recid;
uchar dst[IPaddrlen], src[IPaddrlen];
Conv **c, *s; Conv **c, *s;
Icmp *p; Icmp *p;
uchar dst[IPaddrlen];
ushort recid;
p = (Icmp *) bp->rp; p = (Icmp *) bp->rp;
v4tov6(dst, p->dst); v4tov6(dst, p->dst);
v4tov6(src, p->src);
recid = nhgets(p->icmpid); recid = nhgets(p->icmpid);
for(c = icmp->conv; *c; c++) { for(c = icmp->conv; (s = *c) != nil; c++){
s = *c;
if(s->lport == recid) if(s->lport == recid)
if(ipcmp(s->laddr, src) == 0)
if(ipcmp(s->raddr, dst) == 0){ if(ipcmp(s->raddr, dst) == 0){
if(s->ignoreadvice) if(s->ignoreadvice)
break; break;
@ -494,7 +494,7 @@ icmpstats(Proto *icmp, char *buf, int len)
for(i = 0; i < Nstats; i++) for(i = 0; i < Nstats; i++)
p = seprint(p, e, "%s: %lud\n", statnames[i], priv->stats[i]); p = seprint(p, e, "%s: %lud\n", statnames[i], priv->stats[i]);
for(i = 0; i <= Maxtype; i++){ for(i = 0; i <= Maxtype; i++){
if(icmpnames[i]) if(icmpnames[i] != nil)
p = seprint(p, e, "%s: %lud %lud\n", icmpnames[i], priv->in[i], priv->out[i]); p = seprint(p, e, "%s: %lud %lud\n", icmpnames[i], priv->in[i], priv->out[i]);
else else
p = seprint(p, e, "%d: %lud %lud\n", i, priv->in[i], priv->out[i]); p = seprint(p, e, "%d: %lud %lud\n", i, priv->in[i], priv->out[i]);

View file

@ -221,10 +221,10 @@ icmpadvise6(Proto *icmp, Block *bp, char *msg)
p = (IPICMP *)bp->rp; p = (IPICMP *)bp->rp;
recid = nhgets(p->icmpid); recid = nhgets(p->icmpid);
for(c = icmp->conv; *c; c++) { for(c = icmp->conv; (s = *c) != nil; c++){
s = *c;
if(s->lport == recid) if(s->lport == recid)
if(ipcmp(s->laddr, p->dst) == 0 || ipcmp(s->raddr, p->dst) == 0){ if(ipcmp(s->laddr, p->src) == 0)
if(ipcmp(s->raddr, p->dst) == 0){
if(s->ignoreadvice) if(s->ignoreadvice)
break; break;
qhangup(s->rq, msg); qhangup(s->rq, msg);
@ -309,19 +309,11 @@ goticmpkt6(Proto *icmp, Block *bp, int muxkey)
recid = muxkey; recid = muxkey;
addr = p->dst; addr = p->dst;
} }
for(c = icmp->conv; (s = *c) != nil; c++){
for(c = icmp->conv; *c; c++){ if(s->lport == recid)
s = *c; if(ipcmp(s->laddr, p->dst) == 0 || ipcmp(s->raddr, addr) == 0)
if(s->lport != recid)
continue;
if(ipcmp(s->laddr, addr) == 0){
qpass(s->rq, concatblock(bp));
return;
}
if(ipcmp(s->raddr, addr) == 0)
qpass(s->rq, copyblock(bp, blocklen(bp))); qpass(s->rq, copyblock(bp, blocklen(bp)));
} }
freeblist(bp); freeblist(bp);
} }
@ -417,7 +409,7 @@ icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
memmove(np->lnaddr, mac, sizeof(np->lnaddr)); memmove(np->lnaddr, mac, sizeof(np->lnaddr));
set_cksum(nbp); set_cksum(nbp);
np = (Ndpkt*) nbp->rp; np = (Ndpkt*)nbp->rp;
np->ttl = HOP_LIMIT; np->ttl = HOP_LIMIT;
np->vcf[0] = 0x06 << 4; np->vcf[0] = 0x06 << 4;
ipriv->out[NbrAdvert]++; ipriv->out[NbrAdvert]++;
@ -673,24 +665,22 @@ targettype(Fs *f, Ipifc *ifc, uchar *target)
Iplifc *lifc; Iplifc *lifc;
int t; int t;
rlock(ifc);
if((lifc = iplocalonifc(ifc, target)) != nil) if((lifc = iplocalonifc(ifc, target)) != nil)
t = lifc->tentative? Tunitent: Tunirany; t = lifc->tentative? Tunitent: Tunirany;
else if(ipproxyifc(f, ifc, target)) else if(ipproxyifc(f, ifc, target))
t = Tuniproxy; t = Tuniproxy;
else else
t = 0; t = 0;
runlock(ifc);
return t; return t;
} }
static void static void
icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp) icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp)
{ {
char *msg, m2[128]; char *msg, m2[128];
uchar pktflags; uchar pktflags;
uchar *packet = bp->rp; uchar *packet = bp->rp;
uchar lsrc[IPaddrlen]; uchar ia[IPaddrlen];
Block *r; Block *r;
IPICMP *p = (IPICMP *)packet; IPICMP *p = (IPICMP *)packet;
Icmppriv6 *ipriv = icmp->priv; Icmppriv6 *ipriv = icmp->priv;
@ -698,16 +688,16 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
Ndpkt* np; Ndpkt* np;
Proto *pr; Proto *pr;
if(!valid(icmp, ipifc, bp, ipriv) || p->type > Maxtype6) if(!valid(icmp, ifc, bp, ipriv) || p->type > Maxtype6)
goto raise; goto raise;
ipriv->in[p->type]++; ipriv->in[p->type]++;
switch(p->type) { switch(p->type) {
case EchoRequestV6: case EchoRequestV6:
if(bp->next) if(bp->next != nil)
bp = concatblock(bp); bp = concatblock(bp);
r = mkechoreply6(bp, ipifc); r = mkechoreply6(bp, ifc);
if(r == nil) if(r == nil)
goto raise; goto raise;
ipriv->out[EchoReply]++; ipriv->out[EchoReply]++;
@ -747,7 +737,7 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
} }
p = (IPICMP *)bp->rp; p = (IPICMP *)bp->rp;
pr = Fsrcvpcolx(icmp->f, p->proto); pr = Fsrcvpcolx(icmp->f, p->proto);
if(pr && pr->advise) { if(pr != nil && pr->advise != nil) {
(*pr->advise)(pr, bp, m2); (*pr->advise)(pr, bp, m2);
return; return;
} }
@ -764,21 +754,21 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
case NbrSolicit: case NbrSolicit:
np = (Ndpkt*) p; np = (Ndpkt*) p;
pktflags = 0; pktflags = 0;
if(ipifc->sendra6) if(ifc->sendra6)
pktflags |= Rflag; pktflags |= Rflag;
switch (targettype(icmp->f, ipifc, np->target)) { switch (targettype(icmp->f, ifc, np->target)) {
case Tunirany: case Tunirany:
pktflags |= Oflag; pktflags |= Oflag;
/* fall through */ /* fall through */
case Tuniproxy: case Tuniproxy:
if(ipv6local(ipifc, lsrc, np->src)) { if(ipv6local(ifc, ia, np->src)) {
arpenter(icmp->f, V6, np->src, np->lnaddr, 8*np->olen-2, lsrc, 0); arpenter(icmp->f, V6, np->src, np->lnaddr, 8*np->olen-2, ia, 0);
pktflags |= Sflag; pktflags |= Sflag;
} else } else
ipmove(lsrc, np->target); ipmove(ia, np->target);
icmpna(icmp->f, lsrc, (pktflags & Sflag) ? np->src : v6allnodesL, icmpna(icmp->f, ia, (pktflags & Sflag)? np->src: v6allnodesL,
np->target, ipifc->mac, pktflags); np->target, ifc->mac, pktflags);
break; break;
case Tunitent: case Tunitent:
/* /*
@ -800,11 +790,11 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
* detection part of ipconfig can discover duplication through * detection part of ipconfig can discover duplication through
* the arp table. * the arp table.
*/ */
lifc = iplocalonifc(ipifc, np->target); lifc = iplocalonifc(ifc, np->target);
if(lifc != nil && lifc->tentative) if(lifc != nil && lifc->tentative)
arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, np->target, 0); arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, np->target, 0);
else if(ipv6local(ipifc, lsrc, np->target)) else if(ipv6local(ifc, ia, np->target))
arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, lsrc, 1); arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, ia, 1);
freeblist(bp); freeblist(bp);
break; break;