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:
parent
575398eb9b
commit
26aca332bb
2 changed files with 39 additions and 49 deletions
|
@ -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]);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue