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 * $FreeBSD$ 22 */ 23 24 #ifndef lint 25 static const char rcsid[] = 26 "@(#) $Header: /tcpdump/master/tcpdump/print-icmp.c,v 1.62 2001/07/24 16:56:11 fenner Exp $ (LBL)"; 27 #endif 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <sys/param.h> 34 #include <sys/time.h> 35 #include <sys/socket.h> 36 37 struct mbuf; 38 struct rtentry; 39 40 #include <netinet/in.h> 41 42 #include <stdio.h> 43 #include <string.h> 44 #include <netdb.h> /* for MAXHOSTNAMELEN on some platforms */ 45 46 #include "interface.h" 47 #include "addrtoname.h" 48 #include "extract.h" /* must come after interface.h */ 49 50 #include "ip.h" 51 #include "udp.h" 52 53 /* 54 * Interface Control Message Protocol Definitions. 55 * Per RFC 792, September 1981. 56 */ 57 58 /* 59 * Structure of an icmp header. 60 */ 61 struct icmp { 62 u_int8_t icmp_type; /* type of message, see below */ 63 u_int8_t icmp_code; /* type sub code */ 64 u_int16_t icmp_cksum; /* ones complement cksum of struct */ 65 union { 66 u_int8_t ih_pptr; /* ICMP_PARAMPROB */ 67 struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ 68 struct ih_idseq { 69 u_int16_t icd_id; 70 u_int16_t icd_seq; 71 } ih_idseq; 72 u_int32_t ih_void; 73 74 /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ 75 struct ih_pmtu { 76 u_int16_t ipm_void; 77 u_int16_t ipm_nextmtu; 78 } ih_pmtu; 79 } icmp_hun; 80 #define icmp_pptr icmp_hun.ih_pptr 81 #define icmp_gwaddr icmp_hun.ih_gwaddr 82 #define icmp_id icmp_hun.ih_idseq.icd_id 83 #define icmp_seq icmp_hun.ih_idseq.icd_seq 84 #define icmp_void icmp_hun.ih_void 85 #define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void 86 #define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu 87 union { 88 struct id_ts { 89 u_int32_t its_otime; 90 u_int32_t its_rtime; 91 u_int32_t its_ttime; 92 } id_ts; 93 struct id_ip { 94 struct ip idi_ip; 95 /* options and then 64 bits of data */ 96 } id_ip; 97 u_int32_t id_mask; 98 u_int8_t id_data[1]; 99 } icmp_dun; 100 #define icmp_otime icmp_dun.id_ts.its_otime 101 #define icmp_rtime icmp_dun.id_ts.its_rtime 102 #define icmp_ttime icmp_dun.id_ts.its_ttime 103 #define icmp_ip icmp_dun.id_ip.idi_ip 104 #define icmp_mask icmp_dun.id_mask 105 #define icmp_data icmp_dun.id_data 106 }; 107 108 /* 109 * Lower bounds on packet lengths for various types. 110 * For the error advice packets must first insure that the 111 * packet is large enought to contain the returned ip header. 112 * Only then can we do the check to see if 64 bits of packet 113 * data have been returned, since we need to check the returned 114 * ip header length. 115 */ 116 #define ICMP_MINLEN 8 /* abs minimum */ 117 #define ICMP_TSLEN (8 + 3 * sizeof (u_int32_t)) /* timestamp */ 118 #define ICMP_MASKLEN 12 /* address mask */ 119 #define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ 120 #define ICMP_ADVLEN(p) (8 + (IP_HL(&(p)->icmp_ip) << 2) + 8) 121 /* N.B.: must separately check that ip_hl >= 5 */ 122 123 /* 124 * Definition of type and code field values. 125 */ 126 #define ICMP_ECHOREPLY 0 /* echo reply */ 127 #define ICMP_UNREACH 3 /* dest unreachable, codes: */ 128 #define ICMP_UNREACH_NET 0 /* bad net */ 129 #define ICMP_UNREACH_HOST 1 /* bad host */ 130 #define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ 131 #define ICMP_UNREACH_PORT 3 /* bad port */ 132 #define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ 133 #define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ 134 #define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ 135 #define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ 136 #define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ 137 #define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ 138 #define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ 139 #define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ 140 #define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ 141 #define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ 142 #define ICMP_REDIRECT 5 /* shorter route, codes: */ 143 #define ICMP_REDIRECT_NET 0 /* for network */ 144 #define ICMP_REDIRECT_HOST 1 /* for host */ 145 #define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ 146 #define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ 147 #define ICMP_ECHO 8 /* echo service */ 148 #define ICMP_ROUTERADVERT 9 /* router advertisement */ 149 #define ICMP_ROUTERSOLICIT 10 /* router solicitation */ 150 #define ICMP_TIMXCEED 11 /* time exceeded, code: */ 151 #define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ 152 #define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ 153 #define ICMP_PARAMPROB 12 /* ip header bad */ 154 #define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ 155 #define ICMP_TSTAMP 13 /* timestamp request */ 156 #define ICMP_TSTAMPREPLY 14 /* timestamp reply */ 157 #define ICMP_IREQ 15 /* information request */ 158 #define ICMP_IREQREPLY 16 /* information reply */ 159 #define ICMP_MASKREQ 17 /* address mask request */ 160 #define ICMP_MASKREPLY 18 /* address mask reply */ 161 162 #define ICMP_MAXTYPE 18 163 164 #define ICMP_INFOTYPE(type) \ 165 ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ 166 (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ 167 (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ 168 (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ 169 (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) 170 /* rfc1700 */ 171 #ifndef ICMP_UNREACH_NET_UNKNOWN 172 #define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */ 173 #endif 174 #ifndef ICMP_UNREACH_HOST_UNKNOWN 175 #define ICMP_UNREACH_HOST_UNKNOWN 7 /* destination host unknown */ 176 #endif 177 #ifndef ICMP_UNREACH_ISOLATED 178 #define ICMP_UNREACH_ISOLATED 8 /* source host isolated */ 179 #endif 180 #ifndef ICMP_UNREACH_NET_PROHIB 181 #define ICMP_UNREACH_NET_PROHIB 9 /* admin prohibited net */ 182 #endif 183 #ifndef ICMP_UNREACH_HOST_PROHIB 184 #define ICMP_UNREACH_HOST_PROHIB 10 /* admin prohibited host */ 185 #endif 186 #ifndef ICMP_UNREACH_TOSNET 187 #define ICMP_UNREACH_TOSNET 11 /* tos prohibited net */ 188 #endif 189 #ifndef ICMP_UNREACH_TOSHOST 190 #define ICMP_UNREACH_TOSHOST 12 /* tos prohibited host */ 191 #endif 192 193 /* rfc1716 */ 194 #ifndef ICMP_UNREACH_FILTER_PROHIB 195 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */ 196 #endif 197 #ifndef ICMP_UNREACH_HOST_PRECEDENCE 198 #define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */ 199 #endif 200 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF 201 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ 202 #endif 203 204 /* Most of the icmp types */ 205 static struct tok icmp2str[] = { 206 { ICMP_ECHOREPLY, "echo reply" }, 207 { ICMP_SOURCEQUENCH, "source quench" }, 208 { ICMP_ECHO, "echo request" }, 209 { ICMP_ROUTERSOLICIT, "router solicitation" }, 210 { ICMP_TSTAMP, "time stamp request" }, 211 { ICMP_TSTAMPREPLY, "time stamp reply" }, 212 { ICMP_IREQ, "information request" }, 213 { ICMP_IREQREPLY, "information reply" }, 214 { ICMP_MASKREQ, "address mask request" }, 215 { 0, NULL } 216 }; 217 218 /* Formats for most of the ICMP_UNREACH codes */ 219 static struct tok unreach2str[] = { 220 { ICMP_UNREACH_NET, "net %s unreachable" }, 221 { ICMP_UNREACH_HOST, "host %s unreachable" }, 222 { ICMP_UNREACH_SRCFAIL, 223 "%s unreachable - source route failed" }, 224 { ICMP_UNREACH_NET_UNKNOWN, "net %s unreachable - unknown" }, 225 { ICMP_UNREACH_HOST_UNKNOWN, "host %s unreachable - unknown" }, 226 { ICMP_UNREACH_ISOLATED, 227 "%s unreachable - source host isolated" }, 228 { ICMP_UNREACH_NET_PROHIB, 229 "net %s unreachable - admin prohibited" }, 230 { ICMP_UNREACH_HOST_PROHIB, 231 "host %s unreachable - admin prohibited" }, 232 { ICMP_UNREACH_TOSNET, 233 "net %s unreachable - tos prohibited" }, 234 { ICMP_UNREACH_TOSHOST, 235 "host %s unreachable - tos prohibited" }, 236 { ICMP_UNREACH_FILTER_PROHIB, 237 "host %s unreachable - admin prohibited filter" }, 238 { ICMP_UNREACH_HOST_PRECEDENCE, 239 "host %s unreachable - host precedence violation" }, 240 { ICMP_UNREACH_PRECEDENCE_CUTOFF, 241 "host %s unreachable - precedence cutoff" }, 242 { 0, NULL } 243 }; 244 245 /* Formats for the ICMP_REDIRECT codes */ 246 static struct tok type2str[] = { 247 { ICMP_REDIRECT_NET, "redirect %s to net %s" }, 248 { ICMP_REDIRECT_HOST, "redirect %s to host %s" }, 249 { ICMP_REDIRECT_TOSNET, "redirect-tos %s to net %s" }, 250 { ICMP_REDIRECT_TOSHOST, "redirect-tos %s to host %s" }, 251 { 0, NULL } 252 }; 253 254 /* rfc1191 */ 255 struct mtu_discovery { 256 u_int16_t unused; 257 u_int16_t nexthopmtu; 258 }; 259 260 /* rfc1256 */ 261 struct ih_rdiscovery { 262 u_int8_t ird_addrnum; 263 u_int8_t ird_addrsiz; 264 u_int16_t ird_lifetime; 265 }; 266 267 struct id_rdiscovery { 268 u_int32_t ird_addr; 269 u_int32_t ird_pref; 270 }; 271 272 void 273 icmp_print(const u_char *bp, u_int plen, const u_char *bp2) 274 { 275 char *cp; 276 const struct icmp *dp; 277 const struct ip *ip; 278 const char *str, *fmt; 279 const struct ip *oip; 280 const struct udphdr *ouh; 281 u_int hlen, dport, mtu; 282 char buf[MAXHOSTNAMELEN + 100]; 283 284 dp = (struct icmp *)bp; 285 ip = (struct ip *)bp2; 286 str = buf; 287 288 TCHECK(dp->icmp_code); 289 switch (dp->icmp_type) { 290 291 case ICMP_UNREACH: 292 TCHECK(dp->icmp_ip.ip_dst); 293 switch (dp->icmp_code) { 294 295 case ICMP_UNREACH_PROTOCOL: 296 TCHECK(dp->icmp_ip.ip_p); 297 (void)snprintf(buf, sizeof(buf), 298 "%s protocol %d unreachable", 299 ipaddr_string(&dp->icmp_ip.ip_dst), 300 dp->icmp_ip.ip_p); 301 break; 302 303 case ICMP_UNREACH_PORT: 304 TCHECK(dp->icmp_ip.ip_p); 305 oip = &dp->icmp_ip; 306 hlen = IP_HL(oip) * 4; 307 ouh = (struct udphdr *)(((u_char *)oip) + hlen); 308 dport = ntohs(ouh->uh_dport); 309 switch (oip->ip_p) { 310 311 case IPPROTO_TCP: 312 (void)snprintf(buf, sizeof(buf), 313 "%s tcp port %s unreachable", 314 ipaddr_string(&oip->ip_dst), 315 tcpport_string(dport)); 316 break; 317 318 case IPPROTO_UDP: 319 (void)snprintf(buf, sizeof(buf), 320 "%s udp port %s unreachable", 321 ipaddr_string(&oip->ip_dst), 322 udpport_string(dport)); 323 break; 324 325 default: 326 (void)snprintf(buf, sizeof(buf), 327 "%s protocol %d port %d unreachable", 328 ipaddr_string(&oip->ip_dst), 329 oip->ip_p, dport); 330 break; 331 } 332 break; 333 334 case ICMP_UNREACH_NEEDFRAG: 335 { 336 register const struct mtu_discovery *mp; 337 mp = (struct mtu_discovery *)&dp->icmp_void; 338 mtu = EXTRACT_16BITS(&mp->nexthopmtu); 339 if (mtu) { 340 (void)snprintf(buf, sizeof(buf), 341 "%s unreachable - need to frag (mtu %d)", 342 ipaddr_string(&dp->icmp_ip.ip_dst), mtu); 343 } else { 344 (void)snprintf(buf, sizeof(buf), 345 "%s unreachable - need to frag", 346 ipaddr_string(&dp->icmp_ip.ip_dst)); 347 } 348 } 349 break; 350 351 default: 352 fmt = tok2str(unreach2str, "#%d %%s unreachable", 353 dp->icmp_code); 354 (void)snprintf(buf, sizeof(buf), fmt, 355 ipaddr_string(&dp->icmp_ip.ip_dst)); 356 break; 357 } 358 break; 359 360 case ICMP_REDIRECT: 361 TCHECK(dp->icmp_ip.ip_dst); 362 fmt = tok2str(type2str, "redirect-#%d %%s to net %%s", 363 dp->icmp_code); 364 (void)snprintf(buf, sizeof(buf), fmt, 365 ipaddr_string(&dp->icmp_ip.ip_dst), 366 ipaddr_string(&dp->icmp_gwaddr)); 367 break; 368 369 case ICMP_ROUTERADVERT: 370 { 371 register const struct ih_rdiscovery *ihp; 372 register const struct id_rdiscovery *idp; 373 u_int lifetime, num, size; 374 375 (void)snprintf(buf, sizeof(buf), "router advertisement"); 376 cp = buf + strlen(buf); 377 378 ihp = (struct ih_rdiscovery *)&dp->icmp_void; 379 TCHECK(*ihp); 380 (void)strncpy(cp, " lifetime ", sizeof(buf) - (cp - buf)); 381 cp = buf + strlen(buf); 382 lifetime = EXTRACT_16BITS(&ihp->ird_lifetime); 383 if (lifetime < 60) { 384 (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u", 385 lifetime); 386 } else if (lifetime < 60 * 60) { 387 (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u:%02u", 388 lifetime / 60, lifetime % 60); 389 } else { 390 (void)snprintf(cp, sizeof(buf) - (cp - buf), 391 "%u:%02u:%02u", 392 lifetime / 3600, 393 (lifetime % 3600) / 60, 394 lifetime % 60); 395 } 396 cp = buf + strlen(buf); 397 398 num = ihp->ird_addrnum; 399 (void)snprintf(cp, sizeof(buf) - (cp - buf), " %d:", num); 400 cp = buf + strlen(buf); 401 402 size = ihp->ird_addrsiz; 403 if (size != 2) { 404 (void)snprintf(cp, sizeof(buf) - (cp - buf), 405 " [size %d]", size); 406 break; 407 } 408 idp = (struct id_rdiscovery *)&dp->icmp_data; 409 while (num-- > 0) { 410 TCHECK(*idp); 411 (void)snprintf(cp, sizeof(buf) - (cp - buf), " {%s %u}", 412 ipaddr_string(&idp->ird_addr), 413 EXTRACT_32BITS(&idp->ird_pref)); 414 cp = buf + strlen(buf); 415 ++idp; 416 } 417 } 418 break; 419 420 case ICMP_TIMXCEED: 421 TCHECK(dp->icmp_ip.ip_dst); 422 switch (dp->icmp_code) { 423 424 case ICMP_TIMXCEED_INTRANS: 425 str = "time exceeded in-transit"; 426 break; 427 428 case ICMP_TIMXCEED_REASS: 429 str = "ip reassembly time exceeded"; 430 break; 431 432 default: 433 (void)snprintf(buf, sizeof(buf), "time exceeded-#%d", 434 dp->icmp_code); 435 break; 436 } 437 break; 438 439 case ICMP_PARAMPROB: 440 if (dp->icmp_code) 441 (void)snprintf(buf, sizeof(buf), 442 "parameter problem - code %d", dp->icmp_code); 443 else { 444 TCHECK(dp->icmp_pptr); 445 (void)snprintf(buf, sizeof(buf), 446 "parameter problem - octet %d", dp->icmp_pptr); 447 } 448 break; 449 450 case ICMP_MASKREPLY: 451 TCHECK(dp->icmp_mask); 452 (void)snprintf(buf, sizeof(buf), "address mask is 0x%08x", 453 (unsigned)ntohl(dp->icmp_mask)); 454 break; 455 456 case ICMP_TSTAMP: 457 TCHECK(dp->icmp_seq); 458 (void)snprintf(buf, sizeof(buf), 459 "time stamp query id %u seq %u", 460 (unsigned)ntohs(dp->icmp_id), 461 (unsigned)ntohs(dp->icmp_seq)); 462 break; 463 464 case ICMP_TSTAMPREPLY: 465 TCHECK(dp->icmp_ttime); 466 (void)snprintf(buf, sizeof(buf), 467 "time stamp reply id %u seq %u : org 0x%lx recv 0x%lx xmit 0x%lx", 468 (unsigned)ntohs(dp->icmp_id), 469 (unsigned)ntohs(dp->icmp_seq), 470 (unsigned long)ntohl(dp->icmp_otime), 471 (unsigned long)ntohl(dp->icmp_rtime), 472 (unsigned long)ntohl(dp->icmp_ttime)); 473 break; 474 475 default: 476 str = tok2str(icmp2str, "type-#%d", dp->icmp_type); 477 break; 478 } 479 (void)printf("icmp: %s", str); 480 if (vflag) { 481 if (TTEST2(*bp, plen)) { 482 if (in_cksum((u_short*)dp, plen, 0)) 483 printf(" (wrong icmp csum)"); 484 } 485 } 486 if (vflag > 1 && !ICMP_INFOTYPE(dp->icmp_type)) { 487 bp += 8; 488 (void)printf(" for "); 489 ip = (struct ip *)bp; 490 snaplen = snapend - bp; 491 ip_print(bp, ntohs(ip->ip_len)); 492 } 493 return; 494 trunc: 495 fputs("[|icmp]", stdout); 496 } 497