* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#ifndef lint
-static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-icmp.c,v 1.84 2006-12-12 10:48:43 hannes Exp $ (LBL)";
-#endif
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define icmp_data icmp_dun.id_data
};
-#define ICMP_MPLS_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4)
+#define ICMP_MPLS_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4)
#define ICMP_MPLS_EXT_VERSION 2
/*
#endif
/* Most of the icmp types */
-static struct tok icmp2str[] = {
+static const struct tok icmp2str[] = {
{ ICMP_ECHOREPLY, "echo reply" },
{ ICMP_SOURCEQUENCH, "source quench" },
{ ICMP_ECHO, "echo request" },
};
/* Formats for most of the ICMP_UNREACH codes */
-static struct tok unreach2str[] = {
+static const struct tok unreach2str[] = {
{ ICMP_UNREACH_NET, "net %s unreachable" },
{ ICMP_UNREACH_HOST, "host %s unreachable" },
{ ICMP_UNREACH_SRCFAIL,
};
/* Formats for the ICMP_REDIRECT codes */
-static struct tok type2str[] = {
+static const struct tok type2str[] = {
{ ICMP_REDIRECT_NET, "redirect %s to net %s" },
{ ICMP_REDIRECT_HOST, "redirect %s to host %s" },
{ ICMP_REDIRECT_TOSNET, "redirect-tos %s to net %s" },
u_int8_t icmp_ext_data[1];
};
-struct icmp_mpls_ext_common_header_t {
-};
-
struct icmp_mpls_ext_object_header_t {
u_int8_t length[2];
u_int8_t class_num;
snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%03u",hrs,min,sec,msec);
return buf;
}
-
+
void
icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
{
const struct icmp_mpls_ext_object_header_t *icmp_mpls_ext_object_header;
u_int hlen, dport, mtu, obj_tlen, obj_class_num, obj_ctype;
char buf[MAXHOSTNAMELEN + 100];
+ struct cksum_vec vec[1];
dp = (struct icmp *)bp;
ext_dp = (struct icmp_ext_t *)bp;
case ICMP_UNREACH_NEEDFRAG:
{
register const struct mtu_discovery *mp;
- mp = (struct mtu_discovery *)&dp->icmp_void;
+ mp = (struct mtu_discovery *)(u_char *)&dp->icmp_void;
mtu = EXTRACT_16BITS(&mp->nexthopmtu);
if (mtu) {
(void)snprintf(buf, sizeof(buf),
(void)printf("ICMP %s, length %u", str, plen);
if (vflag && !fragmented) { /* don't attempt checksumming if this is a frag */
u_int16_t sum, icmp_sum;
+ struct cksum_vec vec[1];
if (TTEST2(*bp, plen)) {
- sum = in_cksum((u_short*)dp, plen, 0);
+ vec[0].ptr = (const u_int8_t *)(void *)dp;
+ vec[0].len = plen;
+ sum = in_cksum(vec, 1);
if (sum != 0) {
icmp_sum = EXTRACT_16BITS(&dp->icmp_cksum);
(void)printf(" (wrong icmp cksum %x (->%x)!)",
}
/*
- * Check if the extended ICMP header indicates that there is
- * MPLS extension header present for the "interesting" ICMP types.
+ * Attempt to decode the MPLS extensions only for some ICMP types.
*/
- if (vflag >= 1 && plen > ICMP_EXTD_MINLEN &&
- ext_dp->icmp_length && ICMP_MPLS_EXT_TYPE(dp->icmp_type)) {
+ if (vflag >= 1 && plen > ICMP_EXTD_MINLEN && ICMP_MPLS_EXT_TYPE(dp->icmp_type)) {
TCHECK(*ext_dp);
+
+ /*
+ * Check first if the mpls extension header shows a non-zero length.
+ * If the length field is not set then silently verify the checksum
+ * to check if an extension header is present. This is expedient,
+ * however not all implementations set the length field proper.
+ */
+ if (!ext_dp->icmp_length) {
+ vec[0].ptr = (const u_int8_t *)(void *)&ext_dp->icmp_ext_version_res;
+ vec[0].len = plen - ICMP_EXTD_MINLEN;
+ if (in_cksum(vec, 1)) {
+ return;
+ }
+ }
+
printf("\n\tMPLS extension v%u",
ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)));
-
+
/*
* Sanity checking of the header.
*/
}
hlen = plen - ICMP_EXTD_MINLEN;
- printf(", checksum 0x%04x (unverified), length %u", /* FIXME */
+ vec[0].ptr = (const u_int8_t *)(void *)&ext_dp->icmp_ext_version_res;
+ vec[0].len = hlen;
+ printf(", checksum 0x%04x (%scorrect), length %u",
EXTRACT_16BITS(ext_dp->icmp_ext_checksum),
+ in_cksum(vec, 1) ? "in" : "",
hlen);
hlen -= 4; /* subtract common header size */
hlen-=sizeof(struct icmp_mpls_ext_object_header_t); /* length field includes tlv header */
- /* infinite loop protection */
+ /* infinite loop protection */
if ((obj_class_num == 0) ||
(obj_tlen < sizeof(struct icmp_mpls_ext_object_header_t))) {
return;
printf(", ttl %u", MPLS_TTL(raw_label));
break;
default:
- print_unknown_data(obj_tptr, "\n\t ", obj_tlen);
+ print_unknown_data(gndo,obj_tptr, "\n\t ", obj_tlen);
}
break;
*/
case 2:
default:
- print_unknown_data(obj_tptr, "\n\t ", obj_tlen);
+ print_unknown_data(gndo,obj_tptr, "\n\t ", obj_tlen);
break;
}
if (hlen < obj_tlen)
trunc:
fputs("[|icmp]", stdout);
}
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */