Cut off "snapend" at the length of the IPv4 or IPv6 payload, so we don't

run past the end of that payload.

Check that the IPv4 total length isn't less than the header length.

Use "%u", not "%d", to print unsigned values.

Properly update "len" in the header-processing loop for IPv6.

Doing so means we can trust the length passed to the TCP and UDP
dissectors when constructing the IPv6 pseudo-header; do so (but fix the
length we pass to the UDP-over-IPv6 checksum routine).

That length is unsigned; make the corresponding arguments to the TCP and
UDP checksum routines unsigned.
This commit is contained in:
guy 2003-11-19 00:17:32 +00:00
parent 8a42f11ab0
commit d6cf0925b2
4 changed files with 47 additions and 31 deletions

View File

@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.130 2003-11-16 09:36:23 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.131 2003-11-19 00:17:32 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -358,6 +358,7 @@ ip_print(register const u_char *bp, register u_int length)
{
register const struct ip *ip;
register u_int hlen, len, len0, off;
const u_char *ipend;
register const u_char *cp;
u_char nh;
int advance;
@ -383,14 +384,26 @@ ip_print(register const u_char *bp, register u_int length)
}
hlen = IP_HL(ip) * 4;
if (hlen < sizeof (struct ip)) {
(void)printf("bad-hlen %d", hlen);
(void)printf("bad-hlen %u", hlen);
return;
}
len = EXTRACT_16BITS(&ip->ip_len);
if (length < len)
(void)printf("truncated-ip - %d bytes missing! ",
(void)printf("truncated-ip - %u bytes missing! ",
len - length);
if (len < hlen) {
(void)printf("bad-len %u", len);
return;
}
/*
* Cut off the snapshot length to the end of the IP payload.
*/
ipend = bp + len;
if (ipend < snapend)
snapend = ipend;
len -= hlen;
len0 = len;

View File

@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.34 2003-11-16 09:36:24 guy Exp $";
"@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.35 2003-11-19 00:17:32 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
@ -52,6 +52,7 @@ ip6_print(register const u_char *bp, register u_int length)
register const struct ip6_hdr *ip6;
register int advance;
register u_int len;
const u_char *ipend;
register const u_char *cp;
int nh;
int fragmented = 0;
@ -64,17 +65,25 @@ ip6_print(register const u_char *bp, register u_int length)
(void)printf("truncated-ip6 %d", length);
return;
}
advance = sizeof(struct ip6_hdr);
len = EXTRACT_16BITS(&ip6->ip6_plen);
if (length < len + advance)
len = EXTRACT_16BITS(&ip6->ip6_plen) + sizeof(struct ip6_hdr);
if (length < len)
(void)printf("truncated-ip6 - %d bytes missing!",
len + advance - length);
len - length);
/*
* Cut off the snapshot length to the end of the IP payload.
*/
ipend = bp + len;
if (ipend < snapend)
snapend = ipend;
cp = (const u_char *)ip6;
advance = sizeof(struct ip6_hdr);
nh = ip6->ip6_nxt;
while (cp < snapend) {
cp += advance;
len -= advance;
if (cp == (const u_char *)(ip6 + 1) &&
nh != IPPROTO_TCP && nh != IPPROTO_UDP &&

View File

@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.109 2003-11-16 09:36:39 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.110 2003-11-19 00:17:32 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -100,7 +100,7 @@ static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
static int tcp_cksum(register const struct ip *ip,
register const struct tcphdr *tp,
register int len)
register u_int len)
{
union phu {
struct phdr {
@ -115,7 +115,7 @@ static int tcp_cksum(register const struct ip *ip,
const u_int16_t *sp;
/* pseudo-header.. */
phu.ph.len = htons(len); /* XXX */
phu.ph.len = htons((u_int16_t)len);
phu.ph.mbz = 0;
phu.ph.proto = IPPROTO_TCP;
memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
@ -131,9 +131,9 @@ static int tcp_cksum(register const struct ip *ip,
#ifdef INET6
static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp,
int len)
u_int len)
{
size_t i, tlen;
size_t i;
register const u_int16_t *sp;
u_int32_t sum;
union {
@ -147,14 +147,11 @@ static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp,
u_int16_t pa[20];
} phu;
tlen = EXTRACT_16BITS(&ip6->ip6_plen) + sizeof(struct ip6_hdr) -
((const char *)tp - (const char*)ip6);
/* pseudo-header */
memset(&phu, 0, sizeof(phu));
phu.ph.ph_src = ip6->ip6_src;
phu.ph.ph_dst = ip6->ip6_dst;
phu.ph.ph_len = htonl(tlen);
phu.ph.ph_len = htonl(len);
phu.ph.ph_nxt = IPPROTO_TCP;
sum = 0;
@ -163,10 +160,10 @@ static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp,
sp = (const u_int16_t *)tp;
for (i = 0; i < (tlen & ~1); i += 2)
for (i = 0; i < (len & ~1); i += 2)
sum += *sp++;
if (tlen & 1)
if (len & 1)
sum += htons((*(const u_int8_t *)sp) << 8);
while (sum > 0xffff)

View File

@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.127 2003-11-18 23:26:38 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.128 2003-11-19 00:17:33 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -285,7 +285,7 @@ rtcp_print(const u_char *hdr, const u_char *ep)
static int udp_cksum(register const struct ip *ip,
register const struct udphdr *up,
register int len)
register u_int len)
{
union phu {
struct phdr {
@ -300,7 +300,7 @@ static int udp_cksum(register const struct ip *ip,
register const u_int16_t *sp;
/* pseudo-header.. */
phu.ph.len = htons(len);
phu.ph.len = htons((u_int16_t)len);
phu.ph.mbz = 0;
phu.ph.proto = IPPROTO_UDP;
memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
@ -316,9 +316,9 @@ static int udp_cksum(register const struct ip *ip,
#ifdef INET6
static int udp6_cksum(const struct ip6_hdr *ip6, const struct udphdr *up,
int len)
u_int len)
{
int i, tlen;
int i;
register const u_int16_t *sp;
u_int32_t sum;
union {
@ -332,14 +332,11 @@ static int udp6_cksum(const struct ip6_hdr *ip6, const struct udphdr *up,
u_int16_t pa[20];
} phu;
tlen = EXTRACT_16BITS(&ip6->ip6_plen) + sizeof(struct ip6_hdr) -
((const char *)up - (const char*)ip6);
/* pseudo-header */
memset(&phu, 0, sizeof(phu));
phu.ph.ph_src = ip6->ip6_src;
phu.ph.ph_dst = ip6->ip6_dst;
phu.ph.ph_len = htonl(tlen);
phu.ph.ph_len = htonl(len);
phu.ph.ph_nxt = IPPROTO_UDP;
sum = 0;
@ -348,10 +345,10 @@ static int udp6_cksum(const struct ip6_hdr *ip6, const struct udphdr *up,
sp = (const u_int16_t *)up;
for (i = 0; i < (tlen & ~1); i += 2)
for (i = 0; i < (len & ~1); i += 2)
sum += *sp++;
if (tlen & 1)
if (len & 1)
sum += htons((*(const u_int8_t *)sp) << 8);
while (sum > 0xffff)
@ -588,7 +585,7 @@ udp_print(register const u_char *bp, u_int length,
int sum = up->uh_sum;
/* for IPv6, UDP checksum is mandatory */
if (TTEST2(cp[0], length)) {
sum = udp6_cksum(ip6, up, length);
sum = udp6_cksum(ip6, up, length + sizeof(struct udphdr));
if (sum != 0)
(void)printf("[bad udp cksum %x!] ", sum);
else