print-icmp.c 23 KB

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