10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 30f74e101Schristos * The Regents of the University of California. All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that: (1) source code distributions 70f74e101Schristos * retain the above copyright notice and this paragraph in its entirety, (2) 80f74e101Schristos * distributions including binary code include the above copyright notice and 90f74e101Schristos * this paragraph in its entirety in the documentation or other materials 100f74e101Schristos * provided with the distribution, and (3) all advertising materials mentioning 110f74e101Schristos * features or use of this software display the following acknowledgement: 120f74e101Schristos * ``This product includes software developed by the University of California, 130f74e101Schristos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 140f74e101Schristos * the University nor the names of its contributors may be used to endorse 150f74e101Schristos * or promote products derived from this software without specific prior 160f74e101Schristos * written permission. 170f74e101Schristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 180f74e101Schristos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 190f74e101Schristos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 200f74e101Schristos */ 210f74e101Schristos 2211b3aaa1Schristos #include <sys/cdefs.h> 230f74e101Schristos #ifndef lint 24*26ba0b50Schristos __RCSID("$NetBSD: print-icmp.c,v 1.14 2024/09/02 16:15:31 christos Exp $"); 250f74e101Schristos #endif 260f74e101Schristos 27dc860a36Sspz /* \summary: Internet Control Message Protocol (ICMP) printer */ 28dc860a36Sspz 29c74ad251Schristos #include <config.h> 300f74e101Schristos 31c74ad251Schristos #include "netdissect-stdinc.h" 320f74e101Schristos 330f74e101Schristos #include <stdio.h> 340f74e101Schristos #include <string.h> 350f74e101Schristos 36fdccd7e4Schristos #include "netdissect.h" 370f74e101Schristos #include "addrtoname.h" 38fdccd7e4Schristos #include "extract.h" 390f74e101Schristos 400f74e101Schristos #include "ip.h" 410f74e101Schristos #include "udp.h" 420f74e101Schristos #include "ipproto.h" 430f74e101Schristos #include "mpls.h" 440f74e101Schristos 450f74e101Schristos /* 460f74e101Schristos * Interface Control Message Protocol Definitions. 470f74e101Schristos * Per RFC 792, September 1981. 480f74e101Schristos */ 490f74e101Schristos 500f74e101Schristos /* 510f74e101Schristos * Structure of an icmp header. 520f74e101Schristos */ 530f74e101Schristos struct icmp { 54c74ad251Schristos nd_uint8_t icmp_type; /* type of message, see below */ 55c74ad251Schristos nd_uint8_t icmp_code; /* type sub code */ 56c74ad251Schristos nd_uint16_t icmp_cksum; /* ones complement cksum of struct */ 570f74e101Schristos union { 58c74ad251Schristos nd_uint8_t ih_pptr; /* ICMP_PARAMPROB */ 59c74ad251Schristos nd_ipv4 ih_gwaddr; /* ICMP_REDIRECT */ 600f74e101Schristos struct ih_idseq { 61c74ad251Schristos nd_uint16_t icd_id; 62c74ad251Schristos nd_uint16_t icd_seq; 630f74e101Schristos } ih_idseq; 64c74ad251Schristos nd_uint32_t ih_void; 650f74e101Schristos } icmp_hun; 660f74e101Schristos #define icmp_pptr icmp_hun.ih_pptr 670f74e101Schristos #define icmp_gwaddr icmp_hun.ih_gwaddr 680f74e101Schristos #define icmp_id icmp_hun.ih_idseq.icd_id 690f74e101Schristos #define icmp_seq icmp_hun.ih_idseq.icd_seq 700f74e101Schristos #define icmp_void icmp_hun.ih_void 710f74e101Schristos union { 720f74e101Schristos struct id_ts { 73c74ad251Schristos nd_uint32_t its_otime; 74c74ad251Schristos nd_uint32_t its_rtime; 75c74ad251Schristos nd_uint32_t its_ttime; 760f74e101Schristos } id_ts; 770f74e101Schristos struct id_ip { 780f74e101Schristos struct ip idi_ip; 790f74e101Schristos /* options and then 64 bits of data */ 800f74e101Schristos } id_ip; 81c74ad251Schristos nd_uint32_t id_mask; 82c74ad251Schristos nd_byte id_data[1]; 830f74e101Schristos } icmp_dun; 840f74e101Schristos #define icmp_otime icmp_dun.id_ts.its_otime 850f74e101Schristos #define icmp_rtime icmp_dun.id_ts.its_rtime 860f74e101Schristos #define icmp_ttime icmp_dun.id_ts.its_ttime 870f74e101Schristos #define icmp_ip icmp_dun.id_ip.idi_ip 880f74e101Schristos #define icmp_mask icmp_dun.id_mask 890f74e101Schristos #define icmp_data icmp_dun.id_data 90daed3b99Sthorpej } UNALIGNED; 910f74e101Schristos 920f74e101Schristos /* 930f74e101Schristos * Lower bounds on packet lengths for various types. 940f74e101Schristos * For the error advice packets must first insure that the 95c74ad251Schristos * packet is large enough to contain the returned ip header. 960f74e101Schristos * Only then can we do the check to see if 64 bits of packet 970f74e101Schristos * data have been returned, since we need to check the returned 980f74e101Schristos * ip header length. 990f74e101Schristos */ 1000f74e101Schristos #define ICMP_MINLEN 8 /* abs minimum */ 1010f74e101Schristos #define ICMP_EXTD_MINLEN (156 - sizeof (struct ip)) /* draft-bonica-internet-icmp-08 */ 102b3a00663Schristos #define ICMP_TSLEN (8 + 3 * sizeof (uint32_t)) /* timestamp */ 1030f74e101Schristos #define ICMP_MASKLEN 12 /* address mask */ 1040f74e101Schristos #define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ 1050f74e101Schristos #define ICMP_ADVLEN(p) (8 + (IP_HL(&(p)->icmp_ip) << 2) + 8) 1060f74e101Schristos /* N.B.: must separately check that ip_hl >= 5 */ 1070f74e101Schristos 1080f74e101Schristos /* 1090f74e101Schristos * Definition of type and code field values. 1100f74e101Schristos */ 1110f74e101Schristos #define ICMP_ECHOREPLY 0 /* echo reply */ 1120f74e101Schristos #define ICMP_UNREACH 3 /* dest unreachable, codes: */ 1130f74e101Schristos #define ICMP_UNREACH_NET 0 /* bad net */ 1140f74e101Schristos #define ICMP_UNREACH_HOST 1 /* bad host */ 1150f74e101Schristos #define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ 1160f74e101Schristos #define ICMP_UNREACH_PORT 3 /* bad port */ 1170f74e101Schristos #define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ 1180f74e101Schristos #define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ 1190f74e101Schristos #define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ 1200f74e101Schristos #define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ 1210f74e101Schristos #define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ 1220f74e101Schristos #define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ 1230f74e101Schristos #define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ 1240f74e101Schristos #define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ 1250f74e101Schristos #define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ 1260f74e101Schristos #define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ 1270f74e101Schristos #define ICMP_REDIRECT 5 /* shorter route, codes: */ 1280f74e101Schristos #define ICMP_REDIRECT_NET 0 /* for network */ 1290f74e101Schristos #define ICMP_REDIRECT_HOST 1 /* for host */ 1300f74e101Schristos #define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ 1310f74e101Schristos #define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ 1320f74e101Schristos #define ICMP_ECHO 8 /* echo service */ 1330f74e101Schristos #define ICMP_ROUTERADVERT 9 /* router advertisement */ 1340f74e101Schristos #define ICMP_ROUTERSOLICIT 10 /* router solicitation */ 1350f74e101Schristos #define ICMP_TIMXCEED 11 /* time exceeded, code: */ 1360f74e101Schristos #define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ 1370f74e101Schristos #define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ 1380f74e101Schristos #define ICMP_PARAMPROB 12 /* ip header bad */ 1390f74e101Schristos #define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ 1400f74e101Schristos #define ICMP_TSTAMP 13 /* timestamp request */ 1410f74e101Schristos #define ICMP_TSTAMPREPLY 14 /* timestamp reply */ 1420f74e101Schristos #define ICMP_IREQ 15 /* information request */ 1430f74e101Schristos #define ICMP_IREQREPLY 16 /* information reply */ 1440f74e101Schristos #define ICMP_MASKREQ 17 /* address mask request */ 1450f74e101Schristos #define ICMP_MASKREPLY 18 /* address mask reply */ 1460f74e101Schristos 1470f74e101Schristos #define ICMP_MAXTYPE 18 1480f74e101Schristos 149ba2ff121Schristos #define ICMP_ERRTYPE(type) \ 150ba2ff121Schristos ((type) == ICMP_UNREACH || (type) == ICMP_SOURCEQUENCH || \ 151ba2ff121Schristos (type) == ICMP_REDIRECT || (type) == ICMP_TIMXCEED || \ 152ba2ff121Schristos (type) == ICMP_PARAMPROB) 153c74ad251Schristos #define ICMP_MULTIPART_EXT_TYPE(type) \ 1540f74e101Schristos ((type) == ICMP_UNREACH || \ 1550f74e101Schristos (type) == ICMP_TIMXCEED || \ 1560f74e101Schristos (type) == ICMP_PARAMPROB) 1570f74e101Schristos /* rfc1700 */ 1580f74e101Schristos #ifndef ICMP_UNREACH_NET_UNKNOWN 1590f74e101Schristos #define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */ 1600f74e101Schristos #endif 1610f74e101Schristos #ifndef ICMP_UNREACH_HOST_UNKNOWN 1620f74e101Schristos #define ICMP_UNREACH_HOST_UNKNOWN 7 /* destination host unknown */ 1630f74e101Schristos #endif 1640f74e101Schristos #ifndef ICMP_UNREACH_ISOLATED 1650f74e101Schristos #define ICMP_UNREACH_ISOLATED 8 /* source host isolated */ 1660f74e101Schristos #endif 1670f74e101Schristos #ifndef ICMP_UNREACH_NET_PROHIB 1680f74e101Schristos #define ICMP_UNREACH_NET_PROHIB 9 /* admin prohibited net */ 1690f74e101Schristos #endif 1700f74e101Schristos #ifndef ICMP_UNREACH_HOST_PROHIB 1710f74e101Schristos #define ICMP_UNREACH_HOST_PROHIB 10 /* admin prohibited host */ 1720f74e101Schristos #endif 1730f74e101Schristos #ifndef ICMP_UNREACH_TOSNET 1740f74e101Schristos #define ICMP_UNREACH_TOSNET 11 /* tos prohibited net */ 1750f74e101Schristos #endif 1760f74e101Schristos #ifndef ICMP_UNREACH_TOSHOST 1770f74e101Schristos #define ICMP_UNREACH_TOSHOST 12 /* tos prohibited host */ 1780f74e101Schristos #endif 1790f74e101Schristos 1800f74e101Schristos /* rfc1716 */ 1810f74e101Schristos #ifndef ICMP_UNREACH_FILTER_PROHIB 1820f74e101Schristos #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */ 1830f74e101Schristos #endif 1840f74e101Schristos #ifndef ICMP_UNREACH_HOST_PRECEDENCE 1850f74e101Schristos #define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */ 1860f74e101Schristos #endif 1870f74e101Schristos #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF 1880f74e101Schristos #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ 1890f74e101Schristos #endif 1900f74e101Schristos 1910f74e101Schristos /* Most of the icmp types */ 192870189d2Schristos static const struct tok icmp2str[] = { 1930f74e101Schristos { ICMP_ECHOREPLY, "echo reply" }, 1940f74e101Schristos { ICMP_SOURCEQUENCH, "source quench" }, 1950f74e101Schristos { ICMP_ECHO, "echo request" }, 1960f74e101Schristos { ICMP_ROUTERSOLICIT, "router solicitation" }, 1970f74e101Schristos { ICMP_TSTAMP, "time stamp request" }, 1980f74e101Schristos { ICMP_TSTAMPREPLY, "time stamp reply" }, 1990f74e101Schristos { ICMP_IREQ, "information request" }, 2000f74e101Schristos { ICMP_IREQREPLY, "information reply" }, 2010f74e101Schristos { ICMP_MASKREQ, "address mask request" }, 2020f74e101Schristos { 0, NULL } 2030f74e101Schristos }; 2040f74e101Schristos 2050f74e101Schristos /* rfc1191 */ 2060f74e101Schristos struct mtu_discovery { 207c74ad251Schristos nd_uint16_t unused; 208c74ad251Schristos nd_uint16_t nexthopmtu; 2090f74e101Schristos }; 2100f74e101Schristos 2110f74e101Schristos /* rfc1256 */ 2120f74e101Schristos struct ih_rdiscovery { 213c74ad251Schristos nd_uint8_t ird_addrnum; 214c74ad251Schristos nd_uint8_t ird_addrsiz; 215c74ad251Schristos nd_uint16_t ird_lifetime; 2160f74e101Schristos }; 2170f74e101Schristos 2180f74e101Schristos struct id_rdiscovery { 219c74ad251Schristos nd_uint32_t ird_addr; 220c74ad251Schristos nd_uint32_t ird_pref; 2210f74e101Schristos }; 2220f74e101Schristos 2230f74e101Schristos /* 224c74ad251Schristos * RFC 4884 - Extended ICMP to Support Multi-Part Messages 225c74ad251Schristos * 226c74ad251Schristos * This is a general extension mechanism, based on the mechanism 227c74ad251Schristos * in draft-bonica-icmp-mpls-02 ICMP Extensions for MultiProtocol 228c74ad251Schristos * Label Switching. 2290f74e101Schristos * 2300f74e101Schristos * The Destination Unreachable, Time Exceeded 231c74ad251Schristos * and Parameter Problem messages are slightly changed as per 232c74ad251Schristos * the above RFC. A new Length field gets added to give 233c74ad251Schristos * the caller an idea about the length of the piggybacked 234c74ad251Schristos * IP packet before the extension header starts. 2350f74e101Schristos * 2360f74e101Schristos * The Length field represents length of the padded "original datagram" 2370f74e101Schristos * field measured in 32-bit words. 2380f74e101Schristos * 2390f74e101Schristos * 0 1 2 3 2400f74e101Schristos * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2410f74e101Schristos * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2420f74e101Schristos * | Type | Code | Checksum | 2430f74e101Schristos * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2440f74e101Schristos * | unused | Length | unused | 2450f74e101Schristos * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2460f74e101Schristos * | Internet Header + leading octets of original datagram | 2470f74e101Schristos * | | 2480f74e101Schristos * | // | 2490f74e101Schristos * | | 2500f74e101Schristos * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2510f74e101Schristos */ 2520f74e101Schristos 2530f74e101Schristos struct icmp_ext_t { 254c74ad251Schristos nd_uint8_t icmp_type; 255c74ad251Schristos nd_uint8_t icmp_code; 256c74ad251Schristos nd_uint16_t icmp_checksum; 257c74ad251Schristos nd_byte icmp_reserved; 258c74ad251Schristos nd_uint8_t icmp_length; 259c74ad251Schristos nd_byte icmp_reserved2[2]; 260c74ad251Schristos nd_byte icmp_ext_legacy_header[128]; /* extension header starts 128 bytes after ICMP header */ 261c74ad251Schristos nd_byte icmp_ext_version_res[2]; 262c74ad251Schristos nd_uint16_t icmp_ext_checksum; 263c74ad251Schristos nd_byte icmp_ext_data[1]; 2640f74e101Schristos }; 2650f74e101Schristos 266c74ad251Schristos /* 267c74ad251Schristos * Extract version from the first octet of icmp_ext_version_res. 268c74ad251Schristos */ 269c74ad251Schristos #define ICMP_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4) 270c74ad251Schristos 271c74ad251Schristos /* 272c74ad251Schristos * Current version. 273c74ad251Schristos */ 274c74ad251Schristos #define ICMP_EXT_VERSION 2 275c74ad251Schristos 276c74ad251Schristos /* 277c74ad251Schristos * Extension object class numbers. 278c74ad251Schristos * 279c74ad251Schristos * Class 1 dates back to draft-bonica-icmp-mpls-02. 280c74ad251Schristos */ 281c74ad251Schristos 282c74ad251Schristos /* rfc4950 */ 283c74ad251Schristos #define MPLS_STACK_ENTRY_OBJECT_CLASS 1 284c74ad251Schristos 285c74ad251Schristos struct icmp_multipart_ext_object_header_t { 286c74ad251Schristos nd_uint16_t length; 287c74ad251Schristos nd_uint8_t class_num; 288c74ad251Schristos nd_uint8_t ctype; 2890f74e101Schristos }; 2900f74e101Schristos 291c74ad251Schristos static const struct tok icmp_multipart_ext_obj_values[] = { 2920f74e101Schristos { 1, "MPLS Stack Entry" }, 293c74ad251Schristos { 2, "Interface Identification" }, 2940f74e101Schristos { 0, NULL} 2950f74e101Schristos }; 2960f74e101Schristos 2970f74e101Schristos /* prototypes */ 2980f74e101Schristos const char *icmp_tstamp_print(u_int); 2990f74e101Schristos 3000f74e101Schristos /* print the milliseconds since midnight UTC */ 3010f74e101Schristos const char * 302ba2ff121Schristos icmp_tstamp_print(u_int tstamp) 303ba2ff121Schristos { 3040f74e101Schristos u_int msec,sec,min,hrs; 3050f74e101Schristos 3060f74e101Schristos static char buf[64]; 3070f74e101Schristos 3080f74e101Schristos msec = tstamp % 1000; 3090f74e101Schristos sec = tstamp / 1000; 3100f74e101Schristos min = sec / 60; sec -= min * 60; 3110f74e101Schristos hrs = min / 60; min -= hrs * 60; 3120f74e101Schristos snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%03u",hrs,min,sec,msec); 3130f74e101Schristos return buf; 3140f74e101Schristos } 3150f74e101Schristos 316a8e08e94Skamil UNALIGNED_OK 3170f74e101Schristos void 318b3a00663Schristos icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen, const u_char *bp2, 319b3a00663Schristos int fragmented) 3200f74e101Schristos { 3210f74e101Schristos char *cp; 3220f74e101Schristos const struct icmp *dp; 323c74ad251Schristos uint8_t icmp_type, icmp_code; 3240f74e101Schristos const struct icmp_ext_t *ext_dp; 3250f74e101Schristos const struct ip *ip; 326c74ad251Schristos const char *str; 3270f74e101Schristos const struct ip *oip; 328c74ad251Schristos uint8_t ip_proto; 3290f74e101Schristos const struct udphdr *ouh; 330b3a00663Schristos const uint8_t *obj_tptr; 331b3a00663Schristos uint32_t raw_label; 332c74ad251Schristos const struct icmp_multipart_ext_object_header_t *icmp_multipart_ext_object_header; 333c74ad251Schristos u_int hlen, mtu, obj_tlen, obj_class_num, obj_ctype; 334c74ad251Schristos uint16_t dport; 3350f74e101Schristos char buf[MAXHOSTNAMELEN + 100]; 3360e9868baSchristos struct cksum_vec vec[1]; 3370f74e101Schristos 338c74ad251Schristos ndo->ndo_protocol = "icmp"; 339fdccd7e4Schristos dp = (const struct icmp *)bp; 340fdccd7e4Schristos ext_dp = (const struct icmp_ext_t *)bp; 341fdccd7e4Schristos ip = (const struct ip *)bp2; 3420f74e101Schristos str = buf; 3430f74e101Schristos 344c74ad251Schristos icmp_type = GET_U_1(dp->icmp_type); 345c74ad251Schristos icmp_code = GET_U_1(dp->icmp_code); 346c74ad251Schristos switch (icmp_type) { 3470f74e101Schristos 3480f74e101Schristos case ICMP_ECHO: 3490f74e101Schristos case ICMP_ECHOREPLY: 3500f74e101Schristos (void)snprintf(buf, sizeof(buf), "echo %s, id %u, seq %u", 351c74ad251Schristos icmp_type == ICMP_ECHO ? 3520f74e101Schristos "request" : "reply", 353c74ad251Schristos GET_BE_U_2(dp->icmp_id), 354c74ad251Schristos GET_BE_U_2(dp->icmp_seq)); 3550f74e101Schristos break; 3560f74e101Schristos 3570f74e101Schristos case ICMP_UNREACH: 358c74ad251Schristos switch (icmp_code) { 359c74ad251Schristos 360c74ad251Schristos case ICMP_UNREACH_NET: 361c74ad251Schristos (void)snprintf(buf, sizeof(buf), 362c74ad251Schristos "net %s unreachable", 363c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 364c74ad251Schristos break; 365c74ad251Schristos 366c74ad251Schristos case ICMP_UNREACH_HOST: 367c74ad251Schristos (void)snprintf(buf, sizeof(buf), 368c74ad251Schristos "host %s unreachable", 369c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 370c74ad251Schristos break; 3710f74e101Schristos 3720f74e101Schristos case ICMP_UNREACH_PROTOCOL: 3730f74e101Schristos (void)snprintf(buf, sizeof(buf), 374c74ad251Schristos "%s protocol %u unreachable", 375c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst), 376c74ad251Schristos GET_U_1(dp->icmp_ip.ip_p)); 3770f74e101Schristos break; 3780f74e101Schristos 3790f74e101Schristos case ICMP_UNREACH_PORT: 380c74ad251Schristos ND_TCHECK_1(dp->icmp_ip.ip_p); 3810f74e101Schristos oip = &dp->icmp_ip; 3820f74e101Schristos hlen = IP_HL(oip) * 4; 383fdccd7e4Schristos ouh = (const struct udphdr *)(((const u_char *)oip) + hlen); 384c74ad251Schristos dport = GET_BE_U_2(ouh->uh_dport); 385c74ad251Schristos ip_proto = GET_U_1(oip->ip_p); 386c74ad251Schristos switch (ip_proto) { 3870f74e101Schristos 3880f74e101Schristos case IPPROTO_TCP: 3890f74e101Schristos (void)snprintf(buf, sizeof(buf), 3900f74e101Schristos "%s tcp port %s unreachable", 391c74ad251Schristos GET_IPADDR_STRING(oip->ip_dst), 392fdccd7e4Schristos tcpport_string(ndo, dport)); 3930f74e101Schristos break; 3940f74e101Schristos 3950f74e101Schristos case IPPROTO_UDP: 3960f74e101Schristos (void)snprintf(buf, sizeof(buf), 3970f74e101Schristos "%s udp port %s unreachable", 398c74ad251Schristos GET_IPADDR_STRING(oip->ip_dst), 399fdccd7e4Schristos udpport_string(ndo, dport)); 4000f74e101Schristos break; 4010f74e101Schristos 4020f74e101Schristos default: 4030f74e101Schristos (void)snprintf(buf, sizeof(buf), 404817e9a7eSchristos "%s protocol %u port %u unreachable", 405c74ad251Schristos GET_IPADDR_STRING(oip->ip_dst), 406c74ad251Schristos ip_proto, dport); 4070f74e101Schristos break; 4080f74e101Schristos } 4090f74e101Schristos break; 4100f74e101Schristos 4110f74e101Schristos case ICMP_UNREACH_NEEDFRAG: 4120f74e101Schristos { 413c74ad251Schristos const struct mtu_discovery *mp; 414fdccd7e4Schristos mp = (const struct mtu_discovery *)(const u_char *)&dp->icmp_void; 415c74ad251Schristos mtu = GET_BE_U_2(mp->nexthopmtu); 4160f74e101Schristos if (mtu) { 4170f74e101Schristos (void)snprintf(buf, sizeof(buf), 418c74ad251Schristos "%s unreachable - need to frag (mtu %u)", 419c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst), mtu); 4200f74e101Schristos } else { 4210f74e101Schristos (void)snprintf(buf, sizeof(buf), 4220f74e101Schristos "%s unreachable - need to frag", 423c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 4240f74e101Schristos } 4250f74e101Schristos } 4260f74e101Schristos break; 4270f74e101Schristos 428c74ad251Schristos case ICMP_UNREACH_SRCFAIL: 429c74ad251Schristos (void)snprintf(buf, sizeof(buf), 430c74ad251Schristos "%s unreachable - source route failed", 431c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 432c74ad251Schristos break; 433c74ad251Schristos 434c74ad251Schristos case ICMP_UNREACH_NET_UNKNOWN: 435c74ad251Schristos (void)snprintf(buf, sizeof(buf), 436c74ad251Schristos "net %s unreachable - unknown", 437c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 438c74ad251Schristos break; 439c74ad251Schristos 440c74ad251Schristos case ICMP_UNREACH_HOST_UNKNOWN: 441c74ad251Schristos (void)snprintf(buf, sizeof(buf), 442c74ad251Schristos "host %s unreachable - unknown", 443c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 444c74ad251Schristos break; 445c74ad251Schristos 446c74ad251Schristos case ICMP_UNREACH_ISOLATED: 447c74ad251Schristos (void)snprintf(buf, sizeof(buf), 448c74ad251Schristos "%s unreachable - source host isolated", 449c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 450c74ad251Schristos break; 451c74ad251Schristos 452c74ad251Schristos case ICMP_UNREACH_NET_PROHIB: 453c74ad251Schristos (void)snprintf(buf, sizeof(buf), 454c74ad251Schristos "net %s unreachable - admin prohibited", 455c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 456c74ad251Schristos break; 457c74ad251Schristos 458c74ad251Schristos case ICMP_UNREACH_HOST_PROHIB: 459c74ad251Schristos (void)snprintf(buf, sizeof(buf), 460c74ad251Schristos "host %s unreachable - admin prohibited", 461c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 462c74ad251Schristos break; 463c74ad251Schristos 464c74ad251Schristos case ICMP_UNREACH_TOSNET: 465c74ad251Schristos (void)snprintf(buf, sizeof(buf), 466c74ad251Schristos "net %s unreachable - tos prohibited", 467c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 468c74ad251Schristos break; 469c74ad251Schristos 470c74ad251Schristos case ICMP_UNREACH_TOSHOST: 471c74ad251Schristos (void)snprintf(buf, sizeof(buf), 472c74ad251Schristos "host %s unreachable - tos prohibited", 473c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 474c74ad251Schristos break; 475c74ad251Schristos 476c74ad251Schristos case ICMP_UNREACH_FILTER_PROHIB: 477c74ad251Schristos (void)snprintf(buf, sizeof(buf), 478c74ad251Schristos "host %s unreachable - admin prohibited filter", 479c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 480c74ad251Schristos break; 481c74ad251Schristos 482c74ad251Schristos case ICMP_UNREACH_HOST_PRECEDENCE: 483c74ad251Schristos (void)snprintf(buf, sizeof(buf), 484c74ad251Schristos "host %s unreachable - host precedence violation", 485c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 486c74ad251Schristos break; 487c74ad251Schristos 488c74ad251Schristos case ICMP_UNREACH_PRECEDENCE_CUTOFF: 489c74ad251Schristos (void)snprintf(buf, sizeof(buf), 490c74ad251Schristos "host %s unreachable - precedence cutoff", 491c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst)); 492c74ad251Schristos break; 493c74ad251Schristos 4940f74e101Schristos default: 495c74ad251Schristos (void)snprintf(buf, sizeof(buf), 496c74ad251Schristos "%s unreachable - #%u", 497c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst), 498c74ad251Schristos icmp_code); 4990f74e101Schristos break; 5000f74e101Schristos } 5010f74e101Schristos break; 5020f74e101Schristos 5030f74e101Schristos case ICMP_REDIRECT: 504c74ad251Schristos switch (icmp_code) { 505c74ad251Schristos 506c74ad251Schristos case ICMP_REDIRECT_NET: 507c74ad251Schristos (void)snprintf(buf, sizeof(buf), 508c74ad251Schristos "redirect %s to net %s", 509c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst), 510c74ad251Schristos GET_IPADDR_STRING(dp->icmp_gwaddr)); 511c74ad251Schristos break; 512c74ad251Schristos 513c74ad251Schristos case ICMP_REDIRECT_HOST: 514c74ad251Schristos (void)snprintf(buf, sizeof(buf), 515c74ad251Schristos "redirect %s to host %s", 516c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst), 517c74ad251Schristos GET_IPADDR_STRING(dp->icmp_gwaddr)); 518c74ad251Schristos break; 519c74ad251Schristos 520c74ad251Schristos case ICMP_REDIRECT_TOSNET: 521c74ad251Schristos (void)snprintf(buf, sizeof(buf), 522c74ad251Schristos "redirect-tos %s to net %s", 523c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst), 524c74ad251Schristos GET_IPADDR_STRING(dp->icmp_gwaddr)); 525c74ad251Schristos break; 526c74ad251Schristos 527c74ad251Schristos case ICMP_REDIRECT_TOSHOST: 528c74ad251Schristos (void)snprintf(buf, sizeof(buf), 529c74ad251Schristos "redirect-tos %s to host %s", 530c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst), 531c74ad251Schristos GET_IPADDR_STRING(dp->icmp_gwaddr)); 532c74ad251Schristos break; 533c74ad251Schristos 534c74ad251Schristos default: 535c74ad251Schristos (void)snprintf(buf, sizeof(buf), 536c74ad251Schristos "redirect-#%u %s to %s", icmp_code, 537c74ad251Schristos GET_IPADDR_STRING(dp->icmp_ip.ip_dst), 538c74ad251Schristos GET_IPADDR_STRING(dp->icmp_gwaddr)); 539c74ad251Schristos break; 540c74ad251Schristos } 5410f74e101Schristos break; 5420f74e101Schristos 5430f74e101Schristos case ICMP_ROUTERADVERT: 5440f74e101Schristos { 545c74ad251Schristos const struct ih_rdiscovery *ihp; 546c74ad251Schristos const struct id_rdiscovery *idp; 5470f74e101Schristos u_int lifetime, num, size; 5480f74e101Schristos 5490f74e101Schristos (void)snprintf(buf, sizeof(buf), "router advertisement"); 5500f74e101Schristos cp = buf + strlen(buf); 5510f74e101Schristos 552fdccd7e4Schristos ihp = (const struct ih_rdiscovery *)&dp->icmp_void; 553c74ad251Schristos ND_TCHECK_SIZE(ihp); 5540f74e101Schristos (void)strncpy(cp, " lifetime ", sizeof(buf) - (cp - buf)); 5550f74e101Schristos cp = buf + strlen(buf); 556c74ad251Schristos lifetime = GET_BE_U_2(ihp->ird_lifetime); 5570f74e101Schristos if (lifetime < 60) { 5580f74e101Schristos (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u", 5590f74e101Schristos lifetime); 5600f74e101Schristos } else if (lifetime < 60 * 60) { 5610f74e101Schristos (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u:%02u", 5620f74e101Schristos lifetime / 60, lifetime % 60); 5630f74e101Schristos } else { 5640f74e101Schristos (void)snprintf(cp, sizeof(buf) - (cp - buf), 5650f74e101Schristos "%u:%02u:%02u", 5660f74e101Schristos lifetime / 3600, 5670f74e101Schristos (lifetime % 3600) / 60, 5680f74e101Schristos lifetime % 60); 5690f74e101Schristos } 5700f74e101Schristos cp = buf + strlen(buf); 5710f74e101Schristos 572c74ad251Schristos num = GET_U_1(ihp->ird_addrnum); 573c74ad251Schristos (void)snprintf(cp, sizeof(buf) - (cp - buf), " %u:", num); 5740f74e101Schristos cp = buf + strlen(buf); 5750f74e101Schristos 576c74ad251Schristos size = GET_U_1(ihp->ird_addrsiz); 5770f74e101Schristos if (size != 2) { 5780f74e101Schristos (void)snprintf(cp, sizeof(buf) - (cp - buf), 579c74ad251Schristos " [size %u]", size); 5800f74e101Schristos break; 5810f74e101Schristos } 582fdccd7e4Schristos idp = (const struct id_rdiscovery *)&dp->icmp_data; 583c74ad251Schristos while (num > 0) { 584c74ad251Schristos ND_TCHECK_SIZE(idp); 5850f74e101Schristos (void)snprintf(cp, sizeof(buf) - (cp - buf), " {%s %u}", 586c74ad251Schristos GET_IPADDR_STRING(idp->ird_addr), 587c74ad251Schristos GET_BE_U_4(idp->ird_pref)); 5880f74e101Schristos cp = buf + strlen(buf); 5890f74e101Schristos ++idp; 590c74ad251Schristos num--; 5910f74e101Schristos } 5920f74e101Schristos } 5930f74e101Schristos break; 5940f74e101Schristos 5950f74e101Schristos case ICMP_TIMXCEED: 596c74ad251Schristos ND_TCHECK_4(dp->icmp_ip.ip_dst); 597c74ad251Schristos switch (icmp_code) { 5980f74e101Schristos 5990f74e101Schristos case ICMP_TIMXCEED_INTRANS: 6000f74e101Schristos str = "time exceeded in-transit"; 6010f74e101Schristos break; 6020f74e101Schristos 6030f74e101Schristos case ICMP_TIMXCEED_REASS: 6040f74e101Schristos str = "ip reassembly time exceeded"; 6050f74e101Schristos break; 6060f74e101Schristos 6070f74e101Schristos default: 608817e9a7eSchristos (void)snprintf(buf, sizeof(buf), "time exceeded-#%u", 609c74ad251Schristos icmp_code); 6100f74e101Schristos break; 6110f74e101Schristos } 6120f74e101Schristos break; 6130f74e101Schristos 6140f74e101Schristos case ICMP_PARAMPROB: 615c74ad251Schristos if (icmp_code) 6160f74e101Schristos (void)snprintf(buf, sizeof(buf), 617c74ad251Schristos "parameter problem - code %u", icmp_code); 6180f74e101Schristos else { 6190f74e101Schristos (void)snprintf(buf, sizeof(buf), 620c74ad251Schristos "parameter problem - octet %u", 621c74ad251Schristos GET_U_1(dp->icmp_pptr)); 6220f74e101Schristos } 6230f74e101Schristos break; 6240f74e101Schristos 6250f74e101Schristos case ICMP_MASKREPLY: 6260f74e101Schristos (void)snprintf(buf, sizeof(buf), "address mask is 0x%08x", 627c74ad251Schristos GET_BE_U_4(dp->icmp_mask)); 6280f74e101Schristos break; 6290f74e101Schristos 6300f74e101Schristos case ICMP_TSTAMP: 6310f74e101Schristos (void)snprintf(buf, sizeof(buf), 6320f74e101Schristos "time stamp query id %u seq %u", 633c74ad251Schristos GET_BE_U_2(dp->icmp_id), 634c74ad251Schristos GET_BE_U_2(dp->icmp_seq)); 6350f74e101Schristos break; 6360f74e101Schristos 6370f74e101Schristos case ICMP_TSTAMPREPLY: 638c74ad251Schristos ND_TCHECK_4(dp->icmp_ttime); 6390f74e101Schristos (void)snprintf(buf, sizeof(buf), 6400f74e101Schristos "time stamp reply id %u seq %u: org %s", 641c74ad251Schristos GET_BE_U_2(dp->icmp_id), 642c74ad251Schristos GET_BE_U_2(dp->icmp_seq), 643c74ad251Schristos icmp_tstamp_print(GET_BE_U_4(dp->icmp_otime))); 6440f74e101Schristos 6450f74e101Schristos (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", recv %s", 646c74ad251Schristos icmp_tstamp_print(GET_BE_U_4(dp->icmp_rtime))); 6470f74e101Schristos (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", xmit %s", 648c74ad251Schristos icmp_tstamp_print(GET_BE_U_4(dp->icmp_ttime))); 6490f74e101Schristos break; 6500f74e101Schristos 6510f74e101Schristos default: 652c74ad251Schristos str = tok2str(icmp2str, "type-#%u", icmp_type); 6530f74e101Schristos break; 6540f74e101Schristos } 655c74ad251Schristos ND_PRINT("ICMP %s, length %u", str, plen); 656b3a00663Schristos if (ndo->ndo_vflag && !fragmented) { /* don't attempt checksumming if this is a frag */ 657c74ad251Schristos if (ND_TTEST_LEN(bp, plen)) { 658817e9a7eSchristos uint16_t sum; 659817e9a7eSchristos 660fdccd7e4Schristos vec[0].ptr = (const uint8_t *)(const void *)dp; 6610e9868baSchristos vec[0].len = plen; 6620e9868baSchristos sum = in_cksum(vec, 1); 6630f74e101Schristos if (sum != 0) { 664c74ad251Schristos uint16_t icmp_sum = GET_BE_U_2(dp->icmp_cksum); 665c74ad251Schristos ND_PRINT(" (wrong icmp cksum %x (->%x)!)", 6660f74e101Schristos icmp_sum, 667c74ad251Schristos in_cksum_shouldbe(icmp_sum, sum)); 6680f74e101Schristos } 6690f74e101Schristos } 6700f74e101Schristos } 6710f74e101Schristos 6720f74e101Schristos /* 6730f74e101Schristos * print the remnants of the IP packet. 674c74ad251Schristos * save the snaplength as this may get overridden in the IP printer. 6750f74e101Schristos */ 676c74ad251Schristos if (ndo->ndo_vflag >= 1 && ICMP_ERRTYPE(icmp_type)) { 677c74ad251Schristos const u_char *snapend_save; 678c74ad251Schristos 6790f74e101Schristos bp += 8; 680c74ad251Schristos ND_PRINT("\n\t"); 681fdccd7e4Schristos ip = (const struct ip *)bp; 682b3a00663Schristos snapend_save = ndo->ndo_snapend; 683c74ad251Schristos /* 684c74ad251Schristos * Update the snapend because extensions (MPLS, ...) may be 685c74ad251Schristos * present after the IP packet. In this case the current 686c74ad251Schristos * (outer) packet's snapend is not what ip_print() needs to 687c74ad251Schristos * decode an IP packet nested in the middle of an ICMP payload. 688c74ad251Schristos * 689c74ad251Schristos * This prevents that, in ip_print(), for the nested IP packet, 690c74ad251Schristos * the remaining length < remaining caplen. 691c74ad251Schristos */ 692c74ad251Schristos ndo->ndo_snapend = ND_MIN(bp + GET_BE_U_2(ip->ip_len), 693c74ad251Schristos ndo->ndo_snapend); 694c74ad251Schristos ip_print(ndo, bp, GET_BE_U_2(ip->ip_len)); 695b3a00663Schristos ndo->ndo_snapend = snapend_save; 6960f74e101Schristos } 6970f74e101Schristos 698c74ad251Schristos /* ndo_protocol reassignment after ip_print() call */ 699c74ad251Schristos ndo->ndo_protocol = "icmp"; 700c74ad251Schristos 7010f74e101Schristos /* 702c74ad251Schristos * Attempt to decode multi-part message extensions (rfc4884) only for some ICMP types. 7030f74e101Schristos */ 704c74ad251Schristos if (ndo->ndo_vflag >= 1 && plen > ICMP_EXTD_MINLEN && ICMP_MULTIPART_EXT_TYPE(icmp_type)) { 7050f74e101Schristos 706c74ad251Schristos ND_TCHECK_SIZE(ext_dp); 7070f74e101Schristos 7080f74e101Schristos /* 709c74ad251Schristos * Check first if the multi-part extension header shows a non-zero length. 7100f74e101Schristos * If the length field is not set then silently verify the checksum 7110f74e101Schristos * to check if an extension header is present. This is expedient, 7120f74e101Schristos * however not all implementations set the length field proper. 7130f74e101Schristos */ 714c74ad251Schristos if (GET_U_1(ext_dp->icmp_length) == 0 && 715c74ad251Schristos ND_TTEST_LEN(ext_dp->icmp_ext_version_res, plen - ICMP_EXTD_MINLEN)) { 716fdccd7e4Schristos vec[0].ptr = (const uint8_t *)(const void *)&ext_dp->icmp_ext_version_res; 7170e9868baSchristos vec[0].len = plen - ICMP_EXTD_MINLEN; 7180e9868baSchristos if (in_cksum(vec, 1)) { 7190f74e101Schristos return; 7200f74e101Schristos } 7210e9868baSchristos } 7220f74e101Schristos 723c74ad251Schristos ND_PRINT("\n\tICMP Multi-Part extension v%u", 724c74ad251Schristos ICMP_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res))); 7250f74e101Schristos 7260f74e101Schristos /* 7270f74e101Schristos * Sanity checking of the header. 7280f74e101Schristos */ 729c74ad251Schristos if (ICMP_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)) != 730c74ad251Schristos ICMP_EXT_VERSION) { 731c74ad251Schristos ND_PRINT(" packet not supported"); 7320f74e101Schristos return; 7330f74e101Schristos } 7340f74e101Schristos 7350f74e101Schristos hlen = plen - ICMP_EXTD_MINLEN; 736c74ad251Schristos if (ND_TTEST_LEN(ext_dp->icmp_ext_version_res, hlen)) { 737fdccd7e4Schristos vec[0].ptr = (const uint8_t *)(const void *)&ext_dp->icmp_ext_version_res; 7380e9868baSchristos vec[0].len = hlen; 739c74ad251Schristos ND_PRINT(", checksum 0x%04x (%scorrect), length %u", 740c74ad251Schristos GET_BE_U_2(ext_dp->icmp_ext_checksum), 7410e9868baSchristos in_cksum(vec, 1) ? "in" : "", 742c74ad251Schristos hlen); 74372c96ff3Schristos } 7440f74e101Schristos 7450f74e101Schristos hlen -= 4; /* subtract common header size */ 746fdccd7e4Schristos obj_tptr = (const uint8_t *)ext_dp->icmp_ext_data; 7470f74e101Schristos 748c74ad251Schristos while (hlen > sizeof(struct icmp_multipart_ext_object_header_t)) { 7490f74e101Schristos 750c74ad251Schristos icmp_multipart_ext_object_header = (const struct icmp_multipart_ext_object_header_t *)obj_tptr; 751c74ad251Schristos ND_TCHECK_SIZE(icmp_multipart_ext_object_header); 752c74ad251Schristos obj_tlen = GET_BE_U_2(icmp_multipart_ext_object_header->length); 753c74ad251Schristos obj_class_num = GET_U_1(icmp_multipart_ext_object_header->class_num); 754c74ad251Schristos obj_ctype = GET_U_1(icmp_multipart_ext_object_header->ctype); 755c74ad251Schristos obj_tptr += sizeof(struct icmp_multipart_ext_object_header_t); 7560f74e101Schristos 757c74ad251Schristos ND_PRINT("\n\t %s Object (%u), Class-Type: %u, length %u", 758c74ad251Schristos tok2str(icmp_multipart_ext_obj_values,"unknown",obj_class_num), 7590f74e101Schristos obj_class_num, 7600f74e101Schristos obj_ctype, 761c74ad251Schristos obj_tlen); 7620f74e101Schristos 763c74ad251Schristos hlen-=sizeof(struct icmp_multipart_ext_object_header_t); /* length field includes tlv header */ 7640f74e101Schristos 7650f74e101Schristos /* infinite loop protection */ 7660f74e101Schristos if ((obj_class_num == 0) || 767c74ad251Schristos (obj_tlen < sizeof(struct icmp_multipart_ext_object_header_t))) { 7680f74e101Schristos return; 7690f74e101Schristos } 770c74ad251Schristos obj_tlen-=sizeof(struct icmp_multipart_ext_object_header_t); 7710f74e101Schristos 7720f74e101Schristos switch (obj_class_num) { 773c74ad251Schristos case MPLS_STACK_ENTRY_OBJECT_CLASS: 7740f74e101Schristos switch(obj_ctype) { 7750f74e101Schristos case 1: 776c74ad251Schristos raw_label = GET_BE_U_4(obj_tptr); 777c74ad251Schristos ND_PRINT("\n\t label %u, tc %u", MPLS_LABEL(raw_label), MPLS_TC(raw_label)); 7780f74e101Schristos if (MPLS_STACK(raw_label)) 779c74ad251Schristos ND_PRINT(", [S]"); 780c74ad251Schristos ND_PRINT(", ttl %u", MPLS_TTL(raw_label)); 7810f74e101Schristos break; 7820f74e101Schristos default: 783b3a00663Schristos print_unknown_data(ndo, obj_tptr, "\n\t ", obj_tlen); 7840f74e101Schristos } 7850f74e101Schristos break; 7860f74e101Schristos 7870f74e101Schristos default: 788b3a00663Schristos print_unknown_data(ndo, obj_tptr, "\n\t ", obj_tlen); 7890f74e101Schristos break; 7900f74e101Schristos } 7910f74e101Schristos if (hlen < obj_tlen) 7920f74e101Schristos break; 7930f74e101Schristos hlen -= obj_tlen; 7940f74e101Schristos obj_tptr += obj_tlen; 7950f74e101Schristos } 7960f74e101Schristos } 7970f74e101Schristos 7980f74e101Schristos return; 7990f74e101Schristos trunc: 800c74ad251Schristos nd_print_trunc(ndo); 8010f74e101Schristos } 802