1/* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22#ifndef lint 23static const char rcsid[] _U_ = 24 "@(#) $Header: /tcpdump/master/tcpdump/print-icmp.c,v 1.81.2.2 2005/07/01 16:13:37 hannes Exp $ (LBL)"; 25#endif 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include <tcpdump-stdinc.h> 32 33#include <stdio.h> 34#include <string.h> 35 36#include "interface.h" 37#include "addrtoname.h" 38#include "extract.h" /* must come after interface.h */ 39 40#include "ip.h" 41#include "udp.h" 42#include "ipproto.h" 43#include "mpls.h" 44 45/* 46 * Interface Control Message Protocol Definitions. 47 * Per RFC 792, September 1981. 48 */ 49 50/* 51 * Structure of an icmp header. 52 */ 53struct icmp { 54 u_int8_t icmp_type; /* type of message, see below */ 55 u_int8_t icmp_code; /* type sub code */ 56 u_int16_t icmp_cksum; /* ones complement cksum of struct */ 57 union { 58 u_int8_t ih_pptr; /* ICMP_PARAMPROB */ 59 struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ 60 struct ih_idseq { 61 u_int16_t icd_id; 62 u_int16_t icd_seq; 63 } ih_idseq; 64 u_int32_t ih_void; 65 66 /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ 67 struct ih_pmtu { 68 u_int16_t ipm_void; 69 u_int16_t ipm_nextmtu; 70 } ih_pmtu; 71 } icmp_hun; 72#define icmp_pptr icmp_hun.ih_pptr 73#define icmp_gwaddr icmp_hun.ih_gwaddr 74#define icmp_id icmp_hun.ih_idseq.icd_id 75#define icmp_seq icmp_hun.ih_idseq.icd_seq 76#define icmp_void icmp_hun.ih_void 77#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void 78#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu 79 union { 80 struct id_ts { 81 u_int32_t its_otime; 82 u_int32_t its_rtime; 83 u_int32_t its_ttime; 84 } id_ts; 85 struct id_ip { 86 struct ip idi_ip; 87 /* options and then 64 bits of data */ 88 } id_ip; 89 struct mpls_ext { 90 u_int8_t legacy_header[128]; /* extension header starts 128 bytes after ICMP header */ 91 u_int8_t version_res[2]; 92 u_int8_t checksum[2]; 93 u_int8_t data[1]; 94 } mpls_ext; 95 u_int32_t id_mask; 96 u_int8_t id_data[1]; 97 } icmp_dun; 98#define icmp_otime icmp_dun.id_ts.its_otime 99#define icmp_rtime icmp_dun.id_ts.its_rtime 100#define icmp_ttime icmp_dun.id_ts.its_ttime 101#define icmp_ip icmp_dun.id_ip.idi_ip 102#define icmp_mask icmp_dun.id_mask 103#define icmp_data icmp_dun.id_data 104#define icmp_mpls_ext_version icmp_dun.mpls_ext.version_res 105#define icmp_mpls_ext_checksum icmp_dun.mpls_ext.checksum 106#define icmp_mpls_ext_data icmp_dun.mpls_ext.data 107}; 108 109#define ICMP_MPLS_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4) 110#define ICMP_MPLS_EXT_VERSION 2 111 112/* 113 * Lower bounds on packet lengths for various types. 114 * For the error advice packets must first insure that the 115 * packet is large enought to contain the returned ip header. 116 * Only then can we do the check to see if 64 bits of packet 117 * data have been returned, since we need to check the returned 118 * ip header length. 119 */ 120#define ICMP_MINLEN 8 /* abs minimum */ 121#define ICMP_EXTD_MINLEN (156 - sizeof (struct ip)) /* draft-bonica-icmp-mpls-02 */ 122#define ICMP_TSLEN (8 + 3 * sizeof (u_int32_t)) /* timestamp */ 123#define ICMP_MASKLEN 12 /* address mask */ 124#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ 125#define ICMP_ADVLEN(p) (8 + (IP_HL(&(p)->icmp_ip) << 2) + 8) 126 /* N.B.: must separately check that ip_hl >= 5 */ 127 128/* 129 * Definition of type and code field values. 130 */ 131#define ICMP_ECHOREPLY 0 /* echo reply */ 132#define ICMP_UNREACH 3 /* dest unreachable, codes: */ 133#define ICMP_UNREACH_NET 0 /* bad net */ 134#define ICMP_UNREACH_HOST 1 /* bad host */ 135#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ 136#define ICMP_UNREACH_PORT 3 /* bad port */ 137#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ 138#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ 139#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ 140#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ 141#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ 142#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ 143#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ 144#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ 145#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ 146#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ 147#define ICMP_REDIRECT 5 /* shorter route, codes: */ 148#define ICMP_REDIRECT_NET 0 /* for network */ 149#define ICMP_REDIRECT_HOST 1 /* for host */ 150#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ 151#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ 152#define ICMP_ECHO 8 /* echo service */ 153#define ICMP_ROUTERADVERT 9 /* router advertisement */ 154#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ 155#define ICMP_TIMXCEED 11 /* time exceeded, code: */ 156#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ 157#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ 158#define ICMP_PARAMPROB 12 /* ip header bad */ 159#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ 160#define ICMP_TSTAMP 13 /* timestamp request */ 161#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ 162#define ICMP_IREQ 15 /* information request */ 163#define ICMP_IREQREPLY 16 /* information reply */ 164#define ICMP_MASKREQ 17 /* address mask request */ 165#define ICMP_MASKREPLY 18 /* address mask reply */ 166 167#define ICMP_MAXTYPE 18 168 169#define ICMP_INFOTYPE(type) \ 170 ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ 171 (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ 172 (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ 173 (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ 174 (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) 175#define ICMP_MPLS_EXT_TYPE(type) \ 176 ((type) == ICMP_UNREACH || (type) == ICMP_TIMXCEED) 177/* rfc1700 */ 178#ifndef ICMP_UNREACH_NET_UNKNOWN 179#define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */ 180#endif 181#ifndef ICMP_UNREACH_HOST_UNKNOWN 182#define ICMP_UNREACH_HOST_UNKNOWN 7 /* destination host unknown */ 183#endif 184#ifndef ICMP_UNREACH_ISOLATED 185#define ICMP_UNREACH_ISOLATED 8 /* source host isolated */ 186#endif 187#ifndef ICMP_UNREACH_NET_PROHIB 188#define ICMP_UNREACH_NET_PROHIB 9 /* admin prohibited net */ 189#endif 190#ifndef ICMP_UNREACH_HOST_PROHIB 191#define ICMP_UNREACH_HOST_PROHIB 10 /* admin prohibited host */ 192#endif 193#ifndef ICMP_UNREACH_TOSNET 194#define ICMP_UNREACH_TOSNET 11 /* tos prohibited net */ 195#endif 196#ifndef ICMP_UNREACH_TOSHOST 197#define ICMP_UNREACH_TOSHOST 12 /* tos prohibited host */ 198#endif 199 200/* rfc1716 */ 201#ifndef ICMP_UNREACH_FILTER_PROHIB 202#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */ 203#endif 204#ifndef ICMP_UNREACH_HOST_PRECEDENCE 205#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */ 206#endif 207#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF 208#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ 209#endif 210 211/* Most of the icmp types */ 212static struct tok icmp2str[] = { 213 { ICMP_ECHOREPLY, "echo reply" }, 214 { ICMP_SOURCEQUENCH, "source quench" }, 215 { ICMP_ECHO, "echo request" }, 216 { ICMP_ROUTERSOLICIT, "router solicitation" }, 217 { ICMP_TSTAMP, "time stamp request" }, 218 { ICMP_TSTAMPREPLY, "time stamp reply" }, 219 { ICMP_IREQ, "information request" }, 220 { ICMP_IREQREPLY, "information reply" }, 221 { ICMP_MASKREQ, "address mask request" }, 222 { 0, NULL } 223}; 224 225/* Formats for most of the ICMP_UNREACH codes */ 226static struct tok unreach2str[] = { 227 { ICMP_UNREACH_NET, "net %s unreachable" }, 228 { ICMP_UNREACH_HOST, "host %s unreachable" }, 229 { ICMP_UNREACH_SRCFAIL, 230 "%s unreachable - source route failed" }, 231 { ICMP_UNREACH_NET_UNKNOWN, "net %s unreachable - unknown" }, 232 { ICMP_UNREACH_HOST_UNKNOWN, "host %s unreachable - unknown" }, 233 { ICMP_UNREACH_ISOLATED, 234 "%s unreachable - source host isolated" }, 235 { ICMP_UNREACH_NET_PROHIB, 236 "net %s unreachable - admin prohibited" }, 237 { ICMP_UNREACH_HOST_PROHIB, 238 "host %s unreachable - admin prohibited" }, 239 { ICMP_UNREACH_TOSNET, 240 "net %s unreachable - tos prohibited" }, 241 { ICMP_UNREACH_TOSHOST, 242 "host %s unreachable - tos prohibited" }, 243 { ICMP_UNREACH_FILTER_PROHIB, 244 "host %s unreachable - admin prohibited filter" }, 245 { ICMP_UNREACH_HOST_PRECEDENCE, 246 "host %s unreachable - host precedence violation" }, 247 { ICMP_UNREACH_PRECEDENCE_CUTOFF, 248 "host %s unreachable - precedence cutoff" }, 249 { 0, NULL } 250}; 251 252/* Formats for the ICMP_REDIRECT codes */ 253static struct tok type2str[] = { 254 { ICMP_REDIRECT_NET, "redirect %s to net %s" }, 255 { ICMP_REDIRECT_HOST, "redirect %s to host %s" }, 256 { ICMP_REDIRECT_TOSNET, "redirect-tos %s to net %s" }, 257 { ICMP_REDIRECT_TOSHOST, "redirect-tos %s to host %s" }, 258 { 0, NULL } 259}; 260 261/* rfc1191 */ 262struct mtu_discovery { 263 u_int16_t unused; 264 u_int16_t nexthopmtu; 265}; 266 267/* rfc1256 */ 268struct ih_rdiscovery { 269 u_int8_t ird_addrnum; 270 u_int8_t ird_addrsiz; 271 u_int16_t ird_lifetime; 272}; 273 274struct id_rdiscovery { 275 u_int32_t ird_addr; 276 u_int32_t ird_pref; 277}; 278 279/* draft-bonica-icmp-mpls-02 */ 280struct icmp_mpls_ext_object_header_t { 281 u_int8_t length[2]; 282 u_int8_t class_num; 283 u_int8_t ctype; 284}; 285 286static const struct tok icmp_mpls_ext_obj_values[] = { 287 { 1, "MPLS Stack Entry" }, 288 { 2, "Extended Payload" }, 289 { 0, NULL} 290}; 291 292/* prototypes */ 293const char *icmp_tstamp_print(u_int); 294 295/* print the milliseconds since midnight UTC */ 296const char * 297icmp_tstamp_print(u_int tstamp) { 298 u_int msec,sec,min,hrs; 299 300 static char buf[64]; 301 302 msec = tstamp % 1000; 303 sec = tstamp / 1000; 304 min = sec / 60; sec -= min * 60; 305 hrs = min / 60; min -= hrs * 60; 306 snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%03u",hrs,min,sec,msec); 307 return buf; 308} 309 310void 311icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented) 312{ 313 char *cp; 314 const struct icmp *dp; 315 const struct ip *ip; 316 const char *str, *fmt; 317 const struct ip *oip; 318 const struct udphdr *ouh; 319 const u_int8_t *obj_tptr; 320 u_int32_t raw_label; 321 const struct icmp_mpls_ext_object_header_t *icmp_mpls_ext_object_header; 322 u_int hlen, dport, mtu, obj_tlen, obj_class_num, obj_ctype; 323 char buf[MAXHOSTNAMELEN + 100]; 324 325 dp = (struct icmp *)bp; 326 ip = (struct ip *)bp2; 327 str = buf; 328 329 TCHECK(dp->icmp_code); 330 switch (dp->icmp_type) { 331 332 case ICMP_ECHO: 333 case ICMP_ECHOREPLY: 334 TCHECK(dp->icmp_seq); 335 (void)snprintf(buf, sizeof(buf), "echo %s, id %u, seq %u", 336 dp->icmp_type == ICMP_ECHO ? 337 "request" : "reply", 338 EXTRACT_16BITS(&dp->icmp_id), 339 EXTRACT_16BITS(&dp->icmp_seq)); 340 break; 341 342 case ICMP_UNREACH: 343 TCHECK(dp->icmp_ip.ip_dst); 344 switch (dp->icmp_code) { 345 346 case ICMP_UNREACH_PROTOCOL: 347 TCHECK(dp->icmp_ip.ip_p); 348 (void)snprintf(buf, sizeof(buf), 349 "%s protocol %d unreachable", 350 ipaddr_string(&dp->icmp_ip.ip_dst), 351 dp->icmp_ip.ip_p); 352 break; 353 354 case ICMP_UNREACH_PORT: 355 TCHECK(dp->icmp_ip.ip_p); 356 oip = &dp->icmp_ip; 357 hlen = IP_HL(oip) * 4; 358 ouh = (struct udphdr *)(((u_char *)oip) + hlen); 359 TCHECK(ouh->uh_dport); 360 dport = EXTRACT_16BITS(&ouh->uh_dport); 361 switch (oip->ip_p) { 362 363 case IPPROTO_TCP: 364 (void)snprintf(buf, sizeof(buf), 365 "%s tcp port %s unreachable", 366 ipaddr_string(&oip->ip_dst), 367 tcpport_string(dport)); 368 break; 369 370 case IPPROTO_UDP: 371 (void)snprintf(buf, sizeof(buf), 372 "%s udp port %s unreachable", 373 ipaddr_string(&oip->ip_dst), 374 udpport_string(dport)); 375 break; 376 377 default: 378 (void)snprintf(buf, sizeof(buf), 379 "%s protocol %d port %d unreachable", 380 ipaddr_string(&oip->ip_dst), 381 oip->ip_p, dport); 382 break; 383 } 384 break; 385 386 case ICMP_UNREACH_NEEDFRAG: 387 { 388 register const struct mtu_discovery *mp; 389 mp = (struct mtu_discovery *)&dp->icmp_void; 390 mtu = EXTRACT_16BITS(&mp->nexthopmtu); 391 if (mtu) { 392 (void)snprintf(buf, sizeof(buf), 393 "%s unreachable - need to frag (mtu %d)", 394 ipaddr_string(&dp->icmp_ip.ip_dst), mtu); 395 } else { 396 (void)snprintf(buf, sizeof(buf), 397 "%s unreachable - need to frag", 398 ipaddr_string(&dp->icmp_ip.ip_dst)); 399 } 400 } 401 break; 402 403 default: 404 fmt = tok2str(unreach2str, "#%d %%s unreachable", 405 dp->icmp_code); 406 (void)snprintf(buf, sizeof(buf), fmt, 407 ipaddr_string(&dp->icmp_ip.ip_dst)); 408 break; 409 } 410 break; 411 412 case ICMP_REDIRECT: 413 TCHECK(dp->icmp_ip.ip_dst); 414 fmt = tok2str(type2str, "redirect-#%d %%s to net %%s", 415 dp->icmp_code); 416 (void)snprintf(buf, sizeof(buf), fmt, 417 ipaddr_string(&dp->icmp_ip.ip_dst), 418 ipaddr_string(&dp->icmp_gwaddr)); 419 break; 420 421 case ICMP_ROUTERADVERT: 422 { 423 register const struct ih_rdiscovery *ihp; 424 register const struct id_rdiscovery *idp; 425 u_int lifetime, num, size; 426 427 (void)snprintf(buf, sizeof(buf), "router advertisement"); 428 cp = buf + strlen(buf); 429 430 ihp = (struct ih_rdiscovery *)&dp->icmp_void; 431 TCHECK(*ihp); 432 (void)strncpy(cp, " lifetime ", sizeof(buf) - (cp - buf)); 433 cp = buf + strlen(buf); 434 lifetime = EXTRACT_16BITS(&ihp->ird_lifetime); 435 if (lifetime < 60) { 436 (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u", 437 lifetime); 438 } else if (lifetime < 60 * 60) { 439 (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u:%02u", 440 lifetime / 60, lifetime % 60); 441 } else { 442 (void)snprintf(cp, sizeof(buf) - (cp - buf), 443 "%u:%02u:%02u", 444 lifetime / 3600, 445 (lifetime % 3600) / 60, 446 lifetime % 60); 447 } 448 cp = buf + strlen(buf); 449 450 num = ihp->ird_addrnum; 451 (void)snprintf(cp, sizeof(buf) - (cp - buf), " %d:", num); 452 cp = buf + strlen(buf); 453 454 size = ihp->ird_addrsiz; 455 if (size != 2) { 456 (void)snprintf(cp, sizeof(buf) - (cp - buf), 457 " [size %d]", size); 458 break; 459 } 460 idp = (struct id_rdiscovery *)&dp->icmp_data; 461 while (num-- > 0) { 462 TCHECK(*idp); 463 (void)snprintf(cp, sizeof(buf) - (cp - buf), " {%s %u}", 464 ipaddr_string(&idp->ird_addr), 465 EXTRACT_32BITS(&idp->ird_pref)); 466 cp = buf + strlen(buf); 467 ++idp; 468 } 469 } 470 break; 471 472 case ICMP_TIMXCEED: 473 TCHECK(dp->icmp_ip.ip_dst); 474 switch (dp->icmp_code) { 475 476 case ICMP_TIMXCEED_INTRANS: 477 str = "time exceeded in-transit"; 478 break; 479 480 case ICMP_TIMXCEED_REASS: 481 str = "ip reassembly time exceeded"; 482 break; 483 484 default: 485 (void)snprintf(buf, sizeof(buf), "time exceeded-#%d", 486 dp->icmp_code); 487 break; 488 } 489 break; 490 491 case ICMP_PARAMPROB: 492 if (dp->icmp_code) 493 (void)snprintf(buf, sizeof(buf), 494 "parameter problem - code %d", dp->icmp_code); 495 else { 496 TCHECK(dp->icmp_pptr); 497 (void)snprintf(buf, sizeof(buf), 498 "parameter problem - octet %d", dp->icmp_pptr); 499 } 500 break; 501 502 case ICMP_MASKREPLY: 503 TCHECK(dp->icmp_mask); 504 (void)snprintf(buf, sizeof(buf), "address mask is 0x%08x", 505 EXTRACT_32BITS(&dp->icmp_mask)); 506 break; 507 508 case ICMP_TSTAMP: 509 TCHECK(dp->icmp_seq); 510 (void)snprintf(buf, sizeof(buf), 511 "time stamp query id %u seq %u", 512 EXTRACT_16BITS(&dp->icmp_id), 513 EXTRACT_16BITS(&dp->icmp_seq)); 514 break; 515 516 case ICMP_TSTAMPREPLY: 517 TCHECK(dp->icmp_ttime); 518 (void)snprintf(buf, sizeof(buf), 519 "time stamp reply id %u seq %u: org %s", 520 EXTRACT_16BITS(&dp->icmp_id), 521 EXTRACT_16BITS(&dp->icmp_seq), 522 icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_otime))); 523 524 (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", recv %s", 525 icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_rtime))); 526 (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", xmit %s", 527 icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_ttime))); 528 break; 529 530 default: 531 str = tok2str(icmp2str, "type-#%d", dp->icmp_type); 532 break; 533 } 534 (void)printf("ICMP %s, length %u", str, plen); 535 if (vflag && !fragmented) { /* don't attempt checksumming if this is a frag */ 536 u_int16_t sum, icmp_sum; 537 if (TTEST2(*bp, plen)) { 538 sum = in_cksum((u_short*)dp, plen, 0); 539 if (sum != 0) { 540 icmp_sum = EXTRACT_16BITS(&dp->icmp_cksum); 541 (void)printf(" (wrong icmp cksum %x (->%x)!)", 542 icmp_sum, 543 in_cksum_shouldbe(icmp_sum, sum)); 544 } 545 } 546 } 547 if (vflag >= 1 && !ICMP_INFOTYPE(dp->icmp_type)) { 548 bp += 8; 549 (void)printf("\n\t"); 550 ip = (struct ip *)bp; 551 snaplen = snapend - bp; 552 ip_print(gndo, bp, EXTRACT_16BITS(&ip->ip_len)); 553 } 554 555 if (vflag >= 1 && plen > ICMP_EXTD_MINLEN && ICMP_MPLS_EXT_TYPE(dp->icmp_type)) { 556 557 TCHECK(*(dp->icmp_mpls_ext_version)); 558 printf("\n\tMPLS extension v%u",ICMP_MPLS_EXT_EXTRACT_VERSION(*(dp->icmp_mpls_ext_version))); 559 560 /* 561 * Sanity checking of the header. 562 */ 563 if (ICMP_MPLS_EXT_EXTRACT_VERSION(*(dp->icmp_mpls_ext_version)) != ICMP_MPLS_EXT_VERSION) { 564 printf(" packet not supported"); 565 return; 566 } 567 568 hlen = plen - ICMP_EXTD_MINLEN; 569 TCHECK2(*(dp->icmp_mpls_ext_checksum), 2); 570 printf(", checksum 0x%04x (unverified), length %u", /* FIXME */ 571 EXTRACT_16BITS(dp->icmp_mpls_ext_checksum), 572 hlen); 573 574 hlen -= 4; /* subtract common header size */ 575 obj_tptr = (u_int8_t *)dp->icmp_mpls_ext_data; 576 577 while (hlen > sizeof(struct icmp_mpls_ext_object_header_t)) { 578 579 icmp_mpls_ext_object_header = (struct icmp_mpls_ext_object_header_t *)obj_tptr; 580 TCHECK(*icmp_mpls_ext_object_header); 581 obj_tlen = EXTRACT_16BITS(icmp_mpls_ext_object_header->length); 582 obj_class_num = icmp_mpls_ext_object_header->class_num; 583 obj_ctype = icmp_mpls_ext_object_header->ctype; 584 obj_tptr += sizeof(struct icmp_mpls_ext_object_header_t); 585 586 printf("\n\t %s Object (%u), Class-Type: %u, length %u", 587 tok2str(icmp_mpls_ext_obj_values,"unknown",obj_class_num), 588 obj_class_num, 589 obj_ctype, 590 obj_tlen); 591 592 hlen-=sizeof(struct icmp_mpls_ext_object_header_t); /* length field includes tlv header */ 593 if (obj_tlen < sizeof(struct icmp_mpls_ext_object_header_t)) 594 break; 595 obj_tlen-=sizeof(struct icmp_mpls_ext_object_header_t); 596 597 switch (obj_class_num) { 598 case 1: 599 switch(obj_ctype) { 600 case 1: 601 TCHECK2(*obj_tptr, 4); 602 raw_label = EXTRACT_32BITS(obj_tptr); 603 printf("\n\t label %u, exp %u", MPLS_LABEL(raw_label), MPLS_EXP(raw_label)); 604 if (MPLS_STACK(raw_label)) 605 printf(", [S]"); 606 printf(", ttl %u", MPLS_TTL(raw_label)); 607 break; 608 default: 609 print_unknown_data(obj_tptr, "\n\t ", obj_tlen); 610 } 611 break; 612 613 /* 614 * FIXME those are the defined objects that lack a decoder 615 * you are welcome to contribute code ;-) 616 */ 617 case 2: 618 default: 619 print_unknown_data(obj_tptr, "\n\t ", obj_tlen); 620 break; 621 } 622 if (hlen < obj_tlen) 623 break; 624 hlen -= obj_tlen; 625 obj_tptr += obj_tlen; 626 } 627 } 628 629 return; 630trunc: 631 fputs("[|icmp]", stdout); 632} 633