devip: fix block list handling for icmp/icmp6, use proper MinAdvise for icmp6
This commit is contained in:
parent
a2c0e55e68
commit
a859f05837
|
@ -44,11 +44,6 @@ enum { /* Packet Types */
|
||||||
Maxtype = 18,
|
Maxtype = 18,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MinAdvise = 24, /* minimum needed for us to advise another protocol */
|
|
||||||
};
|
|
||||||
|
|
||||||
char *icmpnames[Maxtype+1] =
|
char *icmpnames[Maxtype+1] =
|
||||||
{
|
{
|
||||||
[EchoReply] "EchoReply",
|
[EchoReply] "EchoReply",
|
||||||
|
@ -70,6 +65,8 @@ enum {
|
||||||
IP_ICMPPROTO = 1,
|
IP_ICMPPROTO = 1,
|
||||||
ICMP_IPSIZE = 20,
|
ICMP_IPSIZE = 20,
|
||||||
ICMP_HDRSIZE = 8,
|
ICMP_HDRSIZE = 8,
|
||||||
|
|
||||||
|
MinAdvise = ICMP_IPSIZE+4, /* minimum needed for us to advise another protocol */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -169,8 +166,7 @@ icmpkick(void *x, Block *bp)
|
||||||
|
|
||||||
if(bp == nil)
|
if(bp == nil)
|
||||||
return;
|
return;
|
||||||
|
if(BLEN(bp) < ICMP_IPSIZE + ICMP_HDRSIZE){
|
||||||
if(blocklen(bp) < ICMP_IPSIZE + ICMP_HDRSIZE){
|
|
||||||
freeblist(bp);
|
freeblist(bp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -350,7 +346,7 @@ static char *unreachcode[] =
|
||||||
static void
|
static void
|
||||||
icmpiput(Proto *icmp, Ipifc*, Block *bp)
|
icmpiput(Proto *icmp, Ipifc*, Block *bp)
|
||||||
{
|
{
|
||||||
int n, iplen;
|
int n;
|
||||||
Icmp *p;
|
Icmp *p;
|
||||||
Block *r;
|
Block *r;
|
||||||
Proto *pr;
|
Proto *pr;
|
||||||
|
@ -359,42 +355,31 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
|
||||||
Icmppriv *ipriv;
|
Icmppriv *ipriv;
|
||||||
|
|
||||||
ipriv = icmp->priv;
|
ipriv = icmp->priv;
|
||||||
|
|
||||||
ipriv->stats[InMsgs]++;
|
ipriv->stats[InMsgs]++;
|
||||||
|
|
||||||
p = (Icmp *)bp->rp;
|
bp = concatblock(bp);
|
||||||
netlog(icmp->f, Logicmp, "icmpiput %s (%d) %d\n",
|
n = BLEN(bp);
|
||||||
(p->type < nelem(icmpnames)? icmpnames[p->type]: ""),
|
|
||||||
p->type, p->code);
|
|
||||||
n = blocklen(bp);
|
|
||||||
if(n < ICMP_IPSIZE+ICMP_HDRSIZE){
|
if(n < ICMP_IPSIZE+ICMP_HDRSIZE){
|
||||||
ipriv->stats[InErrors]++;
|
ipriv->stats[InErrors]++;
|
||||||
ipriv->stats[HlenErrs]++;
|
ipriv->stats[HlenErrs]++;
|
||||||
netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
|
netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
|
||||||
goto raise;
|
goto raise;
|
||||||
}
|
}
|
||||||
iplen = nhgets(p->length);
|
if(ptclcsum(bp, ICMP_IPSIZE, n - ICMP_IPSIZE)){
|
||||||
if(iplen > n){
|
|
||||||
ipriv->stats[LenErrs]++;
|
|
||||||
ipriv->stats[InErrors]++;
|
|
||||||
netlog(icmp->f, Logicmp, "icmp length %d\n", iplen);
|
|
||||||
goto raise;
|
|
||||||
}
|
|
||||||
if(ptclcsum(bp, ICMP_IPSIZE, iplen - ICMP_IPSIZE)){
|
|
||||||
ipriv->stats[InErrors]++;
|
ipriv->stats[InErrors]++;
|
||||||
ipriv->stats[CsumErrs]++;
|
ipriv->stats[CsumErrs]++;
|
||||||
netlog(icmp->f, Logicmp, "icmp checksum error\n");
|
netlog(icmp->f, Logicmp, "icmp checksum error\n");
|
||||||
goto raise;
|
goto raise;
|
||||||
}
|
}
|
||||||
|
p = (Icmp *)bp->rp;
|
||||||
|
netlog(icmp->f, Logicmp, "icmpiput %s (%d) %d\n",
|
||||||
|
(p->type < nelem(icmpnames)? icmpnames[p->type]: ""),
|
||||||
|
p->type, p->code);
|
||||||
if(p->type <= Maxtype)
|
if(p->type <= Maxtype)
|
||||||
ipriv->in[p->type]++;
|
ipriv->in[p->type]++;
|
||||||
|
|
||||||
switch(p->type) {
|
switch(p->type) {
|
||||||
case EchoRequest:
|
case EchoRequest:
|
||||||
if(iplen < n)
|
|
||||||
bp = trimblock(bp, 0, iplen);
|
|
||||||
if(bp->next != nil)
|
|
||||||
bp = concatblock(bp);
|
|
||||||
r = mkechoreply(bp, icmp->f);
|
r = mkechoreply(bp, icmp->f);
|
||||||
if(r == nil)
|
if(r == nil)
|
||||||
goto raise;
|
goto raise;
|
||||||
|
@ -410,7 +395,7 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
|
||||||
msg = unreachcode[p->code];
|
msg = unreachcode[p->code];
|
||||||
|
|
||||||
bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE;
|
bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE;
|
||||||
if(blocklen(bp) < MinAdvise){
|
if(BLEN(bp) < MinAdvise){
|
||||||
ipriv->stats[LenErrs]++;
|
ipriv->stats[LenErrs]++;
|
||||||
goto raise;
|
goto raise;
|
||||||
}
|
}
|
||||||
|
@ -420,7 +405,6 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
|
||||||
(*pr->advise)(pr, bp, msg);
|
(*pr->advise)(pr, bp, msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
|
bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
|
||||||
goticmpkt(icmp, bp);
|
goticmpkt(icmp, bp);
|
||||||
break;
|
break;
|
||||||
|
@ -429,7 +413,7 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
|
||||||
snprint(m2, sizeof m2, "ttl exceeded at %V", p->src);
|
snprint(m2, sizeof m2, "ttl exceeded at %V", p->src);
|
||||||
|
|
||||||
bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE;
|
bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE;
|
||||||
if(blocklen(bp) < MinAdvise){
|
if(BLEN(bp) < MinAdvise){
|
||||||
ipriv->stats[LenErrs]++;
|
ipriv->stats[LenErrs]++;
|
||||||
goto raise;
|
goto raise;
|
||||||
}
|
}
|
||||||
|
@ -441,7 +425,6 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
|
||||||
}
|
}
|
||||||
bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
|
bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
goticmpkt(icmp, bp);
|
goticmpkt(icmp, bp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -67,6 +67,10 @@ enum {
|
||||||
Maxtype6 = 137,
|
Maxtype6 = 137,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MinAdvise = IP6HDR+4, /* minimum needed for us to advise another protocol */
|
||||||
|
};
|
||||||
|
|
||||||
/* on-the-wire packet formats */
|
/* on-the-wire packet formats */
|
||||||
typedef struct IPICMP IPICMP;
|
typedef struct IPICMP IPICMP;
|
||||||
typedef struct Ndpkt Ndpkt;
|
typedef struct Ndpkt Ndpkt;
|
||||||
|
@ -189,13 +193,14 @@ static void
|
||||||
set_cksum(Block *bp)
|
set_cksum(Block *bp)
|
||||||
{
|
{
|
||||||
IPICMP *p = (IPICMP *)(bp->rp);
|
IPICMP *p = (IPICMP *)(bp->rp);
|
||||||
|
int n = blocklen(bp);
|
||||||
|
|
||||||
hnputl(p->vcf, 0); /* borrow IP header as pseudoheader */
|
hnputl(p->vcf, 0); /* borrow IP header as pseudoheader */
|
||||||
hnputs(p->ploadlen, blocklen(bp) - IP6HDR);
|
hnputs(p->ploadlen, n - IP6HDR);
|
||||||
p->proto = 0;
|
p->proto = 0;
|
||||||
p->ttl = ICMPv6; /* ttl gets set later */
|
p->ttl = ICMPv6; /* ttl gets set later */
|
||||||
hnputs(p->cksum, 0);
|
hnputs(p->cksum, 0);
|
||||||
hnputs(p->cksum, ptclcsum(bp, 0, blocklen(bp)));
|
hnputs(p->cksum, ptclcsum(bp, 0, n));
|
||||||
p->proto = ICMPv6;
|
p->proto = ICMPv6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +264,7 @@ icmpkick6(void *x, Block *bp)
|
||||||
bp = padblock(bp, IP6HDR);
|
bp = padblock(bp, IP6HDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(blocklen(bp) < IPICMPSZ){
|
if(BLEN(bp) < IPICMPSZ){
|
||||||
freeblist(bp);
|
freeblist(bp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -524,26 +529,17 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
|
||||||
* RFC 2461, pages 39-40, pages 57-58.
|
* RFC 2461, pages 39-40, pages 57-58.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
valid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv)
|
valid(Proto *icmp, Ipifc *, Block *bp, Icmppriv6 *ipriv)
|
||||||
{
|
{
|
||||||
int sz, osz, unsp, n, ttl, iplen;
|
int sz, osz, unsp, ttl;
|
||||||
int pktsz = BLEN(bp);
|
int pktsz = BLEN(bp);
|
||||||
uchar *packet = bp->rp;
|
uchar *packet = bp->rp;
|
||||||
IPICMP *p = (IPICMP *) packet;
|
IPICMP *p = (IPICMP *) packet;
|
||||||
Ndpkt *np;
|
Ndpkt *np;
|
||||||
|
|
||||||
USED(ifc);
|
if(pktsz < IPICMPSZ) {
|
||||||
n = blocklen(bp);
|
|
||||||
if(n < IPICMPSZ) {
|
|
||||||
ipriv->stats[HlenErrs6]++;
|
ipriv->stats[HlenErrs6]++;
|
||||||
netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
|
netlog(icmp->f, Logicmp, "icmp hlen %d\n", pktsz);
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
iplen = nhgets(p->ploadlen);
|
|
||||||
if(iplen > n - IP6HDR) {
|
|
||||||
ipriv->stats[LenErrs6]++;
|
|
||||||
netlog(icmp->f, Logicmp, "icmp length %d\n", iplen);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,7 +553,7 @@ valid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv)
|
||||||
ttl = p->ttl;
|
ttl = p->ttl;
|
||||||
p->ttl = p->proto;
|
p->ttl = p->proto;
|
||||||
p->proto = 0;
|
p->proto = 0;
|
||||||
if(ptclcsum(bp, 0, iplen + IP6HDR)) {
|
if(ptclcsum(bp, 0, pktsz)) {
|
||||||
ipriv->stats[CsumErrs6]++;
|
ipriv->stats[CsumErrs6]++;
|
||||||
netlog(icmp->f, Logicmp, "icmp checksum error\n");
|
netlog(icmp->f, Logicmp, "icmp checksum error\n");
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -678,15 +674,17 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp)
|
||||||
{
|
{
|
||||||
char *msg, m2[128];
|
char *msg, m2[128];
|
||||||
uchar pktflags;
|
uchar pktflags;
|
||||||
uchar *packet = bp->rp;
|
|
||||||
uchar ia[IPaddrlen];
|
uchar ia[IPaddrlen];
|
||||||
Block *r;
|
Block *r;
|
||||||
IPICMP *p = (IPICMP *)packet;
|
IPICMP *p;
|
||||||
Icmppriv6 *ipriv = icmp->priv;
|
Icmppriv6 *ipriv = icmp->priv;
|
||||||
Iplifc *lifc;
|
Iplifc *lifc;
|
||||||
Ndpkt* np;
|
Ndpkt* np;
|
||||||
Proto *pr;
|
Proto *pr;
|
||||||
|
|
||||||
|
bp = concatblock(bp);
|
||||||
|
p = (IPICMP*)bp->rp;
|
||||||
|
|
||||||
if(!valid(icmp, ifc, bp, ipriv) || p->type > Maxtype6)
|
if(!valid(icmp, ifc, bp, ipriv) || p->type > Maxtype6)
|
||||||
goto raise;
|
goto raise;
|
||||||
|
|
||||||
|
@ -694,8 +692,6 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp)
|
||||||
|
|
||||||
switch(p->type) {
|
switch(p->type) {
|
||||||
case EchoRequestV6:
|
case EchoRequestV6:
|
||||||
if(bp->next != nil)
|
|
||||||
bp = concatblock(bp);
|
|
||||||
r = mkechoreply6(bp, ifc);
|
r = mkechoreply6(bp, ifc);
|
||||||
if(r == nil)
|
if(r == nil)
|
||||||
goto raise;
|
goto raise;
|
||||||
|
@ -710,7 +706,7 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp)
|
||||||
msg = unreachcode[p->code];
|
msg = unreachcode[p->code];
|
||||||
|
|
||||||
bp->rp += IPICMPSZ;
|
bp->rp += IPICMPSZ;
|
||||||
if(blocklen(bp) < 8){
|
if(BLEN(bp) < MinAdvise){
|
||||||
ipriv->stats[LenErrs6]++;
|
ipriv->stats[LenErrs6]++;
|
||||||
goto raise;
|
goto raise;
|
||||||
}
|
}
|
||||||
|
@ -720,7 +716,6 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp)
|
||||||
(*pr->advise)(pr, bp, msg);
|
(*pr->advise)(pr, bp, msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bp->rp -= IPICMPSZ;
|
bp->rp -= IPICMPSZ;
|
||||||
goticmpkt6(icmp, bp, 0);
|
goticmpkt6(icmp, bp, 0);
|
||||||
break;
|
break;
|
||||||
|
@ -730,7 +725,7 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp)
|
||||||
sprint(m2, "ttl exceeded at %I", p->src);
|
sprint(m2, "ttl exceeded at %I", p->src);
|
||||||
|
|
||||||
bp->rp += IPICMPSZ;
|
bp->rp += IPICMPSZ;
|
||||||
if(blocklen(bp) < 8){
|
if(BLEN(bp) < MinAdvise){
|
||||||
ipriv->stats[LenErrs6]++;
|
ipriv->stats[LenErrs6]++;
|
||||||
goto raise;
|
goto raise;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue