#ifndef lint
static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.75 2000-07-22 23:58:01 assar Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.76 2000-08-01 17:36:49 itojun Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
return (hdr + len);
}
+static int udp_cksum(register const struct ip *ip,
+ register const struct udphdr *up,
+ register int len)
+{
+ int i, tlen;
+ union phu {
+ struct phdr {
+ u_int32_t src;
+ u_int32_t dst;
+ u_char mbz;
+ u_char proto;
+ u_int16_t len;
+ } ph;
+ u_int16_t pa[6];
+ } phu;
+ register const u_int16_t *sp;
+ u_int32_t sum;
+ tlen = ntohs(ip->ip_len) - ((const char *)up-(const char*)ip);
+
+ /* pseudo-header.. */
+ phu.ph.len = htons(tlen);
+ phu.ph.mbz = 0;
+ phu.ph.proto = IPPROTO_UDP;
+ memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
+ memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
+
+ sp = &phu.pa[0];
+ sum = sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5];
+
+ sp = (const u_int16_t *)up;
+
+ for (i=0; i<(tlen&~1); i+= 2)
+ sum += *sp++;
+
+ if (tlen & 1) {
+ sum += htons( (*(const char *)sp) << 8);
+ }
+
+ while (sum > 0xffff)
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = ~sum & 0xffff;
+
+ return (sum);
+}
+
+#ifdef INET6
+static int udp6_cksum(const struct ip6_hdr *ip6, const struct udphdr *up,
+ int len)
+{
+ int i, tlen;
+ register const u_int16_t *sp;
+ u_int32_t sum;
+ union {
+ struct {
+ struct in6_addr ph_src;
+ struct in6_addr ph_dst;
+ u_int32_t ph_len;
+ u_int8_t ph_zero[3];
+ u_int8_t ph_nxt;
+ } ph;
+ u_int16_t pa[20];
+ } phu;
+
+ tlen = ntohs(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_nxt = IPPROTO_UDP;
+
+ sum = 0;
+ for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
+ sum += phu.pa[i];
+
+ sp = (const u_int16_t *)up;
+
+ for (i = 0; i < (tlen & ~1); i += 2)
+ sum += *sp++;
+
+ if (tlen & 1)
+ sum += htons((*(const char *)sp) << 8);
+
+ while (sum > 0xffff)
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = ~sum & 0xffff;
+
+ return (sum);
+}
+#endif
+
+
/* XXX probably should use getservbyname() and cache answers */
#define TFTP_PORT 69 /*XXX*/
#define KERBEROS_PORT 88 /*XXX*/
}
#endif
+ if (ip->ip_v == 4 && vflag) {
+ int sum = up->uh_sum;
+ if (sum == 0) {
+ (void)printf(" [no cksum]");
+ } else if (TTEST2(cp[0], length)) {
+ sum = udp_cksum(ip, up, length);
+ if (sum != 0)
+ (void)printf(" [bad udp cksum %x!]", sum);
+ else
+ (void)printf(" [udp sum ok]");
+ }
+ }
+#ifdef INET6
+ if (ip->ip_v == 6 && ip6->ip6_plen && vflag) {
+ int sum = up->uh_sum;
+ /* for IPv6, UDP checksum is mandatory */
+ if (TTEST2(cp[0], length)) {
+ sum = udp6_cksum(ip6, up, length);
+ if (sum != 0)
+ (void)printf(" [bad udp cksum %x!]", sum);
+ else
+ (void)printf(" [udp sum ok]");
+ }
+ }
+#endif
+
if (!qflag) {
#define ISPORT(p) (dport == (p) || sport == (p))
if (ISPORT(NAMESERVER_PORT))