1 /* packet-icmp.c
2  * Routines for ICMP - Internet Control Message Protocol
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * Monday, June 27, 2005
9  * Support for the ICMP extensions for MPLS
10  * (https://tools.ietf.org/html/draft-ietf-mpls-icmp-02
11  *  which has been replaced by rfcs 4884 and 4950)
12  * by   Maria-Luiza Crivat <luizacri@gmail.com>
13  * &    Brice Augustin <bricecotte@gmail.com>
14  *
15  * SPDX-License-Identifier: GPL-2.0-or-later
16  *
17  * Added support for ICMP extensions RFC 4884 and RFC 5837
18  * (c) 2011 Gaurav Tungatkar <gstungat@ncsu.edu>
19  */
20 
21 #include "config.h"
22 
23 #include <stdlib.h>
24 
25 #include <epan/packet.h>
26 #include <epan/prefs.h>
27 #include <epan/expert.h>
28 #include <epan/in_cksum.h>
29 #include <epan/sequence_analysis.h>
30 #include <epan/to_str.h>
31 #include <epan/conversation.h>
32 #include <epan/tap.h>
33 #include <epan/ipproto.h>
34 #include <epan/capture_dissectors.h>
35 #include <epan/proto_data.h>
36 #include <epan/afn.h>
37 
38 #include <wsutil/pint.h>
39 
40 #include "packet-ip.h"
41 #include "packet-icmp.h"
42 
43 void proto_register_icmp(void);
44 void proto_reg_handoff_icmp(void);
45 
46 static heur_dissector_list_t icmp_heur_subdissector_list;
47 static int icmp_tap = -1;
48 
49 /* Conversation related data */
50 static int hf_icmp_resp_in = -1;
51 static int hf_icmp_resp_to = -1;
52 static int hf_icmp_no_resp = -1;
53 static int hf_icmp_resptime = -1;
54 static int hf_icmp_data_time = -1;
55 static int hf_icmp_data_time_relative = -1;
56 
57 typedef struct _icmp_conv_info_t {
58 	wmem_tree_t *unmatched_pdus;
59 	wmem_tree_t *matched_pdus;
60 } icmp_conv_info_t;
61 
62 static icmp_transaction_t *transaction_start(packet_info * pinfo,
63 					     proto_tree * tree,
64 					     guint32 * key);
65 static icmp_transaction_t *transaction_end(packet_info * pinfo,
66 					   proto_tree * tree,
67 					   guint32 * key);
68 
69 /* Decode the end of the ICMP payload as ICMP MPLS extensions
70 if the packet in the payload has more than 128 bytes */
71 static gboolean favor_icmp_mpls_ext = FALSE;
72 
73 static int proto_icmp = -1;
74 
75 static int hf_icmp_type = -1;
76 static int hf_icmp_code = -1;
77 static int hf_icmp_checksum = -1;
78 static int hf_icmp_checksum_status = -1;
79 static int hf_icmp_unused = -1;
80 static int hf_icmp_reserved = -1;
81 static int hf_icmp_ident = -1;
82 static int hf_icmp_ident_le = -1;
83 static int hf_icmp_seq_num = -1;
84 static int hf_icmp_seq_num_le = -1;
85 static int hf_icmp_mtu = -1;
86 static int hf_icmp_num_addrs = -1;
87 static int hf_icmp_addr_entry_size = -1;
88 static int hf_icmp_lifetime = -1;
89 static int hf_icmp_pointer = -1;
90 static int hf_icmp_router_address = -1;
91 static int hf_icmp_pref_level = -1;
92 static int hf_icmp_redir_gw = -1;
93 static int hf_icmp_originate_timestamp = -1;
94 static int hf_icmp_receive_timestamp = -1;
95 static int hf_icmp_transmit_timestamp = -1;
96 static int hf_icmp_address_mask = -1;
97 static int hf_icmp_length = -1;
98 static int hf_icmp_length_original_datagram = -1;
99 
100 /* Mobile ip */
101 static int hf_icmp_mip_type = -1;
102 static int hf_icmp_mip_length = -1;
103 static int hf_icmp_mip_prefix_length = -1;
104 static int hf_icmp_mip_seq = -1;
105 static int hf_icmp_mip_life = -1;
106 static int hf_icmp_mip_flags = -1;
107 static int hf_icmp_mip_r = -1;
108 static int hf_icmp_mip_b = -1;
109 static int hf_icmp_mip_h = -1;
110 static int hf_icmp_mip_f = -1;
111 static int hf_icmp_mip_m = -1;
112 static int hf_icmp_mip_g = -1;
113 static int hf_icmp_mip_v = -1;
114 static int hf_icmp_mip_rt = -1;
115 static int hf_icmp_mip_u = -1;
116 static int hf_icmp_mip_x = -1;
117 static int hf_icmp_mip_reserved = -1;
118 static int hf_icmp_mip_coa = -1;
119 static int hf_icmp_mip_challenge = -1;
120 static int hf_icmp_mip_content = -1;
121 
122 /* extensions RFC 4884*/
123 static int hf_icmp_ext = -1;
124 static int hf_icmp_ext_version = -1;
125 static int hf_icmp_ext_reserved = -1;
126 static int hf_icmp_ext_checksum = -1;
127 static int hf_icmp_ext_checksum_status = -1;
128 static int hf_icmp_ext_length = -1;
129 static int hf_icmp_ext_class = -1;
130 static int hf_icmp_ext_c_type = -1;
131 static int hf_icmp_ext_data = -1;
132 
133 /* Interface information extension RFC 5837 */
134 static int hf_icmp_int_info_ifindex = -1;
135 static int hf_icmp_int_info_ipaddr = -1;
136 static int hf_icmp_int_info_name = -1;
137 static int hf_icmp_int_info_mtu_present = -1;
138 static int hf_icmp_int_info_mtu = -1;
139 static int hf_icmp_int_info_index = -1;
140 static int hf_icmp_int_info_afi = -1;
141 static int hf_icmp_int_info_ipv4 = -1;
142 static int hf_icmp_int_info_ipv6 = -1;
143 static int hf_icmp_int_info_ipunknown = -1;
144 static int hf_icmp_int_info_name_length = -1;
145 static int hf_icmp_int_info_name_string = -1;
146 static int hf_icmp_int_info_role = -1;
147 static int hf_icmp_int_info_reserved = -1;
148 static gint ett_icmp_interface_info_object = -1;
149 static gint ett_icmp_interface_ipaddr = -1;
150 static gint ett_icmp_interface_name = -1;
151 /* MPLS extension object*/
152 static int hf_icmp_mpls_label = -1;
153 static int hf_icmp_mpls_exp = -1;
154 static int hf_icmp_mpls_s = -1;
155 static int hf_icmp_mpls_ttl = -1;
156 static int hf_icmp_mpls_data = -1;
157 
158 static gint ett_icmp = -1;
159 static gint ett_icmp_mip = -1;
160 static gint ett_icmp_mip_flags = -1;
161 
162 /* extensions */
163 static gint ett_icmp_ext = -1;
164 static gint ett_icmp_ext_object = -1;
165 
166 /* MPLS extensions */
167 static gint ett_icmp_mpls_stack_object = -1;
168 
169 static expert_field ei_icmp_resp_not_found = EI_INIT;
170 static expert_field ei_icmp_checksum = EI_INIT;
171 static expert_field ei_icmp_ext_checksum = EI_INIT;
172 
173 /* Extended Echo - Probe */
174 static int hf_icmp_ext_echo_seq_num = -1;
175 static int hf_icmp_ext_echo_req_reserved = -1;
176 static int hf_icmp_ext_echo_req_local = -1;
177 static int hf_icmp_ext_echo_rsp_state = -1;
178 static int hf_icmp_ext_echo_rsp_reserved = -1;
179 static int hf_icmp_ext_echo_rsp_active = -1;
180 static int hf_icmp_ext_echo_rsp_ipv4 = -1;
181 static int hf_icmp_ext_echo_rsp_ipv6 = -1;
182 static int hf_icmp_int_ident_name_string = -1;
183 static int hf_icmp_int_ident_index = -1;
184 static int hf_icmp_int_ident_afi = -1;
185 static int hf_icmp_int_ident_addr_length = -1;
186 static int hf_icmp_int_ident_reserved = -1;
187 static int hf_icmp_int_ident_ipv4 = -1;
188 static int hf_icmp_int_ident_ipv6 = -1;
189 static int hf_icmp_int_ident_address = -1;
190 
191 static dissector_handle_t icmp_handle;
192 
193 
194 /* ICMP definitions */
195 #define ICMP_ECHOREPLY     0
196 #define ICMP_UNREACH       3
197 #define ICMP_SOURCEQUENCH  4
198 #define ICMP_REDIRECT      5
199 #define ICMP_ALTHOST       6
200 #define ICMP_ECHO          8
201 #define ICMP_RTRADVERT     9
202 #define ICMP_RTRSOLICIT   10
203 #define ICMP_TIMXCEED     11
204 #define ICMP_PARAMPROB    12
205 #define ICMP_TSTAMP       13
206 #define ICMP_TSTAMPREPLY  14
207 #define ICMP_IREQ         15
208 #define ICMP_IREQREPLY    16
209 #define ICMP_MASKREQ      17
210 #define ICMP_MASKREPLY    18
211 #define ICMP_PHOTURIS     40
212 #define ICMP_EXTECHO      42
213 #define ICMP_EXTECHOREPLY 43
214 
215 /* ICMP UNREACHABLE */
216 #define ICMP_NET_UNREACH         0	/* Network Unreachable */
217 #define ICMP_HOST_UNREACH        1	/* Host Unreachable */
218 #define ICMP_PROT_UNREACH        2	/* Protocol Unreachable */
219 #define ICMP_PORT_UNREACH        3	/* Port Unreachable */
220 #define ICMP_FRAG_NEEDED         4	/* Fragmentation Needed/DF set */
221 #define ICMP_SR_FAILED           5	/* Source Route failed */
222 #define ICMP_NET_UNKNOWN         6
223 #define ICMP_HOST_UNKNOWN        7
224 #define ICMP_HOST_ISOLATED       8
225 #define ICMP_NET_ANO             9
226 #define ICMP_HOST_ANO           10
227 #define ICMP_NET_UNR_TOS        11
228 #define ICMP_HOST_UNR_TOS       12
229 #define ICMP_PKT_FILTERED       13	/* Packet filtered */
230 #define ICMP_PREC_VIOLATION     14	/* Precedence violation */
231 #define ICMP_PREC_CUTOFF        15	/* Precedence cut off */
232 
233 #define ICMP_MIP_EXTENSION_PAD	 0
234 #define ICMP_MIP_MOB_AGENT_ADV	16
235 #define ICMP_MIP_PREFIX_LENGTHS	19
236 #define ICMP_MIP_CHALLENGE	24
237 
238 static dissector_handle_t ip_handle;
239 
240 static const value_string icmp_type_str[] = {
241 	{ICMP_ECHOREPLY,    "Echo (ping) reply"},
242 	{1,		    "Reserved"},
243 	{2,		    "Reserved"},
244 	{ICMP_UNREACH,	    "Destination unreachable"},
245 	{ICMP_SOURCEQUENCH, "Source quench (flow control)"},
246 	{ICMP_REDIRECT,	    "Redirect"},
247 	{ICMP_ALTHOST,	    "Alternate host address"},
248 	{ICMP_ECHO,	    "Echo (ping) request"},
249 	{ICMP_RTRADVERT,    "Router advertisement"},
250 	{ICMP_RTRSOLICIT,   "Router solicitation"},
251 	{ICMP_TIMXCEED,	    "Time-to-live exceeded"},
252 	{ICMP_PARAMPROB,    "Parameter problem"},
253 	{ICMP_TSTAMP,	    "Timestamp request"},
254 	{ICMP_TSTAMPREPLY,  "Timestamp reply"},
255 	{ICMP_IREQ,	    "Information request"},
256 	{ICMP_IREQREPLY,    "Information reply"},
257 	{ICMP_MASKREQ,	    "Address mask request"},
258 	{ICMP_MASKREPLY,    "Address mask reply"},
259 	{19,		    "Reserved (for security)"},
260 	{30,		    "Traceroute"},
261 	{31,		    "Datagram Conversion Error"},
262 	{32,		    "Mobile Host Redirect"},
263 	{33,		    "IPv6 Where-Are-You"},
264 	{34,		    "IPv6 I-Am-Here"},
265 	{35,		    "Mobile Registration Request"},
266 	{36,		    "Mobile Registration Reply"},
267 	{37,		    "Domain Name Request"},
268 	{38,		    "Domain Name Reply"},
269 	{39,		    "SKIP"},
270 	{ICMP_PHOTURIS,	    "Photuris"},
271 	{41,		    "Experimental mobility protocols"},
272 	{ICMP_EXTECHO,	    "Extended Echo request"},
273 	{ICMP_EXTECHOREPLY, "Extended Echo reply"},
274 	{0, NULL}
275 };
276 
277 static const value_string unreach_code_str[] = {
278 	{ICMP_NET_UNREACH,    "Network unreachable"},
279 	{ICMP_HOST_UNREACH,   "Host unreachable"},
280 	{ICMP_PROT_UNREACH,   "Protocol unreachable"},
281 	{ICMP_PORT_UNREACH,   "Port unreachable"},
282 	{ICMP_FRAG_NEEDED,    "Fragmentation needed"},
283 	{ICMP_SR_FAILED,      "Source route failed"},
284 	{ICMP_NET_UNKNOWN,    "Destination network unknown"},
285 	{ICMP_HOST_UNKNOWN,   "Destination host unknown"},
286 	{ICMP_HOST_ISOLATED,  "Source host isolated"},
287 	{ICMP_NET_ANO,	      "Network administratively prohibited"},
288 	{ICMP_HOST_ANO,	      "Host administratively prohibited"},
289 	{ICMP_NET_UNR_TOS,    "Network unreachable for TOS"},
290 	{ICMP_HOST_UNR_TOS,   "Host unreachable for TOS"},
291 	{ICMP_PKT_FILTERED,   "Communication administratively filtered"},
292 	{ICMP_PREC_VIOLATION, "Host precedence violation"},
293 	{ICMP_PREC_CUTOFF,    "Precedence cutoff in effect"},
294 	{0, NULL}
295 };
296 
297 static const value_string redir_code_str[] = {
298 	{0, "Redirect for network"},
299 	{1, "Redirect for host"},
300 	{2, "Redirect for TOS and network"},
301 	{3, "Redirect for TOS and host"},
302 	{0, NULL}
303 };
304 
305 static const value_string alt_host_code_str[] = {
306 	{0, "Alternate address for host"},
307 	{0, NULL}
308 };
309 
310 static const value_string rtradvert_code_str[] = {
311 	{ 0, "Normal router advertisement"},
312 	{16, "Does not route common traffic"},
313 	{0, NULL}
314 };
315 
316 static const value_string ttl_code_str[] = {
317 	{0, "Time to live exceeded in transit"},
318 	{1, "Fragment reassembly time exceeded"},
319 	{0, NULL}
320 };
321 
322 static const value_string par_code_str[] = {
323 	{0, "Pointer indicates the error"},
324 	{1, "Required option missing"},
325 	{2, "Bad length"},
326 	{0, NULL}
327 };
328 
329 static const value_string photuris_code_str[] = {
330 	{0, "Bad SPI"},
331 	{1, "Authentication Failed"},
332 	{2, "Decompression Failed"},
333 	{3, "Decryption Failed"},
334 	{4, "Need Authentication"},
335 	{5, "Need Authorization"},
336 	{0, NULL}
337 };
338 
339 static const value_string ext_echo_req_code_str[] = {
340 	{0, "No error"},
341 	{0, NULL}
342 };
343 
344 static const value_string ext_echo_reply_code_str[] = {
345 	{0, "No error"},
346 	{1, "Malformed Query"},
347 	{2, "No Such Interface"},
348 	{3, "No Such Table Entry"},
349 	{4, "Multiple Interfaces Satisfy Query"},
350 	{0, NULL}
351 };
352 
353 static const value_string ext_echo_reply_state_str[] = {
354 	{0, "Reserved"},
355 	{1, "Incomplete"},
356 	{2, "Reachable"},
357 	{3, "Stale"},
358 	{4, "Delay"},
359 	{5, "Probe"},
360 	{6, "Failed"},
361 	{0, NULL}
362 };
363 
364 #define ICMP_EXT_ECHO_IDENT_NAME	1
365 #define ICMP_EXT_ECHO_IDENT_INDEX	2
366 #define ICMP_EXT_ECHO_IDENT_ADDRESS	3
367 
368 static const value_string ext_echo_ident_str[] = {
369 	{ICMP_EXT_ECHO_IDENT_NAME,    "Identifies Interface By Name"},
370 	{ICMP_EXT_ECHO_IDENT_INDEX,   "Identifies Interface By Index"},
371 	{ICMP_EXT_ECHO_IDENT_ADDRESS, "Identifies Interface By Address"},
372 	{0, NULL}
373 };
374 
375 static const value_string mip_extensions[] = {
376 	{ICMP_MIP_EXTENSION_PAD,  "One byte padding extension"}, /* RFC 2002 */
377 	{ICMP_MIP_MOB_AGENT_ADV,  "Mobility Agent Advertisement Extension"},
378 	/* RFC 2002 */
379 	{ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"},	 /* RFC 2002 */
380 	{ICMP_MIP_CHALLENGE,	  "Challenge Extension"},	 /* RFC 3012 */
381 	{0, NULL}
382 };
383 
384 static const value_string icmp_ext_class_str[] = {
385 	{1, "MPLS Label Stack Class"},
386 	{2, "Interface Information Object"},
387 	{3, "Interface Identification Object"},
388 	{0, NULL}
389 };
390 
391 /* RFC 5837 ICMP extension - Interface Information Object
392  * Interface Role
393  */
394 static const value_string interface_role_str[] = {
395 	{0, "IP interface upon which datagram arrived"},
396 	{1, "sub-IP component of an IP interface upon which datagram arrived"},
397 	{2, "IP interface through which datagram would be forwarded"},
398 	{3, "IP next-hop to which datagram would be forwarded"},
399 	{0, NULL}
400 };
401 
402 #define INT_INFO_INTERFACE_ROLE                 0xc0
403 #define INT_INFO_RESERVED                       0x30
404 #define INT_INFO_IFINDEX                        0x08
405 #define INT_INFO_IPADDR                         0x04
406 #define INT_INFO_NAME                           0x02
407 #define INT_INFO_MTU                            0x01
408 
409 #define INTERFACE_INFORMATION_OBJECT_CLASS       2
410 
411 #define INTERFACE_IDENTIFICATION_OBJECT_CLASS    3
412 
413 #define MPLS_STACK_ENTRY_OBJECT_CLASS            1
414 #define MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS       0
415 
416 #define MPLS_STACK_ENTRY_C_TYPE                  1
417 #define MPLS_EXTENDED_PAYLOAD_C_TYPE             1
418 
419 /* Return true if the address is in the 224.0.0.0/4 network block */
420 #define is_a_multicast_addr(a)	in4_addr_is_multicast(a)
421 
422 /* Return true if the address is the 255.255.255.255 broadcast address */
423 #define is_a_broadcast_addr(a)	((a) == 0xffffffffU)
424 
425 /*
426  * We check the address type in case some bogus IPv6 packet specifies ICMP
427  * rather than ICMP6 in the next header field.
428  */
429 #define ADDR_IS_MULTICAST(addr) \
430 	(((addr)->type == AT_IPv4) && is_a_multicast_addr(pntoh32((addr)->data)))
431 
432 #define ADDR_IS_BROADCAST(addr) \
433 	(((addr)->type == AT_IPv4) && is_a_broadcast_addr(pntoh32((addr)->data)))
434 
435 #define ADDR_IS_NOT_UNICAST(addr) \
436 	(ADDR_IS_MULTICAST(addr) || ADDR_IS_BROADCAST(addr))
437 
438 
439 /* whenever a ICMP packet is seen by the tap listener */
440 /* Add a new frame into the graph */
441 static tap_packet_status
442 icmp_seq_analysis_packet( void *ptr, packet_info *pinfo, epan_dissect_t *edt _U_, const void *dummy _U_)
443 {
444 	seq_analysis_info_t *sainfo = (seq_analysis_info_t *) ptr;
445 	seq_analysis_item_t *sai = sequence_analysis_create_sai_with_addresses(pinfo, sainfo);
446 
447 	if (!sai)
448 		return TAP_PACKET_DONT_REDRAW;
449 
450 	sai->frame_number = pinfo->num;
451 
452 	sequence_analysis_use_color_filter(pinfo, sai);
453 
454 	sai->port_src=pinfo->srcport;
455 	sai->port_dst=pinfo->destport;
456 
457 	sequence_analysis_use_col_info_as_label_comment(pinfo, sai);
458 
459 	if (pinfo->ptype == PT_NONE) {
460 		icmp_info_t *p_icmp_info = (icmp_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_icmp, 0);
461 
462 		if (p_icmp_info != NULL) {
463 			sai->port_src = 0;
464 			sai->port_dst = p_icmp_info->type * 256 + p_icmp_info->code;
465 		}
466 	}
467 
468 	sai->line_style = 1;
469 	sai->conv_num = 0;
470 	sai->display = TRUE;
471 
472 	g_queue_push_tail(sainfo->items, sai);
473 
474 	return TAP_PACKET_REDRAW;
475 }
476 
477 static conversation_t *_find_or_create_conversation(packet_info * pinfo)
478 {
479 	conversation_t *conv = NULL;
480 
481 	/* Have we seen this conversation before? */
482 	conv =
483 	    find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
484 			      0, 0, 0);
485 	if (conv == NULL) {
486 		/* No, this is a new conversation. */
487 		conv =
488 		    conversation_new(pinfo->num, &pinfo->src,
489 				     &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype), 0, 0, 0);
490 	}
491 	return conv;
492 }
493 
494 /*
495  * Dissect the mobile ip advertisement extensions.
496  */
497 static void
498 dissect_mip_extensions(tvbuff_t * tvb, int offset, proto_tree * tree)
499 {
500 	guint8 type;
501 	guint8 length;
502 	proto_item *ti;
503 	proto_tree *mip_tree = NULL;
504 	gint numCOAs;
505 	gint i;
506 	static int * const flags[] = {
507 		&hf_icmp_mip_r,
508 		&hf_icmp_mip_b,
509 		&hf_icmp_mip_h,
510 		&hf_icmp_mip_f,
511 		&hf_icmp_mip_m,
512 		&hf_icmp_mip_g,
513 		&hf_icmp_mip_v,
514 		&hf_icmp_mip_rt,
515 		&hf_icmp_mip_u,
516 		&hf_icmp_mip_x,
517 		&hf_icmp_mip_reserved,
518 		NULL
519 	};
520 
521 	/* Not much to do if we're not parsing everything */
522 	if (!tree)
523 		return;
524 
525 	while (tvb_reported_length_remaining(tvb, offset) > 0) {
526 		type = tvb_get_guint8(tvb, offset + 0);
527 		if (type) {
528 			length = tvb_get_guint8(tvb, offset + 1);
529 		} else {
530 			length = 0;
531 		}
532 
533 		mip_tree = proto_tree_add_subtree_format(tree, tvb, offset,
534 								1, ett_icmp_mip, &ti,
535 								"Ext: %s", val_to_str(type,
536 								mip_extensions,
537 								"Unknown ext %u"));
538 		proto_tree_add_item(mip_tree, hf_icmp_mip_type,
539 					tvb, offset, 1,
540 					ENC_BIG_ENDIAN);
541 		offset++;
542 		if (type != ICMP_MIP_EXTENSION_PAD)
543 		{
544 			proto_item_set_len(ti, length + 2);
545 
546 			/* length */
547 			proto_tree_add_item(mip_tree, hf_icmp_mip_length,
548 						tvb, offset, 1,
549 						ENC_BIG_ENDIAN);
550 			offset++;
551 		}
552 
553 		switch (type) {
554 		case ICMP_MIP_EXTENSION_PAD:
555 			/* One byte padding extension */
556 			break;
557 		case ICMP_MIP_MOB_AGENT_ADV:
558 			/* Mobility Agent Advertisement Extension (RFC 2002) */
559 			/* Add our fields */
560 			/* sequence number */
561 			proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb,
562 					    offset, 2, ENC_BIG_ENDIAN);
563 			offset += 2;
564 			/* Registration Lifetime */
565 			proto_tree_add_item(mip_tree, hf_icmp_mip_life,
566 					    tvb, offset, 2,
567 					    ENC_BIG_ENDIAN);
568 			offset += 2;
569 			/* flags */
570 			proto_tree_add_bitmask(mip_tree, tvb, offset, hf_icmp_mip_flags, ett_icmp_mip_flags, flags, ENC_BIG_ENDIAN);
571 			offset += 2;
572 
573 			/* COAs */
574 			numCOAs = (length - 6) / 4;
575 			for (i = 0; i < numCOAs; i++) {
576 				proto_tree_add_item(mip_tree,
577 						    hf_icmp_mip_coa, tvb,
578 						    offset, 4,
579 						    ENC_BIG_ENDIAN);
580 				offset += 4;
581 			}
582 			break;
583 		case ICMP_MIP_PREFIX_LENGTHS:
584 			/* Prefix-Lengths Extension  (RFC 2002) */
585 			/* Add our fields */
586 
587 			/* prefix lengths */
588 			for (i = 0; i < length; i++) {
589 				proto_tree_add_item(mip_tree,
590 						    hf_icmp_mip_prefix_length,
591 						    tvb, offset, 1,
592 						    ENC_BIG_ENDIAN);
593 				offset++;
594 			}
595 			break;
596 		case ICMP_MIP_CHALLENGE:
597 			/* Challenge Extension  (RFC 3012) */
598 			/* challenge */
599 			proto_tree_add_item(mip_tree,
600 					    hf_icmp_mip_challenge, tvb,
601 					    offset, length, ENC_NA);
602 			offset += length;
603 
604 			break;
605 		default:
606 			/* data, if any */
607 			if (length != 0) {
608 				proto_tree_add_item(mip_tree, hf_icmp_mip_content, tvb, offset, length - 4, ENC_NA);
609 				offset += length;
610 			}
611 
612 			break;
613 		}
614 	}
615 
616 }				/* dissect_mip_extensions */
617 
618 static gboolean
619 dissect_mpls_extended_payload_object(tvbuff_t * tvb, gint offset,
620 				     proto_tree * ext_object_tree,
621 				     proto_item * tf_object)
622 {
623 
624 	guint16 obj_length, obj_trunc_length;
625 	gboolean unknown_object;
626 	guint8 c_type;
627 	unknown_object = FALSE;
628 	/* Object length */
629 	obj_length = tvb_get_ntohs(tvb, offset);
630 
631 	obj_trunc_length =
632 	    MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
633 
634 	/* C-Type */
635 	c_type = tvb_get_guint8(tvb, offset + 3);
636 	proto_tree_add_uint(ext_object_tree, hf_icmp_ext_c_type, tvb,
637 			    offset + 3, 1, c_type);
638 
639 	/* skip the object header */
640 	offset += 4;
641 
642 	switch (c_type) {
643 	case MPLS_EXTENDED_PAYLOAD_C_TYPE:
644 		proto_item_set_text(tf_object, "Extended Payload");
645 
646 		/* This object contains some portion of the original packet
647 		   that could not fit in the 128 bytes of the ICMP payload */
648 		if (obj_trunc_length > 4) {
649 			proto_tree_add_item(ext_object_tree, hf_icmp_ext_data, tvb, offset, obj_trunc_length - 4, ENC_NA);
650 		}
651 		break;
652 	default:
653 		unknown_object = TRUE;
654 	}			/* end switch c_type */
655 	return unknown_object;
656 }
657 
658 static gboolean
659 dissect_mpls_stack_entry_object(tvbuff_t * tvb, gint offset,
660 				proto_tree * ext_object_tree,
661 				proto_item * tf_object)
662 {
663 
664 	proto_item *tf_entry;
665 	proto_tree *mpls_stack_object_tree;
666 	guint16 obj_length, obj_trunc_length;
667 	gint obj_end_offset;
668 	guint label;
669 	guint8 ttl;
670 	guint8 tmp;
671 	gboolean unknown_object;
672 	guint8 c_type;
673 	unknown_object = FALSE;
674 	/* Object length */
675 	obj_length = tvb_get_ntohs(tvb, offset);
676 
677 	obj_trunc_length =
678 	    MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
679 	obj_end_offset = offset + obj_trunc_length;
680 	/* C-Type */
681 	c_type = tvb_get_guint8(tvb, offset + 3);
682 	proto_tree_add_uint(ext_object_tree, hf_icmp_ext_c_type, tvb,
683 			    offset + 3, 1, c_type);
684 
685 	/* skip the object header */
686 	offset += 4;
687 
688 	switch (c_type) {
689 	case MPLS_STACK_ENTRY_C_TYPE:
690 		proto_item_set_text(tf_object, "MPLS Stack Entry");
691 		/* For each entry */
692 		while (offset + 4 <= obj_end_offset) {
693 			if (tvb_reported_length_remaining(tvb, offset) < 4) {
694 				/* Not enough room in the packet ! */
695 				break;
696 			}
697 			/* Create a subtree for each entry (the text will be set later) */
698 			mpls_stack_object_tree = proto_tree_add_subtree(ext_object_tree,
699 								tvb, offset, 4,
700 								ett_icmp_mpls_stack_object, &tf_entry, " ");
701 
702 			/* Label */
703 			label = (guint) tvb_get_ntohs(tvb, offset);
704 			tmp = tvb_get_guint8(tvb, offset + 2);
705 			label = (label << 4) + (tmp >> 4);
706 
707 			proto_tree_add_uint(mpls_stack_object_tree,
708 					    hf_icmp_mpls_label, tvb,
709 					    offset, 3, label << 4);
710 
711 			proto_item_set_text(tf_entry, "Label: %u", label);
712 
713 			/* Experimental field (also called "CoS") */
714 			proto_tree_add_uint(mpls_stack_object_tree,
715 					    hf_icmp_mpls_exp, tvb,
716 					    offset + 2, 1, tmp);
717 
718 			proto_item_append_text(tf_entry, ", Exp: %u",
719 					       (tmp >> 1) & 0x07);
720 
721 			/* Stack bit */
722 			proto_tree_add_boolean(mpls_stack_object_tree,
723 					       hf_icmp_mpls_s, tvb,
724 					       offset + 2, 1, tmp);
725 
726 			proto_item_append_text(tf_entry, ", S: %u",
727 					       tmp & 0x01);
728 
729 			/* TTL */
730 			ttl = tvb_get_guint8(tvb, offset + 3);
731 
732 			proto_tree_add_item(mpls_stack_object_tree,
733 					    hf_icmp_mpls_ttl, tvb,
734 					    offset + 3, 1, ENC_BIG_ENDIAN);
735 
736 			proto_item_append_text(tf_entry, ", TTL: %u", ttl);
737 
738 			/* Skip the entry */
739 			offset += 4;
740 		}
741 
742 		if (offset < obj_end_offset) {
743 			proto_tree_add_item(ext_object_tree, hf_icmp_mpls_data, tvb, offset, obj_end_offset - offset, ENC_NA);
744 		}
745 		break;
746 
747 	default:
748 
749 		unknown_object = TRUE;
750 
751 		break;
752 	}			/* end switch c_type */
753 	return unknown_object;
754 
755 }				/* end dissect_mpls_stack_entry_object */
756 
757 /* Dissect Interface Information Object RFC 5837*/
758 static gboolean
759 dissect_interface_information_object(tvbuff_t * tvb, gint offset,
760 				     proto_tree * ext_object_tree,
761 				     proto_item * tf_object)
762 {
763 	proto_tree *int_name_object_tree = NULL;
764 	proto_tree *int_ipaddr_object_tree;
765 	guint16 obj_length, obj_trunc_length;
766 	gint obj_end_offset;
767 	guint8 c_type;
768 	gboolean unknown_object;
769 	guint8 if_index_flag;
770 	guint8 ipaddr_flag;
771 	guint8 name_flag;
772 	guint8 mtu_flag;
773 	guint16 afi;
774 	guint8 int_name_length = 0;
775 
776 	unknown_object = FALSE;
777 	/* Object length */
778 	obj_length = tvb_get_ntohs(tvb, offset);
779 
780 	obj_trunc_length =
781 	    MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
782 	obj_end_offset = offset + obj_trunc_length;
783 
784 	/* C-Type */
785 	c_type = tvb_get_guint8(tvb, offset + 3);
786 
787 	proto_item_set_text(tf_object, "Interface Information Object");
788 	if (tvb_reported_length_remaining(tvb, offset) < 4) {
789 		/* Not enough room in the packet ! return unknown_object = TRUE */
790 		return TRUE;
791 	}
792 
793 	if_index_flag = (c_type & INT_INFO_IFINDEX) >> 3;
794 	ipaddr_flag = (c_type & INT_INFO_IPADDR) >> 2;
795 	name_flag = (c_type & INT_INFO_NAME) >> 1;
796 	mtu_flag = (c_type & INT_INFO_MTU) >> 0;
797 
798 	{
799 		static int * const c_type_fields[] = {
800 			&hf_icmp_int_info_role,
801 			&hf_icmp_int_info_reserved,
802 			&hf_icmp_int_info_ifindex,
803 			&hf_icmp_int_info_ipaddr,
804 			&hf_icmp_int_info_name,
805 			&hf_icmp_int_info_mtu_present,
806 			NULL
807 		};
808 		proto_tree_add_bitmask(ext_object_tree, tvb, offset + 3,
809 				       hf_icmp_ext_c_type,
810 				       ett_icmp_interface_info_object,
811 				       c_type_fields, ENC_BIG_ENDIAN);
812 	}
813 
814 	/* skip header */
815 	offset += 4;
816 
817 	/*if ifIndex is set, next 32 bits are ifIndex */
818 	if (if_index_flag) {
819 		proto_tree_add_item(ext_object_tree, hf_icmp_int_info_index, tvb, offset, 4, ENC_NA);
820 		offset += 4;
821 	}
822 
823 	/* IP Address Sub Object */
824 	if (ipaddr_flag && (obj_end_offset >= offset + 2)) {
825 		/* Address Family Identifier */
826 		afi = tvb_get_ntohs(tvb, offset);
827 
828 		/*
829 		 * if afi = 1, IPv4 address, 2 bytes afi, 2 bytes rsvd, 4 bytes IP addr
830 		 * if afi = 2, IPv6 address, 2 bytes afi, 2 bytes rsvd, 16 bytes IP addr
831 		 */
832 		int_ipaddr_object_tree = proto_tree_add_subtree(ext_object_tree, tvb, offset,
833 					 afi == 1 ? 8 : 20, ett_icmp_interface_ipaddr, NULL,
834 					 "IP Address Sub-Object");
835 
836 		proto_tree_add_uint(int_ipaddr_object_tree,
837 				    hf_icmp_int_info_afi, tvb, offset, 2,
838 				    afi);
839 		offset += 2;
840 
841 		proto_tree_add_item(int_ipaddr_object_tree, hf_icmp_reserved, tvb, offset, 2, ENC_NA);
842 		offset += 2;
843 
844 		switch(afi){
845 			case 1: /* IPv4 */
846 			proto_tree_add_item(int_ipaddr_object_tree, hf_icmp_int_info_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
847 			offset += 4;
848 			break;
849 			case 2: /* IPv6 */
850 			proto_tree_add_item(int_ipaddr_object_tree, hf_icmp_int_info_ipv6, tvb, offset, 16, ENC_NA);
851 			offset += 16;
852 			break;
853 			default: /* Unknown ?! */
854 			proto_tree_add_item(int_ipaddr_object_tree, hf_icmp_int_info_ipunknown, tvb, offset, offset - obj_end_offset, ENC_NA);
855 			return FALSE;
856 		}
857 
858 	}
859 
860 	/* Interface Name Sub Object */
861 	if (name_flag) {
862 		if (obj_end_offset >= offset + 1) {
863 			int_name_length = tvb_get_guint8(tvb, offset);
864 			int_name_object_tree = proto_tree_add_subtree(ext_object_tree, tvb,
865 						 offset, int_name_length, ett_icmp_interface_name, NULL,
866 						 "Interface Name Sub-Object");
867 
868 			proto_tree_add_item(int_name_object_tree, hf_icmp_int_info_name_length, tvb, offset, 1, ENC_BIG_ENDIAN);
869 			offset += 1;
870 		}
871 		if (obj_end_offset >= offset + int_name_length) {
872 			proto_tree_add_item(int_name_object_tree, hf_icmp_int_info_name_string, tvb, offset, int_name_length - 1, ENC_ASCII|ENC_NA);
873 			offset += int_name_length - 1;
874 		}
875 	}
876 	/* MTU Sub Object */
877 	if (mtu_flag) {
878 		proto_tree_add_item(ext_object_tree, hf_icmp_int_info_mtu, tvb, offset, 4, ENC_NA);
879 	}
880 
881 
882 	return unknown_object;
883 
884 }				/*end dissect_interface_information_object */
885 
886 /* Dissect Interface Identification Object RFC 8335*/
887 static gboolean
888 dissect_interface_identification_object(tvbuff_t * tvb, gint offset,
889 				     proto_tree * ext_object_tree,
890 				     proto_item * tf_object)
891 {
892 	proto_item *ti;
893 	guint16 obj_length;
894 	guint8 c_type;
895 	gboolean unknown_object;
896 	guint32 afi;
897 	guint32 addr_length;
898 
899 	unknown_object = FALSE;
900 	/* Object length */
901 	obj_length = tvb_get_ntohs(tvb, offset);
902 
903 	/* C-Type */
904 	c_type = tvb_get_guint8(tvb, offset + 3);
905 
906 	proto_item_set_text(tf_object, "Interface Identification Object");
907 	if (tvb_reported_length_remaining(tvb, offset) < 5) {
908 		/* Not enough room in the packet ! return unknown_object = TRUE */
909 		return TRUE;
910 	}
911 
912 	ti = proto_tree_add_uint(ext_object_tree, hf_icmp_ext_c_type, tvb, offset + 3, 1, c_type);
913 	proto_item_append_text(ti, " (%s)", val_to_str(c_type, ext_echo_ident_str, "Unknown C-Type %u"));
914 	offset += 4;
915 
916 	switch(c_type) {
917 		case ICMP_EXT_ECHO_IDENT_NAME:
918 			proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_name_string, tvb, offset, obj_length - 4, ENC_ASCII|ENC_NA);
919 			break;
920 		case ICMP_EXT_ECHO_IDENT_INDEX:
921 			proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_index, tvb, offset, 4, ENC_NA);
922 			break;
923 		case ICMP_EXT_ECHO_IDENT_ADDRESS:
924 			proto_tree_add_item_ret_uint(ext_object_tree, hf_icmp_int_ident_afi, tvb, offset, 2, ENC_BIG_ENDIAN, &afi);
925 			offset += 2;
926 			proto_tree_add_item_ret_uint(ext_object_tree, hf_icmp_int_ident_addr_length, tvb, offset, 1, ENC_BIG_ENDIAN, &addr_length);
927 			offset += 1;
928 			proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_reserved, tvb, offset, 1, ENC_NA);
929 			offset += 1;
930 			switch(afi){
931 				case AFNUM_INET: /* IPv4 */
932 					while(addr_length >= 4 && tvb_reported_length_remaining(tvb, offset) >= 4) {
933 						proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
934 						offset += 4;
935 						addr_length -= 4;
936 					}
937 					break;
938 				case AFNUM_INET6: /* IPv6 */
939 					while(addr_length >= 16 && tvb_reported_length_remaining(tvb, offset) >= 16) {
940 						proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_ipv6, tvb, offset, 16, ENC_NA);
941 						offset += 16;
942 						addr_length -= 16;
943 					}
944 					break;
945 				default: /* Unknown ?! */
946 					proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_address, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
947 			}
948 	}
949 
950 	return unknown_object;
951 
952 }				/*end dissect_interface_identification_object */
953 
954 static int
955 dissect_icmp_extension(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_)
956 {
957 	int offset = 0;
958 	guint8 version;
959 	guint8 class_num;
960 	guint8 c_type;
961 	guint16 obj_length, obj_trunc_length, checksum;
962 	proto_item *ti, *tf_object;
963 	proto_tree *ext_tree, *ext_object_tree;
964 	gint obj_end_offset;
965 	guint reported_length;
966 	gboolean unknown_object;
967 	guint8 int_info_obj_count;
968 
969 	int_info_obj_count = 0;
970 
971 	reported_length = tvb_reported_length_remaining(tvb, offset);
972 
973 	/* Add a tree for multi-part extensions RFC 4884 */
974 	ti = proto_tree_add_none_format(tree, hf_icmp_ext, tvb,
975 					offset, reported_length,
976 					"ICMP Multi-Part Extensions");
977 
978 	if (reported_length < 4 /* Common header */ ) {
979 		return offset;
980 	}
981 
982 	ext_tree = proto_item_add_subtree(ti, ett_icmp_ext);
983 
984 	/* Version */
985 	version = hi_nibble(tvb_get_guint8(tvb, offset));
986 	proto_tree_add_uint(ext_tree, hf_icmp_ext_version, tvb, offset, 1,
987 			    version);
988 
989 	/* Reserved */
990 	proto_tree_add_item(ext_tree, hf_icmp_ext_reserved,
991 				   tvb, offset, 2, ENC_BIG_ENDIAN);
992 
993 	/* Checksum */
994 	checksum = tvb_get_ntohs(tvb, offset + 2);
995 	if (checksum == 0) {
996 		proto_tree_add_checksum(ext_tree, tvb, offset + 2, hf_icmp_ext_checksum, hf_icmp_ext_checksum_status, &ei_icmp_ext_checksum,
997 							pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NOT_PRESENT);
998 
999 	} else {
1000 		proto_tree_add_checksum(ext_tree, tvb, offset + 2, hf_icmp_ext_checksum, hf_icmp_ext_checksum_status, &ei_icmp_ext_checksum,
1001 							pinfo, ip_checksum_tvb(tvb, offset, reported_length), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
1002 	}
1003 
1004 	if (version != 1 && version != 2) {
1005 		/* Unsupported version */
1006 		proto_item_append_text(ti, " (unsupported version)");
1007 		return offset;
1008 	}
1009 
1010 	/* Skip the common header */
1011 	offset += 4;
1012 
1013 	/* While there is enough room to read an object */
1014 	while (tvb_reported_length_remaining(tvb, offset) >=
1015 	       4 /* Object header */ ) {
1016 		/* Object length */
1017 		obj_length = tvb_get_ntohs(tvb, offset);
1018 
1019 		obj_trunc_length =
1020 		    MIN(obj_length,
1021 			tvb_reported_length_remaining(tvb, offset));
1022 
1023 		obj_end_offset = offset + obj_trunc_length;
1024 
1025 		/* Add a subtree for this object (the text will be reset later) */
1026 		ext_object_tree = proto_tree_add_subtree(ext_tree, tvb, offset,
1027 						MAX(obj_trunc_length, 4),
1028 						ett_icmp_ext_object, &tf_object, "Unknown object");
1029 
1030 		proto_tree_add_uint(ext_object_tree, hf_icmp_ext_length,
1031 				    tvb, offset, 2, obj_length);
1032 
1033 		/* Class */
1034 		class_num = tvb_get_guint8(tvb, offset + 2);
1035 		proto_tree_add_item(ext_object_tree, hf_icmp_ext_class,
1036 				    tvb, offset + 2, 1, ENC_BIG_ENDIAN);
1037 
1038 		/* C-Type */
1039 		c_type = tvb_get_guint8(tvb, offset + 3);
1040 
1041 		if (obj_length < 4 /* Object header */ ) {
1042 			/* Thanks doc/README.developer :)) */
1043 			proto_item_set_text(tf_object,
1044 					    "Object with bad length");
1045 			break;
1046 		}
1047 
1048 
1049 		switch (class_num) {
1050 		case MPLS_STACK_ENTRY_OBJECT_CLASS:
1051 			unknown_object =
1052 			    dissect_mpls_stack_entry_object(tvb, offset,
1053 							    ext_object_tree,
1054 							    tf_object);
1055 			break;
1056 		case INTERFACE_INFORMATION_OBJECT_CLASS:
1057 			unknown_object =
1058 			    dissect_interface_information_object(tvb,
1059 								 offset,
1060 								 ext_object_tree,
1061 								 tf_object);
1062 			int_info_obj_count++;
1063 			if (int_info_obj_count > 4) {
1064 				proto_item_set_text(tf_object,
1065 						    "More than 4 Interface Information Objects");
1066 			}
1067 			break;
1068 		case MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS:
1069 			unknown_object =
1070 			    dissect_mpls_extended_payload_object(tvb,
1071 								 offset,
1072 								 ext_object_tree,
1073 								 tf_object);
1074 			break;
1075 		case INTERFACE_IDENTIFICATION_OBJECT_CLASS:
1076 			unknown_object =
1077 			    dissect_interface_identification_object(tvb,
1078 								 offset,
1079 								 ext_object_tree,
1080 								 tf_object);
1081 			break;
1082 		default:
1083 
1084 			unknown_object = TRUE;
1085 
1086 			break;
1087 		}		/* end switch class_num */
1088 
1089 		/* The switches couldn't decode the object */
1090 		if (unknown_object == TRUE) {
1091 			proto_tree_add_item(ext_object_tree, hf_icmp_ext_c_type, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
1092 
1093 			/* Skip the object header */
1094 			offset += 4;
1095 
1096 			proto_item_set_text(tf_object,
1097 					    "Unknown object (%d/%d)",
1098 					    class_num, c_type);
1099 
1100 			if (obj_trunc_length > 4) {
1101 				proto_tree_add_item(ext_object_tree, hf_icmp_ext_data, tvb, offset, obj_trunc_length - 4, ENC_NA);
1102 			}
1103 		}
1104 
1105 		/* */
1106 		if (obj_trunc_length < obj_length) {
1107 			proto_item_append_text(tf_object, " (truncated)");
1108 		}
1109 
1110 		/* Go to the end of the object */
1111 		offset = obj_end_offset;
1112 
1113 	}
1114 	return offset;
1115 }
1116 
1117 /* ======================================================================= */
1118 /*
1119 	Note: We are tracking conversations via these keys:
1120 
1121 	0                   1                   2                   3
1122 	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
1123 	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1124 	|                             |G|            Checksum           |
1125 	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1126 	|           Identifier          |        Sequence Number        |
1127 	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1128 	|                            VLAN ID                            |
1129 	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1130 */
1131 static icmp_transaction_t *transaction_start(packet_info * pinfo,
1132 					     proto_tree * tree,
1133 					     guint32 * key)
1134 {
1135 	conversation_t *conversation;
1136 	icmp_conv_info_t *icmp_info;
1137 	icmp_transaction_t *icmp_trans;
1138 	wmem_tree_key_t icmp_key[3];
1139 	proto_item *it;
1140 
1141 	/* Handle the conversation tracking */
1142 	conversation = _find_or_create_conversation(pinfo);
1143 	icmp_info = (icmp_conv_info_t *)conversation_get_proto_data(conversation, proto_icmp);
1144 	if (icmp_info == NULL) {
1145 		icmp_info = wmem_new(wmem_file_scope(), icmp_conv_info_t);
1146 		icmp_info->unmatched_pdus = wmem_tree_new(wmem_file_scope());
1147 		icmp_info->matched_pdus   = wmem_tree_new(wmem_file_scope());
1148 		conversation_add_proto_data(conversation, proto_icmp,
1149 					    icmp_info);
1150 	}
1151 
1152 	if (!PINFO_FD_VISITED(pinfo)) {
1153 		/* this is a new request, create a new transaction structure and map it to the
1154 		   unmatched table
1155 		 */
1156 		icmp_key[0].length = 3;
1157 		icmp_key[0].key = key;
1158 		icmp_key[1].length = 0;
1159 		icmp_key[1].key = NULL;
1160 
1161 		icmp_trans = wmem_new(wmem_file_scope(), icmp_transaction_t);
1162 		icmp_trans->rqst_frame = pinfo->num;
1163 		icmp_trans->resp_frame = 0;
1164 		icmp_trans->rqst_time = pinfo->abs_ts;
1165 		nstime_set_zero(&icmp_trans->resp_time);
1166 		wmem_tree_insert32_array(icmp_info->unmatched_pdus, icmp_key,
1167 				       (void *) icmp_trans);
1168 	} else {
1169 		/* Already visited this frame */
1170 		guint32 frame_num = pinfo->num;
1171 
1172 		icmp_key[0].length = 3;
1173 		icmp_key[0].key = key;
1174 		icmp_key[1].length = 1;
1175 		icmp_key[1].key = &frame_num;
1176 		icmp_key[2].length = 0;
1177 		icmp_key[2].key = NULL;
1178 
1179 		icmp_trans =
1180 		    (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->matched_pdus,
1181 					   icmp_key);
1182 	}
1183 	if (icmp_trans == NULL) {
1184 		if (ADDR_IS_NOT_UNICAST(&pinfo->dst)) {
1185 			/* Note the non-unicast destination and skip transaction tracking */
1186 			col_append_str(pinfo->cinfo, COL_INFO, ADDR_IS_BROADCAST(&pinfo->dst) ? " (broadcast)" : " (multicast)");
1187 		} else if (PINFO_FD_VISITED(pinfo)) {
1188 			/* No response found - add field and expert info */
1189 			it = proto_tree_add_item(tree, hf_icmp_no_resp, NULL, 0, 0,
1190 						 ENC_NA);
1191 			proto_item_set_generated(it);
1192 
1193 			col_append_fstr(pinfo->cinfo, COL_INFO, " (no response found!)");
1194 
1195 			/* Expert info.  TODO: add to _icmp_transaction_t type and sequence number
1196 			   so can report here (and in taps) */
1197 			expert_add_info_format(pinfo, it, &ei_icmp_resp_not_found,
1198 					       "No response seen to ICMP request");
1199 		}
1200 
1201 		return NULL;
1202 	}
1203 
1204 	/* Print state tracking in the tree */
1205 	if (icmp_trans->resp_frame) {
1206 		it = proto_tree_add_uint(tree, hf_icmp_resp_in, NULL, 0, 0,
1207 					 icmp_trans->resp_frame);
1208 		proto_item_set_generated(it);
1209 
1210 		col_append_frame_number(pinfo, COL_INFO, " (reply in %u)",
1211 				icmp_trans->resp_frame);
1212 	}
1213 
1214 	return icmp_trans;
1215 
1216 }				/* transaction_start() */
1217 
1218 /* ======================================================================= */
1219 static icmp_transaction_t *transaction_end(packet_info * pinfo,
1220 					   proto_tree * tree,
1221 					   guint32 * key)
1222 {
1223 	conversation_t *conversation;
1224 	icmp_conv_info_t *icmp_info;
1225 	icmp_transaction_t *icmp_trans;
1226 	wmem_tree_key_t icmp_key[3];
1227 	proto_item *it;
1228 	nstime_t ns;
1229 	double resp_time;
1230 
1231 	conversation =
1232 	    find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
1233 			      conversation_pt_to_endpoint_type(pinfo->ptype), 0, 0, 0);
1234 	if (conversation == NULL) {
1235 		return NULL;
1236 	}
1237 
1238 	icmp_info = (icmp_conv_info_t *)conversation_get_proto_data(conversation, proto_icmp);
1239 	if (icmp_info == NULL) {
1240 		return NULL;
1241 	}
1242 
1243 	if (!PINFO_FD_VISITED(pinfo)) {
1244 		guint32 frame_num;
1245 
1246 		icmp_key[0].length = 3;
1247 		icmp_key[0].key = key;
1248 		icmp_key[1].length = 0;
1249 		icmp_key[1].key = NULL;
1250 		icmp_trans =
1251 		    (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->unmatched_pdus,
1252 					   icmp_key);
1253 		if (icmp_trans == NULL) {
1254 			return NULL;
1255 		}
1256 
1257 		/* we have already seen this response, or an identical one */
1258 		if (icmp_trans->resp_frame != 0) {
1259 			return NULL;
1260 		}
1261 
1262 		icmp_trans->resp_frame = pinfo->num;
1263 
1264 		/* we found a match. Add entries to the matched table for both request and reply frames
1265 		 */
1266 		icmp_key[0].length = 3;
1267 		icmp_key[0].key = key;
1268 		icmp_key[1].length = 1;
1269 		icmp_key[1].key = &frame_num;
1270 		icmp_key[2].length = 0;
1271 		icmp_key[2].key = NULL;
1272 
1273 		frame_num = icmp_trans->rqst_frame;
1274 		wmem_tree_insert32_array(icmp_info->matched_pdus, icmp_key,
1275 				       (void *) icmp_trans);
1276 
1277 		frame_num = icmp_trans->resp_frame;
1278 		wmem_tree_insert32_array(icmp_info->matched_pdus, icmp_key,
1279 				       (void *) icmp_trans);
1280 	} else {
1281 		/* Already visited this frame */
1282 		guint32 frame_num = pinfo->num;
1283 
1284 		icmp_key[0].length = 3;
1285 		icmp_key[0].key = key;
1286 		icmp_key[1].length = 1;
1287 		icmp_key[1].key = &frame_num;
1288 		icmp_key[2].length = 0;
1289 		icmp_key[2].key = NULL;
1290 
1291 		icmp_trans =
1292 		    (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->matched_pdus,
1293 					   icmp_key);
1294 
1295 		if (icmp_trans == NULL) {
1296 			return NULL;
1297 		}
1298 	}
1299 
1300 
1301 	it = proto_tree_add_uint(tree, hf_icmp_resp_to, NULL, 0, 0,
1302 				 icmp_trans->rqst_frame);
1303 	proto_item_set_generated(it);
1304 
1305 	nstime_delta(&ns, &pinfo->abs_ts, &icmp_trans->rqst_time);
1306 	icmp_trans->resp_time = ns;
1307 	resp_time = nstime_to_msec(&ns);
1308 	it = proto_tree_add_double_format_value(tree, hf_icmp_resptime,
1309 						NULL, 0, 0, resp_time,
1310 						"%.3f ms", resp_time);
1311 	proto_item_set_generated(it);
1312 
1313 	col_append_frame_number(pinfo, COL_INFO, " (request in %d)",
1314 			icmp_trans->rqst_frame);
1315 
1316 	return icmp_trans;
1317 
1318 }				/* transaction_end() */
1319 
1320 #define MSPERDAY            86400000
1321 
1322 /* ======================================================================= */
1323 static guint32
1324 get_best_guess_mstimeofday(tvbuff_t * tvb, gint offset, guint32 comp_ts)
1325 {
1326 	guint32 be_ts, le_ts;
1327 
1328 	/* Account for the special case from RFC 792 as best we can by clearing
1329 	 * the msb.  Ref: [Page 16] of https://tools.ietf.org/html/rfc792:
1330 
1331 	 If the time is not available in milliseconds or cannot be provided
1332 	 with respect to midnight UT then any time can be inserted in a
1333 	 timestamp provided the high order bit of the timestamp is also set
1334 	 to indicate this non-standard value.
1335 	 */
1336 	be_ts = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
1337 	le_ts = tvb_get_letohl(tvb, offset) & 0x7fffffff;
1338 
1339 	if (be_ts < MSPERDAY && le_ts >= MSPERDAY) {
1340 		return be_ts;
1341 	}
1342 
1343 	if (le_ts < MSPERDAY && be_ts >= MSPERDAY) {
1344 		return le_ts;
1345 	}
1346 
1347 	if (be_ts < MSPERDAY && le_ts < MSPERDAY) {
1348 		guint32 saved_be_ts = be_ts;
1349 		guint32 saved_le_ts = le_ts;
1350 
1351 		/* Is this a rollover to a new day, clocks not synchronized, different
1352 		 * timezones between originate and receive/transmit, .. what??? */
1353 		if (be_ts < comp_ts && be_ts <= (MSPERDAY / 4)
1354 		    && comp_ts >= (MSPERDAY - (MSPERDAY / 4)))
1355 			be_ts += MSPERDAY;	/* Assume a rollover to a new day */
1356 		if (le_ts < comp_ts && le_ts <= (MSPERDAY / 4)
1357 		    && comp_ts >= (MSPERDAY - (MSPERDAY / 4)))
1358 			le_ts += MSPERDAY;	/* Assume a rollover to a new day */
1359 		if ((be_ts - comp_ts) < (le_ts - comp_ts))
1360 			return saved_be_ts;
1361 		return saved_le_ts;
1362 	}
1363 
1364 	/* Both are bigger than MSPERDAY, but neither one's msb's are set.  This
1365 	 * is clearly invalid, but now what TODO?  For now, take the one closest to
1366 	 * the comparative timestamp, which is another way of saying, "let's
1367 	 * return a deterministic wild guess. */
1368 	if ((be_ts - comp_ts) < (le_ts - comp_ts)) {
1369 		return be_ts;
1370 	}
1371 	return le_ts;
1372 }				/* get_best_guess_mstimeofday() */
1373 
1374 static gboolean
1375 capture_icmp(const guchar *pd _U_, int offset _U_, int len _U_, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
1376 {
1377 	capture_dissector_increment_count(cpinfo, proto_icmp);
1378 	return TRUE;
1379 }
1380 
1381 /*
1382  * RFC 792 for basic ICMP.
1383  * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1384  * RFC 1256 for router discovery messages.
1385  * RFC 2002 and 3012 for Mobile IP stuff.
1386  */
1387 static int
1388 dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
1389 {
1390 	proto_tree *icmp_tree = NULL;
1391 	proto_item *ti, *checksum_item;
1392 	guint8 icmp_type;
1393 	guint8 icmp_code;
1394 	guint8 icmp_original_dgram_length;
1395 	guint captured_length, reported_length;
1396 	const gchar *type_str, *code_str;
1397 	guint32 num_addrs = 0;
1398 	guint32 addr_entry_size = 0;
1399 	guint32 i;
1400 	gboolean save_in_error_pkt;
1401 	tvbuff_t *next_tvb;
1402 	guint32 conv_key[3];
1403 	icmp_transaction_t *trans = NULL;
1404 	nstime_t ts, time_relative;
1405 	ws_ip4 *iph = WS_IP4_PTR(data);
1406 
1407 	col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1408 	col_clear(pinfo->cinfo, COL_INFO);
1409 
1410 	/* To do: check for runts, errs, etc. */
1411 	icmp_type = tvb_get_guint8(tvb, 0);
1412 	icmp_code = tvb_get_guint8(tvb, 1);
1413 	/* RFC 4884: Length of original datagram carried in the ICMP payload,
1414 	 * or 0 otherwise. Length in terms of 32 bit words.*/
1415 	icmp_original_dgram_length = tvb_get_guint8(tvb, 5);
1416 
1417 	type_str =
1418 	    val_to_str_const(icmp_type, icmp_type_str,
1419 			     "Unknown ICMP (obsolete or malformed?)");
1420 
1421 	switch (icmp_type) {
1422 	case ICMP_UNREACH:
1423 		code_str =
1424 		    val_to_str(icmp_code, unreach_code_str,
1425 			       "Unknown code: %u");
1426 		break;
1427 	case ICMP_REDIRECT:
1428 		code_str =
1429 		    val_to_str(icmp_code, redir_code_str,
1430 			       "Unknown code: %u");
1431 		break;
1432 	case ICMP_ALTHOST:
1433 		code_str =
1434 		    val_to_str(icmp_code, alt_host_code_str,
1435 			       "Unknown code: %u");
1436 		icmp_original_dgram_length = 0;
1437 		break;
1438 	case ICMP_RTRADVERT:
1439 		switch (icmp_code) {
1440 		case 0:	/* Mobile-Ip */
1441 		case 16:	/* Mobile-Ip */
1442 			type_str = "Mobile IP Advertisement";
1443 			break;
1444 		}		/* switch icmp_code */
1445 		code_str =
1446 		    val_to_str(icmp_code, rtradvert_code_str,
1447 			       "Unknown code: %u");
1448 		break;
1449 	case ICMP_TIMXCEED:
1450 		code_str =
1451 		    val_to_str(icmp_code, ttl_code_str,
1452 			       "Unknown code: %u");
1453 		break;
1454 	case ICMP_PARAMPROB:
1455 		code_str =
1456 		    val_to_str(icmp_code, par_code_str,
1457 			       "Unknown code: %u");
1458 		break;
1459 	case ICMP_PHOTURIS:
1460 		code_str =
1461 		    val_to_str(icmp_code, photuris_code_str,
1462 			       "Unknown code: %u");
1463 		break;
1464 	case ICMP_EXTECHO:
1465 		code_str =
1466 		    val_to_str(icmp_code, ext_echo_req_code_str,
1467 			       "Unknown code: %u");
1468 		break;
1469 	case ICMP_EXTECHOREPLY:
1470 		code_str =
1471 		    val_to_str(icmp_code, ext_echo_reply_code_str,
1472 			       "Unknown code: %u");
1473 		break;
1474 	default:
1475 		code_str = NULL;
1476 		break;
1477 	}
1478 
1479 	col_add_fstr(pinfo->cinfo, COL_INFO, "%-20s", type_str);
1480 	if (code_str) {
1481 		col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", code_str);
1482 	}
1483 
1484 	captured_length = tvb_captured_length(tvb);
1485 	reported_length = tvb_reported_length(tvb);
1486 
1487 	ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, captured_length, ENC_NA);
1488 	icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1489 
1490 	ti = proto_tree_add_item(icmp_tree, hf_icmp_type, tvb, 0, 1,
1491 				 ENC_BIG_ENDIAN);
1492 	proto_item_append_text(ti, " (%s)", type_str);
1493 
1494 	ti = proto_tree_add_item(icmp_tree, hf_icmp_code, tvb, 1, 1,
1495 				 ENC_BIG_ENDIAN);
1496 	if (code_str) {
1497 		proto_item_append_text(ti, " (%s)", code_str);
1498 	}
1499 
1500 	if (!pinfo->fragmented && captured_length >= reported_length
1501 	    && !pinfo->flags.in_error_pkt) {
1502 		/* The packet isn't part of a fragmented datagram, isn't
1503 		   truncated, and isn't the payload of an error packet, so we can checksum
1504 		   it. */
1505 		proto_tree_add_checksum(icmp_tree, tvb, 2, hf_icmp_checksum, hf_icmp_checksum_status, &ei_icmp_checksum, pinfo, ip_checksum_tvb(tvb, 0, reported_length),
1506 								ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
1507 	} else {
1508 		checksum_item = proto_tree_add_checksum(icmp_tree, tvb, 2, hf_icmp_checksum, hf_icmp_checksum_status, &ei_icmp_checksum, pinfo, 0,
1509 								ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1510 		proto_item_append_text(checksum_item, " [%s]",
1511 					pinfo->flags.in_error_pkt ? "in ICMP error packet" : "fragmented datagram");
1512 	}
1513 
1514 	/* Decode the second 4 bytes of the packet. */
1515 	switch (icmp_type) {
1516 	case ICMP_ECHOREPLY:
1517 	case ICMP_ECHO:
1518 	case ICMP_TSTAMP:
1519 	case ICMP_TSTAMPREPLY:
1520 	case ICMP_IREQ:
1521 	case ICMP_IREQREPLY:
1522 	case ICMP_MASKREQ:
1523 	case ICMP_MASKREPLY:
1524 		proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, ENC_BIG_ENDIAN);
1525 		proto_tree_add_item(icmp_tree, hf_icmp_ident_le, tvb, 4, 2, ENC_LITTLE_ENDIAN);
1526 		proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2, ENC_BIG_ENDIAN);
1527 		proto_tree_add_item(icmp_tree, hf_icmp_seq_num_le, tvb, 6, 2, ENC_LITTLE_ENDIAN);
1528 		col_append_fstr(pinfo->cinfo, COL_INFO, " id=0x%04x, seq=%u/%u",
1529 				tvb_get_ntohs(tvb, 4), tvb_get_ntohs(tvb, 6), tvb_get_letohs(tvb, 6));
1530 		if (iph != NULL) {
1531 			col_append_fstr(pinfo->cinfo, COL_INFO, ", ttl=%u", iph->ip_ttl);
1532 		}
1533 		break;
1534 
1535 	case ICMP_UNREACH:
1536 		if (icmp_original_dgram_length > 0) {
1537 			proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 4, 1, ENC_NA);
1538 			proto_tree_add_item(icmp_tree, hf_icmp_length, tvb, 5, 1, ENC_BIG_ENDIAN);
1539 			ti = proto_tree_add_uint(icmp_tree, hf_icmp_length_original_datagram,
1540 						 tvb, 5, 1, icmp_original_dgram_length * 4);
1541 			proto_item_set_generated(ti);
1542 			if (icmp_code == ICMP_FRAG_NEEDED) {
1543 				proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, ENC_BIG_ENDIAN);
1544 			} else {
1545 				proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 6, 2, ENC_NA);
1546 			}
1547 		} else if (icmp_code == ICMP_FRAG_NEEDED) {
1548 			proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 4, 2, ENC_NA);
1549 			proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, ENC_BIG_ENDIAN);
1550 		} else {
1551 			proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 4, 4, ENC_NA);
1552 		}
1553 		break;
1554 
1555 	case ICMP_RTRADVERT:
1556 		proto_tree_add_item_ret_uint(icmp_tree, hf_icmp_num_addrs, tvb, 4, 1, ENC_BIG_ENDIAN, &num_addrs);
1557 		proto_tree_add_item_ret_uint(icmp_tree, hf_icmp_addr_entry_size, tvb, 5, 1, ENC_BIG_ENDIAN, &addr_entry_size);
1558 		ti = proto_tree_add_item(icmp_tree, hf_icmp_lifetime, tvb, 6, 2, ENC_BIG_ENDIAN);
1559 		proto_item_append_text(ti, " (%s)", signed_time_secs_to_str(pinfo->pool, tvb_get_ntohs(tvb, 6)));
1560 		break;
1561 
1562 	case ICMP_PARAMPROB:
1563 		proto_tree_add_item(icmp_tree, hf_icmp_pointer, tvb, 4, 1, ENC_BIG_ENDIAN);
1564 		if (icmp_original_dgram_length > 0) {
1565 			proto_tree_add_item(icmp_tree, hf_icmp_length, tvb, 5, 1, ENC_BIG_ENDIAN);
1566 			ti = proto_tree_add_uint(icmp_tree, hf_icmp_length_original_datagram,
1567 						 tvb, 5, 1, icmp_original_dgram_length * 4);
1568 			proto_item_set_generated(ti);
1569 			proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 6, 2, ENC_NA);
1570 		} else {
1571 			proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 5, 3, ENC_NA);
1572 		}
1573 		break;
1574 
1575 	case ICMP_REDIRECT:
1576 		proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, ENC_BIG_ENDIAN);
1577 		break;
1578 
1579 	case ICMP_TIMXCEED:
1580 		if (icmp_original_dgram_length > 0) {
1581 			proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 4, 1, ENC_NA);
1582 			proto_tree_add_item(icmp_tree, hf_icmp_length, tvb, 5, 1, ENC_BIG_ENDIAN);
1583 			ti = proto_tree_add_uint(icmp_tree, hf_icmp_length_original_datagram,
1584 						 tvb, 5, 1, icmp_original_dgram_length * 4);
1585 			proto_item_set_generated(ti);
1586 			proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 6, 2, ENC_NA);
1587 		} else {
1588 			proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 4, 4, ENC_NA);
1589 		}
1590 		break;
1591 
1592 	case ICMP_EXTECHO:
1593 		proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, ENC_BIG_ENDIAN);
1594 		proto_tree_add_item(icmp_tree, hf_icmp_ident_le, tvb, 4, 2, ENC_LITTLE_ENDIAN);
1595 		proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_seq_num, tvb, 6, 1, ENC_BIG_ENDIAN);
1596 		proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_req_reserved, tvb, 7, 1, ENC_BIG_ENDIAN);
1597 		proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_req_local, tvb, 7, 1, ENC_BIG_ENDIAN);
1598 		break;
1599 
1600 	case ICMP_EXTECHOREPLY:
1601 		proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, ENC_BIG_ENDIAN);
1602 		proto_tree_add_item(icmp_tree, hf_icmp_ident_le, tvb, 4, 2, ENC_LITTLE_ENDIAN);
1603 		proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_seq_num, tvb, 6, 1, ENC_BIG_ENDIAN);
1604 		proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_state, tvb, 7, 1, ENC_BIG_ENDIAN);
1605 		proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_reserved, tvb, 7, 1, ENC_BIG_ENDIAN);
1606 		proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_active, tvb, 7, 1, ENC_BIG_ENDIAN);
1607 		proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_ipv4, tvb, 7, 1, ENC_BIG_ENDIAN);
1608 		proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_ipv6, tvb, 7, 1, ENC_BIG_ENDIAN);
1609 		break;
1610 	}
1611 
1612 
1613 	/* Decode the additional information in the packet.  */
1614 	switch (icmp_type) {
1615 	case ICMP_UNREACH:
1616 	case ICMP_TIMXCEED:
1617 	case ICMP_PARAMPROB:
1618 	case ICMP_SOURCEQUENCH:
1619 	case ICMP_REDIRECT:
1620 		/* Save the current value of the "we're inside an error packet"
1621 		   flag, and set that flag; subdissectors may treat packets
1622 		   that are the payload of error packets differently from
1623 		   "real" packets. */
1624 		save_in_error_pkt = pinfo->flags.in_error_pkt;
1625 		pinfo->flags.in_error_pkt = TRUE;
1626 
1627 		/* Decode the IP header and first 64 bits of data from the
1628 		   original datagram. */
1629 		next_tvb = tvb_new_subset_remaining(tvb, 8);
1630 
1631 		/* If the packet is compliant with RFC 4884, then it has
1632 		 * icmp_original_dgram_length*4 bytes of original IP packet that needs
1633 		 * to be decoded, followed by extension objects.
1634 		 */
1635 
1636 		if (icmp_type == ICMP_REDIRECT) {
1637 			/* No icmp_original_dgram_length is available for redirect message,
1638 			 * we expect a max of Internet Header + 64 bits of Original Data Datagram */
1639 			set_actual_length(next_tvb, ((tvb_get_guint8(tvb, 8) & 0x0f) * 4) + 8);
1640 		} else if (icmp_original_dgram_length
1641 		    && (tvb_reported_length(tvb) >
1642 			(guint) (8 + icmp_original_dgram_length * 4))
1643 		    && (tvb_get_ntohs(tvb, 8 + 2) >
1644 			(guint) icmp_original_dgram_length * 4)) {
1645 			set_actual_length(next_tvb,
1646 					  ((tvb_get_guint8(tvb, 8) & 0x0f) + icmp_original_dgram_length) * 4);
1647 		} else {
1648 			/* There is a collision between RFC 1812 and draft-ietf-mpls-icmp-02.
1649 			   We don't know how to decode the 128th and following bytes of the ICMP payload.
1650 			   According to draft-ietf-mpls-icmp-02, these bytes should be decoded as MPLS extensions
1651 			   whereas RFC 1812 tells us to decode them as a portion of the original packet.
1652 			   Let the user decide.
1653 
1654 			   Here the user decided to favor MPLS extensions.
1655 			   Force the IP dissector to decode only the first 128 bytes. */
1656 			if ((tvb_reported_length(tvb) > 8 + 128) &&
1657 			    favor_icmp_mpls_ext
1658 			    && (tvb_get_ntohs(tvb, 8 + 2) > 128)) {
1659 				set_actual_length(next_tvb, 128);
1660 			}
1661 		}
1662 
1663 		call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1664 
1665 		/* Restore the "we're inside an error packet" flag. */
1666 		pinfo->flags.in_error_pkt = save_in_error_pkt;
1667 
1668 		/* Decode MPLS extensions if the payload has at least 128 bytes, and
1669 		   - the original packet in the ICMP payload has less than 128 bytes, or
1670 		   - the user favors the MPLS extensions analysis */
1671 		if ((tvb_reported_length(tvb) > 8 + 128)
1672 		    && (tvb_get_ntohs(tvb, 8 + 2) <= 128
1673 			|| favor_icmp_mpls_ext)) {
1674 			int ext_offset = (icmp_original_dgram_length ? icmp_original_dgram_length * 4 : 128) + 8;
1675 			tvbuff_t * extension_tvb = tvb_new_subset_remaining(tvb, ext_offset);
1676 			dissect_icmp_extension(extension_tvb, pinfo, icmp_tree, NULL);
1677 		}
1678 		break;
1679 	case ICMP_ECHOREPLY:
1680 	case ICMP_ECHO:
1681 		if (icmp_type == ICMP_ECHOREPLY) {
1682 			if (!pinfo->flags.in_error_pkt) {
1683 				conv_key[0] =
1684 				    (guint32) tvb_get_ntohs(tvb, 2);
1685 				if (conv_key[0] == 0xffff) {
1686 					conv_key[0] = 0;
1687 				}
1688 				if (pinfo->flags.in_gre_pkt && prefs.strict_conversation_tracking_heuristics)
1689 					conv_key[0] |= 0x00010000;	/* set a bit for "in GRE" */
1690 				conv_key[1] =
1691 				    ((guint32) tvb_get_ntohs(tvb, 4) << 16) |
1692 				     tvb_get_ntohs(tvb, 6);
1693 				conv_key[2] = prefs.strict_conversation_tracking_heuristics ? pinfo->vlan_id : 0;
1694 				trans =
1695 				    transaction_end(pinfo, icmp_tree,
1696 						    conv_key);
1697 			}
1698 		} else {
1699 			if (!pinfo->flags.in_error_pkt) {
1700 				guint16 tmp[2];
1701 
1702 				tmp[0] = ~tvb_get_ntohs(tvb, 2);
1703 				tmp[1] = ~0x0800;	/* The difference between echo request & reply */
1704 				conv_key[0] =
1705 				    ip_checksum((guint8 *) & tmp,
1706 						sizeof(tmp));
1707 				if (pinfo->flags.in_gre_pkt && prefs.strict_conversation_tracking_heuristics) {
1708 					conv_key[0] |= 0x00010000;	/* set a bit for "in GRE" */
1709 				}
1710 				conv_key[1] =
1711 				    ((guint32) tvb_get_ntohs(tvb, 4) << 16) |
1712 				     tvb_get_ntohs(tvb, 6);
1713 				conv_key[2] = prefs.strict_conversation_tracking_heuristics ? pinfo->vlan_id : 0;
1714 				trans =
1715 				    transaction_start(pinfo, icmp_tree,
1716 						      conv_key);
1717 			}
1718 		}
1719 
1720 		/* Make sure we have enough bytes in the payload before trying to
1721 		 * see if the data looks like a timestamp; otherwise we'll get
1722 		 * malformed packets as we try to access data that isn't there. */
1723 		if (tvb_captured_length_remaining(tvb, 8) < 8) {
1724 			if (tvb_captured_length_remaining(tvb, 8) > 0) {
1725 				call_data_dissector(tvb_new_subset_remaining
1726 					       (tvb, 8), pinfo, icmp_tree);
1727 			}
1728 			break;
1729 		}
1730 
1731 		/* Interpret the first 8 bytes of the icmp data as a timestamp
1732 		 * But only if it does look like it's a timestamp.
1733 		 *
1734 		 * FIXME:
1735 		 *    Timestamps could be in different formats depending on the OS
1736 		 */
1737 		ts.secs = tvb_get_ntohl(tvb, 8);
1738 		ts.nsecs = tvb_get_ntohl(tvb, 8 + 4);	/* Leave at microsec resolution for now */
1739 		if (abs((int)(ts.secs - pinfo->abs_ts.secs)) >=
1740 		    3600 * 24 || ts.nsecs >= 1000000) {
1741 			/* Timestamp does not look right in BE, try LE representation */
1742 			ts.secs = tvb_get_letohl(tvb, 8);
1743 			ts.nsecs = tvb_get_letohl(tvb, 8 + 4);	/* Leave at microsec resolution for now */
1744 		}
1745 		if (abs((int)(ts.secs - pinfo->abs_ts.secs)) <
1746 		    3600 * 24 && ts.nsecs < 1000000) {
1747 			ts.nsecs *= 1000;	/* Convert to nanosec resolution */
1748 			proto_tree_add_time(icmp_tree, hf_icmp_data_time,
1749 					    tvb, 8, 8, &ts);
1750 			nstime_delta(&time_relative, &pinfo->abs_ts,
1751 				     &ts);
1752 			ti = proto_tree_add_time(icmp_tree,
1753 						 hf_icmp_data_time_relative,
1754 						 tvb, 8, 8,
1755 						 &time_relative);
1756 			proto_item_set_generated(ti);
1757 			call_data_dissector(tvb_new_subset_remaining(tvb,
1758 								8 + 8),
1759 				       pinfo, icmp_tree);
1760 		} else {
1761 			heur_dtbl_entry_t *hdtbl_entry;
1762 			next_tvb = tvb_new_subset_remaining(tvb, 8);
1763 			if (!dissector_try_heuristic(icmp_heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
1764 				call_data_dissector(next_tvb, pinfo, icmp_tree);
1765 			}
1766 		}
1767 		break;
1768 
1769 	case ICMP_RTRADVERT:
1770 		if (addr_entry_size == 2) {
1771 			for (i = 0; i < num_addrs; i++) {
1772 				proto_tree_add_item(icmp_tree, hf_icmp_router_address, tvb, 8 + (i * 8), 4, ENC_NA);
1773 				proto_tree_add_item(icmp_tree, hf_icmp_pref_level, tvb, 12 + (i * 8), 4, ENC_NA);
1774 			}
1775 			if ((icmp_code == 0) || (icmp_code == 16)) {
1776 				/* Mobile-Ip */
1777 				dissect_mip_extensions(tvb, 8 + i * 8,
1778 						       icmp_tree);
1779 			}
1780 		} else {
1781 			call_data_dissector(tvb_new_subset_remaining(tvb, 8),
1782 				       pinfo, icmp_tree);
1783 		}
1784 		break;
1785 
1786 	case ICMP_TSTAMP:
1787 	case ICMP_TSTAMPREPLY:
1788 		{
1789 			guint32 frame_ts, orig_ts;
1790 
1791 			frame_ts = (guint32)(((pinfo->abs_ts.secs * 1000) +
1792 				    (pinfo->abs_ts.nsecs / 1000000)) %
1793 			    86400000);
1794 
1795 			orig_ts = get_best_guess_mstimeofday(tvb, 8, frame_ts);
1796 			ti = proto_tree_add_item(icmp_tree, hf_icmp_originate_timestamp, tvb, 8, 4, ENC_BIG_ENDIAN);
1797 			proto_item_append_text(ti, " (%s after midnight UTC)", signed_time_msecs_to_str(pinfo->pool, orig_ts));
1798 
1799 			ti = proto_tree_add_item(icmp_tree, hf_icmp_receive_timestamp, tvb, 12, 4, ENC_BIG_ENDIAN);
1800 			proto_item_append_text(ti, " (%s after midnight UTC)", signed_time_msecs_to_str(pinfo->pool, get_best_guess_mstimeofday(tvb, 12, frame_ts)));
1801 
1802 			ti = proto_tree_add_item(icmp_tree, hf_icmp_transmit_timestamp, tvb, 16, 4, ENC_BIG_ENDIAN);
1803 			proto_item_append_text(ti, " (%s after midnight UTC)", signed_time_msecs_to_str(pinfo->pool, get_best_guess_mstimeofday(tvb, 16, frame_ts)));
1804 
1805 		}
1806 		break;
1807 
1808 	case ICMP_MASKREQ:
1809 	case ICMP_MASKREPLY:
1810 		proto_tree_add_item(icmp_tree, hf_icmp_address_mask, tvb, 8, 4, ENC_BIG_ENDIAN);
1811 		break;
1812 
1813 	case ICMP_EXTECHO:
1814 		if (tvb_reported_length(tvb) > 8) {
1815 			tvbuff_t * extension_tvb = tvb_new_subset_remaining(tvb, 8);
1816 			dissect_icmp_extension(extension_tvb, pinfo, icmp_tree, NULL);
1817 		}
1818 		break;
1819 	}
1820 
1821 	if (!PINFO_FD_VISITED(pinfo)) {
1822 		icmp_info_t *p_icmp_info = wmem_new(wmem_file_scope(), icmp_info_t);
1823 		p_icmp_info->type = icmp_type;
1824 		p_icmp_info->code = icmp_code;
1825 		p_add_proto_data(wmem_file_scope(), pinfo, proto_icmp, 0, p_icmp_info);
1826 	}
1827 
1828 	if (trans) {
1829 		tap_queue_packet(icmp_tap, pinfo, trans);
1830 	}
1831 
1832 	return tvb_reported_length(tvb);
1833 }
1834 
1835 void proto_register_icmp(void)
1836 {
1837 	static hf_register_info hf[] = {
1838 		{&hf_icmp_type,
1839 		 {"Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1840 		  NULL, HFILL}},
1841 
1842 		{&hf_icmp_code,
1843 		 {"Code", "icmp.code", FT_UINT8, BASE_DEC, NULL, 0x0,
1844 		  NULL, HFILL}},
1845 
1846 		{&hf_icmp_checksum,
1847 		 {"Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL,
1848 		  0x0,
1849 		  NULL, HFILL}},
1850 
1851 		{&hf_icmp_checksum_status,
1852 		 {"Checksum Status", "icmp.checksum.status", FT_UINT8, BASE_NONE,
1853 		  VALS(proto_checksum_vals), 0x0,
1854 		  NULL, HFILL}},
1855 
1856 		{&hf_icmp_unused,
1857 		 {"Unused", "icmp.unused", FT_BYTES,
1858 		  BASE_NONE, NULL, 0x0,
1859 		  NULL, HFILL}},
1860 
1861 		{&hf_icmp_reserved,
1862 		 {"Reserved", "icmp.reserved", FT_BYTES,
1863 		  BASE_NONE, NULL, 0x0,
1864 		  NULL, HFILL}},
1865 
1866 		{&hf_icmp_ident,
1867 		 {"Identifier (BE)", "icmp.ident", FT_UINT16, BASE_DEC_HEX,
1868 		  NULL, 0x0,
1869 		  "Identifier (big endian representation)", HFILL}},
1870 
1871 		{&hf_icmp_ident_le,
1872 		 {"Identifier (LE)", "icmp.ident_le", FT_UINT16, BASE_DEC_HEX,
1873 		  NULL, 0x0,
1874 		  "Identifier (little endian representation)", HFILL}},
1875 
1876 		{&hf_icmp_seq_num,
1877 		 {"Sequence Number (BE)", "icmp.seq", FT_UINT16,
1878 		  BASE_DEC_HEX, NULL, 0x0,
1879 		  "Sequence Number (big endian representation)", HFILL}},
1880 
1881 		{&hf_icmp_seq_num_le,
1882 		 {"Sequence Number (LE)", "icmp.seq_le", FT_UINT16,
1883 		  BASE_DEC_HEX, NULL,
1884 		  0x0, "Sequence Number (little endian representation)",
1885 		  HFILL}},
1886 
1887 		{&hf_icmp_mtu,
1888 		 {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL,
1889 		  0x0,
1890 		  NULL, HFILL}},
1891 
1892 		{&hf_icmp_num_addrs,
1893 		 {"Number of addresses", "icmp.num_addrs", FT_UINT8, BASE_DEC, NULL,
1894 		  0x0,
1895 		  NULL, HFILL}},
1896 
1897 		{&hf_icmp_addr_entry_size,
1898 		 {"Address entry size", "icmp.addr_entry_size", FT_UINT8, BASE_DEC, NULL,
1899 		  0x0,
1900 		  NULL, HFILL}},
1901 
1902 		{&hf_icmp_lifetime,
1903 		 {"Lifetime", "icmp.lifetime", FT_UINT16, BASE_DEC, NULL,
1904 		  0x0,
1905 		  NULL, HFILL}},
1906 
1907 		{&hf_icmp_pointer,
1908 		 {"Pointer", "icmp.pointer", FT_UINT32, BASE_DEC, NULL,
1909 		  0x0,
1910 		  NULL, HFILL}},
1911 
1912 		{&hf_icmp_router_address,
1913 		 {"Router address", "icmp.router_address", FT_IPv4, BASE_NONE, NULL,
1914 		  0x0,
1915 		  NULL, HFILL}},
1916 
1917 		{&hf_icmp_pref_level,
1918 		 {"Preference level", "icmp.pref_level", FT_INT32, BASE_DEC, NULL,
1919 		  0x0,
1920 		  NULL, HFILL}},
1921 
1922 		{&hf_icmp_originate_timestamp,
1923 		 {"Originate Timestamp", "icmp.originate_timestamp", FT_UINT32, BASE_DEC, NULL,
1924 		  0x0,
1925 		  NULL, HFILL}},
1926 
1927 		{&hf_icmp_receive_timestamp,
1928 		 {"Receive Timestamp", "icmp.receive_timestamp", FT_UINT32, BASE_DEC, NULL,
1929 		  0x0,
1930 		  NULL, HFILL}},
1931 
1932 		{&hf_icmp_transmit_timestamp,
1933 		 {"Transmit Timestamp", "icmp.transmit_timestamp", FT_UINT32, BASE_DEC, NULL,
1934 		  0x0,
1935 		  NULL, HFILL}},
1936 
1937 		{&hf_icmp_address_mask,
1938 		 {"Address Mask", "icmp.address_mask", FT_IPv4, BASE_NONE, NULL,
1939 		  0x0,
1940 		  NULL, HFILL}},
1941 
1942 		{&hf_icmp_redir_gw,
1943 		 {"Gateway Address", "icmp.redir_gw", FT_IPv4, BASE_NONE,
1944 		  NULL, 0x0,
1945 		  NULL, HFILL}},
1946 
1947 		{&hf_icmp_mip_type,
1948 		 {"Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
1949 		  VALS(mip_extensions), 0x0, NULL, HFILL}},
1950 
1951 		{&hf_icmp_mip_length,
1952 		 {"Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL,
1953 		  0x0,
1954 		  NULL, HFILL}},
1955 
1956 		{&hf_icmp_mip_prefix_length,
1957 		 {"Prefix Length", "icmp.mip.prefixlength", FT_UINT8,
1958 		  BASE_DEC, NULL, 0x0,
1959 		  NULL, HFILL}},
1960 
1961 		{&hf_icmp_mip_seq,
1962 		 {"Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC,
1963 		  NULL, 0x0,
1964 		  NULL, HFILL}},
1965 
1966 		{&hf_icmp_mip_life,
1967 		 {"Registration Lifetime", "icmp.mip.life", FT_UINT16,
1968 		  BASE_DEC, NULL,
1969 		  0x0,
1970 		  NULL, HFILL}},
1971 
1972 		{&hf_icmp_mip_flags,
1973 		 {"Flags", "icmp.mip.flags", FT_UINT16, BASE_HEX, NULL,
1974 		  0x0,
1975 		  NULL, HFILL}},
1976 
1977 		{&hf_icmp_mip_r,
1978 		 {"Registration Required", "icmp.mip.r", FT_BOOLEAN, 16,
1979 		  NULL, 0x8000,
1980 		  "Registration with this FA is required", HFILL}},
1981 
1982 		{&hf_icmp_mip_b,
1983 		 {"Busy", "icmp.mip.b", FT_BOOLEAN, 16, NULL, 0x4000,
1984 		  "This FA will not accept requests at this time", HFILL}},
1985 
1986 		{&hf_icmp_mip_h,
1987 		 {"Home Agent", "icmp.mip.h", FT_BOOLEAN, 16, NULL, 0x2000,
1988 		  "Home Agent Services Offered", HFILL}},
1989 
1990 		{&hf_icmp_mip_f,
1991 		 {"Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 16, NULL,
1992 		  0x1000,
1993 		  "Foreign Agent Services Offered", HFILL}},
1994 
1995 		{&hf_icmp_mip_m,
1996 		 {"Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 16,
1997 		  NULL, 0x0800,
1998 		  "Minimal encapsulation tunneled datagram support",
1999 		  HFILL}},
2000 
2001 		{&hf_icmp_mip_g,
2002 		 {"GRE", "icmp.mip.g", FT_BOOLEAN, 16, NULL, 0x0400,
2003 		  "GRE encapsulated tunneled datagram support", HFILL}},
2004 
2005 		{&hf_icmp_mip_v,
2006 		 {"VJ Comp", "icmp.mip.v", FT_BOOLEAN, 16, NULL, 0x0200,
2007 		  "Van Jacobson Header Compression Support", HFILL}},
2008 
2009 		{&hf_icmp_mip_rt,
2010 		 {"Reverse tunneling", "icmp.mip.rt", FT_BOOLEAN, 16, NULL,
2011 		  0x0100,
2012 		  "Reverse tunneling support", HFILL}},
2013 
2014 		{&hf_icmp_mip_u,
2015 		 {"UDP tunneling", "icmp.mip.u", FT_BOOLEAN, 16, NULL,
2016 		  0x0080,
2017 		  "UDP tunneling support", HFILL}},
2018 
2019 		{&hf_icmp_mip_x,
2020 		 {"Revocation support", "icmp.mip.x", FT_BOOLEAN, 16, NULL,
2021 		  0x0040,
2022 		  "Registration revocation support", HFILL}},
2023 
2024 		{&hf_icmp_mip_reserved,
2025 		 {"Reserved", "icmp.mip.reserved", FT_UINT16, BASE_HEX,
2026 		  NULL, 0x003f,
2027 		  NULL, HFILL}},
2028 
2029 		{&hf_icmp_mip_coa,
2030 		 {"Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE,
2031 		  NULL, 0x0,
2032 		  NULL, HFILL}},
2033 
2034 		{&hf_icmp_mip_challenge,
2035 		 {"Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE,
2036 		  NULL, 0x0,
2037 		  NULL, HFILL}},
2038 
2039 		{&hf_icmp_mip_content,
2040 		 {"Content", "icmp.mip.content", FT_BYTES, BASE_NONE,
2041 		  NULL, 0x0,
2042 		  NULL, HFILL}},
2043 
2044 		{&hf_icmp_ext,
2045 		 {"ICMP Extensions", "icmp.ext", FT_NONE, BASE_NONE, NULL,
2046 		  0x0,
2047 		  NULL, HFILL}},
2048 
2049 		{&hf_icmp_ext_version,
2050 		 {"Version", "icmp.ext.version", FT_UINT8, BASE_DEC, NULL,
2051 		  0x0,
2052 		  NULL, HFILL}},
2053 
2054 		{&hf_icmp_ext_reserved,
2055 		 {"Reserved", "icmp.ext.res", FT_UINT16, BASE_HEX, NULL,
2056 		  0x0fff,
2057 		  NULL, HFILL}},
2058 
2059 		{&hf_icmp_ext_checksum,
2060 		 {"Checksum", "icmp.ext.checksum", FT_UINT16, BASE_HEX,
2061 		  NULL, 0x0,
2062 		  NULL, HFILL}},
2063 
2064 		{&hf_icmp_ext_checksum_status,
2065 		 {"Checksum Status", "icmp.ext.checksum.status", FT_UINT8, BASE_NONE,
2066 		  VALS(proto_checksum_vals),
2067 		  0x0,
2068 		  NULL, HFILL}},
2069 
2070 		{&hf_icmp_ext_length,
2071 		 {"Length", "icmp.ext.length", FT_UINT16, BASE_DEC, NULL,
2072 		  0x0,
2073 		  NULL, HFILL}},
2074 
2075 		{&hf_icmp_ext_class,
2076 		 {"Class", "icmp.ext.class", FT_UINT8, BASE_DEC,
2077 		 VALS(icmp_ext_class_str), 0x0, NULL, HFILL}},
2078 
2079 		{&hf_icmp_ext_c_type,
2080 		 {"C-Type", "icmp.ext.ctype", FT_UINT8, BASE_DEC, NULL,
2081 		  0x0,
2082 		  NULL, HFILL}},
2083 
2084 		{&hf_icmp_ext_data,
2085 		 {"Data", "icmp.ext.data", FT_BYTES, BASE_NONE, NULL, 0x0,
2086 		  NULL, HFILL}},
2087 
2088 		{&hf_icmp_mpls_label,
2089 		 {"Label", "icmp.mpls.label", FT_UINT24, BASE_DEC, NULL,
2090 		  0x00fffff0,
2091 		  NULL, HFILL}},
2092 
2093 		{&hf_icmp_mpls_exp,
2094 		 {"Experimental", "icmp.mpls.exp", FT_UINT24, BASE_DEC,
2095 		  NULL, 0x0e,
2096 		  NULL, HFILL}},
2097 
2098 		{&hf_icmp_mpls_s,
2099 		 {"Stack bit", "icmp.mpls.s", FT_BOOLEAN, 24,
2100 		  TFS(&tfs_set_notset), 0x01,
2101 		  NULL, HFILL}},
2102 
2103 		{&hf_icmp_mpls_ttl,
2104 		 {"Time to live", "icmp.mpls.ttl", FT_UINT8, BASE_DEC,
2105 		  NULL, 0x0,
2106 		  NULL, HFILL}},
2107 
2108 		{&hf_icmp_mpls_data,
2109 		 {"Data", "icmp.mpls.data", FT_BYTES, BASE_NONE ,
2110 		  NULL, 0x0,
2111 		  NULL, HFILL}},
2112 
2113 		{&hf_icmp_resp_in,
2114 		 {"Response frame", "icmp.resp_in", FT_FRAMENUM, BASE_NONE,
2115 		  FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
2116 		  "The frame number of the corresponding response",
2117 		  HFILL}},
2118 
2119 		{&hf_icmp_no_resp,
2120 		 {"No response seen", "icmp.no_resp", FT_NONE, BASE_NONE,
2121 		  NULL, 0x0,
2122 		  "No corresponding response frame was seen",
2123 		  HFILL}},
2124 
2125 		{&hf_icmp_resp_to,
2126 		 {"Request frame", "icmp.resp_to", FT_FRAMENUM, BASE_NONE,
2127 		  FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
2128 		  "The frame number of the corresponding request", HFILL}},
2129 
2130 		{&hf_icmp_resptime,
2131 		 {"Response time", "icmp.resptime", FT_DOUBLE, BASE_NONE,
2132 		  NULL, 0x0,
2133 		  "The time between the request and the response, in ms.",
2134 		  HFILL}},
2135 
2136 		{&hf_icmp_data_time,
2137 		 {"Timestamp from icmp data", "icmp.data_time",
2138 		  FT_ABSOLUTE_TIME,
2139 		  ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2140 		  "The timestamp in the first 8 bytes of the icmp data",
2141 		  HFILL}},
2142 
2143 		{&hf_icmp_data_time_relative,
2144 		 {"Timestamp from icmp data (relative)",
2145 		  "icmp.data_time_relative",
2146 		  FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2147 		  "The timestamp of the packet, relative to the timestamp in the first 8 bytes of the icmp data",
2148 		  HFILL}},
2149 
2150 		{&hf_icmp_length,
2151 		 {"Length", "icmp.length", FT_UINT8,
2152 		  BASE_DEC, NULL,
2153 		  0x0,
2154 		  "The length of the original datagram", HFILL}},
2155 		{&hf_icmp_length_original_datagram,
2156 		 {"Length of original datagram", "icmp.length.original_datagram", FT_UINT8,
2157 		  BASE_DEC, NULL,
2158 		  0x0,
2159 		  "The length of the original datagram (length * 4)", HFILL}},
2160 		{&hf_icmp_int_info_role,
2161 		 {"Interface Role", "icmp.int_info.role",
2162 		  FT_UINT8, BASE_DEC, VALS(interface_role_str),
2163 		  INT_INFO_INTERFACE_ROLE,
2164 		  NULL, HFILL}},
2165 		{&hf_icmp_int_info_reserved,
2166 		 {"Reserved", "icmp.int_info.reserved",
2167 		  FT_UINT8, BASE_DEC, NULL, INT_INFO_RESERVED,
2168 		  NULL, HFILL}},
2169 		{&hf_icmp_int_info_ifindex,
2170 		 {"ifIndex", "icmp.int_info.ifindex", FT_BOOLEAN, 8, NULL,
2171 		  INT_INFO_IFINDEX,
2172 		  "True: ifIndex of the interface included; False: ifIndex of the interface not included ",
2173 		  HFILL}},
2174 		{&hf_icmp_int_info_ipaddr,
2175 		 {"IP Address", "icmp.int_info.ipaddr", FT_BOOLEAN, 8,
2176 		  TFS(&tfs_present_not_present),
2177 		  INT_INFO_IPADDR,
2178 		  NULL, HFILL}},
2179 		{&hf_icmp_int_info_name,
2180 		 {"Interface Name", "icmp.int_info.name_present", FT_BOOLEAN, 8,
2181 		  TFS(&tfs_present_not_present),
2182 		  INT_INFO_NAME,
2183 		  NULL,
2184 		  HFILL}},
2185 		{&hf_icmp_int_info_mtu_present,
2186 		 {"MTU", "icmp.int_info.mtu_present", FT_BOOLEAN, 8, TFS(&tfs_present_not_present),
2187 		  INT_INFO_MTU,
2188 		  NULL, HFILL}},
2189 		{&hf_icmp_int_info_index,
2190 		 {"Interface Index", "icmp.int_info.index",
2191 		  FT_UINT32, BASE_DEC,
2192 		  NULL, 0x0,
2193 		  NULL, HFILL}},
2194 		{&hf_icmp_int_info_afi,
2195 		 {"Address Family Identifier", "icmp.int_info.afi",
2196 		  FT_UINT16, BASE_DEC,
2197 		  NULL, 0x0,
2198 		  "Address Family of the interface address", HFILL}},
2199 		{&hf_icmp_int_info_ipv4,
2200 		 {"Source", "icmp.int_info.ipv4", FT_IPv4, BASE_NONE, NULL,
2201 		  0x0,
2202 		  NULL, HFILL}},
2203 		{&hf_icmp_int_info_ipv6,
2204 		 {"Source", "icmp.int_info.ipv6", FT_IPv6, BASE_NONE, NULL,
2205 		  0x0,
2206 		  NULL, HFILL}},
2207 		{&hf_icmp_int_info_ipunknown,
2208 		 {"Source", "icmp.int_info.ipunknown", FT_BYTES, BASE_NONE, NULL,
2209 		  0x0,
2210 		  NULL, HFILL}},
2211 		{&hf_icmp_int_info_name_length,
2212 		 {"Name Length", "icmp.int_info.name_length", FT_UINT8, BASE_DEC, NULL,
2213 		  0x0,
2214 		  NULL, HFILL}},
2215 		{&hf_icmp_int_info_name_string,
2216 		 {"Name", "icmp.int_info.name", FT_STRING, BASE_NONE, NULL,
2217 		  0x0,
2218 		  NULL, HFILL}},
2219 		{&hf_icmp_int_info_mtu,
2220 		 {"Maximum Transmission Unit", "icmp.int_info.mtu",
2221 		  FT_UINT32, BASE_DEC,
2222 		  NULL, 0x0,
2223 		  NULL, HFILL}},
2224 
2225 
2226 		{&hf_icmp_ext_echo_seq_num,
2227 		 {"Sequence Number", "icmp.ext.echo.seq", FT_UINT8,
2228 		  BASE_DEC_HEX, NULL, 0x0,
2229 		  NULL, HFILL}},
2230 		{&hf_icmp_ext_echo_req_reserved,
2231 		 {"Reserved", "icmp.ext.echo.req.res", FT_UINT8,
2232 		  BASE_HEX, NULL, 0xFE,
2233 		  NULL, HFILL}},
2234 		{&hf_icmp_ext_echo_req_local,
2235 		 {"Local bit", "icmp.ext.echo.req.local", FT_BOOLEAN,
2236 		  8, TFS(&tfs_set_notset), 0x01,
2237 		  NULL, HFILL}},
2238 		{&hf_icmp_ext_echo_rsp_state,
2239 		 {"State", "icmp.ext.echo.rsp.state", FT_UINT8,
2240 		  BASE_DEC, VALS(ext_echo_reply_state_str), 0xE0,
2241 		  NULL, HFILL}},
2242 		{&hf_icmp_ext_echo_rsp_reserved,
2243 		 {"Reserved", "icmp.ext.echo.rsp.res", FT_UINT8,
2244 		  BASE_HEX, NULL, 0x18,
2245 		  NULL, HFILL}},
2246 		{&hf_icmp_ext_echo_rsp_active,
2247 		 {"Active bit", "icmp.ext.echo.rsp.active", FT_BOOLEAN,
2248 		  8, TFS(&tfs_set_notset), 0x04,
2249 		  NULL, HFILL}},
2250 		{&hf_icmp_ext_echo_rsp_ipv4,
2251 		 {"IPv4 bit", "icmp.ext.echo.rsp.ipv4", FT_BOOLEAN,
2252 		  8, TFS(&tfs_set_notset), 0x02,
2253 		  NULL, HFILL}},
2254 		{&hf_icmp_ext_echo_rsp_ipv6,
2255 		 {"IPv6 bit", "icmp.ext.echo.rsp.ipv6", FT_BOOLEAN,
2256 		  8, TFS(&tfs_set_notset), 0x01,
2257 		  NULL, HFILL}},
2258 		{&hf_icmp_int_ident_name_string,
2259 		 {"Name", "icmp.int_ident.name", FT_STRING,
2260 		  BASE_NONE, NULL, 0x0,
2261 		  NULL, HFILL}},
2262 		{&hf_icmp_int_ident_index,
2263 		 {"Interface Index", "icmp.int_ident.index", FT_UINT32,
2264 		  BASE_DEC, NULL, 0x0,
2265 		  NULL, HFILL}},
2266 		{&hf_icmp_int_ident_afi,
2267 		 {"Address Family Identifier", "icmp.int_ident.afi", FT_UINT16,
2268 		  BASE_DEC, VALS(afn_vals), 0x0,
2269 		  "Address Family of the interface address", HFILL}},
2270 		{&hf_icmp_int_ident_addr_length,
2271 		 {"Address Length", "icmp.int_ident.addr_length", FT_UINT8,
2272 		  BASE_DEC, NULL, 0x0,
2273 		  NULL, HFILL}},
2274 		{&hf_icmp_int_ident_reserved,
2275 		 {"Reserved", "icmp.int_ident.reserved", FT_BYTES,
2276 		  BASE_NONE, NULL, 0x0,
2277 		  NULL, HFILL}},
2278 		{&hf_icmp_int_ident_ipv4,
2279 		 {"Address", "icmp.int_ident.ipv4", FT_IPv4,
2280 		  BASE_NONE, NULL, 0x0,
2281 		  NULL, HFILL}},
2282 		{&hf_icmp_int_ident_ipv6,
2283 		 {"Address", "icmp.int_ident.ipv6", FT_IPv6,
2284 		  BASE_NONE, NULL, 0x0,
2285 		  NULL, HFILL}},
2286 		{&hf_icmp_int_ident_address,
2287 		 {"Address", "icmp.int_ident.address", FT_BYTES,
2288 		  BASE_NONE, NULL, 0x0,
2289 		  NULL, HFILL}},
2290 
2291 	};
2292 
2293 	static gint *ett[] = {
2294 		&ett_icmp,
2295 		&ett_icmp_mip,
2296 		&ett_icmp_mip_flags,
2297 		/* MPLS extensions */
2298 		&ett_icmp_ext,
2299 		&ett_icmp_ext_object,
2300 		&ett_icmp_mpls_stack_object,
2301 		/* Interface Information Object RFC 5837 */
2302 		&ett_icmp_interface_info_object,
2303 		&ett_icmp_interface_ipaddr,
2304 		&ett_icmp_interface_name
2305 	};
2306 
2307 	static ei_register_info ei[] = {
2308 		{ &ei_icmp_resp_not_found, { "icmp.resp_not_found", PI_SEQUENCE, PI_WARN, "Response not found", EXPFILL }},
2309 		{ &ei_icmp_checksum, { "icmp.checksum_bad", PI_CHECKSUM, PI_WARN, "Bad checksum", EXPFILL }},
2310 		{ &ei_icmp_ext_checksum, { "icmp.ext.checksum_bad", PI_CHECKSUM, PI_WARN, "Bad checksum", EXPFILL }},
2311 	};
2312 
2313 	module_t *icmp_module;
2314 	expert_module_t* expert_icmp;
2315 
2316 	proto_icmp =
2317 	    proto_register_protocol("Internet Control Message Protocol",
2318 				    "ICMP", "icmp");
2319 	proto_register_field_array(proto_icmp, hf, array_length(hf));
2320 	expert_icmp = expert_register_protocol(proto_icmp);
2321 	expert_register_field_array(expert_icmp, ei, array_length(ei));
2322 	proto_register_subtree_array(ett, array_length(ett));
2323 
2324 	icmp_module = prefs_register_protocol(proto_icmp, NULL);
2325 
2326 	prefs_register_bool_preference(icmp_module, "favor_icmp_mpls",
2327 				       "Favor ICMP extensions for MPLS",
2328 				       "Whether the 128th and following bytes of the ICMP payload should be decoded as MPLS extensions or as a portion of the original packet",
2329 				       &favor_icmp_mpls_ext);
2330 
2331 	register_seq_analysis("icmp", "ICMP Flows", proto_icmp, NULL, TL_REQUIRES_COLUMNS, icmp_seq_analysis_packet);
2332 	icmp_handle = register_dissector("icmp", dissect_icmp, proto_icmp);
2333 	icmp_heur_subdissector_list = register_heur_dissector_list("icmp", proto_icmp);
2334 	register_dissector("icmp_extension", dissect_icmp_extension, proto_icmp);
2335 	icmp_tap = register_tap("icmp");
2336 }
2337 
2338 void proto_reg_handoff_icmp(void)
2339 {
2340 	capture_dissector_handle_t icmp_cap_handle;
2341 
2342 	/*
2343 	 * Get handle for the IP dissector.
2344 	 */
2345 	ip_handle = find_dissector_add_dependency("ip", proto_icmp);
2346 
2347 	dissector_add_uint("ip.proto", IP_PROTO_ICMP, icmp_handle);
2348 	icmp_cap_handle = create_capture_dissector_handle(capture_icmp, proto_icmp);
2349 	capture_dissector_add_uint("ip.proto", IP_PROTO_ICMP, icmp_cap_handle);
2350 }
2351 
2352 /*
2353  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2354  *
2355  * Local variables:
2356  * c-basic-offset: 8
2357  * tab-width: 8
2358  * indent-tabs-mode: t
2359  * End:
2360  *
2361  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2362  * :indentSize=8:tabSize=8:noTabs=false:
2363  */
2364