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.
#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
{
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;
}
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;
#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
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;
(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 &&
#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
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 {
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));
#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 {
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;
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)
#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
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 {
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));
#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 {
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;
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)
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